object adds velocity instead of maintaining in opposite direct - javascript

I have a group of objects i want to rotate , there is a button which should onclick change from left to right and a stop button which should stop the current group position at its current location , however every time i click rotate , it changes direction but increases in speed even though it is bound to a slider, ive tried calling the animation frame last and cancelling it on each call but nothing works
var speedslider = document.getElementById("speedinput");
var direction = true;
var stopped = true;
speedslider.addEventListener("change",DirectionBTN.onclick);
zoomOutButton.addEventListener("change", zoomOutFunction);
speedslider.addEventListener("change",StopStartBTN.onclick);
//rotation of group
const rotateGroup = function()
{
if(stopped == true){
group.rotation.y =!group.rotation.y
}
if(direction == true){
group.rotation.y += speedslider.value/1000;
requestAnimationFrame(rotateGroup)
}
if(direction == false){
group.rotation.y -= speedslider.value/1000;
requestAnimationFrame(rotateGroup)
}
};
//start rotation left
StopStartBTN.onclick = function() {
stopped = !stopped
rotateGroup()
};
DirectionBTN.onclick = function() {
direction = !direction;
rotateGroup();
};

Related

Stop a running loop/function when another is called and reset to 0

I have a render rotating , the rotating is done by constant changing the y position
i have 2 buttons , 1 for rotate left and 1 for rotate right and a slider to indicate rotation speed -
my problem is once ive pressed one button it keeps the function running , i need to stop the function when the opposite function is called and vice versa
<button id="LeftBTN" type="button">Rotate Left</button>
<button id="RightBTN" type="button">Rotate Right</button>
>
<input class="bar" type="range" id="speedinput" min="0" max="100" value="0" onchange="speed.value=value"/>
<span class="highlight"></span>
<output id="speed">0</output>
var speedslider = document.getElementById("speedinput");
speedslider.addEventListener("change",LeftBTN.onclick);
speedslider.addEventListener("change",RightBTN.onclick);
zoomOutButton.addEventListener("change", zoomOutFunction);
//set rotation functions
const rotategroupright = function() {
requestAnimationFrame(rotategroupright);
group.rotation.y -= 0;
group.rotation.y += speedslider.value/10000;
console.log(group.rotation.y)
};
const rotategroupleft = function() {
requestAnimationFrame(rotategroupleft);
group.rotation.y +=0;
group.rotation.y -= speedslider.value/10000;
console.log(group.rotation.y)
};
//start rotation left
LeftBTN.onclick = function() {
speedslider.value = 0;
speed.value = [0];
rotategroupleft();
};
//start rotation right
RightBTN.onclick = function() {
speedslider.value = 0;
speed.value = [0];
rotategroupright();
};
how about trying something like the following? Instead of having two different functions for left vs right, combine them into a single function called rotateGroup() and use a conditional statement to control the direction of rotation. This requires a "direction" variable outside of the functions so they can access it.
Then all you have to do is change the onclick handlers to set the value of the direction variable. To kick off the animation, you could just call rotateGroup() on page load, or as I did in this example, start the animation on the first button press and use another if statement to prevent the buttons from calling rotateGroup() more than once.
If that isn't what you want, look up cancelAnimationFrame(). If you assign a global id to requestAnimationFrame(), you will be able to call cancelAnimationFrame(idGoesHere) to stop the animation. I'm not sure which method is better, but this might be closer to the answer you were asking for.
More info on cancelAnimationFrame() on developer.mozilla.org
Below is an example of the first suggestion. Let me know if this helps, or if something is broken. Otherwise, happy animating. Cheers!
var direction = "";
var stopped = true;
const rotateGroup = function() {
if(direction == "left"){
group.rotation.y +=0;
group.rotation.y -= speedslider.value/10000;
}else {
group.rotation.y -= 0;
group.rotation.y += speedslider.value/10000;
}
console.log(group.rotation.y);
requestAnimationFrame(rotateGroup);
};
//start rotation left
LeftBTN.onclick = function() {
speedslider.value = 0;
speed.value = [0];
direction = "left";
if(stopped){
stopped = false;
rotateGroup();
}
};
//start rotation right
RightBTN.onclick = function() {
speedslider.value = 0;
speed.value = [0];
direction = "right";
if(stopped){
stopped = false;
rotateGroup();
}
};

Sidescrolling jittery when changing directions

