Phaser: Key Down + Collision Kill - javascript

Forewarning: semi-newbie
Basically, if the user has the left cursor down and a "token" collides with the lftRect, I want to kill the token. For some reason my kill callback function for the collision is not working (below is relevant code):  
gumballGoGo.Preloader = function(game){
this.player = null;
this.ground = null;
//this.tokens = null;
this.ready = false;
};
var cursors, lftInit, rghtInit, ground, testDrp, sprite, tokens, rect, lftRect, ctrRect, rghtRect, lftToken;
var total = 0;
function lftHit(lftRect, lftToken) {
if ( lftInit == true ){
lftToken.kill()
}
};
gumballGoGo.Preloader.prototype = {
preload: function(){
},
create: function() {
// LFT BOX
lftRect = this.add.sprite(0, this.world.height - 150, null);
this.physics.enable(lftRect, Phaser.Physics.ARCADE);
lftRect.body.setSize(100, 100, 0, 0);
// CNTR BOX
ctrRect = this.add.sprite(100, this.world.height - 150, null);
this.physics.enable(ctrRect, Phaser.Physics.ARCADE);
ctrRect.body.setSize(100, 100, 0, 0);
// RGHT BOX
rghtRect = this.add.sprite(200, this.world.height - 150, null);
this.physics.enable(rghtRect, Phaser.Physics.ARCADE);
rghtRect.body.setSize(100, 100, 0, 0);
// INIT TOKEN GROUP
tokens = this.add.group();
tokens.enableBody = true;
this.physics.arcade.enable(tokens);
testDrp = tokens.create(125, -50, 'token');
testDrp.body.gravity.y = 300;
// CONTROLS
this.cursors = this.input.keyboard.createCursorKeys();
},
update: function() {
this.ready = true;
if (this.cursors.left.isDown)
{
lftInit = true;
}
else if (this.cursors.right.isDown)
{
rghtInit = true;
}
else
{
lftInit, rghtInit = false;
}
if (total < 20)
{
tokenSpawn();
}
this.physics.arcade.collide(lftRect, lftToken, lftHit, null, this);
}
};
function tokenSpawn() {
lftToken = tokens.create(25, -(Math.random() * 800), 'token');
lftToken.body.gravity.y = 300;
total++;
}
The ultimate goal is to recreate this type of gameplay. 
One additional note: as of now I am dropping "tokens" using a random spawn loop. I'd rather use a timed patter for the token drop. If you have any advice on that please share as well. Thanks :]

Not sure, so this is a guess, but you're applying the last parameter of 'this' to the function 'lfthit' that is outside of the gumballGoGo.Preloader.prototype object. What error are you getting in the console?

Related

sprite won't collide with 2 different arrays, only one

