Phaser.js Game objects collide as intended, but collision callback isn't - javascript

I am making a simple game where a ball object hits with a bullet object. The objects collide properly, but the callback function(addscore()), included in the same collides() function for the objects, only gets called once(most probably during the objects' first creation).
Here is the code snippet for the create() function. The collision parts are at the bottom:
create: function() {
this.cursors = this.game.input.keyboard.createCursorKeys();
//background
this.cloud = game.add.sprite(50, 100, 'cloud');
this.cloud.scale.setTo(.4,.4);
this.cloud1 = game.add.sprite(250, 200, 'cloud');
this.cloud1.scale.setTo(.5,.5);
this.grass = game.add.sprite(0, 470, 'grass');
game.stage.backgroundColor = '#71c5cf';
//Ball and cannon
game.physics.startSystem(Phaser.Physics.P2JS);
game.physics.p2.restitution = .9;
this.ball = game.add.sprite(200, 245, 'ball');
this.cannon = game.add.sprite(200, 490, 'cannon');
this.ball.anchor.setTo(0.4, 0.4);
this.cannon.anchor.setTo(0.5, 0.5);
this.cannon.scale.setTo(.4,.4);
this.ball.scale.setTo(.4,.4);
game.physics.p2.enable(this.ball);
this.ball.body.setCircle(29);
this.game.debug.body(this.ball)
//gravity and bounce, collision
this.game.physics.p2.gravity.y = 1500;
this.ballCollisionGroup = this.game.physics.p2.createCollisionGroup();
this.bulletCollisionGroup = this.game.physics.p2.createCollisionGroup();
this.game.physics.p2.updateBoundsCollisionGroup();
this.ball.body.setCollisionGroup(this.ballCollisionGroup);
this.ball.body.collides([this.bulletCollisionGroup], this.addscore);
this.bullet = game.add.group();
this.bullet.createMultiple(20, 'bullet');
this.bullet.callAll('events.onOutOfBounds.add', 'events.onOutOfBounds', this.resetbullet);
this.bullet.callAll('anchor.setTo', 'anchor', 0.1, 0.1);
this.bullet.callAll('scale.setTo', 'scale', .1, .1);
this.bullet.setAll('checkWorldBounds', true);
this.bullet.enableBody = true;
this.bullet.physicsBodyType = Phaser.Physics.P2JS;
game.physics.p2.enable(this.bullet);
this.bullet.forEach(function(child){
child.body.setCircle(7);
child.body.setCollisionGroup(this.bulletCollisionGroup);
child.body.collides([this.ballCollisionGroup]);
child.body.collideWorldBounds=false;
}, this);
},
you can view the game here: http://gabrnavarro.github.io/Volleyball.js .
view the source to see the whole code. Thanks for your help. :)

Looking at code snipped you posted here everything looks good for first glance. However when I looked at your code on gh I see that you don't pass addScore as callback but instead just call it.
Changing main.js line 67 from
this.ball.body.collides([this.bulletCollisionGroup], this.addscore(), this);
to
this.ball.body.collides([this.bulletCollisionGroup], this.addscore, this);
Should do the trick.

I have not had any experience with the P2 physics, so this may be completely wrong. When using arcade physics, the groups are initialised in the create function, but the collision is checked in the update function.
So you would have to do is move:
this.ball.body.collides([this.bulletCollisionGroup], this.addscore, this);
To your update function (Along with any other code that checks for collision).
Again, I have not had any experience with the p2 physics system, so this may be incorrect.
Sorry if this did not help.

Related

How to get Phaser 3 timerEvent and methods to work properly? And get objects to already be instantiated when the game begins?

