Phaser, make a button click event continuous - javascript

I'm using Phaser.js to create a map (tileSprite) and have some sprites on it, because not all the sprites can get in, I'm using the camera to pan right and left.
I want the user to either click a keyboard key (left or right) or a directional button sprite to continuously pan the camera until the user releases the control.
I've implemented keyboard panning similar to this example, I hold down a key and the camera moves/pans (10 pixels to each side on an event) and stops on key release.
However, when I've tried to implement the same thing using the 2 sprite buttons, each button fired only 1 event and panned the camera only 10 pixels per click. I need to to keep firing until I let go of the key.
var panRightButton = game.add.button(800, 5, 'right_pan_btn', onClickAction, this);
panRightButton.onInputOver.add(onButtonOver, this);
panRightButton.onInputOut.add(onButtonOut, this);
panRightButton.onInputDown.add(panScreenRight, this);
function panScreenRight() {
game.camera.x += 10;
}
I've tried using a boolean flag (isPanning) that would turn to true if i'm clicking a button and false on release. and have a while loop on game.camera.x += 10;, but it just slowed and stopped the script.
function onClickAction() {
isPanning = true;
}
function onButtonOut() {
isPanning = false;
}
function onButtonUp() {
isPanning = false;
}
function panScreenLeft() {
if (isPanning) {
game.camera.x -= 10;
}
}

The proper way to do it is on the update method, but not within a loop. Using a flag to know if the button is being pressed is ok, but just let Phaser to update the camera position, like in the example that you have linked:
function update() {
//...
if (isPanningLeft) {
game.camera.x -= 10;
} else if (isPanningRight) {
game.camera.x += 10;
}
//...
}
You don't need a loop because the update method is executed within a loop (and it is expected to be executed once by frame)

Related

Paper.js scale transform continues outside the onFrame event

I'm running into a bit of an odd issue with Paper.js - I'm using the library to scale the "petals" of a randomly generated flower while audio plays.
The issue crops up if the flower is "growing" and the user navigates to a different tab in the browser. Even though it appears that the onFrame event is not firing when the window is out of view, whichever petal is currently scaling at the time will continue to scale indefinitely.
I even tried using a special js library to determine if the window is in view and still wasn't able to get the petals to stop scaling.
You can view a demo here, as I was not even able to replicate this in a Paper sketch: https://demos2.paperbeatsscissors.com/
Also including my onFrame code here in case the problem is obvious to someone:
view.onFrame = function(event) {
// See if something is playing
if (playing > -1) {
// Get the active flower
var activeFlower = garden[playing],
activeData = activeFlower.data;
// Active layer and petal
var activeLayer = getEl(activeFlower, activeData.lIndex),
activePetal = getEl(activeLayer, activeData.pIndex);
// Variables
var time = activeData.audio.seek(),
scaleAmount = (1 / (activeData.timing / event.delta.toFixed(3))) * 2;
// Petal progression
if (!activeData.completed) {
if (activePetal.scaling.x < 1 && activePetal.scaling.y < 1) {
activePetal.pivot = {x: 0, y: activePetal.height / 2};
activePetal.scaling.x = activePetal.scaling.x + scaleAmount;
activePetal.scaling.y = activePetal.scaling.y + scaleAmount;
} else {
if (activeData.pIndex < (activeLayer.children.length - 1)) {
// If the petal is scaled, jump to a new petal
activeData.pIndex += 1;
} else {
if (activeData.lIndex > 0) {
// When all petals are bloomed, jump to a new layer
activeData.pIndex = 0;
activeData.lIndex -= 1;
} else {
// Set the flower as completed
activeData.completed = true;
}
}
}
}
activeFlower.rotate(.125, activeData.center);
// Reset the playing variable if the audio clip is complete and the flower has completed
if (!activeData.audio.playing() && time === 0 && activeData.completed) {
playing = -1;
}
}
}
Really stumped on this one so any help is greatly appreciated!
I think that your problem is coming from the fact that you base your scaling calculation on event.delta which represents the time elapsed since the last event fired.
The thing is that, if I'm not mistaken, under the hood, Paper.js onFrame event relies on requestAnimationFrame which does not fire when the tab if inactive.
So when you switch tab, wait for a while and get back to your tab event.delta value is big and your scaling value too, hence the size of your petals. This basic sketch showcase this behavior.
So in my opinion, you should simply check event.delta value and limit it if it's too high.

Why did it take chrome performance system time so long?

I listened for the mouse wheel event in the code and executed a rendering of WebGL each time the wheel event was triggered. However, there was one problem that could not be solved: when scrolling, frames were often lost.
I'm making a map app, and the mouse scroll triggers the map to zoom in and out.
// Render function call:
public requestRender() {
if (!this._waitingRender) {
this._waitingRender = requestAnimationFrame(
this._renderFrame.bind(this),
);
}
}
// Render function defined
private _renderFrame() {
if (!this._styleLoaded) {
cancelAnimationFrame((this._waitingRender = 0));
this._waitingRender = 0;
return;
}
const frameState = this._getState();
this._sourceManager.loadData(
frameState.viewState,
this,
this._mapRender.context,
);
this._mapRender.renderFrame(frameState);
this._waitingRender = 0;
this._diffState();
return;
}
This is my performance:

How to trigger an event onMousewheel?