I made my own sidescrolling parallax using jQuery and the mousewheel plugin. It's working great so far except for the fact that when I change directions of the scroll, it jitters first before actually scrolling (as though it's scrolling one unit to the previous side before actually moving to the correct one). I've tried adding a handler for this which supposedly stops the scroll completely.
Here is my script so far:
var scroll = 0; // Where the page is supposed to be
var curr = scroll; // The current location while scrolling
var isScrolling = false; // Tracker to check if scrolling
var previous = 0; // Tracks which direction it was previously
var loop // setInterval variable
function parallax() {
isScrolling = true;
// Loops until it's where it's supposed to be
loop = setInterval(() => {
if ( curr - scroll == 0 ) {
clearInterval(loop);
isScrolling = false;
return;
}
// Move the individual layers
$('.layer').each(function() {
$(this).css('left', -curr * $(this).data("speed"));
});
// Add/subtract to current to get closer to where it's supposed to be
curr += (scroll < curr) ? -0.5 : 0.5;
}, 25);
}
$(document).ready(() => {
$('.scrolling-container').mousewheel((e, dir) => {
e.preventDefault();
// If the speed's magnitude is greater than 1, revert it back to 1
if ( Math.abs(dir) > 1) {
dir = Math.sign(dir);
}
// If the direction changes, stop the current animation then set scroll to where it currently is
if ( previous !== dir ) {
previous = dir;
isScrolling = false;
scroll = curr;
clearInterval(loop);
}
// If not at the left most scrolling to the left, add to scroll
if ( scroll - dir >= 0 ) scroll -= dir;
// Call parallax function if it's not yet running
if ( !isScrolling ) {
parallax();
}
})
})
I think it's easier to show so here's a codepen of the functional parts: https://codepen.io/ulyzses/pen/yLyoYZm
Try scrolling for a while then change direction, the jittery behaviour should be noticeable.

Make a character move upwards on click

I am making a game similar to Flappy Bird. The character is supposed to move upwards when the browser window is clicked, but my code for this does not work. Here are the relevant lines of code:
var dudeYSpeed = 0;
var dudeXSpeed = 0;
var dudeJumping = false;
var jumpSpeed = -3;
if (mouseDown && dudeJumping === false){
dudeJumping = true;
dudeYSpeed = jumpSpeed;
}
else {
translateY += dudeYSpeed;
dudeYSpeed += gravity;
dudeJumping = false;
}
translateX += dudeXSpeed;
You only update translateY and dudeYSpeed if dudeJumping is true. You should update these variables in every frame, no matter what the input was.

Touch Events not registering for HTML5 Canvas Authoring using Flash CC

I have been having some issues when it comes to authoring HTML 5 Canvas in Flash CC, mostly as a result of the lack of information on writing JavaScript inside Flash.
I have been converting an existing drag and drop .fla into HTML 5 with the hope of making it iOS and Android compatible. It is already functioning with mouse, but I have hit a brick wall on trying to add touch support.
The only way I have been able to even register the touch events is by listening to the entire window, which isn't very useful when I have multiple pieces that I want to move around.
This is what I have so far, all this code is located on the first frame of the main Scene Timeline, and the scene is composed of 5 pieces and 5 targets for those pieces, as well as a pop up task completed box and a reset button.
this.stop();
MainStage = this;//Declare
//*********************
//Actual Drag and Dropping
// Initialize:
var numPieces = 5;//<---------------Place number of pieces HERE---------------
var homePosX = [];
var homePosY = [];
var correctAns = 0;
var isClickableAry = [];
var whoAmI = [];//Declared "Globally" so that I can identify which piece is being grabbed later
for (var i = 0; i < numPieces; i++)
{
var pieceName = "p" + (i + 1);
var piece = this[pieceName];
//This sets the starting position for each piece
homePosX[i+1] = piece.x;//(i+1) is so that Piece names line up with Target names and MC names
homePosY[i+1] = piece.y;
whoAmI[i] = piece;
isClickableAry[i] = 1;//Makes it so each pieces is set as clickable
if( piece ){
piece.name = pieceName;
piece.on("mousedown" || "touchstart", function(evt)
{
evt.preventDefault();
//Debug
console.log(checkPiece(this));
//Rather than adding and removing event listeners, just check to see if piece is clickable
if(isClickableAry[checkPiece(this)] == 1){
this.parent.addChild(this);// Bump to top
this.offset = {x:this.x - evt.stageX, y:this.y - evt.stageY};
//Debug
console.log(piece + "PICKED UP, X " + piece.x + ", Y " + piece.y + " is Clickable? ");
//Set Home Coordinates (Where it was picked up)
homeX = this.x;
homeY = this.y;
}
});
piece.on("touchmove",function(evt)
{
console.log("touch moved! " + touchobj);
evt.preventDefault();
});
piece.on("pressmove", function(evt)
{
if(isClickableAry[checkPiece(this)] == 1){
this.x = evt.stageX + this.offset.x;
this.y = evt.stageY + this.offset.y;
//Mouse Cursor change
document.body.style.cursor='move';
}
});
piece.on("pressup" || "touchend" || "touchcancel", function(evt)
{
var target = this.parent["t"+this.name.substr(1)];
//Reset Cursor
document.body.style.cursor='auto';
if( target && hitTestInRange( target, 60) && isClickableAry[checkPiece(this)] == 1 ){
this.x = target.x;
this.y = target.y;
//If it is correct add one
correctAns++;
//Make that button Unclickable
isClickableAry[checkPiece(this)] = 0;
if(correctAns >= numPieces){
//If they have answered correctly equal to the the number of pieces
MainStage.complete_mc.parent.addChild(MainStage.complete_mc);//Bump to top
MainStage.complete_mc.gotoAndStop(1);
//reset answer counter and make drag pieces and buttons unclickable
correctAns = 0;
//Debug
console.log(correctAns + "CORRECT!";)
}
}else{
//Return to home Coordinates (Where it was on intialization)
if(isClickableAry[checkPiece(this)] == 1){
this.x = homePosX[checkPiece(this)+1];
this.y = homePosY[checkPiece(this)+1];
}
}
});
piece.on("mouseover", function(evt)
{
if(isClickableAry[checkPiece(this)] == 1){
//Makes cursor a pointer finger
document.body.style.cursor='pointer';
}
});
piece.on('mouseout',function(evt)
{
//sets cursor back to normal
document.body.style.cursor='auto';
});
}
}
function hitTestInRange( target, range )
{
if( target.x > stage.mouseX - range &&
target.x < stage.mouseX + range &&
target.y > stage.mouseY - range &&
target.y < stage.mouseY + range )
{
return true;
}
return false;
}
//Check which piece it is
function checkPiece(checkName)
{
for (var i = 0; i < numPieces; i++)
{
if (checkName == whoAmI[i]){
return i;
}
}
}
//Reset Functionality
this.complete_mc.reset_btn.addEventListener("click", resetPos.bind(this));
function resetPos(){
for (var i = 0; i < numPieces; i++)
{
var pieceName = "p" + (i + 1);
var piece = this[pieceName];
correctAns = 0;
//Makes Pieces Grabable again
isClickableAry[i] = 1;
//This returns each piece to their Original Starting Positions
piece.x = homePosX[i+1];
piece.y = homePosY[i+1];
}
}
//Controlling the Pop Up Window, window pops up when user answers everything correctly
this.complete_mc.exitComplete_btn.addEventListener("click", closePopUp.bind(this));
this.complete_mc.exitComplete_btn_alt. addEventListener("click", closePopUp.bind(this));
function closePopUp(){
MainStage.complete_mc.gotoAndStop(0);
}
In my own troubleshooting with other problems that have come up generally the issue has to do with scope of either functions or variables, since when flash exports the files it generates its own .js file and turns all of your movie clips into code and separates the code that you have written by whichever frame you wrote it on.
Any help at all would be appreciated.
EDIT: After a bit more research I think the problem might have something to do with touch events only being able to target separate elements? So it isn't able to grab objects inside the canvas element just the canvas element itself?
Turns out that adding touch support is incredibly easy. All I was missing was one line of code
createjs.Touch.enable(stage);
this makes all the touch events respond as mouse events. and fixed all my issues.

