PhaserJS: add physics to graphic objects - javascript

Most examples use sprites to add physics, but I want to add physics to objects created using the Graphics class. For example:
var square = game.add.graphics( 0, 0 );
//some definitions
game.physics.arcade.enable( square );
This doesn't work at all with graphics, but it does right away with sprites. Why is that and how can I achieve this?
Thanks in advance.

I had to investigate quite a bit since it seems this is not the standard (at least tutorial wise), but you have to create a BitmapData object and use canvas to draw the figures. This is not nearly as fun as using game.add.graphics to create circles and poligons, etc. but it works well.
This is how you create a platform:
//creates the BitmapData object, you can use it to create figures:
var floor = game.add.bitmapData( 400, 20 ); //width, height
//this fills the whole object with a color:
floor.fill( 200, 100, 0, 1 ); //Red, Green, Blue, Alpha
//floor will have a canvas context object to draw figures.
//Here are some more examples:
//http://www.html5canvastutorials.com/tutorials/html5-canvas-circles/
//after you finish drawing, you need to convert the object to a sprite:
var floorSprite = game.add.sprite( 100, 500, floor );
//this adds physics to the object and adds a .body property:
game.physics.arcade.enable( floorSprite );
//stops the object in place and prevents other objects from displacing it:
floorSprite.body.allowGravity = false;
floorSprite.body.immovable = true;
And that's how you can create a platform without having to rely on image files. I have seen a few tutorials using files instead of generating the platform and I think it's such a waste.
Also, I think you need to convert your vector to a bitmap is because vector physics is quite heavy on the hardware (or so it seems).
Hope this can help a few more people!

maybe it works with this:
anySprite.addChild(yourGraphicsObject);
and after that:
game.physics.arcade.enable( anySprite );

Related

There are 3 method "this.add.rectangle()", "new Phaser.GameObjects.Rectangle()" and "fillRectShape()", when should I use which?

I'm new to Phaser 3 and trying to figure out the difference between the (at least) 3 methods to create rectangles. Here is the code
var game = new Phaser.Game({
scene: {
create: create
}
});
function create() {
let rect1 = this.add.rectangle(300, 100, 100, 30, 0x00f000, .5);
let rect2 = new Phaser.GameObjects.Rectangle(this, 300, 150, 100, 30, 0xf00000)
this.add.existing(rect2);
let rect3 = this.add.graphics({
fillStyle: {
color: 0x00f0f0
}
});
let rect = new Phaser.Geom.Rectangle(300, 200, 100, 30);
rect3.fillRectShape(rect);
}
<script src="https://cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>
rect1 uses the simplest one which just needs 1 line of code.
rect2 instantiates the Phaser.GameObjects.Rectangle class. I guess it's more powerful if I need a bunch of rectangle-like objects where I can create a subclass of the class, predefine some properties and methods and instantiate my customized rectangle-like object.
rect3 uses Phaser.GameObjects.Graphics which I cannot image its use case where it beats the previous two. Could someone give me a hint?
The short Answer:
if you need a Rectangle for bounderies or other calculations or so use: new Phaser.Geom.Rectangle(...)
if you need a simple rectangle GameObject use: this.add.rectangle(...)
if you don't want to add it into the scene right away use: new Phaser.GameObjects.Rectangle(...)
if you need special rectangle GameObject with more bells and whistles use: this.add.graphics(...)
The long Answer:
It depends on the tasks at hand. Since each Object creates more or less a differnet Object with different properties/methods.
Type Phaser.GameObjects.Graphics:
Is a GameObject but very "lowlevel", you can paint almost anything on it. like rectanlges, circles, ... but it's more work.
Details can be found here https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.Graphics.html
Here an example of a special rectangle: https://phaser.io/examples/v3/view/game-objects/graphics/fill-rounded-rectangle
Type Phaser.GameObjects.Rectangle:
Is a GameObject as the Phaser.GameObjects.Graphics, but is specialized for creating rectangles.
this.add.rectangle(...) and new Phaser.GameObjects.Rectangle(...) create both a rectangle of this type. this.add.rectangle is only a more convenient way to achive this, and adds it straight to the current scene.
Details can be found here https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.Rectangle.html)
Here an example of basic rectangles: https://phaser.io/examples/v3/view/game-objects/shapes/rectangle
Type Phaser.Geom.Rectangle:
Is a geometric Shape, good for bounderies and/or other calculations (but you can also draw with it).
Details can be found here https://photonstorm.github.io/phaser3-docs/Phaser.Geom.Rectangle.html
Here an example of how it is used to check if an GameObject is in a specific rectangle: https://phaser.io/examples/v3/view/geom/rectangle/contains-rect

