how to get click duration on pointerdown PhaserJs 3 [duplicate] - javascript

I'm creating pinball game using Phaser Framework.
When the ball holder is pressed (please check attached screenshot so you have an idea what I mean ball holder), depending on the press speed, it should move the ball around the spiral channel. So now trying to detect the down pressed duration of the holder.
Here is my code:
var ballButton;
ballButton = game.add.sprite(196, 100, 'ballHolder');
ballButton.inputEnabled = true;
ballButton.events.onInputDown.add(inputDownAction, this);
function inputDownAction(ballButton, pointer) {
/* returns 0 */
console.log( pointer.duration);
}
So pointer.duration is not working and returns 0.
But game.input.activePointer.duration inside update() function is working and returns duration.
if (game.input.activePointer.duration > 200 && game.input.activePointer.duration < 500){
console.log('first range '+game.input.activePointer.duration);
}else if(game.input.activePointer.duration > 500 && game.input.activePointer.duration < 700){
console.log('second range '+game.input.activePointer.duration);
}else if(game.input.activePointer.duration > 700){
console.log('third range '+game.input.activePointer.duration);
}
How can I make it work for specific item/sprite? Any ideas please?

in phaser 3 something like
function update(){
var duration = 0
if( this.input.activePointer.isDown ){
duration++;
}
}

You can get the time from the scene and calculate it with the downTime from the activePointer. So, you can try this approach:
function update(time, delta){
console.log(time - window.game.input.activePointer.downTime);
}
I came to the conclusion that this is the best approach when you want to get the duration on press down key because there is not duration attribute in activePointer anymore(Phaser3). So, this code works on Phaser 3 as well.
I hope it helps!

Related

Detect new mouse wheel event

I'm using the following event listener to detect mouse wheel and scroll direction:
window.addEventListener('wheel', ({ deltaY }) => {
console.log(deltaY);
if (deltaY > 0) scrollDown();
else if (deltaY < 0) scrollUp();
});
The following happens here:
2 finger touch pad scroll on Macbook triggers the event handler
deltaY keeps logging due to the scroll accelerometer
scrollDown() or scrollUp() keep firing until accelerometer stops
I only want to fire scrollUp and scrollDown once per user interaction. I therefore need to detect a new mouse scroll event, not every mouse scroll events. Is this possible?
I did try a timeout to detect if deltaY was still changing due to the accelerometer, but this wasn't sufficient because if it was still changing, a second user interaction did not trigger scrollUp or scrollDown.
Here's a CodePen of what I'm trying to achieve: https://codepen.io/anon/pen/dQmPNN
It's very close to the required functionality, but if you hammer the mouse wheel hard on the first slide, then try to scroll to the next one immediately, the timeout solution locks it so you have to wait another second or so until the timeout completes and you can continue scrolling.
This is old but I found it when looking for an answer to pretty much the same problem.
I solved the problem for my purposes, so here's my solution in case it helps anyone else.
The problem is really to define what counts as one continuous action. Without something more concrete to work with, it's just a question of timing. It's the time between events that's the key - so the algorithm is to keep accumulating events until there's a certain gap between them. All that then remains is to figure out how big the allowed gap should be, which is solution specific. That's then the maximum delay after the user stops scrolling until they get feedback. My optimum is a quarter of a second, I'm using that as a default in the below.
Below is my JavaScript, I'm attaching the event to a div with the id 'wheelTestDiv' using jQuery but it works the same with the window object, as in the question.
It's worth noting that the below looks for any onWheel event but only tracks the Y axis. If you need more axes, or specifically only want to count events towards the timer when there's a change in deltaY, you'll need to change the code appropriately.
Also worth noting, if you don't need the flexibility of tracking events against different DOM objects, you could refactor the class to have static methods and properties, so there would be no need to create a global object variable. If you do need to track against different DOM objects (I do), then you may need multiple instances of the class.
"use strict";
class MouseWheelAggregater {
// Pass in the callback function and optionally, the maximum allowed pause
constructor(func, maxPause) {
this.maxAllowedPause = (maxPause) ? maxPause : 250; // millis
this.last = Date.now();
this.cummulativeDeltaY = 0;
this.timer;
this.eventFunction = func;
}
set maxPause(pauseTime) {
this.maxAllowedPause = pauseTime;
}
eventIn(e) {
var elapsed = Date.now() - this.last;
this.last = Date.now();
if ((this.cummulativeDeltaY === 0) || (elapsed < this.maxAllowedPause)) {
// Either a new action, or continuing a previous action with little
// time since the last movement
this.cummulativeDeltaY += e.originalEvent.deltaY;
if (this.timer !== undefined) clearTimeout(this.timer);
this.timer = setTimeout(this.fireAggregateEvent.bind(this),
this.maxAllowedPause);
} else {
// just in case some long-running process makes things happen out of
// order
this.fireAggregateEvent();
}
}
fireAggregateEvent() {
// Clean up and pass the delta to the callback
if (this.timer !== undefined) clearTimeout(this.timer);
var newDeltaY = this.cummulativeDeltaY;
this.cummulativeDeltaY = 0;
this.timer = undefined;
// Use a local variable during the call, so that class properties can
// be reset before the call. In case there's an error.
this.eventFunction(newDeltaY);
}
}
// Create a new MouseWheelAggregater object and pass in the callback function,
// to call each time a continuous action is complete.
// In this case, just log the net movement to the console.
var mwa = new MouseWheelAggregater((deltaY) => {
console.log(deltaY);
});
// Each time a mouse wheel event is fired, pass it into the class.
$(function () {
$("#wheelTestDiv").on('wheel', (e) => mwa.eventIn(e));
});
Web page ...
<!DOCTYPE html>
<html>
<head>
<title>Mouse over test</title>
<script src="/mouseWheelEventManager.js"></script>
</head>
<body>
<div id="wheelTestDiv" style="margin: 50px;">Wheel over here</div>
</body>
</html>
Have you tried breaking this out into functions with a flag to check if an interaction has occurred?
For example:
// Create a global variable which will keep track of userInteraction
let shouldScroll = true;
// add the event listener, and call the function when triggered
window.addEventListener('wheel', () => myFunction());
//Create a trigger function, checking if shouldScroll is true or false.
myFunction(){
shouldScroll ? (
if (deltaY > 0) scrollDown();
else if (deltaY < 0) scrollUp();
// Change back to false to prevent further scrolling.
shouldScroll = false;
) : return;
}
/* call this function when user interaction occurs
and you want to allow scrolling function again.. */
userInteraction(){
// set to true to allow scrolling
shouldScroll = true;
}
We can avoid such a situation by delay execution and removing the events in between the delay, refer below example and have added 1000ms as delay which can be modified based on your requirements.
let scrollPage = (deltaY)=>{
console.log(deltaY);
if (deltaY > 0) scrollDown();
else if (deltaY < 0) scrollUp();
};
var delayReg;
window.addEventListener('wheel', ({ deltaY }) => {
clearTimeout(delayReg);
delayReg = setTimeout(scrollPage.bind(deltaY),1000);
});