The goal of my project is to make a tree planting game. When the game starts it should already have say, 10 trees in random positions as a starting point. Then, the duck can plant trees via moving with the cursor and planting with the spacebar. Every 1 second that passes, i want a random number of trees between 5-15 inclusive to destruct on their own. There will be a counter for the number of trees currently on screen and it updates every second. Game over when it hits 0.
Here is what I have so far/planning on implementing:
Counter for the trees
Duck moving and planting on canvas
Here is what I'm having trouble with:
Getting the game to already start off with 10 trees.
I am getting an error message that says that onEvent() method is not defined when it seems like it is in the code for destroying trees.
Here is my code so far, trying to implement the destruction of trees and I do not know how to instantiate the initial 10 trees :( :
As you can see, I've already tried fix the onEvent not defined error by putting it before i call the method but im still recieving the same error.
class Scene2 extends Phaser.Scene{
constructor(){
super("playGame");
}
//var timedEvent;
onEvent(){
for(var i = 0; i<2; i++){
var tree = this.projectiles.getChildren()[i];
tree.update();
}
}
create(){
this.grass = this.add.tileSprite(0,0,config.width,config.height,'grass').setOrigin(0,0);
//maybe add loops (and some updated sprites) for animals to move in place. i can learn that from one of gamedev acad's tutorials.
this.ella = this.add.sprite(200, 400, "ella"); // later do random spots
this.ella.play("ella_anim");
this.ella.setScale(.45);
this.tiger = this.add.sprite(500, 200, "tiger"); // later do random spots
this.tiger.play("tiger_anim");
this.tiger.setScale(.4);
this.monkey = this.add.sprite(100, 100, "monkey"); // later do random spots
this.monkey.play("monkey_anim");
this.monkey.setScale(.4);
this.duck =this.physics.add.sprite(200,300, "duck");
var follower = this.duck.setDepth(100);
follower.play("duck_anim");
follower.setScale(.6);
this.input.on('pointermove', function(pointer)
{
this.physics.moveToObject(follower, pointer, 240);
},this);
follower.setCollideWorldBounds(true);
//follower.setScale(.5);
this.add.text(20,20, "Playing game", {font: "25px Arial", fill: "yellow"});
this.spacebar = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE);
var timedEvent = this.time.addEvent({ delay: 1000, callback: onEvent, callbackScope: this, loop: true });
this.projectiles = this.add.group(); //holds all the trees
}
update(){
text.setText('Event.progress: ' + timedEvent.getProgress().toString().substr(0, 4));
if(Phaser.Input.Keyboard.JustDown(this.spacebar)){
this.plantTree();
}
}
plantTree(){
var tree = new Tree(this).setScale(.2);
}
}
This is the tree class:
class Tree extends Phaser.GameObjects.Sprite{
constructor(scene,place){
var x = scene.duck.x;
var y = scene.duck.y;
super(scene,x,y, "tree");
scene.add.existing(this);
}
update(){
this.destroy();
}
}
I'm fairly new to Phaser. Pls let me know if you know the answer to how to instantiate trees in the game initially and how to fix the error with onEvent. Thanks.
Error is:
Uncaught ReferenceError: onEvent is not defined
at Scene2.create (Scene2.js:44)
at initialize.create (phaser.min.js:1)
at initialize.bootScene (phaser.min.js:1)
at initialize.start (phaser.min.js:1)
at initialize.processQueue (phaser.min.js:1)
at initialize.update (phaser.min.js:1)
at initialize.step (phaser.min.js:1)
at initialize.step (phaser.min.js:1)
at e (phaser.min.js:1)

how to flip a cube in air using three.js

