Phaser overlap doesnt work - javascript

Why my Phaser.js 's overlap work sometimes and doesn't somtimes.
I have enabled arcade for my character and obstacle.
Here are the codes.
function create(){
...//other sprite
obs = game.add.group();
obs.enableBody = true;
obstacle = obs.create(800, game.world.height - 68, 'obstacle');
obstacle.scale.setTo(0.5,0.5);
game.physics.arcade.enable(obstacle);
obstacle.events.onOutOfBounds.add(function(obstacle) {
obstacle.kill();
}, this);
}
function update(){
...
game.physics.arcade.collide(character, obstacle, gameOver, null, this);
}
function generateObs(){//its where i generate new obstacle, and is my biggest suspect as well
obstacle = obs.create(800, game.world.height - 68, 'obstacle');
obstacle.scale.setTo(0.5,0.5);
game.physics.arcade.enable(obstacle);
obstacle.body.velocity.x = -300;
}
Thks a lot

Before giving you a possible solution to your problem:
It is not necessary to apply physics to the element created within
the group that already has physics.
If you need to know if two bodies
overlap but you do not need to emulate a complete collision use 'overlap'.
Try this:
var obs;
function create(){
//Active Physics ARCADE
game.physics.startSystem(Phaser.Physics.ARCADE);
...//other sprite
obs = game.add.group();
obs.enableBody = true;
obs.physicsBodyType = Phaser.Physics.ARCADE;
var obstacle = obs.create(800, game.world.height - 68, 'obstacle');
obstacle.scale.setTo(0.5,0.5);
obstacle.events.onOutOfBounds.add(function(obstacle) {
obstacle.kill();
}, this);
}
function update(){
...
//Use the group, since the callback will automatically pass the group element that overlaps with the player. A group is used to handle multiple elements, otherwise use only one variable :)
game.physics.arcade.overlap(character, obs, gameOver, null, this);
/*If you want your obstacle to move in the game you must implement this in the Update function
You can access an element of the group, for this there are multiple methods one of them is to get the element from the element's exists attribute
var obstacle = obs.getFirstExists(true);
if (obstacle) { obstacle.body.velocity.x = -300; }
*/
}
function gameOver(character, obstacle) {
//From here you have access to the element that collides with the player (you can evaluate with a condition if it is the obstacle you want)
//if (obstacle.name == 'x') { console.log(obstacle); }
console.log('Game Over!');
}
function generateObs(){
var obstacle = obs.create(800, game.world.height - 68, 'obstacle');
obstacle.scale.setTo(0.5,0.5);
obstacle.body.velocity.x = -300;
}

Related

Javascript function draw

var random = randomNumber(1, 7);
var Block = createSprite(200, 0);
var Blocks = createGroup();
Blocks.add(Block);
Blocks.setAnimationEach(random.toString());
createEdgeSprites();
function draw() {
background("white");
Move("down", 4, 1);
Move2("right", 4, 0, "left");
Move2("left", -4, 0, "right");
if (Blocks.isTouching(bottomEdge)) {
var Block = createSprite(200, 0);
Blocks.add(Block);
Blocks.setAnimationEach(randomNumber(1, 7).toString());
}
if (Blocks.isTouching(edges)) {
Blocks.collide(edges);
}
drawSprites();
}
function Move(Key, Velocity, Velocity2) {
if (keyDown(Key)) {
Block.velocityY = Velocity;
} else {
Block.velocityY = Velocity2;
}
}
function Move2(Key, Velocity, Velocity2, Key2) {
if (keyDown(Key)) {
Block.velocityX = Velocity;
} else if ((!keyDown(Key2))) {
Block.velocityX = Velocity2;
}
}
My issue is with
if (Blocks.isTouching(bottomEdge)) {
var Block = createSprite(200, 0);
Blocks.add(Block);
Blocks.setAnimationEach(randomNumber(1, 7).toString());
}
That code is basically for when a piece touches the ground, a new piece is made with a random Animation, that is the shape. I know I have to fix other stuff, but I know how to fix it. The thing I don't know how to do is set an animation once? Is there a code for that, because it constantly randomly changes the animation because the function draw() runs multiple times. But if I put it outside of that function, it only runs in the beginning of the program. Should I like push my sprite back up a little afterwards? I can't use const and I don't even know how to use it. Each time a sprite touches the ground, I want a new sprite to made and that animation is only set once. My biggest issue is that, I know there are other issues in that segment, but I can fix it myself