I am currently making a small platformer game, where the player jumps up infinitely, much like the android game "Abduction". I have managed to create platforms in random locations on a timed interval and adding it to an array. However i can only get the player sprite to collide with 1 of the platform arrays, which is this.walls array that i have made so i have a set starting place for the player. Does anyone know what the issue might be.
Ugly code alert by the way, i am quite new at this.
I have checked update: function to see if i had forgot to add some stuff there. ive spellchecked the code and all sorts of things but i am at a completel loss.
var playState = {
preload: function () {
},
create: function () {
game.add.image (0, 0,'bg');
game.physics.startSystem(Phaser.Physics.ARCADE);
game.renderer.renderSession.roundPixels = true;
this.cursor = game.input.keyboard.createCursorKeys();
game.input.keyboard.addKeyCapture(
[Phaser.Keyboard.UP, Phaser.Keyboard.DOWN, Phaser.Keyboard.LEFT, Phaser.Keyboard.RIGHT]);
this.wasd = {
up: game.input.keyboard.addKey(Phaser.Keyboard.W), left: game.input.keyboard.addKey(Phaser.Keyboard.A), right: game.input.keyboard.addKey(Phaser.Keyboard.D)
};
this.player = game.add.sprite(game.width/2, game.height/1.2, 'player');
this.player.anchor.setTo(0.5, 0.5);
game.physics.arcade.enable(this.player);
this.player.body.gravity.y = 800;
this.scoreLabel = game.add.text(30, 30, 'score: 0',
{ font: '18px Arial', fill: '#ffffff' });
game.global.score = 0;
game.time.events.loop(1000, this.updateScore);
game.time.events.loop(4000, this.addPlatform);
this.createWorld();
},
update: function () {
game.physics.arcade.collide(this.player, this.walls);
game.physics.arcade.collide(this.player, this.platforms);
if (!this.player.inWorld) {
this.playerDie();
}
this.movePlayer();
},
updateScore: function(){
this.score +=1;
game.global.score +=1;
//fix this at some point
},
createWorld: function() {
this.walls = [];
this.walls.push(game.add.sprite(170, 750, 'platform', 0));
this.walls.push(game.add.sprite(70, 650, 'platform', 0));
this.walls.push(game.add.sprite(320, 550, 'platform', 0));
this.walls.push(game.add.sprite(200, 450, 'platform', 0));
this.walls.push(game.add.sprite(10, 550, 'platform', 0));
this.walls.push(game.add.sprite(70, 350, 'platform', 0));
this.walls.push(game.add.sprite(310, 300, 'platform', 0));
this.walls.push(game.add.sprite(230, 200, 'platform', 0));
this.walls.push(game.add.sprite(100, 100, 'platform', 0));
this.walls.push(game.add.sprite(270, 0, 'platform', 0));
for (var x=0; x< this.walls.length; x++) {
game.physics.arcade.enable(this.walls[x]);
this.walls[x].enableBody = true;
this.walls[x].body.immovable = true;
this.walls[x].body.velocity.y = 20;
}
},
addPlatform: function() {
this.platforms = [];
this.platforms.push(game.add.sprite(game.rnd.integerInRange(0, 350),-20,'platform',0));
for (var x=0; x< this.platforms.length; x++) {
game.physics.arcade.enable(this.platforms[x]);
this.platforms[x].enableBody = true;
this.platforms[x].body.immovable = true;
this.platforms[x].body.velocity.y = 20;
}
},
movePlayer: function() {
if (this.cursor.left.isDown || this.wasd.left.isDown) {
this.player.body.velocity.x = -250;
}
else if (this.cursor.right.isDown || this.wasd.right.isDown) {
this.player.body.velocity.x = 250;
}
else {
this.player.body.velocity.x = 0;
}
if ((this.cursor.up.isDown || this.wasd.up.isDown)
&& this.player.body.touching.down){
this.player.body.velocity.y = -450;
}
},
playerDie: function() {
this.player.kill();
//this.deadSound.play();
//this.emitter.x = this.player.x;
//this.emitter.y = this.player.y;
//this.emitter.start(true, 800, null, 15);
game.time.events.add(1000, this.startMenu, this);
game.camera.shake(0.02, 300);
},
startMenu: function() {
game.state.start('menu');
},
};
this.walls is so i have a starting ground of set platforms and this.platforms is the randomly generated platforms.
I want to be able to actually jump on those platforms and not just
fall through, which i do at the moment
Your platform is an array of sprites, so you have to parse through each sprite inside your array.
Or, you can make a "Group" object, instead of plain array. You can make a Group of each plaform, then do collision with this Group and player.

How to prevent objects to jump off platforms?