I am using three.js framework and using physi.js for forces and gravity. My problem is that i has given some position to a dice on a plane and want to lob it or flip it from its position with some angle by clicking on it such that it rotate in air and fall on plane due to gravity force of plane.
i have idea about onclickevent method but i don't know how to set the dice to jump with some height in 90 degree and rotate it with some angle only one time for one click.
if you have some suggestion please give me method to set up the dice
thank you
i have no experience with physi.js, for physics i use cannon.js, so i do have some experience with physics. i can tell you how it's done, but i cant provide an example just yet. the first thing you need to do is cast a ray from the camera to the dice. This tells you if the object is clicked on. from there you apply a force to where the object is clicked. i hope this helps.
EDIT/Follow up:
I've been looking over physi.js, and it seems pretty similar to cannon.js. Also, there are many aspects to what you're asking, but i'll try to be as comprehensive as possible.
The first thing to do is set the gravity. In the examples it is done by:
var scene = new Physijs.Scene({ fixedTimeStep: 1 / 120 });
scene.setGravity(new THREE.Vector3( 0, -30, 0 ));
the next thing to do is define the plane the dice is sitting on as a rigid body, and the dice as a rigid body.
var dice = new Physijs.BoxMesh(
new THREE.CubeGeometry(5, 5, 5), //the collision geometry
new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture('images/dicetexture.jpg' )});, // material of the dice
5, // mass, for the plane use 0, meaning it doesnt move.
{ restitution: .2, friction: .8 } //contact material
);
and finally, you need to apply a force, i cant find an example of it, but going over the source real quick, i found:
// Physijs.Mesh.applyForce
Physijs.Mesh.prototype.applyForce = function ( force, offset ) {
if ( this.world ) {
this.world.execute( 'applyForce', { id: this._physijs.id, force_x: force.x, force_y : force.y, force_z : force.z, x: offset.x, y: offset.y, z: offset.z } );
}
};
both force and offset should be vectors. force being the direction and magnitude, offset being the point of origin.
i'll experiment a bit more with physi.js it seems to have solved some problems i've been pondering with. if this still doesnt solve the problem. i'll post an example.
as for letting it spin for a set number of times in a preset height, i think that's a lot of experimenting with the values...
EDIT 2:
In the fiddle you posted the problem you explained was an undefined variable, effect.
if (intersects.length > 0) {
intersects[ 0 ].applyImpulse(effect, offset);
}
change this to:
if (intersects.length > 0) {
var effect = new THREE.Vector3( 0, 100, 0 );
var offset = new THREE.Vector3( 0, 0, 0 );
intersects[ 0 ].object.applyImpulse(effect, offset);
}
the values ARE defined, but you define them in a different function.
function apply_force(){
var effect = new THREE.Vector3( 0, 100, 0 );
var offset = new THREE.Vector3( 0, 0, 0 );
object.applyImpulse( effect, offset );
}
this function will not be used anymore, so you might as well remove it.
CLICK TIMER:
if(canClick == true){
//process click
canClick = false;
setTimeout(function(){canClick = true}, 5000)//5 seconds before the user can click again.
}

Error 1105: Target of Assignment must be a Reference Value

Flash says the code is on my second line, but I've done some reading and it says this error is mainly due to me trying to assign a value to a value, and I've looked back over my code, and I can't seem to find any instance of this.
Here is my code:
this.mc=new MovieClip();
addChild(mc)=("myButton1", this.DisplayOBjectContainer.numChildren());
myButton1.createEmptyMovieClip("buttonBkg", myButton1.getNextHighestDepth());
myButton1.buttonBkg.lineStyle(0, 0x820F26, 60, true, "none", "square", "round");
myButton1.buttonBkg.lineTo(120, 0);
myButton1.buttonBkg.lineTo(120, 30);
myButton1.buttonBkg.lineTo(0, 30);
myButton1.buttonBkg.lineTo(0, 0);
Thanks!
Check what you are trying to in these lines:
addChild(mc)=("myButton1", this.DisplayOBjectContainer.numChildren());
myButton1.createEmptyMovieClip("buttonBkg", myButton1.getNextHighestDepth());
To create an empty MovieClip, you can just create a new display object w/o linking it to a clip in the library like this:
addChild(mc);
var myButton1:MovieClip = new MovieClip(); // creates an empty MovieClip
addChildAt(myButton1, numChildren); // adds the MovieClip at a defined level (on this case, the numChildren added on stage
Your code is very confusing. You mix AS2 methods (createEmptyMovieClip, getNextHighestDepth) with AS3 methods (addChild). Here is what you are trying to do:
const MC:Sprite = new Sprite(); // Sprite container
this.addChild(MC);
const MYBUTTON1:Sprite = new Sprite(); // button in container
MC.addChild(MYBUTTON1);
const BUTTONBKG:Shape = new Shape(); // background in button
MYBUTTON1.addChild(BUTTONBKG);
const BTG:* = BUTTONBKG.graphics;
BTG.beginFill(0x86B1FB);
BTG.lineStyle(0, 0x820F26, 0.6, true, "none", "square", "round");
BTG.lineTo(120, 0);
BTG.lineTo(120, 30);
BTG.lineTo(0, 30);
BTG.lineTo(0, 0);
MYBUTTON1.addEventListener(MouseEvent.CLICK, pressButton);
function pressButton(e:MouseEvent):void {
trace('I click on you');
}
Notes : the alpha value in AS3 is between 0 and 1. If you want your button to be clickable, you should use beginfill method.