how to get activePointer pressed duration of sprite in Phaser

I'm creating pinball game using Phaser Framework.
When the ball holder is pressed (please check attached screenshot so you have an idea what I mean ball holder), depending on the press speed, it should move the ball around the spiral channel. So now trying to detect the down pressed duration of the holder.
Here is my code:
var ballButton;
ballButton = game.add.sprite(196, 100, 'ballHolder');
ballButton.inputEnabled = true;
ballButton.events.onInputDown.add(inputDownAction, this);
function inputDownAction(ballButton, pointer) {
/* returns 0 */
console.log( pointer.duration);
}
So pointer.duration is not working and returns 0.
But game.input.activePointer.duration inside update() function is working and returns duration.
if (game.input.activePointer.duration > 200 && game.input.activePointer.duration < 500){
console.log('first range '+game.input.activePointer.duration);
}else if(game.input.activePointer.duration > 500 && game.input.activePointer.duration < 700){
console.log('second range '+game.input.activePointer.duration);
}else if(game.input.activePointer.duration > 700){
console.log('third range '+game.input.activePointer.duration);
}
How can I make it work for specific item/sprite? Any ideas please?
in phaser 3 something like
function update(){
var duration = 0
if( this.input.activePointer.isDown ){
duration++;
}
}
You can get the time from the scene and calculate it with the downTime from the activePointer. So, you can try this approach:
function update(time, delta){
console.log(time - window.game.input.activePointer.downTime);
}
I came to the conclusion that this is the best approach when you want to get the duration on press down key because there is not duration attribute in activePointer anymore(Phaser3). So, this code works on Phaser 3 as well.
I hope it helps!

Javascript animation flickering when run multiple times