I have a game set up like this:
var game = new Phaser.Game(800, 600, Phaser.AUTO, '', {preload: preload, create: create, update: update});
var platforms;
var aGroup;
function preload() {
game.load.image('platform', 'img/platform.png');
game.load.image('a', 'img/a.png');
}
function create() {
game.physics.startSystem(Phaser.Physics.ARCADE);
platforms = game.add.group();
platforms.enableBody = true;
var platform = platforms.create(100, 100, 'platform');
aGroup = game.add.group();
aGroup.enableBody = true;
platforms.forEach(function(item) {
item.body.immovable = true;
aGroup.create(item.x, item.y - 32, 'a');
}, this);
aGroup.forEach(function(a) {
a.body.velocity.x = 100;
}
}
function update() {
game.physics.arcade.collide(aGroup, platforms);
aGroup.forEach(function(a) {
if(a.body.blocked.right) {
a.body.velocity.x = -100;
}
else if(a.body.blocked.left) {
a.body.velocity.x = 100;
}, this);
}
}
Currently I can check if a is colliding with the world boundaries and if it does it changes direction. Right now when a reaches the end of the platform it just falls down. I want a to change direction when it reaches the end of the platform.
How can I do it?

How to properly obfuscate javascript code with javascript2img?

I tried obfuscating JS code using javascript2img. It gave me the obfuscated code. They state, "Copy this code and paste it into your js or HTML file. That's all!". But I keep getting this error.
"Uncaught SyntaxError: Unexpected identifier game.js:1"
Un-obfuscated the code works just fine.
Example: The following doesnt work obfuscated but does without obfuscation.
var game = new Phaser.Game(400, 490, Phaser.AUTO, "gameDiv");
var mainState = {
preload: function() {
if(!game.device.desktop) {
game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
game.scale.setMinMax(game.width/2, game.height/2, game.width, game.height);
}
game.scale.pageAlignHorizontally = true;
game.scale.pageAlignVertically = true;
game.stage.backgroundColor = '#71c5cf';
game.load.image('bird', 'assets/bird.png');
game.load.image('pipe', 'assets/pipe.png');
// Load the jump sound
// game.load.audio('jump', 'assets/jump.wav');
},
create: function() {
game.physics.startSystem(Phaser.Physics.ARCADE);
this.pipes = game.add.group();
this.timer = game.time.events.loop(1500, this.addRowOfPipes, this);
this.bird = game.add.sprite(100, 245, 'bird');
game.physics.arcade.enable(this.bird);
this.bird.body.gravity.y = 1000;
// New anchor position
this.bird.anchor.setTo(-0.2, 0.5);
var spaceKey = game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);
spaceKey.onDown.add(this.jump, this);
game.input.onDown.add(this.jump, this);
this.score = 0;
this.labelScore = game.add.text(20, 20, "0", { font: "30px Arial", fill: "#ffffff" });
// Add the jump sound
this.jumpSound = game.add.audio('jump');
this.jumpSound.volume = 0.2;
},
update: function() {
if (this.bird.y < 0 || this.bird.y > game.world.height)
this.restartGame();
game.physics.arcade.overlap(this.bird, this.pipes, this.hitPipe, null, this);
// Slowly rotate the bird downward, up to a certain point.
if (this.bird.angle < 20)
this.bird.angle += 1;
},
jump: function() {
// If the bird is dead, he can't jump
if (this.bird.alive == false)
return;
this.bird.body.velocity.y = -350;
// Jump animation
game.add.tween(this.bird).to({angle: -20}, 100).start();
// Play sound
// this.jumpSound.play();
},
hitPipe: function() {
// If the bird has already hit a pipe, we have nothing to do
if (this.bird.alive == false)
return;
// Set the alive property of the bird to false
this.bird.alive = false;
// Prevent new pipes from appearing
game.time.events.remove(this.timer);
// Go through all the pipes, and stop their movement
this.pipes.forEach(function(p){
p.body.velocity.x = 0;
}, this);
},
restartGame: function() {
game.state.start('main');
},
addOnePipe: function(x, y) {
var pipe = game.add.sprite(x, y, 'pipe');
this.pipes.add(pipe);
game.physics.arcade.enable(pipe);
pipe.body.velocity.x = -200;
pipe.checkWorldBounds = true;
pipe.outOfBoundsKill = true;
},
addRowOfPipes: function() {
var hole = Math.floor(Math.random()*5)+1;
for (var i = 0; i < 8; i++)
if (i != hole && i != hole +1)
this.addOnePipe(400, i*60+10);
this.score += 1;
this.labelScore.text = this.score;
},
};
game.state.add('main', mainState);
game.state.start('main');

Problems with a class for virtual controls in the Phaser framework

