I'm trying to shake an html element for my game.
I found this code here:
shake = function (sprite, magnitude = 16, angular = false) {
//A counter to count the number of shakes
var counter = 1;
//The total number of shakes (there will be 1 shake per frame)
var numberOfShakes = 10;
//Capture the sprite's position and angle so you can
//restore them after the shaking has finished
var startX = sprite.x,
startY = sprite.y,
startAngle = sprite.rotation;
// Divide the magnitude into 10 units so that you can
// reduce the amount of shake by 10 percent each frame
var magnitudeUnit = magnitude / numberOfShakes;
//The `randomInt` helper function
var randomInt = (min, max) => {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
//Add the sprite to the `shakingSprites` array if it
//isn't already there
if(shakingSprites.indexOf(sprite) === -1) {
//console.log("added")
shakingSprites.push(sprite);
//Add an `updateShake` method to the sprite.
//The `updateShake` method will be called each frame
//in the game loop. The shake effect type can be either
//up and down (x/y shaking) or angular (rotational shaking).
sprite.updateShake = () => {
if(angular) {
angularShake();
} else {
upAndDownShake();
}
};
}
//The `upAndDownShake` function
function upAndDownShake() {
//Shake the sprite while the `counter` is less than
//the `numberOfShakes`
if (counter < numberOfShakes) {
//Reset the sprite's position at the start of each shake
sprite.x = startX;
sprite.y = startY;
//Reduce the magnitude
magnitude -= magnitudeUnit;
//Randomly change the sprite's position
sprite.x += randomInt(-magnitude, magnitude);
sprite.y += randomInt(-magnitude, magnitude);
//Add 1 to the counter
counter += 1;
}
//When the shaking is finished, restore the sprite to its original
//position and remove it from the `shakingSprites` array
if (counter >= numberOfShakes) {
sprite.x = startX;
sprite.y = startY;
shakingSprites.splice(shakingSprites.indexOf(sprite), 1);
}
}
//The `angularShake` function
//First set the initial tilt angle to the right (+1)
var tiltAngle = 1;
function angularShake() {
if (counter < numberOfShakes) {
//Reset the sprite's rotation
sprite.rotation = startAngle;
//Reduce the magnitude
magnitude -= magnitudeUnit;
//Rotate the sprite left or right, depending on the direction,
//by an amount in radians that matches the magnitude
sprite.rotation = magnitude * tiltAngle;
counter += 1;
//Reverse the tilt angle so that the sprite is tilted
//in the opposite direction for the next shake
tiltAngle *= -1;
}
//When the shaking is finished, reset the sprite's angle and
//remove it from the `shakingSprites` array
if (counter >= numberOfShakes) {
sprite.rotation = startAngle;
shakingSprites.splice(shakingSprites.indexOf(sprite), 1);
//console.log("removed")
}
}
}
However it only works for canvas sprites. How can I get it to work with HTML elements? Thanks.
You can use css animation like this example
#-webkit-keyframes shake {
0% { -webkit-transform: translate(2px, 1px) rotate(0deg); }
10% { -webkit-transform: translate(-1px, -2px) rotate(-1deg); }
20% { -webkit-transform: translate(-3px, 0px) rotate(1deg); }
30% { -webkit-transform: translate(0px, 2px) rotate(0deg); }
40% { -webkit-transform: translate(1px, -1px) rotate(1deg); }
50% { -webkit-transform: translate(-1px, 2px) rotate(-1deg); }
60% { -webkit-transform: translate(-3px, 1px) rotate(0deg); }
70% { -webkit-transform: translate(2px, 1px) rotate(-1deg); }
80% { -webkit-transform: translate(-1px, -1px) rotate(1deg); }
90% { -webkit-transform: translate(2px, 2px) rotate(0deg); }
100% { -webkit-transform: translate(1px, -2px) rotate(-1deg); }
}
.shake:hover {
-webkit-animation-name: shake;
-webkit-animation-duration: 0.5s;
-webkit-transform-origin:50% 50%;
-webkit-animation-iteration-count: infinite;
}
.shake {
display:inline-block
}
<div class="shake">Shake me</div>
<img class="shake" src="https://www.w3.org/2008/site/images/logo-w3c-screen-lg" />
To change speed of shaking, change values of animation-duration, translate(), rotate().
If you want to shake element using javascript see jsfiddle
I have adapted your function so that it works on DOM elements. It is a pretty hefty shake though, you might want to play with the parameters to damped it a little bit:
var shakingElements = [];
var shake = function (element, magnitude = 16, angular = false) {
//First set the initial tilt angle to the right (+1)
var tiltAngle = 1;
//A counter to count the number of shakes
var counter = 1;
//The total number of shakes (there will be 1 shake per frame)
var numberOfShakes = 15;
//Capture the element's position and angle so you can
//restore them after the shaking has finished
var startX = 0,
startY = 0,
startAngle = 0;
// Divide the magnitude into 10 units so that you can
// reduce the amount of shake by 10 percent each frame
var magnitudeUnit = magnitude / numberOfShakes;
//The `randomInt` helper function
var randomInt = (min, max) => {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
//Add the element to the `shakingElements` array if it
//isn't already there
if(shakingElements.indexOf(element) === -1) {
//console.log("added")
shakingElements.push(element);
//Add an `updateShake` method to the element.
//The `updateShake` method will be called each frame
//in the game loop. The shake effect type can be either
//up and down (x/y shaking) or angular (rotational shaking).
if(angular) {
angularShake();
} else {
upAndDownShake();
}
}
//The `upAndDownShake` function
function upAndDownShake() {
//Shake the element while the `counter` is less than
//the `numberOfShakes`
if (counter < numberOfShakes) {
//Reset the element's position at the start of each shake
element.style.transform = 'translate(' + startX + 'px, ' + startY + 'px)';
//Reduce the magnitude
magnitude -= magnitudeUnit;
//Randomly change the element's position
var randomX = randomInt(-magnitude, magnitude);
var randomY = randomInt(-magnitude, magnitude);
element.style.transform = 'translate(' + randomX + 'px, ' + randomY + 'px)';
//Add 1 to the counter
counter += 1;
requestAnimationFrame(upAndDownShake);
}
//When the shaking is finished, restore the element to its original
//position and remove it from the `shakingElements` array
if (counter >= numberOfShakes) {
element.style.transform = 'translate(' + startX + ', ' + startY + ')';
shakingElements.splice(shakingElements.indexOf(element), 1);
}
}
//The `angularShake` function
function angularShake() {
if (counter < numberOfShakes) {
console.log(tiltAngle);
//Reset the element's rotation
element.style.transform = 'rotate(' + startAngle + 'deg)';
//Reduce the magnitude
magnitude -= magnitudeUnit;
//Rotate the element left or right, depending on the direction,
//by an amount in radians that matches the magnitude
var angle = Number(magnitude * tiltAngle).toFixed(2);
console.log(angle);
element.style.transform = 'rotate(' + angle + 'deg)';
counter += 1;
//Reverse the tilt angle so that the element is tilted
//in the opposite direction for the next shake
tiltAngle *= -1;
requestAnimationFrame(angularShake);
}
//When the shaking is finished, reset the element's angle and
//remove it from the `shakingElements` array
if (counter >= numberOfShakes) {
element.style.transform = 'rotate(' + startAngle + 'deg)';
shakingElements.splice(shakingElements.indexOf(element), 1);
//console.log("removed")
}
}
};
DEMO
Have a look at the demo in the fiddle. The red block is the regular upAndDownShake, whereas the green one uses angularShake:
https://jsfiddle.net/12aueufy/1/
Maybe you should take a look in Animate.css, https://daneden.github.io/animate.css/, this is a css library that provides a lot of animations, including a shake one... I hope that this might work for your problem!
function shake(e, oncomplete, distance, time) {
var time = 500;
var distance = 5;
var start = (new Date()).getTime();
animate();
function animate() {
var now = (new Date()).getTime();
// Get current time
var elapsed = now - start;
// How long since we started
var fraction = elapsed / time;
// What fraction of total time?
if (fraction < 1) {
var x = distance * Math.sin(fraction * 4 * Math.PI);
e.style.left = x + "px";
// We're aiming for a smooth 40 frames/second animation.
setTimeout(animate, Math.min(25, time - elapsed));
} else {
// Otherwise, the animation is complete
if (oncomplete) oncomplete(e);
// Invoke completion callback
}
}
}
function shakeme(event1) {
shake(event1.target);
}
document.getElementById("wood").addEventListener("mouseover", shakeme, false);
HTML Element
<button id="wood">Hello World</button>
Source
http://javascriipt.blogspot.com/2015/02/how-to-mimic-shake-animation-effect.html
You could use some library for javascript animations like Velocity
It's really flexible and easy to use.
Please check this working sample, I'm pretty sure that you can create wished effect in minutes
Hope it help
It's possible to have the animation done entirely with very simple CSS and JS. The strategy involves two things:
transition: all 500ms; — This bit of CSS means that anytime we want to do a transition (i.e., animation), that transition will complete in 500ms.
transform(rotate) — Then every CSS change takes place in 500ms, so, we can shake the icon with margin-left and margin-right, or, we can use transform(rotate), let's try the latter!
Note: You can use any type of CSS effect here, try experimenting with something else! I'm curious if there's anything better than transform(rotate).
Demo
const wiggletime = 100;
function rotateElement(el) {
el.classList.add('rotateable');
el.style.transform = 'rotate(20deg)';
setTimeout(function() {
el.style.transform = 'rotate(-20deg)';
setTimeout(function() {
el.style.transform = 'rotate(0deg)';
}, wiggletime);
}, wiggletime);
return true;
}
function squishElement(el) {
el.classList.add('rotateable');
el.style.transform = 'scaleX(1.5)';
setTimeout(function() {
el.style.transform = 'scaleX(0.5)';
setTimeout(function() {
el.style.transform = 'scaleX(1)';
}, wiggletime);
}, wiggletime);
return true;
}
function shakeElement(el) {
el.classList.add('rotateable');
el.style.marginLeft = '20px';
setTimeout(function() {
el.style.marginLeft = '-20px';
setTimeout(function() {
el.style.marginLeft = '0px';
}, wiggletime);
}, wiggletime);
return true;
}
function skewElement(el) {
el.classList.add('rotateable');
el.style.transform = 'skewX(20deg)';
setTimeout(function() {
el.style.transform = 'skewX(-20deg)';
setTimeout(function() {
el.style.transform = 'skewX(0deg)';
}, wiggletime);
}, wiggletime);
return true;
}
function borderElement(el) {
el.classList.add('rotateable');
el.style.border = '4px solid black';
el.style.marginLeft = '-4px';
el.style.marginTop = '-4px';
setTimeout(function() {
el.style.border = '2px solid black';
el.style.marginLeft = '-2px';
el.style.marginTop = '-2px';
setTimeout(function() {
el.style.border = '1px solid black';
el.style.marginLeft = '0px';
el.style.marginTop = '0px';
}, wiggletime);
}, wiggletime);
return true;
}
document.getElementById('rotate-me').addEventListener('click', function(ev) {
rotateElement(this);
});
document.getElementById('shake-me').addEventListener('click', function(ev) {
shakeElement(this);
});
document.getElementById('squish-me').addEventListener('click', function(ev) {
squishElement(this);
});
document.getElementById('skew-me').addEventListener('click', function(ev) {
skewElement(this);
});
document.getElementById('border-me').addEventListener('click', function(ev) {
borderElement(this);
});
.rotateable {
transition: all 100ms;
}
<button id="shake-me">Shake Me!</button>
<br><br>
<button id="rotate-me">Rotate Me!</button>
<br><br>
<button id="squish-me">Squish Me!</button>
<br><br>
<button id="skew-me">Skew Me!</button>
<br><br>
<button id="border-me" style="position:absolute;">Border Me!</button>
Demo - Extended
Why not extended animations?
const wiggletime = 100;
function rotateElement(el) {
el.classList.add('rotateable');
el.style.transform = 'rotate(20deg)';
setTimeout(function() {
el.style.transform = 'rotate(-20deg)';
setTimeout(function() {
el.style.transform = 'rotate(10deg)';
setTimeout(function() {
el.style.transform = 'rotate(-10deg)';
setTimeout(function() {
el.style.transform = 'rotate(0deg)';
}, wiggletime);
}, wiggletime);
}, wiggletime);
}, wiggletime);
return true;
}
function squishElement(el) {
el.classList.add('rotateable');
el.style.transform = 'scaleX(1.5)';
setTimeout(function() {
el.style.transform = 'scaleX(0.5)';
setTimeout(function() {
el.style.transform = 'scaleX(1.25)';
setTimeout(function() {
el.style.transform = 'scaleX(0.75)';
setTimeout(function() {
el.style.transform = 'scaleX(1)';
}, wiggletime);
}, wiggletime);
}, wiggletime);
}, wiggletime);
return true;
}
function skewElement(el) {
el.classList.add('rotateable');
el.style.transform = 'skewX(20deg)';
setTimeout(function() {
el.style.transform = 'skewX(-20deg)';
setTimeout(function() {
el.style.transform = 'skewX(10deg)';
setTimeout(function() {
el.style.transform = 'skewX(-10deg)';
setTimeout(function() {
el.style.transform = 'skewX(0deg)';
}, wiggletime);
}, wiggletime);
}, wiggletime);
}, wiggletime);
return true;
}
function shakeElement(el) {
el.classList.add('rotateable');
el.style.marginLeft = '20px';
setTimeout(function() {
el.style.marginLeft = '-20px';
setTimeout(function() {
el.style.marginLeft = '10px';
setTimeout(function() {
el.style.marginLeft = '-10px';
setTimeout(function() {
el.style.marginLeft = '0px';
}, wiggletime);
}, wiggletime);
}, wiggletime);
}, wiggletime);
return true;
}
document.getElementById('rotate-me').addEventListener('click', function(ev) {
rotateElement(this);
});
document.getElementById('shake-me').addEventListener('click', function(ev) {
shakeElement(this);
});
document.getElementById('squish-me').addEventListener('click', function(ev) {
squishElement(this);
});
document.getElementById('skew-me').addEventListener('click', function(ev) {
skewElement(this);
});
.rotateable {
transition: all 100ms;
}
<button id="shake-me">Shake Me!</button>
<br><br>
<button id="rotate-me">Rotate Me!</button>
<br><br>
<button id="squish-me">Squish Me!</button>
<br><br>
<button id="skew-me">Skew Me!</button>
Related
I'm having quite a bit of trouble with this, and after working tirelessly on it I've decided to just post my problem on here. My boss wants me to figure out a problem with his org-board. The problem arises when the user wants to move from division 6 to division 7--instead of it going anti-clockwise to division 7, it rotates all the way back to division 6 going clockwise. I understand why it's doing this, but I haven't figured out how to make it go anti-clockwise to the next panel without having it rotate all the way back to division 7. I have a CodePen for it, figured it would be easier than posting a ton of code on here: https://codepen.io/jamesaluna/pen/gNRWNJ . If you're not quite sure what I'm trying to exactly do please ask me, thank you!
I tried creating an 'm' variable that calculated the amount of rotations, but that hasn't done much good. I also put the elements in an array and fiddled around with that a bit, using a for/in loop, but I have yet to figure out a solution using that.
var carousel = document.querySelector('.carousel');
var cellCount = 7;
var selectedIndex = 1;
function rotateCarousel() {
var angle = selectedIndex / cellCount * -360;
carousel.style.transform = 'translateZ(-898px) rotateY(' + angle + 'deg)';
}
rotateCarousel();
var sevenButton = document.querySelector('.seven-button');
sevenButton.addEventListener( 'click', function() {
var m = Math.floor(selectedIndex / cellCount);
selectedIndex = m + 1;
if (selectedIndex == 7) {
selectedIndex = 1 ;
}
rotateCarousel();
document.getElementById("demo").innerHTML = m;
document.getElementById("demo2").innerHTML = selectedIndex;
});
var oneButton = document.querySelector('.one-button');
oneButton.addEventListener( 'click', function() {
var m = Math.floor(selectedIndex / cellCount);
selectedIndex = m + 2;
rotateCarousel();
document.getElementById("demo").innerHTML = m;
document.getElementById("demo2").innerHTML = selectedIndex;
});
var twoButton = document.querySelector('.two-button');
twoButton.addEventListener( 'click', function() {
var m = Math.floor(selectedIndex / cellCount);
selectedIndex = m + 3;
rotateCarousel();
document.getElementById("demo").innerHTML = m;
document.getElementById("demo2").innerHTML = selectedIndex;
});
var threeButton = document.querySelector('.three-button');
threeButton.addEventListener( 'click', function() {
var m = Math.floor(selectedIndex / cellCount);
selectedIndex = m + 4;
rotateCarousel();
document.getElementById("demo").innerHTML = m;
document.getElementById("demo2").innerHTML = selectedIndex;
});
var fourButton = document.querySelector('.four-button');
fourButton.addEventListener( 'click', function() {
var m = Math.floor(selectedIndex / cellCount);
selectedIndex = m + 5;
rotateCarousel();
document.getElementById("demo").innerHTML = m;
document.getElementById("demo2").innerHTML = selectedIndex;
});
var fiveButton = document.querySelector('.five-button');
fiveButton.addEventListener( 'click', function() {
var m = Math.floor(selectedIndex / cellCount);
selectedIndex = m + 6;
rotateCarousel();
document.getElementById("demo").innerHTML = m;
document.getElementById("demo2").innerHTML = selectedIndex;
});
var sixButton = document.querySelector('.six-button');
sixButton.addEventListener( 'click', function() {
var m = Math.floor(selectedIndex / cellCount);
selectedIndex = m + 7;
rotateCarousel();
if (selectedIndex == 7) {
selectedIndex = 6 ;
}
document.getElementById("demo").innerHTML = m;
document.getElementById("demo2").innerHTML = selectedIndex;
});
``` CSS
.carousel__cell:nth-child(7n+3) { background: hsla( 360, 100%, 100%, 1); border: 2px solid #B754F7;}
.carousel__cell:nth-child(7n+4) { background: hsla( 360, 100%, 100%, 1);border: 2px solid #FF91FF; }
.carousel__cell:nth-child(7n+5) { background: hsla( 360, 100%, 100%, 1);border: 2px solid #009C00; }
.carousel__cell:nth-child(7n+6) { background: hsla( 360, 100%, 100%, 1);border: 2px solid #999; }
.carousel__cell:nth-child(7n+7) { background: hsla( 360, 100%, 100%, 1);border: 2px solid #FFED8A; }
.carousel__cell:nth-child(7n+1) { background: hsla( 360, 100%, 100%, 1); border: 2px solid #3A43F9; }
.carousel__cell:nth-child(7n+2) { background: hsla( 360, 100%, 100%, 1); border: 2px solid #F4D100; }
.carousel__cell:nth-child(7) { transform: rotateY( 0deg) translateZ(1030px); }
.carousel__cell:nth-child(1) { transform: rotateY( 51.428deg) translateZ(1030px); }
.carousel__cell:nth-child(2) { transform: rotateY(102.856deg) translateZ(1030px); }
.carousel__cell:nth-child(3) { transform: rotateY(154.284deg) translateZ(1030px); }
.carousel__cell:nth-child(4) { transform: rotateY(205.712deg) translateZ(1030px); }
.carousel__cell:nth-child(5) { transform: rotateY(257.14deg) translateZ(1030px); }
.carousel__cell:nth-child(6) { transform: rotateY(308.568deg) translateZ(1030px); }
It has to do with how high your angle of rotation is set and if it is negative or positive. When you get to 6, you have a high angle of rotation, and then to go 'back' to 7, it calculates a heavy rotation value for your angle. It sounds like what you want is to see which angle of rotation is the closest (forward or backwards) and go that direction. That way it won't always go backwards from 6 to 7 and instead go forwards if the ANGLE is closer (rather than the index.
To do that, modify your rotation function with a conditional like so:
function rotateCarousel() {
var angle = selectedIndex / cellCount * -360;
if (angle < -180)
angle = angle % 360;
carousel.style.transform = 'translateZ(-898px) rotateY(' + angle + 'deg)';
}
That way if you're making a rotation that is more than half the full direction, it goes the other way instead. What you desire is to not make a rotation more than 180 deg (esp from 6 to 7, which is 300+ deg) if that makes sense. So we check and go the other direction around the circle instead.
I have been working on a game project for a while and have hit a snag with a particular control. I have decided to change some of the mechanics a bit to deal with this. I had written a chunk of code to make an object rotate with my mouse movement but now I need to make my object rotate on keypress.
I want to make it rotate 45 degrees clockwise when I press the right arrow key, and 45 degrees counter clockwise on left arrow key press. I have the input key call all written up I just need to translate my old code to the new code.
This is my existing code
window.onmouseclick = function(event) {
var box = hypeDocument.getElementById('bolt')
cx = event.pageX; // Mouse X
cy = event.pageY; // Mouse Y
bx = parseInt(hypeDocument.getElementById('group').style.left);
by = parseInt(hypeDocument.getElementById('group').style.top);
tx = hypeDocument.getElementProperty(box, 'left') +
(hypeDocument.getElementProperty(box, 'width')/2) + bx;
ty = hypeDocument.getElementProperty(box, 'top') +
(hypeDocument.getElementProperty(box, 'height')/2) + by;
angle = Math.atan2((cy-ty),(cx-tx)) * (180/Math.PI) ; // AHHHH MATH!
hypeDocument.setElementProperty(box, 'rotateZ', angle)
}
hypeDocument.setElementProperty(box, 'rotateZ', angle) // hype api code for
box.style.webkitTransform = "rotate(" + angle + "deg)";
box.style.mozTransform = "rotate(" + angle + "deg)";
box.style.transform = "rotate(" + angle + "deg)";
This is the code I want to change, as I state in the comment the last line is hype api for the 3 box styles below it to help anybody who reads this understand what that line is.
I'm not sure about the hypedocument markup, but I put this together for you. Can you extract the meaningful parts re: the keycodes to make it work with your project?
window.addEventListener('keyup',function(e) {
var keyCode = e.keyCode,
dir = '',
box = document.getElementById('box');
if (keyCode == 39) {
dir = 'left';
} else if (keyCode == 37) {
dir = 'right';
}
box.setAttribute('data-dir','');
setTimeout(function() {
box.setAttribute('data-dir',dir);
})
})
#box {
width: 100px;
height: 100px;
background: black;
transform: rotate(0);
}
[data-dir="left"] {
animation: left .5s forwards;
}
[data-dir="right"] {
animation: right .5s forwards;
}
#keyframes left {
from {
transform: rotate(0);
}
to {
transform: rotate(90deg);
}
}
#keyframes right {
to {
transform: rotate(-90deg);
}
}
<div id="box"></div>
I have a jQuery function that loops. What I want to do is for the $bird_wing_left element to rotate 30 degrees and then rotate back to 0 degree (in an infinite loop).
$(document).ready(function() {
var rotate = 0;
setInterval(function(){
rotate = 30;
$bird_wing_left.css({ transform: "rotate(" + rotate + "deg)" }).delay(1000).queue(function(){
rotate = 0;
$(this).css({ transform: "rotate(" + rotate + "deg)" });
});
}, 3000);
});
The first time it did rotate 30 degrees, then to 0 degrees, then to 30 degrees. However, afterwards, it seems to ignore the callback (which resets the degree value to 0), hence, it just keeps on being at 30 degrees on and on.
What could be the issue?
This is the jsFiddle: https://jsfiddle.net/iamacatperson/86z26hdw/
When you queue a function, within the function you have to dequeue (or call "next", more below) to allow the queue to continue processing (as shown in the examples). Just add $(this).dequeue() within your queue callback:
var $bird_wing_left = $("#wing");
$(document).ready(function() {
var rotate = 0;
setInterval(function() {
rotate = rotate + 30;
$bird_wing_left.css({
transform: "rotate(" + rotate + "deg)"
}).delay(1000).queue(function() {
rotate = rotate - 30;
$(this).css({
transform: "rotate(" + rotate + "deg)"
}).dequeue(); // <====================
});
}, 3000);
});
body {
padding-top: 2em;
}
<div id="wing" style="width: 10em">Bird wing</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Alternately, since jQuery 1.4 the queue callback has been given an argument (traditionally called next) it can call to keep the queue going:
var $bird_wing_left = $("#wing");
$(document).ready(function() {
var rotate = 0;
setInterval(function() {
rotate = rotate + 30;
$bird_wing_left.css({
transform: "rotate(" + rotate + "deg)"
}).delay(1000).queue(function(next) { // <=====
rotate = rotate - 30;
$(this).css({
transform: "rotate(" + rotate + "deg)"
});
next(); // <=====
});
}, 3000);
});
body {
padding-top: 2em;
}
<div id="wing" style="width: 10em">Bird wing</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Side note: You can use += and -= if you like, e.g. rotate += 30; and rotate -= 30;
Quick fix could be to check rotate variable value before setting it.
if(rotate == 0)
rotate = rotate + 30;
else
rotate = 0;
I am making a top-down racing game using the Phaser framework which uses JS. I am having some trouble getting the car to slow down, at the moment it just stops when no button is pressed. I want it to slow down to stopped. Here is my code so far:
create: function () {
//run in canvas mode
this.game.renderer.clearBeforeRender - false;
this.game.renderer.roundPixels = true;
//Add arcade physics
this.game.physics.startSystem(Phaser.Physics.ARCADE);
//Add background sprites
this.game.add.sprite(0, 0, 'background');
this.game.add.sprite(0, 0, 'track');
//Add car sprite
car = this.game.add.sprite(800, 135, 'car-concept');
//Car physics settings
this.game.physics.enable(car, Phaser.Physics.ARCADE);
car.body.drag.set(100);
car.body.maxVelocity.set(200);
car.body.maxAngular = 500;
car.body.angularDrag = 500;
car.body.collideWorldBounds = true;
//Game input
cursors = this.game.input.keyboard.createCursorKeys();
this.game.input.keyboard.addKeyCapture([ Phaser.Keyboard.SPACEBAR]);
//pivot point
car.pivot.x = car.width * .3;
car.pivot.y = car.height * .5;
car.anchor.setTo(0.3, 0.5);
//scale the car
car.scale.setTo(0.3, 0.3);
},
update: function () {
car.body.velocity.x = 0;
car.body.velocity.y = 0;
car.body.angularVelocity = 0;
if(cursors.left.isDown)
{
car.body.angularVelocity = -200;
}
else if(cursors.right.isDown)
{
car.body.angularVelocity = 200;
}
if(cursors.up.isDown)
{
this.game.physics.arcade.velocityFromAngle(car.angle, -200, car.body.velocity)
if(this.currentSpeed < this.maxSpeed)
{
this.currentSpeed += 10;
}
}
else
{
if(this.currentSpeed > 0)
{
this.currentSpeed -= 10;
}
}
if(cursors.down.isDown)
{
this.game.physics.arcade.velocityFromAngle(car.angle, 200, car.body.velocity)
if(this.currentSpeed > 0)
{
this.currentSpeed -= 30;
}
}
},
speed: function()
{
this.maxSpeed = 100;
this.currentSpeed = 0;
},
I have looked a few questions on here about the same problem and this is how I got to the point where I am now. I have set the maxSpeed and currentSpeed but for some reason it won't allow me to actually use it. The console in the browser does not give me any errors, so if anyone can guide me on this, that would be great!
Thanks.
The reason it stops dead is because you're moving it with velocity, not acceleration - and are setting velocity to zero in your update loop (this effectively says "stop, now!").
Remove those lines and in your call to velocityFromAngle you should feed that into body.acceleration instead of body.velocity.
Here is an update loop you can use, although you'll need to mix in your currentSpeed settings and such like:
function update() {
if (cursors.up.isDown)
{
game.physics.arcade.accelerationFromRotation(sprite.rotation, 200, sprite.body.acceleration);
}
else
{
sprite.body.acceleration.set(0);
}
if (cursors.left.isDown)
{
sprite.body.angularVelocity = -300;
}
else if (cursors.right.isDown)
{
sprite.body.angularVelocity = 300;
}
else
{
sprite.body.angularVelocity = 0;
}
}
you never used currentSpeed. You set your speed to -200 and 200 in velocityFromAngle.
I've been trying to figure out how to get this script to rotate an image infinitely onclick and then stop it when you click it again. Can anyone modify it to get it to do that?
$(function() {
var $rota = $('.spin'),
degree = 0,
timer;
function rotate() {
$rota.css({ transform: 'rotate(' + degree + 'deg)'});
// timeout increase degrees:
timer = setTimeout(function() {
++degree;
rotate(); // loop it
},5);
}
rotate(); // run it!
});
you could create a bool to determine if the element has been clicked, change it on click and stop the process if the click has happened.
$(function() {
var $rota = $('.spin'),
degree = 0,
clicked = false,
timer;
$rota.on('click', function() { clicked = true; return false; } );
function rotate() {
if ( clicked )
$rota.css({ transform: 'rotate(' + degree + 'deg)'});
// timeout increase degrees:
timer = setTimeout(function() {
++degree;
rotate(); // loop it
},5);
}
rotate(); // run it!
});
Try using setInterval and clearInterval instead of setTimeout:
function rotate() {
$rota.css({ transform: 'rotate(' + degree + 'deg)'});
++degree;
}
var loop;
$rota.click(function() {
if(loop) {
clearInterval(loop);
loop = false;
}
else {
loop = setInterval(rotate, 5);
}
});
You can read up on setInterval here
Try
$(function() {
var $rota = $('.spin')
$rota.click(function(){
var $this = $(this);
if($this.data('rotating')){
clearInterval($this.data('rotating'));
$this.data('rotating', false)
} else {
$this.data('rotating', setInterval(function(){
var degree = $this.data('degree') || 0;
$this.css({ transform: 'rotate(' + degree + 'deg)'});
$this.data('degree', ++degree)
}, 5));
}
});
});
Demo: Fiddle
$(function() {
var $rota = $('img'), degree = 0, timer, enabled;
var rotate = function() {
timer = setInterval(function() {
++degree;
$rota.css({
transform: 'rotate(' + degree + 'deg)'
});
},5);
};
$rota.on('click', function(){
enabled = !enabled;
enabled ? rotate() : clearInterval(timer);
});
});