Save mouse location then have a second value that updates

I'm using the Phaser engine, and I want to have a line be drawn on a click and hold event from the initial mouse position and have it constantly update to draw to the mouse position as it moves. My problem is that when i try to store the initial mouse position it keeps changing. This seems like a simple problem but i'm not very good with this stuff. Here is the code:
var unitLine;
if(game.input.activePointer.isDown) {
const firstX = game.input.x;
const firstY = game.input.y;
unitLine = game.add.graphics(100, 100);
unitLine.beginFill(0xFF3300);
unitLine.lineStyle(10, 0xffd900, 1);
unitLine.moveTo(firstX, firstY);
unitLine.lineTo(game.input.x, game.input.y);
}
that firstX and firstY are changing even when i declare them as a const. Not sure what to do here.
The problem is that you're setting firstX and firstY whenever the mouse isDown, so they're basically overwritten every frame that the mouse is down.
To get around this, try using Phaser's game.input.onDown function:
var game = new Phaser.Game(500, 500, Phaser.CANVAS, 'test', {
preload: preload,
create: create,
update: update
});
function preload() {}
let firstX;
let firstY;
function create() {
game.input.onDown.add(function() {
firstX = game.input.x;
firstY = game.input.y;
}, this);
}
var unitLine;
function update() {
if (game.input.activePointer.isDown) {
unitLine = game.add.graphics(0, 0);
unitLine.beginFill(0xFF3300);
unitLine.lineStyle(10, 0xffd900, 1);
unitLine.moveTo(firstX, firstY);
unitLine.lineTo(game.input.x, game.input.y);
}
}
<script src="https://github.com/photonstorm/phaser-ce/releases/download/v2.11.1/phaser.min.js"></script>
(Also, I had to change the 100, 100 to 0, 0)
It's because you're declaring them in the statement, so the declaration is newly hit each time and the variables are created afresh.
Firsly, you need to create the variables outside of the statement.
And then, to fix your issue, I would use a bool to lock them in.
Something like this:
var unitLine;
var firstX;
var firstY;
var needToset_XY = true;
if(game.input.activePointer.isDown) {
if(needToset_XY){
firstX = game.input.x;
firstY = game.input.y;
needToset_XY = false;
}
unitLine = game.add.graphics(100, 100);
unitLine.beginFill(0xFF3300);
unitLine.lineStyle(10, 0xffd900, 1);
unitLine.moveTo(firstX, firstY);
unitLine.lineTo(game.input.x, game.input.y);
}
This means the firstX and firstY values can't be changed after the first time.
If this is all in a game loop, you'll need to declare the top four variables outside of the loop, otherwise they'll renew themselves each time.

Simple ball animation HTML5 using requestAnimationFrame

I am just starting trying to make some animation using HTML5 and JavaScript.
Currently I have created a JavaScript class for the ball. It has an update function which should update the position of the ball and a draw function which should draw it:
/*global Vector*/
var Ball = (function () {
function Ball(pPostion) {
this.setPosition(pPostion);
}
Ball.prototype.getPosition = function () {
return this.mPosition;
};
Ball.prototype.setPosition = function (pPosition) {
this.mPosition = pPosition;
};
Ball.prototype.draw = function (pContext) {
pContext.save();
pContext.beginPath();
pContext.arc(100, 100, 20, 0, Math.PI * 2, true);
pContext.closePath();
pContext.fillStyle = '#ff0000';
pContext.stroke();
pContext.restore();
};
Ball.prototype.update = function () {
this.getPosition().add(new Vector(10, 0));
};
return Ball;
}());
In the my main section I have created the following method:
function ballGameLoop() {
ball.draw(mainContext);
ball.update();
requestAnimationFrame(ballGameLoop);
}
And when called, it does draw the ball but it doesn't seem to move at all. I don't have a specific type of way I want the ball to be animated, just any kind of movement would be good. Can anyone give any advice on where I may be going wrong?
From the looks of it, it seems you are just drawing an arc at the same coordinates over and over again (center at (100,100)).
Incorporating your Ball's position into this would be the way to make the render location dependent on the object's position. From what it seems, something along the lines of the following would give movement:
Ball.prototype.draw = function (pContext) {
var coordinates = this.getPosition();
pContext.save();
pContext.beginPath();
pContext.arc(coordinates.X, coordinates.Y, 20, 0, Math.PI * 2, true);
pContext.closePath();
pContext.fillStyle = '#ff0000';
pContext.stroke();
pContext.restore();
};
I'm of course assuming on how you setup the Vector object, so I'm guessing x and y can be accessed by (Vector).X and (Vector).Y respectively.
anyway just my approach at it.