In my game, I need some buttons that will work on mobile devices (buttons that you can press and/or hold in the game). I saw this example (note that the version of Phaser being used here is old, however, it still works) and was able to temporarily have some working buttons. Here's the source code for that example.
However, one thing bothered me about this example's code for the creation of these virtual gamepad buttons: the buttons' code wasn't DRY (Don't Repeat Yourself). You can see how these buttons keep getting created in the same fashion here over and over again:
// create our virtual game controller buttons
buttonjump = game.add.button(660, 340, 'buttonjump', null, this, 0, 1, 0, 1); //game, x, y, key, callback, callbackContext, overFrame, outFrame, downFrame, upFrame
buttonjump.anchor.setTo(0.5, 0.5);
buttonjump.fixedToCamera = true; //our buttons should stay on the same place
buttonjump.events.onInputOver.add(function(){jump=true;});
buttonjump.events.onInputOut.add(function(){jump=false;});
buttonjump.events.onInputDown.add(function(){jump=true;});
buttonjump.events.onInputUp.add(function(){jump=false;});
buttonfire = game.add.button(750, 340, 'buttonfire', null, this, 0, 1, 0, 1);
buttonfire.anchor.setTo(0.5, 0.5);
buttonfire.fixedToCamera = true;
buttonfire.events.onInputOver.add(function(){fire=true;});
buttonfire.events.onInputOut.add(function(){fire=false;});
buttonfire.events.onInputDown.add(function(){fire=true;});
buttonfire.events.onInputUp.add(function(){fire=false;});
buttonleft = game.add.button(40, 312, 'buttonhorizontal', null, this, 0, 1, 0, 1);
buttonleft.anchor.setTo(0.5, 0.5);
buttonleft.fixedToCamera = true;
buttonleft.events.onInputOver.add(function(){left=true;});
buttonleft.events.onInputOut.add(function(){left=false;});
buttonleft.events.onInputDown.add(function(){left=true;});
buttonleft.events.onInputUp.add(function(){left=false;});
buttonbottomleft = game.add.button(48, 352, 'buttondiagonal', null, this, 6, 4, 6, 4);
buttonbottomleft.anchor.setTo(0.5, 0.5);
buttonbottomleft.fixedToCamera = true;
buttonbottomleft.events.onInputOver.add(function(){left=true;duck=true;});
buttonbottomleft.events.onInputOut.add(function(){left=false;duck=false;});
buttonbottomleft.events.onInputDown.add(function(){left=true;duck=true;});
buttonbottomleft.events.onInputUp.add(function(){left=false;duck=false;});
buttonright = game.add.button(136, 312, 'buttonhorizontal', null, this, 0, 1, 0, 1);
buttonright.anchor.setTo(0.5, 0.5);
buttonright.fixedToCamera = true;
buttonright.events.onInputOver.add(function(){right=true;});
buttonright.events.onInputOut.add(function(){right=false;});
buttonright.events.onInputDown.add(function(){right=true;});
buttonright.events.onInputUp.add(function(){right=false;});
buttonbottomright = game.add.button(128, 352, 'buttondiagonal', null, this, 7, 5, 7, 5);
buttonbottomright.anchor.setTo(0.5, 0.5);
buttonbottomright.fixedToCamera = true;
buttonbottomright.events.onInputOver.add(function(){right=true;duck=true;});
buttonbottomright.events.onInputOut.add(function(){right=false;duck=false;});
buttonbottomright.events.onInputDown.add(function(){right=true;duck=true;});
buttonbottomright.events.onInputUp.add(function(){right=false;duck=false;});
buttondown = game.add.button(88, 360, 'buttonvertical', null, this, 0, 1, 0, 1);
buttondown.anchor.setTo(0.5, 0.5);
buttondown.fixedToCamera = true;
buttondown.events.onInputOver.add(function(){duck=true;});
buttondown.events.onInputOut.add(function(){duck=false;});
buttondown.events.onInputDown.add(function(){duck=true;});
buttondown.events.onInputUp.add(function(){duck=false;});
Because they were created in such a non-DRY and, what I feel to be, inefficient way, I decided that my buttons should have a gamepad button class that they all inherit from. Unfortunately, I've been running into lots of problems trying to make this button class work.
I have an example here that models what I'm trying to do in my game.
(Here's the source code for my example)
// Global constants
var GAME_WIDTH = 800;
var GAME_HEIGHT = 600;
var ORIGIN = 0;
var TEXT_X_POS = 50;
var TEXT_Y_POS = 100;
var TEXT_STYLE = { fontSize: "16px" };
var RIGHT_BUTTON_X_POS = 600;
var RIGHT_BUTTON_Y_POS = 400;
var LEFT_BUTTON_X_POS = 100;
var LEFT_BUTTON_Y_POS = 400;
var PHASER_DUDE_Y_POS = 300;
var PHASER_DUDE_GRAVITY = 300;
var PHASER_DUDE_RIGHT_VELOCITY = 100;
var PHASER_DUDE_LEFT_VELOCITY = -100;
var STOPPED = 0;
// Global variables
var background;
var rightButton;
var movingRight;
var rightButtonDown;
var leftButton;
var movingLeft;
var leftButtonDown;
var phaserDude;
var rightKey;
var leftKey;
// New instance of Phaser.Game
var game = new Phaser.Game(GAME_WIDTH, GAME_HEIGHT, Phaser.AUTO, "game", {preload: preload, create: create, update: update});
// Mobile button class
var MobileButton = function (button, movingInADirection, isTheButtonDown, pressedMethod) {
button.events.onInputOver.add(function () {
if (isTheButtonDown === true) {
movingInADirection = true;
}
});
button.events.onInputDown.add(function () {
isTheButtonDown = true;
movingInADirection = true;
});
button.events.onInputUp.add(function () {
movingInADirection = false;
});
};
function preload () {
game.load.image("background", "sprites/sky.png");
game.load.image("left arrow", "sprites/left_arrow.png");
game.load.image("right arrow", "sprites/right_arrow.png");
game.load.image("phaser dude", "sprites/phaser_dude.png");
}
function create () {
background = game.add.image(ORIGIN, ORIGIN, "background");
game.add.text(TEXT_X_POS, TEXT_Y_POS, "Use the arrow keys or the arrow buttons below to move", TEXT_STYLE);
rightButton = game.add.button(RIGHT_BUTTON_X_POS, RIGHT_BUTTON_Y_POS, "right arrow", moveRight);
leftButtonDown = game.add.button(LEFT_BUTTON_X_POS, LEFT_BUTTON_Y_POS, "left arrow", moveLeft);
phaserDude = game.add.sprite(game.world.centerX, PHASER_DUDE_Y_POS, "phaser dude");
game.physics.arcade.enable(phaserDude);
phaserDude.body.collideWorldBounds = true;
phaserDude.body.gravity.y = PHASER_DUDE_GRAVITY;
rightKey = game.input.keyboard.addKey(Phaser.Keyboard.RIGHT);
leftKey = game.input.keyboard.addKey(Phaser.Keyboard.LEFT);
}
function update () {
stopMoving();
if (leftKey.isDown || movingLeft === true) {
moveLeft();
}
if (rightKey.isDown || movingRight === true) {
moveRight();
}
}
function moveRight () {
phaserDude.body.velocity.x = PHASER_DUDE_RIGHT_VELOCITY;
}
function moveLeft () {
phaserDude.body.velocity.x = PHASER_DUDE_LEFT_VELOCITY;
}
function stopMoving () {
phaserDude.body.velocity.x = STOPPED;
}
As you can see, the arrow keys work fine for moving the sprite, but the mobile buttons do not work well; they only move the sprite for a frame, and then it stops moving again. I'm not sure why the keys work, yet the mobile buttons don't. The problem seems to be that the code in the class is not being run the way that I am thinking it should run (i.e., it seems like all of the code concerning the onInputOver, onInputDown, and onInputUp events is not being correctly run and the class is only paying attention to the method to run when a button is pressed). Can anyone figure out what the problem is with my button class?
Your problem is that the onInputDown of Phaser.Button only fires once each time the button is pressed.
What you need to do is set an isDown property on the button something like this:
button.events.onInputDown.add(function () {
button.isDown = true;
});
button.events.onInputUp.add(function () {
button.isDown = false;
});
And the in your update method check for that property:
function update () {
stopMoving();
if (leftKey.isDown || leftButton.isDown) {
moveLeft();
}

How can I create a running animation on an HTML5 canvas?

I am building a simple 2D game as an attempt to learn canvas. The character can run around a virtual environment, and a variable called yOffset controls his offset from the top of the screen. I also have a global variable called running which sets itself to true or false based on whether or not the character is running (not shown here). My goal is to make the character bob up and down whilst he is running, and all the below code does is spawn lots of setInterval()s. Is this the right way to make my character run, or should I do it another way? If so, how?
$(document).keydown(function(e) {
if(e.which == 97) {
running = true;
run();
} else if(e.which == 100) {
running = true;
run();
} else if(e.which == 119) {
running = true;
run();
} else if(e.which == 115) {
running = true;
run();
}
});
(yes, if the character stops running, the running variable does go to false [not shown here] - I've already made sure the running variable works well)
runTimer = 0;
function run() {
if(runTimer == 0 && running) {
runTimer = 1;
yOffset = 80;
setTimeout(function() {
yOffset = 120;
}, 150);
setTimeout(function() { if (running) { runTimer = 0;run(); } }, 300);
}
}
If you need more information, the version that I am currently working on is available here.
I think you can simplify your code, and in fact you must in the quite probable case where you'd like to add some other characters.
To allow re-use of the animation, it's better to separate what is an animation (== the different steps that your character will go through), and an animation state (== in which step your character is now).
I wrote here some elements of an animation system.
So i define what is an animation step, a whole Animation (which is so far only an array of animation step), and an Animator (which holds the state, one might see it as a 'reader' of an animation).
Once you defined the animation and animators, and started the animators, you just have to call tick(time) to have the animation move on, and offset() to read the offset, which is way simpler than fighting with a bunch of setIntervals.
http://jsfiddle.net/xWwFf/
// --------------------
function AnimationStep(duration, offset) {
this.duration = duration;
this.offset = offset;
// you might add : image index, rotation, ....
}
// --------------------
function Animation(animationSteps) {
this.steps = animationSteps; // Array of AnimationStep
}
// define a read-only length property
Object.defineProperty(Animation.prototype, 'length', {
get: function () {
return this.steps.length
}
});
// --------------------
function Animator() {
this.currentAnimation = null;
this.step = -1;
this.running = false;
this.remainingTime = 0; // remaining time in current step;
}
Animator.prototype.startAnim = function (newAnim, firstStep) {
this.currentAnimation = newAnim;
this.step = firstStep || 0;
this.remainingTime = newAnim.steps[this.step].duration;
this.running = true;
}
Animator.prototype.tick = function (dt) {
// do nothing if no animation ongoing.
if (!this.running) return;
this.remainingTime -= dt;
// 'eat' as many frames as required to have a >0 remaining time
while (this.remainingTime <= 0) {
this.step++;
if (this.step == this.currentAnimation.length) this.step = 0;
this.remainingTime += this.currentAnimation.steps[this.step].duration;
}
};
Animator.prototype.offset = function () {
return this.currentAnimation.steps[this.step].offset;
}
// ______________________________
// example
var bounceAnim = [];
bounceAnim.push(new AnimationStep(200, 10));
bounceAnim.push(new AnimationStep(180, 20));
bounceAnim.push(new AnimationStep(150, 30));
bounceAnim.push(new AnimationStep(300, 40));
bounceAnim.push(new AnimationStep(320, 45));
bounceAnim.push(new AnimationStep(200, 40));
bounceAnim.push(new AnimationStep(120, 30));
bounceAnim.push(new AnimationStep(100, 20));
var anim1 = new Animation(bounceAnim);
var animator1 = new Animator();
var animator2 = new Animator();
animator1.startAnim(anim1);
animator2.startAnim(anim1, 3);
// in action :
var ctx = document.getElementById('cv').getContext('2d');
function drawScene() {
ctx.fillStyle = 'hsl(200,60%, 65%)';
ctx.fillRect(0, 0, 600, 200);
ctx.fillStyle = 'hsl(90,60%,75%)';
ctx.fillRect(0, 200, 600, 200);
ctx.fillStyle = 'hsl(10,60%,75%)';
ctx.fillRect(200, 200 + animator1.offset(), 22, 22);
ctx.fillStyle = 'hsl(40,60%,75%)';
ctx.fillRect(400, 200 + animator2.offset(), 22, 22);
animator1.tick(20);
animator2.tick(20);
}
setInterval(drawScene, 20);

Categories