So this is my first attempt at playing with JS animations. I just modified a simple tutorial to create a border that fades out when you click an element. It works perfectly the first time but every subsequent click it flickers and acts strangely. I can't work out what the issue is.
function move(elem) {
var left = 1
function frame() {
left = left - 0.1 // update parameters
elem.style.border = '6px solid rgba(48, 28, 237, '+left+')';
if (left == 0) // check finish condition
clearInterval(id)
}
var id = setInterval(frame, 100) // draw every 10ms
}
HTML:
<div onclick="move(this)" class="example_path"></div>
Codepen - http://codepen.io/anon/pen/jqrwoo
javascript count float number is inaccuracy,
for example:
console.log(0.1+0.2);
not 0.3,is 0.30000000000000004,
so...
"left = left - 0.1" forever not equal to "0"
should be
"if(left == 0)"
modification
"if(left <= 0)"
I`m sorry my English is not good,express dimness.
Your interval is not clearing. Try this (if) condition:
if (left <= 0) { // check finish condition
clearInterval(id)
// alert("cleared")
}

detecting collision between two images in jquery

i have this game :http://jsfiddle.net/Qfe6L/5/
i am trying to detect when a shuriken hit an enemy so when it hit it the enemy should disappear and the score should be increased by 1 what i searched for is that i should calculate the position of the two images to check whether their is a collision but i don't seem i can do that any help from you guys ?
$(window).keypress(function (e) {
if (e.which == 32) {
CreateChuriken();
$("#Shuriken" + Shurikengid).animate({ left: '+=300px' }, 'slow');
if ($(".Shuriken").css('left') == $(".Enemy").css('left'))
{ alert("Met"); }
}
});
You need to check for collision in each animation step. Fortunately jQuery .animate() has a progress option, which you can pass a function to be called every frame.
$("#Shuriken" + Shurikengid).animate(
{ left: '+=300px' },
{ duration : 'slow',
progress: function(){
/* collision detection here */
}
}
);
Keep in mind that
if ($(".Shuriken").css('left') == $(".Enemy").css('left'))
will only compare position of first projectile and first enemy, while there are more of them on the screen. You need to iterate over every projectile and compare its powition with every enemy to find a colliding pair, like:
$('.Shuriken').each( function(){
var sOffset = $(this).offset();
$('.Enemy').each( function(){
var eOffset = $(this).offset();
if( sOffset.left == eOffset.left ){
/* boom! */
}
});
});
The above is close, but still won't work. Animation doesn't progress by 1px each frame, so you may go from Shuriken at 100px left and Enemy at 101px left at one frame to Shuriken at 102px left and Enemy at 99px left in the next one. They'll pass each other, but won't meet at the same point. So you'd need to round these values to, say, nearest 10s which will give you a bigger tolerance. You sholud also compare the vertical positions.
Updated fiddle: http://jsfiddle.net/Qfe6L/8/
(Fixed vertical posiotion of Enemies for easier testing).
Edit:
as suggested by #Kasyx it would be better to move all of this out of animation function and create a Game Loop and Scene Graph. Scene graph would keep track of elements' positions, and within Game Loop you'd check for collisions, then call a rendering function which would draw elements on screen based on the scene graph.
At the moment you’re running your hit check function once, directly after you’ve started the animation. What you need to be doing is running it every frame to see the intersect. Luckily jQuery provides a callback handler for this: $.animate’s step option. If you pass a second object into $.animate you can specify both your duration and step function like so:
$(window).keypress(function (e) {
if (e.which == 32) {
CreateChuriken();
$("#Shuriken" + Shurikengid).animate({
left: '+=300px'
}, {
duration: 'slow',
step: function(){
if ($(".Shuriken").css('left') == $(".Enemy").css('left')) {
alert("Met");
}
}
});
}
});
As you’re calling your step function once every frame you’ll want to cache your selectors inside ($('.Shuriken'), $('.Enemy')) first:
$(window).keypress(function (e) {
if (e.which == 32) {
var shuriken, enemy;
CreateChuriken();
shuriken = $('.Shuriken');
enemy = $('.Enemy');
$("#Shuriken" + Shurikengid).animate({
left: '+=300px'
}, {
duration: 'slow',
step: function(){
if (shuriken.css('left') == enemy.css('left')) {
alert("Met");
}
}
});
}
});

Youtube player API and jQuery slider

I am using the YouTube API to get the current elapsed time of a video: player.getCurrentTime(); and the player.getDuration(); functions; I have set a slider in jQuery that will have the max value set to player.getDuration and the min to 0;
Using those two functions I have built the following piece of code:
var progress = setInterval(function(){
$("#progressbar").slider({value: Math.floor(player.getCurrentTime())});
},1000);
that will update a slider with the elapsed time of the Youtube video.
The problem is that when I pause the video, the value of the slider flickers between an earlier value, and the current elapsed time (player.getCurrentTime()) value.
Can someone explain?
EDIT: here is the proper code that updates the slider on player play state and stops the update function on player pause state:
function playerStateChange(newState) {
globalYtState = newState;
if(newState == 0){
$("#hSongSearcher").val('').trigger('keyup');
setTimeout(playNextVideo(),1500);
}
if(newState == 2){
clearInterval(progressUpdater);
}
if(newState == 1){
progressUpdater = setInterval(function(){
//console.log(Math.floor(player.getCurrentTime()));
if(Math.floor($("#progressbar").slider('value')) != Math.floor(player.getCurrentTime())){
$("#progressbar").slider({value: Math.floor(player.getCurrentTime())});
}
$('.current_elapsed').html(getPropperDuration(Math.floor(player.getCurrentTime())));
},1000);
}
}
So, this may help anyone else. I have found out that when running this piece of code:
$("progressbar").on('slidechange',function(event,ui) { ...
it seems that the ui.value flickers in my example between the current getCurrentTime() value and a maybe random value? ( I don't know exactly from where that value is! but I know a good workaround that will fix that);
SO I have made a var that holds the player current time on each second, and just pass by that random flickering value of the slider as follows:
if(newState == 1){
progressUpdater = setInterval(function(){
ctime = Math.floor(player.getCurrentTime());
$("#progressbar").slider("value", ctime);
//Here starts the flickering fix
$("#progressbar").on('slidechange',function(event,ui){
//Fix Flcikering;
if(ui.value < ctime){
$("#progressbar").slider("value", ctime);
}
});
//And here it ends.
$('.current_elapsed').html(getPropperDuration(Math.floor(player.getCurrentTime())));
},1000);
}

Categories

Resources