Keydown producing unexpected result. HTML5 Game

So I am at the very beginning stages of creating my first platform style game in html5.So far I have only implemented left and right movement and no 'gravity' or collision detection is at play.
However, I've already hit an issue.
If you go left or right for a short period of time the 'character' acts as intended (I use character loosely as it's the map that is actually moving). If, however, you hold the key down the map moves too fast.
I figure the issue is that the keydown event listener is listening all of the time, there for moving the map is moving before each tick or frame of the game.
So my question is how can I make the keydown increase the map offset only on every tick of the game (20 milliseconds).
Here is my JSFiddle: CLICK HERE
document.addEventListener('keydown',function(event){
var dir = event.which;
if(dir == directions.LEFT){
mapOffsetX += mapOffsetDistanceX;
event.preventDefault();
};
if(dir == directions.RIGHT){
mapOffsetX -= mapOffsetDistanceX;
event.preventDefault();
};
});
document.addEventListener('keyup',function(event){
var dir = event.which;
if(dir == directions.LEFT){
mapOffsetX -= mapOffsetDistanceX;
};
if(dir == directions.RIGHT){
mapOffsetX += mapOffsetDistanceX;
};
});
initFloorObject(100,c.height/2,300,20,0,0,0,1);
var myInt = setInterval(function(){
clearScreen();
for(var i=0;i<floorObject.length;i++){
floorObject[i][0] = parseInt(floorObject[i][0])+mapOffsetX;
};
drawChar();
drawFloorObjects();
},20);
Set variable to false every time you keydown and set it back to true every 20 milliseconds.
var isKeydownAvailable = true;
document.addEventListener('keydown', function (event) {
var dir = event.which;
if(isKeydownAvailable){
if (dir == directions.LEFT) {
mapOffsetX += mapOffsetDistanceX;
event.preventDefault();
};
if (dir == directions.RIGHT) {
mapOffsetX -= mapOffsetDistanceX;
event.preventDefault();
};
isKeydownAvailable = false;
};
});
In the interval, reset the isKeydownAvailable to true.
var myInt = setInterval(function () {
clearScreen();
for (var i = 0; i < floorObject.length; i++) {
floorObject[i][0] = parseInt(floorObject[i][0]) + mapOffsetX;
};
drawChar();
drawFloorObjects();
isKeydownAvailable = true;
}, 20);
Use booleans for actions and check for them inside your interval.
On keydown you set the boolean isMovingLeft to true, then you add the offset in your interval function only if(isMovingLeft).
Do that for the other actions and you are good to go.

Categories

Resources