So when I shoot the enemies they get wiped from the screen, this works.
However what I want to happen is I want to place an explosion (4 pngs one after another)
basically where the enemy was. The code for the explosion works on its own but im stuck trying to integrate it with my code.
Here is the explosion class, as you can see I am having some trouble with the interval as I have no experience with them. I think the error or wrong logic lies in this object.
Also for some reason it wipes the other canvas layers :/
Try it here: http://www.taffatech.com/DarkOrbit.html
function Explosion()
{
this.srcX = 0;
this.srcY = 1250;
this.drawX = 0;
this.drawY = 0;
this.width = 70;
this.height = 70;
this.currentFrame =0;
this.totalFrames =5;
this.hasHit = false;
}
Explosion.prototype.draw = function() //makes it last 10 frames using total frames
{
if(this.currentFrame <= this.totalFrames)
{
this.currentFrame++;
Exploder(this.drawX,this.drawY);
}
else
{
this.hasHit = false;
currentFrame =0;
}
}
function Exploder(srcX,srcY)
{
whereX = this.srcX;
whereY = this.srcY;
intervalT = setInterval(BulletExplosionAnimate, 80);
}
var bulletExplosionStart = 0;
var whereX =0;
var whereY =0;
function BulletExplosionAnimate(intervalT)
{
var wide = 70;
var high = 70;
if (bulletExplosionStart > 308)
{
bulletExplosionStart = 0;
clearInterval(intervalT);
}
else
{
ctxExplosion.clearRect(0,0,canvasWidth,canvasHeight)
ctxExplosion.drawImage(spriteImage,bulletExplosionStart,1250,wide,high,whereX,whereY,wide,high);
bulletExplosionStart += 77;
}
}
my Bullet object:
function Bullet() //space weapon uses this
{
this.srcX = 0;
this.srcY = 1240;
this.drawX = -20;
this.drawY = 0;
this.width = 11;
this.height = 4;
this.bulletSpeed = 10;
this.bulletReset = -20;
this.explosion = new Explosion();
}
Bullet.prototype.draw = function()
{
this.drawX += this.bulletSpeed;
ctxPlayer.drawImage(spriteImage,this.srcX,this.srcY,this.width,this.height,this.drawX,this.drawY,this.width,this.height);
this.checkHitEnemy();
if (this.drawX > canvasWidth)
{
this.recycle();
}
}
Bullet.prototype.fire = function(startX, startY)
{
this.drawX = startX;
this.drawY = startY;
}
Bullet.prototype.checkHitEnemy = function()
{
for(var i = 0; i < enemies.length; i++)
{
if( this.drawX >= enemies[i].drawX && this.drawX <= enemies[i].drawX + enemies[i].enemyWidth && this.drawY >= enemies[i].drawY && this.drawY <= enemies[i].drawY + enemies[i].enemyHeight)
{
this.explosion.drawX = enemies[i].drawX - (this.explosion.width/2);
this.explosion.drawY = enemies[i].drawY;
this.explosion.hasHit = true;
this.recycle(); //bullet resets after hit enemy
enemies[i].recycleEnemy(); //change this soon to have if loop if health is down
}
}
}
Bullet.prototype.recycle = function()
{
this.drawX = this.bulletReset;
}
In my player object I have a function that checks if it has hit an enemy, it works:
Player.prototype.drawAllBullets = function()
{
for(var i = 0; i < this.bullets.length; i++)
{
if(this.bullets[i].drawX >= 0)
{
this.bullets[i].draw();
}
if(this.bullets[i].explosion.hasHit)
{
this.bullets[i].explosion.draw();
}
}
}
Currently when I shoot an enemy they disappear but not explosion happens, I know my interval is not great coding, so I need some help with it, thanks!
Playing a spritesheet in canvas
It’s becoming best practice to use requestAnimationFrame to do your animations. It does some nice event grouping and performance enhancing. Here’s a good post on requestAnimationFrame: http://creativejs.com/resources/requestanimationframe/
This is how you can use requestAnimationFrame to play a spritesheet:
In this case, it’s a 4x4 spritesheet that will play over 1 second:
var fps = 16;
function explode() {
// are we done? ... if so, we're outta here
if(spriteIndex>15){return;}
// It's good practice to use requestAnimation frame
// We wrap it in setTimeout because we want timed frames
setTimeout(function() {
// queue up the next frame
requestAnimFrame(explode);
// Draw the current frame
var x=spriteIndex%(cols-1)*width;
var y=parseInt(spriteIndex/(rows-1))*height;
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.drawImage(sheet,x,y,width,height,0,0,width,height);
// increment the sprite counter
spriteIndex++;
}, 1000 / fps);
}
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/nSGyx/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
// This is Paul Irish's great cross browser shim for requestAnimationFrame
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
// define the spritesheet
var spriteIndex=0;
var width=64;
var height=64;
var rows=4;
var cols=4;
// load the sheet image
var sheet=document.createElement("img");
sheet.onload=function(){
canvas.width=width;
canvas.height=height;
// call the animation
explode();
}
sheet.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/explodeSprite.png";
var fps = 16;
function explode() {
// are we done? ... if so, we're outta here
if(spriteIndex>15){return;}
// It's good practice to use requestAnimation frame
// We wrap it in setTimeout because we want timed frames
setTimeout(function() {
// queue up the next frame
requestAnimFrame(explode);
// Draw the current frame
var x=spriteIndex%(cols-1)*width;
var y=parseInt(spriteIndex/(rows-1))*height;
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.drawImage(sheet,x,y,width,height,0,0,width,height);
// increment the sprite counter
spriteIndex++;
}, 1000 / fps);
}
$("#explode").click(function(){ spriteIndex=0; explode(); });
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=64 height=64></canvas><br>
<button id="explode">Explode</button>
</body>
</html>
.
.
.
[Edited to show more details of how animation fits into your code]
This is a recoding of your explosion functions.
Declare your explosion related variables outside the functions:
var bulletExplosionStart;
var whereX =0;
var whereY =0;
var wide = 70;
var high = 70;
Next, in Exploder(), set where the explosion will occur and reset the sprite index (bulletExplosionStart) to 0
Possible error: Check your Exploder function: you supply srcX,srcY but then do whereX=this.srcX, whereY=this.srcY. I assume you meant to use the srcX,srcY supplied as arguments to Exploder() instead of this.srcX,this.srcY.
function Exploder(srcX,srcY)
{
whereX = srcX;
whereY = srcY;
bulletExplosionStart=0;
BulletExplosionAnimate();
}
This is the recoded bulletExplosionAnimate function that plays the 4 frames of the spritesheet.
After 4 frames this animation automatically stops.
var fps = 2;
function bulletExplosionAnimate() {
// are we done? ... if so, we're outta here
if(bulletExplosionStart>308){return;}
// It's good practice to use requestAnimation frame
// We wrap it in setTimeout because we want timed frames
setTimeout(function() {
// queue up the next frame
requestAnimFrame(bulletExplosionAnimate);
// Draw the current frame
ctxExplosion.clearRect(0,0,canvasWidth,canvasHeight)
ctxExplosion.drawImage(spriteImage,
bulletExplosionStart,1250,wide,high,
whereX,whereY,wide,high);
// increment the sprite position
bulletExplosionStart += 77;
}, 1000 / fps);
}
Related
I have a snowfall effect in JavaScript, I want the create a click event on the 10th snowflake that falls down. I would also like to add a Class that says "clickable". We want to achieve this, so if user clicks the 10th snowflake only, then they will be redirected to a prize (we also want to add a Class so we can style this nicely via CSS).
I must admit, my JavaScript knowledge isn't as strong as my jQuery, so could someone please help? Here is the codepen that I am using:-
https://codepen.io/scottYg55/pen/GRRzOgO
#snowflakeContainer {
position: absolute;
left: 0px;
top: 0px;
bottom: 0;
right: 0;
background-color: #2c3e50;
}
.snowflake {
padding-left: 15px;
font-family: Cambria, Georgia, serif;
font-size: 14px;
line-height: 24px;
position: fixed;
color: #FFFFFF;
user-select: none;
z-index: 1000;
}
<div id="snowflakeContainer">
<p class="snowflake">*</p>
</div>
JS
// The star of every good animation
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
var transforms = ["transform",
"msTransform",
"webkitTransform",
"mozTransform",
"oTransform"];
var transformProperty = getSupportedPropertyName(transforms);
// Array to store our Snowflake objects
var snowflakes = [];
// Global variables to store our browser's window size
var browserWidth;
var browserHeight;
// Specify the number of snowflakes you want visible
var numberOfSnowflakes = 50;
// Flag to reset the position of the snowflakes
var resetPosition = false;
//
// It all starts here...
//
function setup() {
window.addEventListener("DOMContentLoaded", generateSnowflakes, false);
window.addEventListener("resize", setResetFlag, false);
}
setup();
//
// Vendor prefix management
//
function getSupportedPropertyName(properties) {
for (var i = 0; i < properties.length; i++) {
if (typeof document.body.style[properties[i]] != "undefined") {
return properties[i];
}
}
return null;
}
//
// Constructor for our Snowflake object
//
function Snowflake(element, radius, speed, xPos, yPos) {
// set initial snowflake properties
this.element = element;
this.radius = radius;
this.speed = speed;
this.xPos = xPos;
this.yPos = yPos;
// declare variables used for snowflake's motion
this.counter = 0;
this.sign = Math.random() < 0.5 ? 1 : -1;
// setting an initial opacity and size for our snowflake
this.element.style.opacity = .1 + Math.random();
this.element.style.fontSize = 12 + Math.random() * 50 + "px";
}
//
// The function responsible for actually moving our snowflake
//
Snowflake.prototype.update = function () {
// using some trigonometry to determine our x and y position
this.counter += this.speed / 5000;
this.xPos += this.sign * this.speed * Math.cos(this.counter) / 40;
this.yPos += Math.sin(this.counter) / 40 + this.speed / 30;
// setting our snowflake's position
setTranslate3DTransform(this.element, Math.round(this.xPos), Math.round(this.yPos));
// if snowflake goes below the browser window, move it back to the top
if (this.yPos > browserHeight) {
this.yPos = -50;
}
}
//
// A performant way to set your snowflake's position
//
function setTranslate3DTransform(element, xPosition, yPosition) {
var val = "translate3d(" + xPosition + "px, " + yPosition + "px" + ", 0)";
element.style[transformProperty] = val;
}
//
// The function responsible for creating the snowflake
//
function generateSnowflakes() {
// get our snowflake element from the DOM and store it
var originalSnowflake = document.querySelector(".snowflake");
// access our snowflake element's parent container
var snowflakeContainer = originalSnowflake.parentNode;
// get our browser's size
browserWidth = document.documentElement.clientWidth;
browserHeight = document.documentElement.clientHeight;
// create each individual snowflake
for (var i = 0; i < numberOfSnowflakes; i++) {
// clone our original snowflake and add it to snowflakeContainer
var snowflakeCopy = originalSnowflake.cloneNode(true);
snowflakeContainer.appendChild(snowflakeCopy);
// set our snowflake's initial position and related properties
var initialXPos = getPosition(50, browserWidth);
var initialYPos = getPosition(50, browserHeight);
var speed = 5+Math.random()*40;
var radius = 4+Math.random()*10;
// create our Snowflake object
var snowflakeObject = new Snowflake(snowflakeCopy,
radius,
speed,
initialXPos,
initialYPos);
snowflakes.push(snowflakeObject);
}
// remove the original snowflake because we no longer need it visible
snowflakeContainer.removeChild(originalSnowflake);
// call the moveSnowflakes function every 30 milliseconds
moveSnowflakes();
}
//
// Responsible for moving each snowflake by calling its update function
//
function moveSnowflakes() {
for (var i = 0; i < snowflakes.length; i++) {
var snowflake = snowflakes[i];
snowflake.update();
}
// Reset the position of all the snowflakes to a new value
if (resetPosition) {
browserWidth = document.documentElement.clientWidth;
browserHeight = document.documentElement.clientHeight;
for (var i = 0; i < snowflakes.length; i++) {
var snowflake = snowflakes[i];
snowflake.xPos = getPosition(50, browserWidth);
snowflake.yPos = getPosition(50, browserHeight);
}
resetPosition = false;
}
requestAnimationFrame(moveSnowflakes);
}
//
// This function returns a number between (maximum - offset) and (maximum + offset)
//
function getPosition(offset, size) {
return Math.round(-1*offset + Math.random() * (size+2*offset));
}
//
// Trigger a reset of all the snowflakes' positions
//
function setResetFlag(e) {
resetPosition = true;
}
Thank you in advance for your help!
Greatly appreciated
When generating the snowflakes, try to catch the 10th one and apply what you want
...
function generateSnowflakes() {
...
// create each individual snowflake
for (var i = 0; i < numberOfSnowflakes; i++) {
// clone our original snowflake and add it to snowflakeContainer
var snowflakeCopy = originalSnowflake.cloneNode(true);
snowflakeContainer.appendChild(snowflakeCopy);
// <------------------------------------------>
// catch the tenth snowflake and add your changes here
if (i === 9) {
snowflakeCopy.classList.add("clickable");
snowflakeCopy.addEventListener("click",function (e) {
//the stuff you want to do
//when the 10th snowflake is clicked
// for example :
window.location.replace("URL/OF/PRIZE");
})
}
....
}
...
```
Theres some wierd behaviour when playing with Paperjs, i was trying to curve a line up with 7 points separately - which works fine once, but when trying to make the link overshoot and return to 3 different points (to create a bounce effect) doesn't seem to play ball. On the second if statement, the 'counter' variable doesnt seem to increase instead of decrease, '+ steps' instead of '- steps'.
Maybe i'm not using if statements properly in this case, or paperjs has some strange behaviour?
Heres the codepen for it in full, click above the blue line to trigger it off. . Following is one setInterval for one of the points of the segment.
var seg6first = true;
var seg6sec = false;
var seg6thir = false;
setInterval(function() {
if (seg6first == true) {
counter = counter - steps;
if (counter >= 230) {
path.segments[6].point.y = counter;
path.smooth(); }
else {
seg6first = false;
seg6sec = true;
}
}
if (seg6sec == true) {
counter = counter + steps;
if (counter <= 260) {
path.segments[6].point.y = counter;
path.smooth();}
else {
seg6sec = false;
seg6thir = true;
}
}
if (seg6sec == true) {
counter = counter - steps;
if (counter >= 250) {
path.segments[6].point.y = counter;
path.smooth(); }
else {
seg6thir = false;
}
}
}, mintiming);
Thanks!
Rather than manually building your bounce effect, you can use an animation library like GSAP.
It has a lot of features that will make your task easier (see easing documentation).
Here is an example of what you are trying to do (click on the canvas to animate the line).
html,
body {
margin: 0;
overflow: hidden;
height: 100%;
}
canvas[resize] {
width: 100%;
height: 100%;
}
<canvas id="canvas" resize></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.11.8/paper-full.min.js"></script>
<script type="text/paperscript" canvas="canvas">
// user defined constants
var SEGMENTS_COUNT = 6;
var CURVE_HEIGHT = 80;
var ANIMATION_DURATION = 2;
// init path
var path = new Path({
fillColor: 'orange',
selected: true
});
// add points
for (var i = 0; i <= SEGMENTS_COUNT; i++) {
path.add([view.bounds.width * i / SEGMENTS_COUNT, view.center.y]);
}
// on mouse down...
function onMouseDown() {
// ...animate points
for (var i = 0, l = path.segments.length; i < l; i++) {
// get a reference to the point
var point = path.segments[i].point;
// calculate offset using sine function to form a curve
var offset = CURVE_HEIGHT * Math.sin(point.x * Math.PI / view.bounds.width);
// register animation
TweenLite.fromTo(
// target
point,
// duration
ANIMATION_DURATION,
// initial value
{ y: view.center.y },
{
// final value
y: view.center.y - offset,
// easing
ease: Elastic.easeOut.config(1, 0.3),
// on update...
onUpdate: function() {
// ...smooth the path
path.smooth();
}
}
);
}
}
</script>
I'm developing an HTML5 application and I'm drawing a sequence of images on the canvas with a certain speed and a certain timeout between every animation.
Able to use it multiple times I've made a function for it.
var imgNumber = 0;
var lastImgNumber = 0;
var animationDone = true;
function startUpAnimation(context, imageArray, x, y, timeOut, refreshFreq) {
if (lastImgNumber == 0) lastImgNumber = imageArray.length-1;
if (animationDone) {
animationDone = false;
setTimeout(playAnimationSequence, timeOut, refreshFreq);
}
context.drawImage(imageArray[imgNumber], x, y);
}
function playAnimationSequence(interval) {
var timer = setInterval(function () {
if (imgNumber >= lastImgNumber) {
imgNumber = 0;
clearInterval(timer);
animationDone = true;
} else imgNumber++;
}, interval);
}
Now in my main code, every time startUpAnimation with the right parameters it works just fine. But when I want to draw multiple animations on the screen at the same time with each of them at a different interval and speed it doesnt work!
startUpAnimation(context, world.mushrooms, canvas.width / 3, canvas.height - (canvas.height / 5.3), 5000, 300);
startUpAnimation(context, world.clouds, 100, 200, 3000, 100);
It now displays both animations at the right location but they animate both at the interval and timeout of the first one called, so in my case 5000 timeout and 300 interval.
How do I fix this so that they all play independently? I think I need to make it a class or something but I have no idea how to fix this. In some cases I even need to display maybe 5 animations at the same time with this function.
Any help would be appreciated!
try something like this
var Class = function () {
this.imgNumber = 0;
this.lastImgNumber = 0;
this.animationDone = true;
}
Class.prototype.startUpAnimation = function(context, imageArray, x, y, timeOut, refreshFreq) {
// if (lastImgNumber == 0) lastImgNumber = imageArray.length-1;
if (this.animationDone) {
this.animationDone = false;
setTimeout(this.playAnimationSequence, timeOut, refreshFreq, this);
}
// context.drawImage(imageArray[imgNumber], x, y);
};
Class.prototype.playAnimationSequence = function (interval, object) {
var that = object; // to avoid flobal this in below function
var timer = setInterval(function () {
if (that.imgNumber >= that.lastImgNumber) {
that.imgNumber = 0;
clearInterval(timer);
that.animationDone = true;
console.log("xxx"+interval);
} else that.imgNumber++;
}, interval);
};
var d = new Class();
var d1 = new Class();
d.startUpAnimation(null, [], 300, 300, 5000, 50);
d1.startUpAnimation(null,[], 100, 200, 3000, 60);
It should work,
As far as I can see, each call to startUpAnimation will draw immediately to the canvas because this execution (your drawImage(..) call) hasn't been included in the callback of the setTimeout or setInterval.
I recently began developing a little javascript game, just for fun. The idea was that you controlled a little dot with the arrow keys (or awsd or i don't care what) within a box on the screen. Little rectangles would then randomly spawn on all edges of the box and progress across it. you have to avoid contact with them. The project turned out to be harder than I expected and I couldn't get the movement to work right. If you could help me with that that would be great. also, feel free to take the concept and what little I have done so far and do whatever you want with it. I would be interested to see your results. Below is the code I used for the spawns without any of the movement scripts. I was using the basic idea of this code to do the movement:
var x = 5; //Starting Location - left
var y = 5; //Starting Location - top
var dest_x = 300; //Ending Location - left
var dest_y = 300; //Ending Location - top
var interval = 2; //Move 2px every initialization
function moveImage() {
//Keep on moving the image till the target is achieved
if(x<dest_x) x = x + interval;
if(y<dest_y) y = y + interval;
//Move the image to the new location
document.getElementById("ufo").style.top = y+'px';
document.getElementById("ufo").style.left = x+'px';
if ((x+interval < dest_x) && (y+interval < dest_y)) {
//Keep on calling this function every 100 microsecond
// till the target location is reached
window.setTimeout('moveImage()',100);
}
}
main body:
<html>
<head>
<style type="text/css">
html::-moz-selection{
background-color:Transparent;
}
html::selection {
background-color:Transparent;
}
img.n {position:absolute; top:0px; width:5px; height:10px;}
img.e {position:absolute; right:0px; width:10px; height:5px;}
img.s {position:absolute; bottom:0px; width:5px; height:10px;}
img.w {position:absolute; left:0px; width:10px; height:5px;}
#canvas {
width:300px;
height:300px;
background-color:black;
position:relative;
}
</style>
<script type="text/javascript">
nmecount=0
function play(){
spawn()
var t=setTimeout("play()",1000);
}
function spawn(){
var random=Math.floor(Math.random()*290)
var side=Math.floor(Math.random()*5)
var name=1
var z=10000
if (side=1)
{
var nme = document.createElement('img');
nme.setAttribute('src', '1.png');
nme.setAttribute('class', 'n');
nme.setAttribute('id', name);
nme.setAttribute('style', 'left:'+random+'px;');
nme.onload = moveS;
document.getElementById("canvas").appendChild(nme);
}
if (side=2)
{
var nme = document.createElement('img');
nme.setAttribute('src', '1.png');
nme.setAttribute('class', 'e');
nme.setAttribute('id', name);
nme.setAttribute('style', 'top:'+random+'px;');
nme.onload = moveW;
document.getElementById("canvas").appendChild(nme);
}
if (side=3)
{
var nme = document.createElement('img');
nme.setAttribute('src', '1.png');
nme.setAttribute('class', 's');
nme.setAttribute('id', name);
nme.setAttribute('style', 'left:'+random+'px;');
nme.onload = moveN;
document.getElementById("canvas").appendChild(nme);
}
if (side=4)
{
var nme = document.createElement('img');
nme.setAttribute('src', '1.png');
nme.setAttribute('class', 'w');
nme.setAttribute('id', name);
nme.setAttribute('style', 'top:'+random+'px;');
nme.onload = moveE;
document.getElementById("canvas").appendChild(nme);
}
name=name+1
}
</script>
</head>
<body onLoad="play()">
<div id="canvas">
<img id="a" src="1.png" style="position:absolute; z-index:5; left:150px; top:150px; height:10px; width=10px;" />
<button onclick="moveleft()"><</button>
</body>
</html>
I can't figure out what your game is about, and so don't know what to do with that code. However, since you mentioned you were having trouble with movement, I wrote a quick JavaScript movement engine just for you, complete with acceleration and deceleration. Use the arrow keys to move. The following code represents a complete HTML document, so copy and paste it into a blank text file and save as .html. And make sure you have a 10x10 image called '1.png' in the same folder as the file.
<html>
<head>
<script type='text/javascript'>
// movement vars
var xpos = 100;
var ypos = 100;
var xspeed = 1;
var yspeed = 0;
var maxSpeed = 5;
// boundary
var minx = 0;
var miny = 0;
var maxx = 490; // 10 pixels for character's width
var maxy = 490; // 10 pixels for character's width
// controller vars
var upPressed = 0;
var downPressed = 0;
var leftPressed = 0;
var rightPressed = 0;
function slowDownX()
{
if (xspeed > 0)
xspeed = xspeed - 1;
if (xspeed < 0)
xspeed = xspeed + 1;
}
function slowDownY()
{
if (yspeed > 0)
yspeed = yspeed - 1;
if (yspeed < 0)
yspeed = yspeed + 1;
}
function gameLoop()
{
// change position based on speed
xpos = Math.min(Math.max(xpos + xspeed,minx),maxx);
ypos = Math.min(Math.max(ypos + yspeed,miny),maxy);
// or, without boundaries:
// xpos = xpos + xspeed;
// ypos = ypos + yspeed;
// change actual position
document.getElementById('character').style.left = xpos;
document.getElementById('character').style.top = ypos;
// change speed based on keyboard events
if (upPressed == 1)
yspeed = Math.max(yspeed - 1,-1*maxSpeed);
if (downPressed == 1)
yspeed = Math.min(yspeed + 1,1*maxSpeed)
if (rightPressed == 1)
xspeed = Math.min(xspeed + 1,1*maxSpeed);
if (leftPressed == 1)
xspeed = Math.max(xspeed - 1,-1*maxSpeed);
// deceleration
if (upPressed == 0 && downPressed == 0)
slowDownY();
if (leftPressed == 0 && rightPressed == 0)
slowDownX();
// loop
setTimeout("gameLoop()",10);
}
function keyDown(e)
{
var code = e.keyCode ? e.keyCode : e.which;
if (code == 38)
upPressed = 1;
if (code == 40)
downPressed = 1;
if (code == 37)
leftPressed = 1;
if (code == 39)
rightPressed = 1;
}
function keyUp(e)
{
var code = e.keyCode ? e.keyCode : e.which;
if (code == 38)
upPressed = 0;
if (code == 40)
downPressed = 0;
if (code == 37)
leftPressed = 0;
if (code == 39)
rightPressed = 0;
}
</script>
</head>
<body onload="gameLoop()" onkeydown="keyDown(event)" onkeyup="keyUp(event)" bgcolor='gray'>
<!-- The Level -->
<div style='width:500;height:500;position:absolute;left:0;top:0;background:black;'>
</div>
<!-- The Character -->
<img id='character' src='1.png' style='position:absolute;left:100;top:100;height:10;width:10;'/>
</body>
</html>
It works as follows: There is a game loop that gets called as soon as the body loads. This game loop calls itself every 10 millis for smooth animation. While it might not actually loop every 10 millis because of run-time speeds, such a low value will ensure that the frame rate is as smooth as can be for any browser.
Within the game loop we manipulate the x and y position of the object based on its current speed. Simple: add x speed to x position, and y speed to y position. Then, we change the actual position of the element based on the current x and y coordinates.
To manipulate the x and y speeds, we take keyboard input using event handlers. Based on the key code, we set a variable which tells the game if a key is down or up. Based on whether the key is down or up, we accelerate or decelerate the object up to the maximum speed. For more gradual speed-ups and slow-downs, floating point values can be used.
You should be able to get the gist of this simple engine by examining the code. Hopefully this will help you in implementing your own movement engine for the game.
In this demo http://www.htmldrive.net/items/demo/527/Animated-background-image-with-jQuery
This code is for one background only. I want to add multiple background with different direction and speed.
var scrollSpeed = 70;
var step = 1;
var current = 0;
var imageWidth = 2247;
var headerWidth = 800;
var restartPosition = -(imageWidth - headerWidth);
function scrollBg(){
current -= step;
if (current == restartPosition){
current = 0;
}
$('#header').css("background-position",current+"px 0");
}
var init = setInterval("scrollBg()", scrollSpeed);
Currently it has settings for
$('#header').css("background-position",current+"px 0");
In a website I want to use this effect on #footer or #content background also. but with different speed and direction.
And is there any better and more optimized jquery method to achieve same effect?
And can we get same effect using CSS 3, without javascript?
Just saw the OP's answer, but decided to post anyway:
I've created a jQuery plugin to do this:
(function($) {
$.fn.scrollingBackground = function(options) {
// settings and defaults.
var settings = options || {};
var speed = settings.speed || 1;
var step = settings.step || 1;
var direction = settings.direction || 'rtl';
var animStep;
// build up a string to pass to animate:
if (direction === 'rtl') {
animStep = "-=" + step + "px";
}
else if (direction === 'ltr') {
animStep = '+=' + step + "px";
}
var element = this;
// perform the animation forever:
var animate = function() {
element.animate({
backgroundPosition: animStep + " 0px"
}, speed, animate);
};
animate();
};
})(jQuery);
Usage:
$("#header").scrollingBackground({
speed: 50,
step: 50,
direction: 'ltr'
});
This is pretty basic, and assumes that you're background-repeat is 'repeat-x' on the element you call it on. This way, there's no need to reset the background position every so often.
Working example: http://jsfiddle.net/andrewwhitaker/xmtpr/
I could work out the following solution. Am not sure if it is efficient. Will wait for anyone to comment or provide a better option.
Till then...:
var scrollSpeed = 70;
var step = 1;
var current = 0;
var images =
[
{
imageWidth:2247,
imagePath:"images/image1"
},
{
imageWidth:1200,
imagePath:"images/image2"
}
]
var headerWidth = 800;
var imageRotateCount = 0;
var imagesLength = images.length;
$('#header').css("background-image", images[0].imagePath);
function scrollBg(){
var curIndex = imageRotateCount%imagesLength;
var curImage = images[curIndex];
current -= step;
var restartPosition = -(curImage.imageWidth - headerWidth);
if (current == restartPosition){
current = 0;
imageRotateCount++;
curIndex = imageRotateCount%imagesLength;
curImage = images[curIndex];
$('#header').css("background-image", curImage.imagePath);
}
$('#header').css("background-position",current+"px 0");
}
var init = setInterval("scrollBg()", scrollSpeed);