recommended way to extend classes in Paper.js

Is there a recommended way to extend classes in Paper.js? In particular, I am interested in extending Path
Pardon if my terminology is incorrect, but I am essentailly asking the same question about paper that is being asked about three here
Based on your comment to the initial version of my answer, you are looking for the 'extend' function (oops, that was exactly what you meant) to do subclassing. In an email to the paper.js mailing list, Jürg Lehni (one of the creators) said:
As for subclassing, that's not something that is supported at the
moment. It might work, it might not, it might work in most cases, but
not in very rare cases that are hard to pinpoint, it might need only a
couple of changes to make it work well, but those might be in many
different places.
For example, each Item subclass has a _type property which is a string
representing its type. Sometimes we check that instead of using
instanceof, because it's faster, and so far, for example for Path we
just assumed there would be no subclassing.
A complication is that there are no paper.Path.Rectangle objects. There are paths, and there are rectangles, but when you call new paper.Path.Rectangle() it creates a new Path using initialization code (createRectangle) that creates a rectangular shape.
So we would need to extend paper.Path. Unfortunately, when you call new paper.Path.Rectangle it calls createPath, which always returns a Path (not your extension). It may be possible to do something like:
var SuperRectangle = paper.Path.extend({
otherFunc: function() {
console.log('dat');
}
});
...and with correctly substituting/overriding for createRectangle or createPath get a subclass to work. Unfortunately, I have not been able to manage it.
My first working recommendation is to make a factory and add your functions to the objects in that factory (jsbin here):
var createSuperRectangle = function(arguments){
var superRect = new paper.Path.Rectangle(arguments);
superRect.otherFunc = function(){
console.log('dat');
}
return superRect;
}
var aRect = new Rectangle(20, 30, 10, 15);
var aPath = createSuperRectangle({
rectangle: aRect,
strokeColor: 'black'
});
aPath.otherFunc();
Similarly, you can use the factory to just change the prototype for your SuperRectangles, having added your functions to that prototype object (and making its prototype the one from paper.Path.__proto__) (jsbin here):
var superRectProto = function(){};
var tempRect = new paper.Path.Rectangle();
tempRect.remove();
superRectProto.__proto__ = tempRect.__proto__;
superRectProto.otherFunc = function(){
console.log('dat');
}
delete tempRect;
var createSuperRectangle = function(arguments){
var superRect = new paper.Path.Rectangle(arguments);
superRect.__proto__ = superRectProto;
return superRect;
}
var aRect = new Rectangle(20, 30, 10, 15);
var aPath = createSuperRectangle({
rectangle: aRect,
strokeColor: 'black'
});
aPath.otherFunc();
Alternatively, you can make an object that encapsulates the Path (jsbin here):
var SuperRectangle = function(arguments){
this.theRect = new paper.Path.Rectangle(arguments);
this.otherFunc = function(){
console.log('dat');
}
}
var aRect = new Rectangle(20, 30, 10, 15);
var aPath = new SuperRectangle({
rectangle: aRect,
strokeColor: 'black'
});
aPath.otherFunc();
aPath.theRect.strokeWidth = 5;
Unfortunately, then to access the path you have to use the theRect variable.
Initial incorrect answer follows:
I don't think you mean "extending classes". In Javascript you can extend objects so that they have more functions, so extending the Path "class" would mean all Path objects have the same new functions. Javascript object extension is further described here.
If I'm wrong, and you do want to extend Path, then you can use:
paper.Path.inject({
yourFunctionName: function(anyArgumentsHere) {
// your function here
}
});
However, I think you are actually talking about creating new objects that mostly behave like Path objects but have different functionality from each other. If that is the case, then you may want to look at this answer about Javascript using prototypical inheritance. For example, here I create two Rectangle objects that behave differently when I ask them to doSomething (jsbin here):
var rect1 = new Path.Rectangle({
point: [0, 10],
size: [100, 100],
strokeColor: 'black'
});
rect1.doSomething = function() {
this.fillColor = new Color('red');
};
var rect2 = new Path.Rectangle({
point: [150, 10],
size: [100, 100],
strokeColor: 'black'
});
rect2.doSomething = function() {
this.strokeWidth *= 10;
};
rect1.doSomething();
rect2.doSomething();
A couple of things.
1) You can wrap the original paperjs object but this is very much a hack
paperjs playground
function SuperSquare() {
this.square = new Path.Rectangle({
size:50,
fillColor:'red',
onFrame:function(base) {
var w2 = paper.view.element.width / 2;
this.position.x = Math.sin(base.time) * w2 + w2;
}
});
}
SuperSquare.prototype.setFillColor = function(str) {
this.square.fillColor = str;
}
var ss = new SuperSquare();
ss.setFillColor('blue');
2) I may clone & create a paper 2017 which operates off of es6 so that you can use the extend keyword.
3) I wrote an application called Flavas but it never gained a following so I just kind of left it. That being said, I have been playing with it lately; upgrading it to es6. With it you can do what you're talking about.
class Square extends com.flanvas.display.DisplayObject {
constructor(size) {
this.graphics.moveTo(this.x, this.y);
this.graphics.lineTo(this.x + size, this.y);
this.graphics.lineTo(this.x + size, this.y + size);
this.graphics.lineTo(this.x, this.y + size);
}
someMethod(param) {
trace("do something else", param);
}
);
I wrote all this kind of quick so feel free to hit me up with Q's.

Dynamically calling Canvas Functions

Is there any way to call canvas functions using apply() or a similar method, as to dynamically call canvas methods or to be able to pass an array of arguments?
Im looking for this effect
context.fillRect.apply(this,args);
If I understand you correctly:
var op = "fillRect";
var args = [
10, 10, 180, 180
];
ctx[op].apply(ctx, args);
Example: http://jsfiddle.net/eZwYQ/
your apply method should work just fine :
function rectangle(){
ctx.fillRect.apply(ctx,arguments);
}
And of course this can get more "dynamic" :
function doSomethingWithCanvas(context,action,arg1,arg2/*,...argn*/){
context[action].apply(context,Array.prototype.slice.call(arguments,2));
}
And you could use the same function to fill a rectangle, to draw a circle or to draw a simple line :
// simple line
doSomethingWithCanvas(ctx,'lineTo',10, 100);
// circle
doSomethingWithCanvas(ctx,'arc',275, 275, 200, 0, Math.PI*2, true);
// fillRect
doSomethingWithCanvas(ctx,'fillRect,10, 10, 180, 180);
PS : by providing the canvas context as an argument, you can use this function to draw on any canvas.

Categories