HTML5 Canvas, Having Trouble Running Multiple Animations At Once

I have written code that takes two arrays, both of which contain co-ordinates for a four-cornered shape (effectively a start frame and an end frame), a canvas ID and a time value. The function then calculates dX and dY of each corner and uses window.performance.now() to create a timestamp. Then, on every requestAnimationFrame(), it calculates what the co-ordinates should be by using dX, dY, the old timestamp, a new timestamp and the time value from the function call. It looks like this:
function doAnim(cv, startFrame, endFrame, animTime)
{
this.canvas = document.getElementById(cv);
this.ctx = this.canvas.getContext('2d');
if(startFrame.length != endFrame.length)
{
return('Error: Keyframe arrays do not match in length');
};
this.animChange = new Array();
for(i=1;i<=startFrame.length;i++)
{
var a = startFrame[i];
var b = endFrame[i]
var c = b - a;
this.animChange[i] = c;
}
this.timerStart = window.performance.now();
function draw()
{
this.requestAnimationFrame(draw, cv);
this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);
this.currentFrame = new Array();
for(i=1;i<=startFrame.length;i++)
{
this.currentFrame[i] = startFrame[i]+(this.animChange[i]*((window.performance.now()-this.timerStart)/animTime));
}
if((window.performance.now()-this.timerStart)>=animTime)
{
this.ctx.beginPath()
this.ctx.moveTo(endFrame[1], endFrame[2]);
this.ctx.lineTo(endFrame[3], endFrame[4]);
this.ctx.lineTo(endFrame[5], endFrame[6]);
this.ctx.lineTo(endFrame[7], endFrame[8]);
this.ctx.fill();
return;
}
else
{
this.ctx.beginPath()
this.ctx.moveTo(this.currentFrame[1], this.currentFrame[2]);
this.ctx.lineTo(this.currentFrame[3], this.currentFrame[4]);
this.ctx.lineTo(this.currentFrame[5], this.currentFrame[6]);
this.ctx.lineTo(this.currentFrame[7], this.currentFrame[8]);
this.ctx.fill();
}
}
draw();
}
The goal is to have multiple animations of objects happening at once. I took the whole co-ordinate approach because I want the objects to appear as if they are coming from the horizon, creating a fake 3D perspective effect (all objects' starting frames would be a single point at the center of the canvas), and I do not want to warp the objects' textures.
Well, it works great for a single animation, but if I try to start a new animation on a completely different canvas while the first one is running, then the first animation stops dead in its tracks.
As you can see from my JS, I've tried getting around this with gratuitous use of this (I do not fully understand how this works yet, and every explanation I've read has left me even more confused), but it has not worked. I also tried a horrific approach which stored all the functions' own variables in one global array (the first time the function runs, all the variables are put in entries 1-30, the second time they're put in 31-60, etc). Unsurprisingly, that did not work either.
Here is a JSFiddle so you can see this scenario for yourself and play with my code. I am officially out of ideas. Any help will be greatly appreciated.
Like markE linked too, trying to call requestAnimationFrame multiple times won't work.
Instead you make multiple objects and then call some sort of function on them each frame.
I have created an example using your code:
https://jsfiddle.net/samcarlin/2bxn1r79/7/
var anim0frame1 = new Array();
anim0frame1[1] = 0;
anim0frame1[2] = 0;
anim0frame1[3] = 50;
anim0frame1[4] = 0;
anim0frame1[5] = 50;
anim0frame1[6] = 150;
anim0frame1[7] = 0;
anim0frame1[8] = 150;
var anim0frame2 = new Array();
anim0frame2[1] = 200;
anim0frame2[2] = 200;
anim0frame2[3] = 300;
anim0frame2[4] = 250;
anim0frame2[5] = 300;
anim0frame2[6] = 300;
anim0frame2[7] = 200;
anim0frame2[8] = 250;
//Call global
animations = [];
requestAnimationFrame( GlobalStep );
function GlobalStep(delta){
//Functions called by request animation frame have the new time as an argument
//so delta should be approximately the same as window.performance.now()
//especially in realtime applications, which this is
//Check if we have any animation objects
if(animations.length > 0){
//Iterate through and call draw on all animations
for(var i=0; i<animations.length; i++){
if(animations[i].draw(delta)){
//Basically we have it so if the draw function returns true we stop animating the object
//And remove it from the array, so have the draw function return true when animation is complete
animations[i].splice(i, 0);
//We removed an object from the array, so we decrement i
i--;
}
}
}
//And of course call requestAnimationFrame
requestAnimationFrame( GlobalStep );
}
function AnimationObject(cv, startFrame, endFrame, animTime){
//Add this object to the objects arrays
animations.push(this);
//We need to store start and end frame
this.startFrame = startFrame;
this.endFrame = endFrame;
this.animTime = animTime;
//Your code
this.canvas = document.getElementById(cv);
this.ctx = this.canvas.getContext('2d');
if (startFrame.length != endFrame.length) {
return ('Error: Keyframe arrays do not match in length');
};
this.animChange = new Array();
for (i = 1; i <= startFrame.length; i++) {
var a = startFrame[i];
var b = endFrame[i]
var c = b - a;
this.animChange[i] = c;
}
this.timerStart = window.performance.now();
}
//This adds a function to an object, but in such a way that every object shares the same function
//Imagine a kitchen, each object is a person, and this function is a spoon
//by defining this function in this manner Object.prototype.function_name = function(arguments){}
//We make it so one function definition is needed, essentially allowing all the people to share one spoon,
//the 'this' variable still refers to whichever object we call this method, and we save memory etc.
AnimationObject.prototype.draw = function(newTime){
//I added this to start frame so we get what we stored earlier
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.currentFrame = new Array();
for (i = 1; i <= this.startFrame.length; i++) {
this.currentFrame[i] = this.startFrame[i] + (this.animChange[i] * ((newTime - this.timerStart) / this.animTime));
}
if ((newTime - this.timerStart) >= this.animTime) {
this.ctx.beginPath()
this.ctx.moveTo(this.endFrame[1], this.endFrame[2]);
this.ctx.lineTo(this.endFrame[3], this.endFrame[4]);
this.ctx.lineTo(this.endFrame[5], this.endFrame[6]);
this.ctx.lineTo(this.endFrame[7], this.endFrame[8]);
this.ctx.fill();
return;
} else {
this.ctx.beginPath()
this.ctx.moveTo(this.currentFrame[1], this.currentFrame[2]);
this.ctx.lineTo(this.currentFrame[3], this.currentFrame[4]);
this.ctx.lineTo(this.currentFrame[5], this.currentFrame[6]);
this.ctx.lineTo(this.currentFrame[7], this.currentFrame[8]);
this.ctx.fill();
}
}
Notes:
Everytime you press the button a new object is added and simply overwrites previous ones for each frame, you should implement your program so that it checks if a specific animation has already started, you could also use the builtin mechanism to stop animation when complete (read the comments in the code)
You also need to change the on button click code
<button onclick="new AnimationObject('canvas1', anim0frame1, anim0frame2, 3000);">
Lastly if you have further questions feel free to contact me

