I'm trying to achieve this effect using this tutorial to dynamically add on images from a collection to a canvas to give the appearance of animation as you scroll past the canvas. There are three divs on the page top to bottom: div_1 is a full page static image, div_2 is the canvas, and div_3 is a full-page static image. After scrolling past div_1, the desired behavior is:
- Once div_1 is out of view, the scrolling action of the mouse/trackpad would cease scrolling down the page
- pause over div_2/canvas
- the mouse/trackpad would begin cycling through all of the images (displayed via the canvas) in the collection until the last image is displayed
- the scrolling action would resume to continue down the page to div_3.
I cannot figure out how to engage/disengage the mouseWheel event that I am tying into; from the very top of the page it's (understandably) tied into cycling the images, but I can't figure out a way to trigger it once div_1 is out of view and then disengage it once the scroll-based animation has completed.
Any help is greatly appreciated.
html.erb
<body>
<div class="div_1">
<!-- Full screen image to scroll past -->
</div>
<div class="div_2">
<canvas id="background" width="1280" height="720"></canvas>
</div>
<div class="div_3">
<!-- Full screen image to scroll to once animation is complete -->
</div>
</body>
Javascript
var totalImages = IMAGE_URLS.length;
var images = new Array();
for(var i = 0; i < totalImages; i++) {
var img = new Image;
img.src = IMAGE_URLS[i];
images.push(img);
}
var currentLocation = 0;
var canv;
var context;
$(document).ready(function(){
canv = document.getElementById('background');
context = canv.getContext('2d');
mouseWheel();
// See above for where this gets called
});
var mouseWheel = function() {
window.addEventListener('mousewheel', function(e) {
e.preventDefault(); // No scroll
// The following equation will return either a 1 for scroll down
// or -1 for a scroll up
var delta = Math.max(-1, Math.min(1, e.wheelDelta));
// This code mostly keeps us from going too far in either direction
if(delta == -1) currentLocation += .5;
if(delta == 1) currentLocation -= .5`;
if(currentLocation < 0) currentLocation = 0;
if(currentLocation > images.length)
currentLocation = images.length;
// See below for the details of this function
setImage(currentLocation);
});
}
var setImage = function(newLocation) {
// drawImage takes 5 arguments: image, x, y, width, height
context.drawImage(images[newLocation], 0, 0, 1280, 720);
}
jsFiddle : https://jsfiddle.net/jvLk0vhp/1/
javascript :
var images = new Array();
var currentLocation = 0;
var totalImages = 7;
for (var i = 0; i < totalImages; i++) {
var img = new Image;
switch (i) {
case 0:
img.src = "http://img.pokemondb.net/sprites/black-white/normal/mewtwo.png";
break;
case 1:
img.src = "http://img.pokemondb.net/sprites/black-white/normal/keldeo-ordinary.png";
break;
case 2:
img.src = "http://img.pokemondb.net/sprites/black-white/normal/darkrai.png";
break;
case 3:
img.src = "http://floatzel.net/pokemon/black-white/sprites/images/5.png";
break;
case 4:
img.src = "http://vignette1.wikia.nocookie.net/capx/images/0/03/001.png/revision/latest?cb=20140322003659";
break;
case 5:
img.src = "http://img.pokemondb.net/sprites/black-white/normal/absol.png";
break;
case 6:
img.src = "http://img.pokemondb.net/sprites/black-white/normal/dewgong.png";
break;
case 7:
img.src = "http://orig05.deviantart.net/e770/f/2013/008/c/6/froakie_by_baconboy914-d5qvrjo.gif";
break;
}
images.push(img);
}
var c = document.getElementById("background");
var ctx = c.getContext("2d");
var mouseWheel = function () {
window.addEventListener('mousewheel', function (e) {
e.preventDefault(); // No scroll
// The following equation will return either a 1 for scroll down
// or -1 for a scroll up
var delta = Math.max(-1, Math.min(1, e.wheelDelta));
// This code mostly keeps us from going too far in either direction
if (delta == -1) currentLocation += 1;
if (delta == 1) currentLocation -= 1;
if (currentLocation < 0) currentLocation = 0;
if (currentLocation >= (totalImages - 1)) currentLocation = (totalImages - 1);
console.log("Current location " + currentLocation);
// See below for the details of this function
setImage(currentLocation);
});
}
var setImage = function (newLocation) {
// drawImage takes 5 arguments: image, x, y, width, height
ctx.fillRect(0, 0, c.width, c.height);
ctx.drawImage(images[newLocation], 0, 0, 150, 150);
}
images[0].onload = function () {
ctx.fillRect(0, 0, c.width, c.height);
ctx.drawImage(images[currentLocation], 0, 0, 150, 150);
mouseWheel();
};
I have just used a canvas to achieve the expected output, if you still want to use a div for the first and last check my second answer below
jsfiddle : https://jsfiddle.net/jvLk0vhp/2/
javascript (also using divs)
var images = new Array();
var currentLocation = 0;
var totalImages = 7;
var div1 = document.getElementById("id_1");
var div2 = document.getElementById("id_2");
var div3 = document.getElementById("id_3");
div2.style.display = "none";
div3.style.display = "none";
for (var i = 0; i < totalImages; i++) {
var img = new Image;
switch (i) {
case 1:
img.src = "http://img.pokemondb.net/sprites/black-white/normal/keldeo-ordinary.png";
break;
case 2:
img.src = "http://img.pokemondb.net/sprites/black-white/normal/darkrai.png";
break;
case 3:
img.src = "http://floatzel.net/pokemon/black-white/sprites/images/5.png";
break;
case 4:
img.src = "http://vignette1.wikia.nocookie.net/capx/images/0/03/001.png/revision/latest?cb=20140322003659";
break;
case 5:
img.src = "http://img.pokemondb.net/sprites/black-white/normal/absol.png";
break;
case 6:
img.src = "http://img.pokemondb.net/sprites/black-white/normal/dewgong.png";
break;
}
images.push(img);
}
var c = document.getElementById("background");
var ctx = c.getContext("2d");
var mouseWheel = function () {
window.addEventListener('mousewheel', function (e) {
e.preventDefault(); // No scroll
// The following equation will return either a 1 for scroll down
// or -1 for a scroll up
var delta = Math.max(-1, Math.min(1, e.wheelDelta));
// This code mostly keeps us from going too far in either direction
if (delta == -1) currentLocation += 1;
if (delta == 1) currentLocation -= 1;
if (currentLocation < 0) currentLocation = 0;
if (currentLocation >= (totalImages - 1)) currentLocation = (totalImages - 1);
console.log("Current location " + currentLocation);
// See below for the details of this function
setImage(currentLocation);
});
}
var setImage = function (newLocation) {
// drawImage takes 5 arguments: image, x, y, width, height
if (newLocation == 0) {
div1.style.display = "block";
div2.style.display = "none";
div3.style.display = "none";
} else if (newLocation == (totalImages - 1)) {
div1.style.display = "none";
div2.style.display = "none";
div3.style.display = "block";
} else {
div1.style.display = "none";
div2.style.display = "block";
div3.style.display = "none";
ctx.fillRect(0, 0, c.width, c.height);
ctx.drawImage(images[newLocation], 0, 0, 150, 150);
}
}
ctx.fillRect(0, 0, c.width, c.height);
ctx.drawImage(images[currentLocation], 0, 0, 150, 150);
mouseWheel();
Related
The Problem
I have been creating a game, I have got to a stage where I want to see what it looks like with a mockup background I have created.
The Question
Where about in my code should I place this code as the place it currently is doesnt show the background.
I want this background on the canvas, the dimensions are correct.
The Code
var game = create_game();
game.init();
function create_game() {
debugger;
var level = 1;
var projectiles_per_level = 1;
var min_speed_per_level = 1;
var max_speed_per_level = 2;
var last_projectile_time = 0;
var next_projectile_time = 0;
var width = 600;
var height = 500;
var delay = 1000;
var item_width = 30;
var item_height = 30;
var total_projectiles = 0;
var projectile_img = new Image();
var projectile_w = 30;
var projectile_h = 30;
var player_img = new Image();
var background_img = new Image();
var c, ctx;
var projectiles = [];
var player = {
x: 200,
y: 400,
score: 0
};
function init() {
projectile_img.src = "projectile.png";
player_img.src = "player.png";
background_img.src = "background.png";
background_img.onload = function(){
context.drawImage(background_img, 0, 0);
}
level = 1;
total_projectiles = 0;
projectiles = [];
c = document.getElementById("c");
ctx = c.getContext("2d");
ctx.fillStyle = "#410b11";
ctx.fillRect(0, 0, 500, 600);
c.addEventListener("mousemove", function (e) {
//moving over the canvas.
var bounding_box = c.getBoundingClientRect();
player.x = (e.clientX - bounding_box.left) * (c.width / bounding_box.width) - player_img.width / 2;
}, false);
setupProjectiles();
requestAnimationFrame(tick);
}
function setupProjectiles() {
var max_projectiles = level * projectiles_per_level;
while (projectiles.length < max_projectiles) {
initProjectile(projectiles.length);
}
}
function initProjectile(index) {
var max_speed = max_speed_per_level * level;
var min_speed = min_speed_per_level * level;
projectiles[index] = {
x: Math.round(Math.random() * (width - 2 * projectile_w)) + projectile_w,
y: -projectile_h,
v: Math.round(Math.random() * (max_speed - min_speed)) + min_speed,
delay: Date.now() + Math.random() * delay
}
total_projectiles++;
}
function collision(projectile) {
if (projectile.y + projectile_img.height < player.y + 20) {
return false;
}
if (projectile.y > player.y + 74) {
return false;
}
if (projectile.x + projectile_img.width < player.x + 20) {
return false;
}
if (projectile.x > player.x + 177) {
return false;
}
return true;
}
function maybeIncreaseDifficulty() {
level = Math.max(1, Math.ceil(player.score / 10));
setupProjectiles();
}
function tick() {
var i;
var projectile;
var dateNow = Date.now();
c.width = c.width;
for (i = 0; i < projectiles.length; i++) {
projectile = projectiles[i];
if (dateNow > projectile.delay) {
projectile.y += projectile.v;
if (collision(projectile)) {
initProjectile(i);
player.score++;
} else if (projectile.y > height) {
initProjectile(i);
} else {
ctx.drawImage(projectile_img, projectile.x, projectile.y);
}
}
}
ctx.font = "bold 24px sans-serif";
ctx.fillStyle = "#410b11";
ctx.fillText(player.score, c.width - 50, 50);
ctx.fillText("Level: " + level, 20, 50);
ctx.drawImage(player_img, player.x, player.y);
maybeIncreaseDifficulty();
requestAnimationFrame(tick);
ctx.drawImage(background_img, 0, backgroundY);
}
return {
init: init
};
}
As already pointed out in a comment, here more precisely:
First of all, the background picture must be rendered first in every animation frame.
However, the picture didn't show up at all. This is due to the fact that variable was used (backgroundY), which is never declared somewhere.
This should actually printed to the console as an error "backgroundY" is not defined.
Whenever an the property src of an image object is set to a value, it takes some time until it's loaded. So in many cases, it's necessary to indicate the moment, when it's finished loading by the onload callback.
In this case, however, it's not necessary. The tick / animation loop function will just draw nothing (an empty image object) until it's loaded. After it's loaded it will continue to draw the loaded image every frame.
If the background is really important, meaning, the app should only start, when it's there, of course, one can only start the whole game / animation from within the img.onload handler.
You must draw:
the background first
the player later
level/score info last
Background < Player < UI < You Looking
The drawing order is from back to top (painters algorithm)
Also note that for performance reasons if you background never changes you could draw it in another 'static' canvas under the game canvas.
Otherwise the background will be drawn above/over the player and hide it.
UPDATE
changed it to the following and noticed speed improvements. The issue now is that the player will just slide without animating the frames.
var animator, frames;
animator = window.setInterval(function(){
if(currentFrame == totalFrames){
clearInterval(animator);
currentFrame = 0;
update();
isMoving = 0;
return;
}
xPosition += x;
yPosition += y;
frames = window.requestAnimationFrame(animator);
currentFrame++;
update();
},frames);
Some of the issues I am currently facing are: the map edges code section is completely broken. I am just trying to make it so that the player cannot move beyond the canvas.width/canvas.height. Also, my player movement is very sluggish and unresponsive. I think it's because of the isMoving check I added. I want to be able to move much smoother. Right now the character takes so long to move that I feel as if I am lagging. Also, for some reason, sometimes it'll move more than one time. It is completely random when it happens. Any help would be appreciated
var playerSprite = new Image();
playerSprite.src = "male.png";
var playerWidth = 64;
var playerHeight = 64;
var currentFrame = 0;
var totalFrames = 8;
var moveDistance = 4; // move 4 pixels
var xPosition = 300;
var yPosition = 200;
var direction = 2; // south, options: 0 - 3
var isMoving = 0;
var canvas, context;
window.addEventListener("load", function(){
canvas = document.getElementById('map');
context = canvas.getContext('2d');
})
function draw(){
context.drawImage(playerSprite,currentFrame * playerWidth, direction* playerHeight ,playerWidth,playerHeight,xPosition,yPosition,playerWidth,playerHeight);
}
function update()
{
clearMap();
draw();
}
function move(x, y){
if(isMoving)return;
isMoving = 1;
if(x > 0) direction = 3;
else if(x < 0) direction = 1;
if(y > 0) direction = 2;
else if(y < 0) direction = 0;
//update direction no matter what, implemented
// in order for directions to update
// when changing directions in map edges
//update();
/* Broken
if(xPosition + playerWidth + x > canvas.width)return; //works
else if(xPosition - x < 0)return; // player gets stuck
if(yPosition + playerHeight + y > canvas.height)return; //works
else if(yPosition - y < 0)return; // player gets stuck
//xPosition += x;
//yPosition += y;
*/
//actual animation update
var animator;
animator = window.setInterval(function(){
if(currentFrame == totalFrames){
clearInterval(animator);
currentFrame = 0;
update();
isMoving = 0;
return;
}
xPosition += x;
yPosition += y;
currentFrame++;
update();
},1000/16);
}
function clearMap(){
context.clearRect(0, 0, canvas.width, canvas.height);
}
function keyPress(e)
{
if(currentFrame == totalFrames){
currentFrame = 0;
}
switch(e.keyCode){
case 38: move(0, -moveDistance); break;
case 40: move(0, +moveDistance); break;
case 39: move(+moveDistance, 0); break;
case 37: move(-moveDistance, 0); break;
}
}
window.addEventListener("load", update, false);
window.addEventListener("keydown",keyPress);
Main points I changed:
No use of setInterval anywhere. Instead we let the browser handle the FPS at a rate it can handle using requestAnimationFrame.
One central game loop (update()). Before, you were doing a bunch of calculations and starting new background loops every time you press a key. That's bad. If someone were to mash the arrow keys, the browser would have to process 100+ setIntervals in the background.
Instead of doing any calculation in the key events, we're just using a variable to keep track of which buttons are pressed. Then in the game loop, which happens each frame, we can move the player a few pixels if an arrow key is held.
Exercises for you:
The animation is insanely fast because the player-frame is advanced every game-frame. Slow it down!
If a faster computer runs at 60fps, the player will move 60 * 4 = 240 pixels every second. If a slower computer runs at 20fps, the player will only move 20 * 4 = 80 pixels every second. That's actually a huge difference. To make your game run consistently regardless of platform, you should move the player more or less depending on how fast the game is running. Here's a good article to get you started. Also the requestAnimationFrame documentation will be helpful.
Here's the code:
var playerSprite = new Image();
playerSprite.src = "male.png";
var playerWidth = 64;
var playerHeight = 64;
var currentFrame = 0;
var totalFrames = 8;
var direction = 2; // south, options: 0 - 3
var moveDistance = 4; // move 4 pixels
var xPosition = 300;
var yPosition = 200;
var left = 0,
right = 0,
up = 0,
down = 0;
var canvas, context;
window.addEventListener("keydown", keyPress);
window.addEventListener("keyup", keyRelease);
window.addEventListener("load", function(){
canvas = document.getElementById('map');
context = canvas.getContext('2d');
// tells the browser to call update() as soon as it's ready
// this prevents lockups, and also the browser regulates the FPS
window.requestAnimationFrame(update);
});
function update() {
// EVERYTHING game related happens in update (except listening for key events).
// This keeps everything organized, and prevents any lag/slowdown issues
// handles player movement and animation
movePlayer();
// handles all drawing
draw();
// lets the browser know we're ready to draw the next frame
window.requestAnimationFrame(update);
}
function movePlayer() {
if(left) {
xPosition -= moveDistance;
direction = 1;
}
if(right) {
xPosition += moveDistance;
direction = 3;
}
if(up) {
yPosition -= moveDistance;
direction = 0;
}
if(down) {
yPosition += moveDistance;
direction = 2;
}
// all this code happens every frame
// in english: if we're moving, advance to the next frame
if(left || right || up || down) {
currentFrame ++;
if(currentFrame == totalFrames) currentFrame = 0;
}
}
function draw() {
// clear the map
context.clearRect(0, 0, canvas.width, canvas.height);
// draw the next frame
context.drawImage(playerSprite, currentFrame * playerWidth, direction * playerHeight,
playerWidth, playerHeight,
xPosition, yPosition,
playerWidth, playerHeight);
}
// keyPress and keyRelease ensure that the variables are
// equal to 1 if pressed and 0 otherwise.
function keyPress(e)
{
switch(e.keyCode){
case 38: up = 1; break;
case 40: down = 1; break;
case 39: right = 1; break;
case 37: left = 1; break;
}
}
function keyRelease(e)
{
switch(e.keyCode){
case 38: up = 0; break;
case 40: down = 0; break;
case 39: right = 0; break;
case 37: left = 0; break;
}
}
EDIT: Forgot to mention that I opted to include delta on my player's movement instead of on my update() redraws to prevent the whole game from running at 20 fps.
Forgot to post my revised and fully functional code. Thanks #Entity for helping me out <3. As you can see, I've begun to take more liberties and experimenting as well.
var fps = 20, fpsInterval = 1000/fps, now, then = Date.now(), delta;
var moving = {38:0, 40:0, 39:0, 37:0} // north, south, east, west
function move(direction, toggle){moving[direction] = toggle}
function keyDown(e){move(e.keyCode,1)}
function keyUp(e){move(e.keyCode,0)}
function playerMovement(){
now = Date.now();
delta = now - then;
if(delta > fpsInterval){
then = now - (delta % fpsInterval);
// north = 38, south = 40, east = 39, west = 37
// stop movement stall from opposite directions
if(moving[38] && moving[40]){move(40,0)}
if(moving[39] && moving[37]){move(37,0)}
// flip order to change diagonal rendering mode
if(moving[38]) {direction = 0; yPosition -= moveDistance};
if(moving[40]) {direction = 2; yPosition += moveDistance};
if(moving[39]) {direction = 3; xPosition += moveDistance};
if(moving[37]) {direction = 1; xPosition -= moveDistance};
if(moving[38] || moving[40] || moving[39] || moving[37]) currentFrame++;
if(currentFrame == totalFrames) currentFrame = 0;
}
}
I'm trying to get an image in a canvas to move back and forth using setInterval. I've been struggling find the solution with no avail. Can anyone figure out the problem?
Here's my code:
...
var img = new Image;
var url = ["sprite-right.png","sprite-left.png"];
var ctx2;
for (i=0; i<3; i++) {
img.src = url[i];
}
img.onload = function() {
start();
}
function start() {
var canv2 = document.getElementById("canvas2");
ctx2 = canv2.getContext("2d");
var x = 50, y = 100;
var direction = "right";
var interval = setInterval(function() {
if (direction == "right") {
img.src=url[0];
ctx2.clearRect(0, 0, ctx2.canvas.width, ctx2.canvas.height);
ctx2.drawImage(img, x, y);
x++;
if (x>690) {
direction = "left";
} // end if
} else if (direction == "left") {
img.src=url[1];
ctx2.clearRect(0, 0, ctx2.canvas.width, ctx2.canvas.height);
ctx2.drawImage(img, x, y);
x--;
if (x<50) {
direction = "right";
} // end if
} // end if
},1); // end set interval
} // end function
Your code is infinite-looping.
(Working plunkr)
Everytime your Image loads, it runs the 'start' function; however, that function changes the image url, so it loads again, which runs the 'start' function, etc.
I got your code running by making multiple Images instead of using just one; this way, the Image isn't constantly reloading.
Notable changes were the addition of the 'img2' variable and reordering the code; everything else was fine the way it was.
var img = new Image(),
img2 = new Image();
var url = ["https://www.google.com/images/srpr/logo11w.png","http://upload.wikimedia.org/wikipedia/commons/thumb/8/85/Smiley.svg/220px-Smiley.svg.png"];
var ctx2;
function start() {
console.log('whirrr');
var canv2 = document.getElementById("canvas2");
ctx2 = canv2.getContext("2d");
var x = 50, y = 100;
var direction = "right";
var interval = setInterval(function() {
if (direction == "right") {
//img.src=url[0];
ctx2.clearRect(0, 0, ctx2.canvas.width, ctx2.canvas.height);
ctx2.drawImage(img, x, y);
x++;
if (x>690) {
direction = "left";
} // end if
} else if (direction == "left") {
//img.src=url[1];
ctx2.clearRect(0, 0, ctx2.canvas.width, ctx2.canvas.height);
ctx2.drawImage(img2, x, y);
x--;
if (x<50) {
direction = "right";
} // end if
} // end if
},1); // end set interval
} // end function
img.onload = function() {
start();
}
//for (i=0; i<3; i++) {
// img.src = url[i];
//}
img.src = url[0];
img2.src = url[1];
I'm beginning with an isometric game, and my canvas is blinking(Not in IE) when draws all the parts of the ground. When I set fps to 20 or less, the blinking stops. How can I solve that? Any ideas?
var camerax = 300, cameray = 100;
var fps = 60;
function draw() {
clearCanvas();
drawGround();
}
function drawGround() {
var img = new Image();
img.onload = function() {
var width = img.width;
var height = img.height;
for (var x = 0; x < 3; x++) {
for (var y = 3; y >= 0; y--) {
mx = (x-y)*height + camerax;
my = (x+y)*height/2 + cameray;
ctx.drawImage(img, mx, my);
}
}
}
img.src = "ground.png";
}
var loop = setInterval(function() {
update();
draw();
}, 1000/fps);
Right now you're reloading the image every frame and unless the onload callback fires within the 16ms of the frame you're going to see a blank canvas.
You should only need to call the new Image, img.onload sequence once, to preload your images. The onload callback would then kick off your first frame, and the draw calls are free to use the image in memory.
Something like:
var camerax = 300, cameray = 100;
var fps = 60;
var img;
var loop;
function init() {
img = new Image();
img.onload = function() {
loop = setInterval(function() {
update();
draw();
}, 1000/fps);
};
img.src = "ground.png";
}
function draw() {
clearCanvas();
drawGround();
}
function drawGround() {
var width = img.width;
var height = img.height;
for (var x = 0; x < 3; x++) {
for (var y = 3; y >= 0; y--) {
mx = (x-y)*height + camerax;
my = (x+y)*height/2 + cameray;
ctx.drawImage(img, mx, my);
}
}
}
}
Of course, it gets more complex once you're waiting for multiple images to preload since you need to start the loop only once all of them are done.
Nice tip, freejosh! Thanks! My screen now is not blinking and the code result was that:
var canvas = document.getElementById("game");
var ctx = canvas.getContext("2d");
var camerax = 300, cameray = 100;
var fps = 60;
var img;
var loop;
function update() {
}
function draw() {
clearCanvas();
drawGround();
}
function clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function drawGround() {
var width = img.width;
var height = img.height;
for (var x = 0; x < 3; x++) {
for (var y = 3; y >= 0; y--) {
mx = (x-y)*height + camerax;
my = (x+y)*height/2 + cameray;
ctx.drawImage(img, mx, my);
}
}
}
function init() {
img = new Image();
img.onload = function() {
drawGround();
};
img.src = "ground.png";
}
function keyListener(e){
e = e || window.event
if(e.keyCode==37){
camerax--;
}
else if(e.keyCode==39){
camerax++;
}
else if(e.keyCode==38){
cameray--;
}
else if(e.keyCode==40){
cameray++;
}
}
window.onkeypress = function(e) {
keyListener(e);
}
init();
var loop = setInterval(function() {
update();
draw();
}, 1000/fps);
I m Drawing the image on canvas with this code
and it successfully draw the image on canvas now i want to move the image on canvas for that i write the code i check that if the right key of my keyboard is pressed i will increment the x coordinate of an image if left key is pressed i will decrement the x coordinate but image is not moving on the canvas
player = new Image();
player.src = "game_character.png";
context.drawImage(player,player.x * wallDim + wallDim ,player.y * wallDim + wallDim ,50,50);
how to move an image on canvas
var handleInput = function(event, keyState) {
switch(event.which) {
case 37: { // Left Arrow
keyDown.arrowLeft = keyState;
break;
}
case 38: { // Up Arrow
keyDown.arrowUp = keyState;
break;
}
case 39: { // Right Arrow
keyDown.arrowRight = keyState;
break;
}
case 40: { // Down Arrow
keyDown.arrowDown = keyState;
break;
}
}
}
/**
* physics
*
* This function contains the basic logic for the maze.
*/
var physics = function() {
console.log("physics ");
console.log("first condition "+keyDown.arrowRight +player.x+1);
if(keyDown.arrowLeft && player.x-1 >= 0 && map[player.y][player.x-1] != 1) {
player.x--;
redraw = true;
}
if(keyDown.arrowUp && player.y-1 >= 0 && map[player.y-1][player.x] != 1) {
player.y--;
redraw = true;
}
if(keyDown.arrowRight && player.x+1 < map[0].length && map[player.y][player.x+1] != 1) {
console.log("arrow right");
player.x++;
redraw = true;
}
if(keyDown.arrowDown && player.y+1 < map.length && map[player.y+1][player.x] != 1) {
player.y++;
redraw = true;
}
if(keyDown.arrowRight && player.x+1 >= map[0].length)
{
player.x++;
document.getElementById("canvas_div").style.display="none";
document.getElementById("end_screen_div").style.display="block";
//alert("completed");
}
}
/**
* draw
*
* This function simply draws the current state of the game.
*/
var draw = function() {
// Don't redraw if nothing has changed
if(!redraw)
return;
context.clearRect(0, 0, cols, rows);
context.beginPath();
// Draw the maze
for(var a = 0; a < rows; a++) {
for(var b = 0; b < cols; b++) {
switch(map[a][b]) {
case C.EMPTY: context.fillStyle = colors.empty; break;
case C.WALL: context.fillStyle = colors.wall; break;
}
context.fillRect(b * wallDim, a * wallDim, wallDim, wallDim); // x, y, width, height
}
}
// Draw the player
/* context.fillStyle = colors.player;
context.arc(
player.x * wallDim + wallDim / 2, // x position
player.y * wallDim + wallDim / 2, // y position
wallDim / 2, // Radius
0, // Starting angle
Math.PI * 2, // Ending angle
true // antiClockwise
);*/
player = new Image();
player.src = "game_character.png";
context.drawImage(player,player.x * wallDim + wallDim ,player.y * wallDim + wallDim ,50,50);
var firstplayer=new Image();
firstplayer.src="top_character01.png";
context.drawImage(firstplayer,680,0,60,60);
var secondplayer= new Image();
secondplayer.src="top_character02.png";
context.drawImage(secondplayer,750,0,60,60);
context.fill();
context.closePath();
redraw = false;
}
In your draw method, you reinitialize the player each time :
player = new Image();
player.src = "game_character.png";
So you erase the player.x modified by your event handler.
You should initialize the player only once, outside the draw function. You can move the initialization like this :
var player = new Image();
player.src = "game_character.png";
var draw = function() {
There is absolutely no need to call player.src = "game_character.png"; inside the draw function.
As a general rule, when dealing with animation, try to remove all what you can from the draw function, which should be as fast as possible.
You will need to redraw the canvas each time. Something like this:
function init()
{
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
x = canvas.width / 2; //align to centre of the screen
y = canvas.height / 2; //same as above
speed = 5; //speed for the player to move at
width = 50; //width of the player
height = 50; //height of the player
playerimage = new Image();
playerimage.src = "path/to/image/for/player"; //path to the image to use for the player
canvas.addEventListener("keypress", update);
}
function update(event)
{
if (event.keyCode == 38)
{
y -= speed; //going up
}
if (event.keyCode == 40)
{
y += speed; //going down
}
if (event.keyCode == 37)
{
x -= speed; //going left
}
if (event.keyCode == 39)
{
x += speed; //going right
}
render();
}
function render()
{
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(playerimage, x, y, width, height);
}
I haven't tested it, so I don't know whether it works and there may be some mistakes here and there. It should work though! If nothing else, it will (hopefully) give you an idea of one way in which you can go about doing it...