I'm having issues resuming my game after pausing. It seems like the code never reads my else statement but I'm not sure how to fix it.
I've tried to use different keys and even clicking to pause/resume. I've also tried to add a function in both the create function and the update loop but I get the same issue from both.
this.input.keyboard.once('keydown_ESC', function () {
if (game.scene.isActive('default')){
game.scene.pause('default');
} else {
game.scene.resume('default');
}
});
I expect the game to resume after pressing the esc key a second time.
The reason is that the scene becomes inactive altogether, thus no function in it will run. In other words this scene's code dead stops from running. So you need some other part of the game, which will remain active (e.g running) to take over the 'resume' functionality. Without me being an expert in phaser 3. This is a workaround to achieve this by putting this inside your scripts but outside of any scene's class or code. Let's say you define your
var game = new Phaser.Game(config);
inside the script called game.html. So in there and still inside the javascript tag put this:
var global_scene_paused = false;
var global_time_paused = Date.now() - 10000;
function global_pause(scene){
if(Date.now() - global_time_paused > 2000 && game.scene.isActive(scene)){
game.scene.pause(scene);
console.log('--------- global_pause called');
global_time_paused = Date.now();
global_scene_paused = scene;
}
}
// keyCode 80 : P. Will resume by pressing 'P'
document.addEventListener('keydown', function(event) {
if(event.keyCode == 80 && Date.now() - global_time_paused > 2000 && global_scene_paused) {
game.scene.resume(global_scene_paused);
console.log('+++++++++++ RESUME');
global_scene_paused = false;
global_time_paused = Date.now();
}
});
Inside your scene add this call instead of pause:
this.input.keyboard.once('keydown_ESC', function () {
global_pause('default'); //will be unpaused in game.html
});
Related
I've been making a game to practice programming, and I am having trouble using the Jquery .click() function. I have two buttons in my code, the start button and the attack button. When I click the start button, the .click() function fires the code for the other button as well, which causes my main menu to freeze up and not draw the game screen. I've used separate id's for the buttons, but they both seem to recognize the click on the start button. I can't get it to work in JSFiddle, but all the code is there. Can someone please tell me how to use multiple buttons?
//start button
$('#startButton').click(function() {
stage.state = "battle";
stage.update();
})
//attack button
$('#attack').click(firstTurn());
//attack button code
function firstTurn() {
console.log("firstTurn Fired");
if(p1.speed > opp.speed){
turn = 1;
} else{
turn = 0;
}
battle();
};
function battle(){
var battling = 1;
while(battling == 1) {
if(turn == 0) {
p1.health = p1.health-opp.attack;
$("#textBox").append('<p>'+opp.name+' hit you for '+ opp.attack+' points.</p><br/>');
draw();
sleep(1000);
console.log("attacked");
} else{
opp.health = opp.health-p1.attack;
$('#textBox').append('<p> You hit '+opp.name+' for '+p1.attack+' points.</p><br/>');
draw();
sleep(1000);
}
}
};
https://jsfiddle.net/memersond/m3gvv8y6/
$('#attack').click(firstTurn());
Should be:
$('#attack').click(firstTurn);
You want to pass the function as a reference, not have it executed immediately.
$('#attack').click(firstTurn());
This causes firstTurn() to be called when the listener is initiated, use one of the alternatives:
$('#attack').click(firstTurn );
$('#attack').click(function() {
firstTurn()
});
I am trying to implement kind of player on my website.
If press 'Play' button, the music starts and the page smoothly scrolls down.
But when you press 'Mute' button (function(){music.volume=0}) I am not sure why the page appears at the top again. window.scroll() doesn't do anything without delay. So i am using setTimeout function to scroll the page on the current place. The problem is that in Opera and IE setTimeout takes about 10 ms, so when i click 'Mute' button i see like ticks to top and back. In chrome it takes only 2 ms and there is no problems.
Now when i decide to create my own timeout function the window.scroll() does not work again.
Here is my code:
var isMuted = false;
muteButton.onclick = function() { ////This function works with big delay.
if (!isMuted) {
mainAudio.volume = 0;
isMuted = true;
} else {
mainAudio.volume = bgAudioTrackVolume;
isMuted = false;
}
setTimeout(function() {
window.scroll(0, offset); /// Works
}, 0)
};
Change setTimeout with:
i = 9542155.873; /// I have tried delay time from 1ms - 250ms by changing this value.
while (i > 0.00001) {
i = i / 1.0001234567;
if (i < 0.00001) {
window.scroll(0, offset); /// Does not do anything. Strange! Have tried to change variable with a number.
}
}
Every time i check offset value, it is always available before calling scroll function.
I know that my problem is not usual and i am realy need your help.
The reason that the page scrolls to the top is that you are using a link with the empty bookmark #, which represents the top of the page. The reason that the scroll method doesn't work without a timeout is that jumping to the bookmark happens after the event handler.
Instead of trying to scroll the page back to where it was, just stop the default action of the link by returning false from the event handler:
var isMuted = false;
muteButton.onclick = function() {
if (!isMuted) {
mainAudio.volume = 0;
isMuted = true;
} else {
mainAudio.volume = bgAudioTrackVolume;
isMuted = false;
}
return false;
};
Alternatively, use some other element than a link.
I know that mousedown happens when a user depresses the mouse button, mouseup happens when the release the mouse and click is of course two events mousedown and mouseup. I have three different events each dealing with these three events mouseup down and click. My question is how to differentiate between the three, now my mouse down has a timer, so I was thinking of adding a boolean in that timer and testing it within the click I tried this and it didn't work to my standards.
Mousedown- timer checks for certain classes then if none of these classes exist within the targeted element proceed
Mouseup- clear the timer
Click- open a module
I may have not made the boolean a global variable that each can read or not, or I am missing something completely. Here is an example quick code of my full code:
var isDown = false;
ee[i].addEventListener('click',function(){
if(isDown===false){
openModule();
}
},false);
ee[i].addEventListener('mousedown',function(){
var timer;
var $this = this;
timer = setTimeout(function(){
if($this.className == "class"){
isDown=true;
createActive();
}
},500);
},true);
ee[i].addEventListener('mouseup',function(){
clearTimeout(timer);
},false);
That is just a quick example. I may have missed some coding but I hope you catch my drift in the code above. Anyone know of a good way to differentiate between the three events?
I've rewritten your code utilizing jQuery...
var isDown = false;
var timer;
$('.class').mousedown(function(){
isDown = false;
timer = setTimeout(function(){
isDown = true;
//createActive();
console.log('MOUSE DOWN');
}, 500);
}).mouseup(function(){
if(isDown === false){
//openModule();
console.log('CLICK');
}else{
console.log('MOUSE UP');
}
clearTimeout(timer);
});
If you simply add jQuery to your page, my code will automatically attach itself to any element in your document with a class of 'class'.
I've commented out your createActive(); and openModule(); calls so that you can play around with it (viewing your javascript console at runtime will show you the script in action - remove the console.log() stuff when you're done playing). This code could be optimised a bit more but it will give you the general idea.
Your timer variable needed to be created globally (I moved it out of the function).
In this case (declaring a mousedown time barrier) the click function will be rendered useless so I've improvised it into the mouseup function.
It's good to know core javascript, but jQuery is just too easy and powerful to ignore.
Try this:
const isDown = ref(false)
const timer = ref(0)
const mouseDown = () => {
isDown.value = true
timer.value = setTimeout(() => {
isDown.value = false
}, 120)
}
const mouseUp = () => {
if (isDown.value === true) {
hideModal()
} else {
return
}
clearTimeout(timer.value)
}
I'm using Three.js with the WebGL renderer to make a game which fullscreens when a play link is clicked. For animation, I use requestAnimationFrame.
I initiate it like this:
self.animate = function()
{
self.camera.lookAt(self.scene.position);
self.renderer.render(self.scene, self.camera);
if (self.willAnimate)
window.requestAnimationFrame(self.animate, self.renderer.domElement);
}
self.startAnimating = function()
{
self.willAnimate = true;
self.animate();
}
self.stopAnimating = function()
{
self.willAnimate = false;
}
When I want to, I call the startAnimating method, and yes, it does work as intended. But, when I call the stopAnimating function, things break! There are no reported errors, though...
The setup is basically like this:
There is a play link on the page
Once the user clicks the link, a renderer's domElement should fullscreen, and it does
The startAnimating method is called and the renderer starts rendering stuff
Once escape is clicked, I register an fullscreenchange event and execute the stopAnimating method
The page tries to exit fullscreen, it does, but the entire document is completely blank
I'm pretty sure my other code is OK, and that I'm somehow stopping requestAnimationFrame in a wrong way. My explanation probably sucked, so I uploaded the code to my website, you can see it happening here: http://banehq.com/Placeholdername/main.html.
Here is the version where I don't try to call the animation methods, and fullscreening in and out works: http://banehq.com/Correct/Placeholdername/main.html.
Once play is clicked the first time, the game initializes and it's start method is executed. Once the fullscreen exits, the game's stop method is executed. Every other time that play has been clicked, the game only executes it's start method, because there is no need for it to be initialized again.
Here's how it looks:
var playLinkHasBeenClicked = function()
{
if (!started)
{
started = true;
game = new Game(container); //"container" is an empty div
}
game.start();
}
And here's how the start and stop methods look like:
self.start = function()
{
self.container.appendChild(game.renderer.domElement); //Add the renderer's domElement to an empty div
THREEx.FullScreen.request(self.container); //Request fullscreen on the div
self.renderer.setSize(screen.width, screen.height); //Adjust screensize
self.startAnimating();
}
self.stop = function()
{
self.container.removeChild(game.renderer.domElement); //Remove the renderer from the div
self.renderer.setSize(0, 0); //I guess this isn't needed, but welp
self.stopAnimating();
}
The only difference between this and the working version is that startAnimating and stopAnimating method calls in start and stop methods are commented out.
One way to start/stop is like this
var requestId;
function loop(time) {
requestId = undefined;
...
// do stuff
...
start();
}
function start() {
if (!requestId) {
requestId = window.requestAnimationFrame(loop);
}
}
function stop() {
if (requestId) {
window.cancelAnimationFrame(requestId);
requestId = undefined;
}
}
Working example:
const timeElem = document.querySelector("#time");
var requestId;
function loop(time) {
requestId = undefined;
doStuff(time)
start();
}
function start() {
if (!requestId) {
requestId = window.requestAnimationFrame(loop);
}
}
function stop() {
if (requestId) {
window.cancelAnimationFrame(requestId);
requestId = undefined;
}
}
function doStuff(time) {
timeElem.textContent = (time * 0.001).toFixed(2);
}
document.querySelector("#start").addEventListener('click', function() {
start();
});
document.querySelector("#stop").addEventListener('click', function() {
stop();
});
<button id="start">start</button>
<button id="stop">stop</button>
<div id="time"></div>
Stopping is as simple as not calling requestAnimationFrame anymore, and restarting is to call it it again.
ex)
var pause = false;
function loop(){
//... your stuff;
if(pause) return;
window.requestionAnimationFrame(loop);
}
loop(); //to start it off
pause = true; //to stop it
loop(); //to restart it
var myAnim //your requestId
function anim()
{
//bla bla bla
//it's important to update the requestId each time you're calling reuestAnimationFrame
myAnim=requestAnimationFrame(anim)
}
Let's start it
myAnim=requestAnimationFrame(anim)
Let's stop it
//the cancelation uses the last requestId
cancelAnimationFrame(myAnim)
Reference
I played around with the tutorial of a 2D Breakout Game where they also used requestAnimationFrame and I stopped it with a simple return. The return statement ends function execution if the value of return is omitted.
if(!lives) {
alert("GAME OVER");
return;
}
// looping the draw()
requestAnimationFrame(draw);
I would suggest having a look at the requestAnimationFrame polyfill gibhub page. There are discussions about how this is implemented.
So, after doing some more testing, I've found out that it was, indeed, my other code that posed a problem, not the animation stopping (it was a simple recursion after all). The problem was in dynamically adding and removing the renderer's domElement from the page. After I've stopped doing that, for there was really no reason to do so, and included it once where the initialization was happening, everything started working fine.
i'm looking for another way to execute this code :
$.each($("#gallery > img"), function(index,curImg) {
setTimeout(function() {
clearCanvas();
cvsCtx.drawImage(curImg,0,0);
} , index*animationMs);
});
This code draw an image from my gallery to my canvas every animationMs .
But i would like to make it possible to stop the animation, with a "Play/stop" button, I can't do it this way...
Any idea or workaround ?? thank you !!
I can't test it. But you can stop animation by using a variable to hold the setTimeout function as following:
var x; // public var
....
x = setTimeout(......);
// To stop it use:
clearTimeout(x);
Hope this works for you
I find that creating timeouts in a loop is usually too hard to manage - you don't want to have to cancel multiple timeouts. Better to have the function doing the work call itself (indirectly) by setting a timeout just before it completes, because then you can put in a simple if test to decide whether to set the next timeout and continue your animation.
Perhaps a little something like this:
<input id="playPause" type="button" value="Play">
<script>
function initAnimation(animationMs, autoRepeat, waitForPlayButton) {
var currentFrame = 0,
$imgList = $("#gallery > img"),
paused = waitForPlayButton;
function drawNext() {
clearCanvas();
cvsCtx.drawImage($imgList[currentFrame++],0,0);
if (currentFrame >= $imgList.length) {
currentFrame = 0;
if (!autoRepeat) {
paused = true;
$("playPause").prop("value", "Play");
}
}
if (!paused)
setTimeout(drawNext, animationMs);
}
$("playPause").prop("value", waitForPlayButton ? "Play" : "Pause")
.click(function() {
this.value = (paused = !paused) ? "Play" : "Pause";
if (!paused)
drawNext();
});
if (!waitForPlayButton)
drawNext();
}
initAnimation(100, true, false);
</script>
If autoRepeat param is false the animation will run once and stop, but can be restarted via the button, otherwise (obviously) it just keeps repeating.
If waitForPlayButton is false the animation will start immediately, otherwise (obviously) it will start when the button is pressed.
Pressing the button will pause at the current frame.
(Not tested since I don't have a bunch of images handy, but I'm sure you get the idea and can fix any problems yourself. Or let me know if you get errors...)
var images = $("#gallery > img").clone(), interval;
function startLoop() {
interval = setInterval(function(){
var image = images[0];
clearCanvas();
cvsCtx.drawImage(image,0,0);
images.append(image);
}, animationMs);
}
$(".stop").click(function() {clearInterval(interval);});
$(".start").click(startLoop);
setTimeout return a timeoutID which can be given to clearTimeout as a parameter to stop the timeout from happening.
You can read more about this at: https://developer.mozilla.org/en/DOM/window.setTimeout
Good luck
It's not really an animation... but still:
$("#gallery > img").each(function(index,curImg) {
$(this).delay(index*animationMs).queue(function(next) {
clearCanvas();
cvsCtx.drawImage(curImg,0,0);
if (next) next();
});
});
Using jQuery queues like I did allows you to do .stop(true), on $("#gallery > img") or a single image and stop their "animation".
First you could add images to a javascript array variable (eventually global) and then call a function cycle() on that array for all its length.
You should put your setTimeout() call inside that function, assigning it to a variable: var t=setTimeout("cycle()",animationMs); and execute clearTimeout(t); when you want to stop the animation.
Of course you could also save in a variable the frame where you were when stopping the animation and restart exactly from that frame when pressing "play" button.