Paper js 'dot' paths showing up in firefox but not in IE or Chrome

Using the code in the paper js sketch here I am able to see the dots that are drawn by simply clicking without moving the mouse. Also you can see the element is in fact added in all 3 browsers. However, Chrome and IE do not display the element and I cannot for the life of me understand why.
// The minimum distance the mouse has to drag
// before firing the next onMouseDrag event:
tool.minDistance = 1;
tool.maxDistance = 1;
function onMouseDown(e) {
// Create a new path and give it a stroke color:
path = new Path();
path.strokeColor = 'black';
path.strokeWidth = 2;
// Add a segment to the path where
// you clicked:
path.add(e.point);
}
function onMouseDrag(e) {
var top = e.middlePoint;
var bottom = e.middlePoint;
path.add(top);
path.insert(0, bottom);
}
function onMouseUp(e) {
var pt = e.point;
path.add(pt);
path.closed = true;
console.log(path);
}
Got a reply from Jürg Lehni
It's probably a difference of the underlying rendering system, but an
open path with only one segment should simply not be rendered,
something that we should handle in the library internally.
A closed path should be rendered if it defines handles, as that can
actually be a tiny little loop.
I had to setup specific behavior to handle dot paths. In my case I used circles.
This is how i solved it:
function onMouseUp(e) {
var pt = e.point;
if (path.segments.length < 2) {
// draw a dot
pt.y ++;
}
path.add(pt);
path.closed = true;
console.log(path);
}

Categories

Resources