Helper Function Needed to Turn WebGL / Three.js Lengths to Pixesl

I'm am searching for how WebGL / Three.js in general sets their heights and widths.
As in what numbers systems do they use to set x,y,z.
For the Example below, the arrow it pointing straight up with the Y being set to 1 but in pixels it looks like 15- - 200 pixels.
Is there a helper function that i can write that I could pass in 100 for the pixels and it would return me the correct number to float number to use with THREE.js.
Excuse me if I am not talking in correct terms when it comes to number system but this is he only way i know how to reference it at this point.
The only thing i am missing below is creating the scene. but the rest is there, the image shows what it looks lik.
Once again is there a helper function that i can pass pixels to and in return get back the correct number in float for use with THREE.js?
Here is my arrow:
//scene.remove(cube);
scene.remove(group);
// create a new one
var sphere = createMesh(new THREE.SphereGeometry(5, 10, 10));
var cube = createMesh(new THREE.BoxGeometry(6, 6, 6));
sphere.position.set(controls.spherePosX, controls.spherePosY, controls.spherePosZ);
cube.position.set(controls.cubePosX, controls.cubePosY, controls.cubePosZ);
// add it to the scene.
// also create a group, only used for rotating
var group = new THREE.Group();
group.add(sphere);
group.add(cube);
scene.add(group);
controls.positionBoundingBox();
var arrow = new THREE.ArrowHelper(new THREE.Vector3(0, 1, 0), 0, 10, 0x0000ff);
scene.add(arrow);
I receive these JS objects with the Pixels then write to screen, but how do i convert the pixels down to usable units in 3D?
The lengths in 3D do not translate to lengths in 2D uniformly. Especially when perspective projection is employed.
Let's consider your example: Two arrows of the same 3D length and the same orientation would render to different 2D lengths depending on their distance from the camera. The arrow that is closer to camera will be rendered longer than the arrow farther from camera.
In order to maintain a certain pixel length for a certain arrow, you'd have to adjust the 3D length of the arrow every time some parameters of the camera change (e.g. position, orientation, FOV). And also every time the position or orientation of the arrow changes. This is possible (see comment by #WacławJasper ) but rather complicated.
If you could explain the bigger picture of what you wish to achieve there might be a simpler solution to your problem.

Sprite animations in paper.js

I'm working on my project in Paper.js.
In the part of It, I need to use sprite with animation.
To examplain It, I've got a space ship that can be everywhere on the screen, and there is an effect of disortion that happens sometimes.
I got prepared a spritesheet with 10 frames, and all I want is use Paper.js RASTER class to load It and animate on every frame.
The problem is in the positions, that I don't know how to calculate them...
When I load a raster
let slide = new Raster({
source: 'assets/sprite.png',
position: [0, 0]
});
I see center of a very long image, when I need to see the first frame.
My idea was to use group with containts mask (square)
let mask = new Rectangle({
position: [220, 100],
size: [186, 154],
});
That I can change position dynamically and animate the spread at the same time.
Is It possible that way?
It would be cool, If I cant calculate the position of raster against the mask, but for me now It seems impossible.
Anyone have idea how to attain this in a simple way?
Cheers.
I've looked into this in my project. The key is using a group with a pivot point. This code is admittedly unfinished and in raw javascript but it should give you a good idea:
var Sprite = paper.Group.extend({
_class: 'Sprite',
initialize: function Sprite(url, size) {
var maskSize = size || new paper.Size(256, 256);
var that = this;
this._raster = new paper.Raster(url);
this._raster.pivot = new paper.Point();
this._raster.on('load', function () {
that._spriteSheetWidth = Math.floor(this.size.width / maskSize.width);
that.setIndex(that._spriteIndex || 0);
});
this._clipRect = new paper.Path.Rectangle(new paper.Point(), maskSize);
Sprite.base.call(this, [this._clipRect, this._raster]);
this.clipped = true;
// Just use a blank point if you want the position to be in the corner
this.pivot = new paper.Point(maskSize.divide(2));
},
setIndex: function (index) {
if (typeof this._spriteSheetWidth !== "undefined") {
// TODO: FINISH SPRITE SHEET IMPLEMENTATION
}
this._spriteIndex = index;
}
});
I'm not actually using sprites in my project anymore so I never finished the implementation. But the complicated concepts should be completed above. Namely the way that paper.js implements pivot points and clipping masks. The position of an object is the center of it's bounds by default... this is kind of unweildy for a lot of reasons, like an images position will appear to change when it loads etc... or when the contents of a path change. So I like to set a pivot of 0,0 immediately after making any object. The next key section is that clipping masks only work on Groups. And finally you can extend the Group class to make a standard Sprite class.
Normal sprite shifting of this._raster.position.x and this._raster.position.y should finish this implementation off.
Edit: Finished my implementation... https://jsfiddle.net/willstott101/vgxq9kak/