I am developing a WebGL application. For example, I have a sphere object that uses orbit controls for Zoom in/out.
Now I want to setup an event for the mousewheel. When zooming on my current WebGL block corresponding map location it can be zoomed in/out (used inline-block) for maps and WebGL. But the problem is that first of all my event is being triggered when I use the mousewheel. I also want to know whether my event logic is correct or not.
root.addEventListener('mousewheel', mousewheel, false);
function mousewheel(event) {
var mX = (event.wheeldetailX/width)* 2 - 1;
var mY = (event.wheeldetailY/height)* 2 + 1;
var WebGLZoom = new THREE.Vector3(mX, mY, 1);
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera(WebGLZoom, camera);
WebGLZoom.sub(camera.position);
var mapzoom = map.getZoom();
if (WebGLZoom.z <= 5 && WebGLZoom.z > 2) {
map.setZoom(17);
} else if (WebGLZoom.z <= 2 && WebGLZoom.z > 0.0) {
map.setZoom(19);
} else {
map.setZoom(14);
}
}
You can use the wheel event like so.
document.addEventListener('wheel', function(event){
console.log(event.deltaY);
}, false);
This will result in a console log every time your mousewheel scrolls over the document. The deltaX and deltaY properties of the MouseWheel event are especially useful to figure out exactly how much the user scrolled and in which direction.
The event to use is wheel. You can find a working example here.

EaselJS SpriteSheet isn't responding to gotoAndPlay

I'm developing a Fez-based HTML5 Canvas game using EaselJS and I've found a problem, that I can't solve myself, while trying to implement SpriteSheets to the hero.
The problem is that I've defined three animations to my hero ("stand", "jump" and "run") and when I try to change from one animation to another using hero.gotoAndPlay("run") or hero.gotoAndStop("stand") the animations don't change, change but show the first frame only or change to the wrong animation.
Can someone help me? What I'm doing wrong and how can I fix it? Thanks.
Here's the relevant JavaScript code I'm using to create the hero Sprite:
var data = {
images: ["http://i.imgur.com/M0GmFnz.png"],
frames: {width:34, height:46},
animations: {
stand:0,
run:[0,12,true,0.25],
jump:13
}
};
var spriteSheet = new createjs.SpriteSheet(data);
var hero = new createjs.Sprite(spriteSheet, "stand");
hero.offset = 4 + 1; // "+1" is important, change the first number only.
hero.regX = hero.offset + 2;
hero.regY = hero.offset;
hero.width = 34 - (hero.offset*2) - 12;
hero.height = 46 - (hero.offset*2);
hero.x = 0;
hero.y = 0;
hero.jumping = true;
stage.addChild(hero);
And the code I'm using to change the animation:
if(!left && !right){ // User isn't pressing left arrow or right arrow
hero.gotoAndStop("stand");
}else{
hero.gotoAndPlay("run");
}
JSFiddle
Official Site
If you are calling gotoAndStop or gotoAndPlay in a tick (or similar) then it will constantly reset to the first frame. You have to ensure you only call these functions one time when the animation changes.
A good way to set this up is to store the current animation, store it, and only change it up if the animation changes. Something like:
var animation;
if(!left && !right){ // User isn't pressing left arrow or right arrow
animation = "stand";
}else{
animation = "run";
}
if (currentAnimation != animation) {
hero.gotoAndStop(animation);
}
This is just an example, but should give you an idea. You should only call these methods one time to kick off an animation.

canvas button onmouseover change color

I have a drawButtons function that takes an argument of "nonhover", "hover1" or "hover2" and draws up a new button set to the canvas, and depending on the argument it takes, will draw the buttons different colors. It does work when i call it from setUpGame() but not when I call it from draw(). I want to call it from draw() because draw() is called 80 times a second in setInterval(). That way it can keep checking if the mouse is hovering over the button and draw the appropriate button set.
setUpGame() is called outside of any object or function. draw() is called by setInterval() which is outside of any function or object. setInterval calls draw 80 times a second.
getMouseOver() another function that is the one that should actually be called by draw(), because it says "if mouse is over button one: drawButtons("hover1") and so on. It just doesn't draw the buttons when I call it.
There are no errors in the browser Javascript console. I am using Chrome which works best with my game.
From this we can deduce that there is no problem with drawButtons() as it worked when called from setUpGame().
There is possibly a problem with draw() as drawButtons() doesn't work when I call it from there (but to perplex us more, displayNumbers does display the numbers when I call it from there) and it worked fine when playing the game (here we are not playing the game, we are on a start screen).
There is probably a problem with getMouseOver() because that doesn't work anywhere.
I will show you getMouseOver() for now. My program is getting big and it is overwhelming to show too much right from the start. I intend for this function to be called 80 times a second.
getMouseOver: function() {
window.onload = (function(){
window.onmouseover = function(e) {
// IE doesn't always have e here
e = e || window.event;
// get event location
// change the code so that it gives the relative location
var location = {
x: e.pageX - offset.x,
y: e.pageY - offset.y
};
if (location.x > 103.5 && location.x < 265.5) {
if (location.y > 240 && location.y < 291) {
nonGameContent.drawButtons("hover1");
}
}
if (location.x > 103.5 && location.x < 265.5) {
if (location.y > 160 && location.y < 212) {
nonGameContent.drawButtons("hover2");
}
}
else{
nonGameContent.drawButtons("nonHover");
}
}
})},
In this fiddle you have click() and onmousemove() that are working.
I didn't understand well if you want to display button at the beginning or just when the mouse hovers somewhere on the future place of the button but it's a beginning :
http://jsfiddle.net/Akinaru/3a7g2/57/
Main modification :
canvas.onmousedown = nonGameContent.getMouseClick;
canvas.onmousemove = nonGameContent.getMouseOver;
to change the canvas rectangle color when you mouse over it use onmousemove to find if you are over it, then redraw the canvas with a different color rectangle
getMouseClick: function() {
window.onmousemove = function(e) {

Categories