Inverse of camera.lookAt()

I googled far and wide but I haven't found the solution to what I think to actually be a pretty common situation. Say I have a THREE.PerspectiveCamera initialized to look at a certain point in space:
var camera = new THREE.PerspectiveCamera(45, 2, 0.1, 100);
var target = new THREE.Vector3(1, 2, 3);
camera.lookAt(target);
Now, later on in the code I'd like to be able to find out the coordinates of target by simply querying camera.
I tried what suggested in this question, adapting it to my own scenario:
var vector = new THREE.Vector3();
vector.applyQuaternion(camera.quaternion);
console.log(vector);
But it logs a vector of coordinates (0, 0, 0) instead of the correct coordinates (which, in my example, should be (1, 2, 3)).
Any insights? Cheers.
EDIT:
Ok so I'm going to try to contextualize here, so as to justify why MrTrustworthy's solution is unfortunately not applicable in my scenario. I'm trying to tweak the THREE.OrbitControls library for my purposes, since I noticed that when using it, it overrides whichever position the camera was looking at originally. This has also been reported here. Basically, on line 36 of OrbitControls.js (I'm using the version which can be found here) this.target is initialized to a new THREE.Vector3(); I found out that if I manually set it to equal the same vector I use as argument of camera.lookAt() everything works just fine: I can start panning, orbiting and zooming the scene from the same POV I would see the scene from if I didn't apply the controls. Of course, I cannot hard-code this information into OrbitControls.js because it would require me to change it every time I want to change the initial "lookAt" of my camera; and if I were to follow MrTrustworthy's suggestion I would have to change line 36 of OrbitControls.js to read like this: this.target = object.targetRef (or this.target = object.targetRef || new THREE.Vecotr3()), which is also too "opinionated" (it would always require object to have a targetRef property, whereas I'm trying to stick to using only three.js's existing object properties and methods). Hope this helps get a better understanding of my case. Cheers.
If your only usecase is "I want to be able to access the camera-targets position via the camera object", you could just put a reference into the camera object.
var camera = new THREE.PerspectiveCamera(45, 2, 0.1, 100);
var target = new THREE.Vector3(1, 2, 3);
camera.lookAt(target);
camera.targetRef = target;
//access it
var iNeedThisNow = camera.targetRef;
I figured it out and wrote my solution here. Since the issue affects both THREE.TrackballControls and THREE.OrbitControls, the solution involves applying a slight change to both those files. I wonder if it can be considered a valid change and make its way to rev. 70; I will issue a PR on github just for the sake of it :)
Thanks to all those who pitched in.
well you could put the object in parent, have parent lookat, and have the child object rotated 180 degrees. That's the quick noob solution

Creating a room with Three.js and cannon.js

I'm just getting started with Three.js and cannon.js and I've been trying to create a simple room for a while with no success. I'm working off of this example and I've been trying to add walls and a ceiling. What is the easiest way to do this? Right now I have
// wall?
wallGeometry = new THREE.PlaneGeometry( 300, 300 );
wallGeometry.applyMatrix( new THREE.Matrix4().makeRotationX( Math.PI));
wallMesh = new THREE.Mesh( wallGeometry, material );
wallMesh.castShadow = false;
wallMesh.receiveShadow = true;
scene.add(wallMesh);
But it's light up weird and I don't bump into it.... And if I try to add it through cannon.js I get an invisible wall but can't see it. Can anyone point me to the right direction?
THREE.js itself has no physics included so when you create any object in it, it will never make you 'bump' into them by itself. You have to code such features yourself or use another library for that (as you are already trying to do with cannon.js).
Next - per default, THREE js will only create one ambient light for your scene. If you want dynamic lightning and shadows, all lights must be provided by you and objects you want to react to lights must be using MeshLambertMaterial or MeshPhongMaterial, for shadows you will have to set couple of properies and use specific types of lights.
In your example, you don't seem to define wall material anywhere - this might be why walls are invisible.
check these and steal pieces of code you need (and it seems like you will need a lot :-)
http://threejs.org/examples/
http://stemkoski.github.io/Three.js/index.html

Categories

Resources