Keep firing keydown event after a keyup - javascript

I'm trying to implements movement in a 3D game, for this to work I have to deal with multikeys detection.
So I got this to work
setControls(){
this.keyMap = {};
window.addEventListener('keydown', this.onMove.bind(this));
window.addEventListener('keyup', this.onMove.bind(this));
}
onMove(event){
this.keyMap[event.key] = event.type === "keydown";
//Move according to key pressed
}
The keydown event works fine, my object moves on two directions at the same time when 2 keys are pressed. But when the keyup event is fired, keyMap is set to proper values but onMove is called just once, and even though there's still one key pressed my keyMap is not updating anymore.
I tried a few things that got me into an infinite loop.
Thanks.

When creating a game with input, don't put the logic of the movement within the key press itself. Instead have a "Main Game Loop" that will move the object based on whether or not an input value is set in your keymap.
Placing the movement logic within the input causes the input to get delayed so there will be a pause between the initial input and the following inputs making the movement look and act strangely. By adding it to your game logic instead of the input event you will not see that delay.
Here is an example it doesn't use a canvas or anything, but it demonstrates the point (use WASD to move):
const player = document.querySelector('.player')
const playerSpeed = 2
let x = 0, y = 0
const keyMap = {
a: false, d: false,
w: false, s: false
}
window.addEventListener('keydown', setKey)
window.addEventListener('keyup', setKey)
function setKey(event) {
keyMap[event.key] = event.type === 'keydown'
}
// Main Game loop
setInterval(() => {
// Calculate the internal x position
if (keyMap.a) { x -= playerSpeed }
if (keyMap.d) { x += playerSpeed }
// Calculate the internal y position
if (keyMap.w) { y -= playerSpeed }
if (keyMap.s) { y += playerSpeed }
// Set the new position of the player
// based on the internal x/y position
player.style.left = x + 'px'
player.style.top = y + 'px'
}, 10)
.player {
background: red;
position: absolute;
height: 50px;
width: 50px;
}
<div class="player"></div>

Related

requestAnimationFrame only when needed runs the animation much faster than having requestAnimationFrame all the time

I am trying to create a "smooth" animation by "lerping" the difference between an element that follows the mouse and the mouse position.
This is just for demo purposes, the issue happens with scrolling events and other kinds of animations too.
In the original code, a requestAnimationFrame "loop" starts when JS is loaded, and never stops. And it feels to me like this is not the optimal way of doing it, but the animation works perfectly with this method.
Here is the original demo: https://codepen.io/ReGGae/pen/NQKENZ?editors=0010
let target = 0
let current = 0
const ease = 0.075
const element = document.querySelector('.js-lerp-me')
window.addEventListener('mousemove', (e) => {
target = e.clientX // Stores the mouse (X) positon
})
function animate() {
current += ((target - current) * ease) // This is where the magic happens
element.style.transform = `translate3d(${current}px, 0, 0)`
requestAnimationFrame(animate)
}
animate() // Runs 60 times per second
(This example kindly provided to me by Jesper Landberg in order to explain to me lerping)
In my code, I try to optimize it by running the requestAnimationFrame "loop" only when the mousemove event is fired and stop it when its nearly finished(nearly because it can never finish with lerping).
My version: https://codepen.io/samuelgozi/pen/QeWzWy?editors=0010
let target = 0
let current = 0
const ease = 0.075
const element = document.querySelector('.js-lerp-me')
// Checks that both numbers are within a range.
// The default range is 1 because the units passed to this are pixels,
// and with lerping the last pixel never really arrives at the target.
function nearlyEqual(a, b, targetDiff = 1) {
return Math.abs(a - b) < targetDiff;
}
window.addEventListener('mousemove', (e) => {
target = e.clientX // Stores the mouse (X) positon
animate()
})
function animate() {
current += ((target - current) * ease)
element.style.transform = `translate3d(${current}px, 0, 0)`
if (nearlyEqual(target, current)) return // If we are close enough to the target, then dont request another animation frame.
requestAnimationFrame(animate)
}
As you can see in the demos, in my version it runs much faster, and feels less "eased", in other words the effect is lost. even if you bring down the ease multiplier down it still feels different.
Can someone please explain to me what is going on?
The original only runs one loop. and I think it's because you start a new animate every time you there is a mousemove event and then several will run at the same time so I modified your code a bit to only start a new animation until the current animation loop has stopped.
let target = 0
let current = 0
let animating = false
const ease = 0.075
const element = document.querySelector('.js-lerp-me')
// Checks that both numbers are within a range.
// The default range is 1 because the units passed to this are pixels,
// and with lerping the last pixel never really arrives at the target.
function nearlyEqual(a, b, targetDiff = 1) {
return Math.abs(a - b) < targetDiff;
}
window.addEventListener('mousemove', (e) => {
target = e.clientX // Stores the mouse (X) positon
if (!animating) {
animate()
animating = true
}
})
function animate() {
current += ((target - current) * ease) // This is where the magic happens
element.style.transform = `translate3d(${current}px, 0, 0)`
if (nearlyEqual(target, current)) {
animating = false
return
}
requestAnimationFrame(animate)
}

Move canvas object on touchmove in Javascript

I’m fairly new to web development and I’ve only ever used jQuery to write my scripts. Today however, I’d like to improve my skills and build a little game that could be used on a smartphone as a web app in vanilla JS.
The game’s pretty straightforward:
You hold your phone in portrait mode and control a character that stays at the bottom of the screen and has to dodge objects that are falling on him. The character can only move left or right and thus always stays on the same x-axis. In order to control him, your finger has to stay on the screen. Once you take it off, you lose. Also, the move isn’t triggered by tapping the screen, but by moving your finger left or right.
For now, I’ve only been experimenting to get the hang of touchevents and was able to make the character move when swiping:
document.addEventListener('touchmove',function(e){
e.preventDefault(); //disable scroll
var board = document.getElementById(‘board);
var character = document.getElementById(‘character’);
if (e.targetTouches.length === 1) {
var touch = e.targetTouches[0];
board.classList.add(‘moving’);
character.style.left = touch.pageX + 'px';
}
}, false);
(The ‘moving’ class is used to move the background-position of the board and animate the character’s sprite in plain CSS.)
Separately, I made a little script that puts objects with random classes in a container with a set interval. These objects are then animated in css and fall from the top to the bottom of the screen.
Now, here comes the tricky part: the collision detection.
As I said, I’m new to development and vanilla JS, so I searched a bit to figure out how to detect when two objects collide, and it seems that most tutorials do this using canvases. The thing is, I’ve never used them and they scare me quite a bit. What’s more, I think it would render what I’ve done so far useless.
I’m okay with trying the canvas way, but before I do, I’d like to know if there’s any other way to detect if two moving objects collide?
Also, if there turns out to be no real way to do this without canvas, I plan on using this tutorial to learn how to build the app. However, this game wasn’t built for touchscreen devices, and the spaceship’s position changes on certain keystrokes (left & right) :
function update() {
if (keydown.left) {
player.x -= 5;
}
if (keydown.right) {
player.x += 5;
}
player.x = player.x.clamp(0, CANVAS_WIDTH - player.width);
}
My question is: how should I do to update the position using touchmove instead of keystrokes?
Thank you all in advance.
1) the idea : 'if you stop touching, you loose', is just a bad idea, drop it.
2) most convenient way to control is to handle any touch event (touch start/move/end/cancel), and to have the character align on the x coordinate of this event.
3) the intersection test is just a basic boundig box intersection check.
I made a very basic demo here, that uses touch, but also mouse to ease testing :
http://jsbin.com/depo/1/edit?js,output
a lot of optimisations are possible here, but you will see that touches adjust the ship's position, and that collisions are detected, so it will hopefully lead you to your own solution
Edit : i added default to 0 for left, top, in case they were not set.
boilerplate code :
var collisionDisplay = document.getElementById('collisionDisplay');
// hero ship
var ship = document.getElementById('ship');
ship.onload = launchWhenReady ;
// bad ship
var shipBad = document.getElementById('shipBad');
shipBad.onload = launchWhenReady ;
// image loader
imagesCount = 2 ;
function launchWhenReady() {
imagesCount --;
if (imagesCount) return;
setInterval(animate, 20);
}
var shipBadY = 0;
touch events :
// listen any touch event
document.addEventListener('touchstart', handleTouchEvent, true);
document.addEventListener('touchmove', handleTouchEvent, true);
document.addEventListener('touchend', handleTouchEvent, true);
document.addEventListener('touchcancel', handleTouchEvent, true);
// will adjust ship's x to latest touch
function handleTouchEvent(e) {
if (e.touches.length === 0 ) return;
e.preventDefault();
e.stopPropagation();
var touch = e.touches[0];
ship.style.left = (touch.pageX - ship.width / 2) + 'px';
}
animation :
// animation loop
function animate()  {
// move ship
shipBadY += 1;
shipBad.style.top = Math.ceil(shipBadY) + 'px';
// test collision
var isColliding = testCollide(shipBad);
collisionDisplay.style.display = isColliding ? 'block' : 'none';
}
collision :
// collision test when the enemy and the ship are images
function testCollide(enemi) {
var shipPosX = parseInt(ship.style.left) || 0 ;
var shipPosY = parseInt(ship.style.top) || 0 ;
var shipWidth = ship.width ;
var shipHeight = ship.height;
var badX = parseInt(enemi.style.left) || 0 ;
var badY = parseInt(enemi.style.top) || 0 ;
var badWidth = enemi.width;
var badHeight = enemi.height;
return bBoxIntersect(shipPosX, shipPosY, shipWidth, shipHeight,
badX, badY, badWidth, badHeight);
}
EDIT : in case you're not using images :
// collision test when the enemy and the ship are ** NOT ** images
function testCollide(o) {
var characterPosX = parseInt(character.style.left);
var characterPosY = parseInt(character.style.top);
var characterWidth = parseInt(character.style.width);
var characterHeight = parseInt(character.style.height);
var obstacleX = parseInt(o.style.left) || 0 ;
var obstacleY = parseInt(o.style.top) || 0 ;
var obstacleWidth = parseInt(o.style.width);
var obstacleHeight = parseInt(o.style.height);
return boundingBoxIntersect(characterPosX, characterPosY, characterWidth, characterHeight, obstacleX, obstacleY, obstacleWidth, obstacleHeight);
}
function bBoxIntersect(x1, y1, w1, h1, x2, y2, w2, h2) {
return !(x1 + w1 < x2 || x1 > x2 + w2 || y1 + h1 < y2 || y1 > y2 + w2);
}
mouse events :
// -----------------------------------------------------
// Handle mouse event for easy testing on Browser
document.addEventListener('mousemove', handleMouseEvent);
function handleMouseEvent(e) {
ship.style.left = (e.pageX - ship.width / 2) + 'px';
}

Continue keydown event even when an additional button is pressed

Let's say we have a ball that can be moved left and right around the screen. When you click space, the ball should jump.
I got the ball to move left and right in a canvas. However, when the ball is moving left (for example) and I hit the space bar before anything, the ball stops moving left.
Check out my example so far!
I am using the KeyboardJS library to handle my key events:
KeyboardJS.on("left", function () {
cc();
x -= xv;
if (x < r) {
circle(x + width, y, r);
if (x + width <= width - r) {
x = x + width;
}
}
circle(x, y, r);
});
KeyboardJS.on("space", null, function () {
console.log("space!");
});
How could I get this behavior to stop so that when the space bar is hit, the ball jumps up but at the same time still moves to the left?
One thought added to everyone else's good ideas:
Separate your user input from your drawing.
Keyboarding:
If you’re having problems with KeyboardJS, check out Keydrown: http://jeremyckahn.github.io/keydrown/
Don’t do any drawing when capturing keys…just capture the user’s input of which direction they want the circle to go.
Set up an “direction” variable to hold how many times the user has pressed [left] or [right]:
var direction=0;
When [left] is pressed:
direction--;
When [right] is pressed:
direction++;
Direction is a net number. So if the user holds down the left key for 20 strokes and the right key for 15 strokes, direction will be -5 ( -20 + 15 ).
Set up an “altitude” variable to hold how many times the user has pressed [space]:
var altitude=0;
When [space] is pressed:
altitude-=10;
Altitude is a net number also.
Drawing:
Do all your drawing in a separate animation loop. Rather than using javascript’s setInterval, use the new and improved way of creating an imation loop -- requestAnimationFrame.
// set the starting circle positions
var currentX=canvas.width;
var currentY=canvas.height-r;
function animate(){
// even as we're executing this current animation loop
// request another loop for next time
requestAnimationFrame(animate);
// change the currentX position by the accumulated direction
currentX+=direction;
direction=0;
// change the currentY position by the accumulated altitude
currentY+=altitude;
altitude=0;
// draw the circle at its current position
cc();
circle(currentX,currentY,r);
// apply gravity to the circle
// to make it fall if its in the air
if(currentY<canvas.height-r){
currentY++;
}
}
Good Luck with your project!
What the problem is, is that if you press another key after pressing the first key, it will trigger that event, and stop triggering the other keydown event. This can be seen in this simplified example:
addEventListener('keydown',function(e) {console.log(e.keyCode, e.keyIdentifier)});
If you run that script, and then press left and then up, it will first show 37 Left a bunch of times, and then it'll show 32 U+0020 once and stop logging the left keydowns.
This is simply how the browser (and most other basic programs too) work. You can try doing the same thing in for example notepad, if you press the A key first, and then press space, it'll stop adding more As. This also means that you can't rely on key events (or key event libraries) to do this for you.
What you could do though, is make a global object that holds all keys that are pressed. For example:
window.KeysDown = {
37: false, //Left
39: false, //Right
38: false, //Up
40: false, //Down
32: false, //Space
};
addEventListener('keydown', function(e) {
var keyCode = e.keyCode||e.charCode||e.which;
if (keyCode == 32 && !window.KeysDown[keyCode])
onSpace();//This will only run when the spacebar is first pressed down.
if (window.KeysDown.hasOwnProperty(keyCode))
window.KeysDown[keyCode] = true;
});
addEventListener('keyup', function(e) {
var keyCode = e.keyCode||e.charCode||e.which;
if (window.KeysDown.hasOwnProperty(keyCode)) window.KeysDown[keyCode] = false;
});
var interval = setInterval(function() {
for (var i in window.KeysDown) {
if (window.KeysDown[i]) switch (i+'') {
case '37': onLeft(); break;
//case '38': window.KeysDown[i] && onUp(); break;
case '39': onRight(); break;
//case '40': window.KeysDown[i] && onDown(); break;
}
}
}, 50);
The syntax window.KeysDown[i] && onLeft() causes the onLeft function only to run if window.KeysDown[i] is true. I hope this solution works for you.
EDIT: I've changed the code to the working one. I've also made a JSFiddle that demonstrates this. The problem in my previous code was that apparently a switch doesn't handle integer values well, so I needed to convert i to a string.
EDIT: I've also added an extra part to the script that makes the onSpace function only run when the spacebar is first pressed down, and so that it won't run again until the spacebar is released and pressed again. I've also updated my JSFiddle to include these changes.
I would create a main function, which runs at a regular interval, and each time it runs, it updates the position of the circle based on what keys are currently down.
The main function can be done like this:
var keyDown = {};
function mainLoop() {
cc();
//pseudo code
if (keyDown["left"]) {
x -= 5;
}
if(keyDown["space"]) {
y -= 10;
}
// redraw circle at new location
circle(x,y,r);
}
setInterval(mainLoop, 30) //sets the function to be called every 30 milliseconds
// key event handler, first function handles the keydown, second function handles keyup
KeyboardJS.on("left", function() {
keyDown["left"] = true;
}, function() {
keyDown["left"] = false;
});
With this example, if the user had the left arrow key and space bar pressed when the mainLoop function ran, then the circle would move to the left 5 pixels, and up 10 pixels.
jsFiddle Demo
You are going to have to manually create a framework for this. KeyboardJS just wasn't cutting it. I guess I kind of set that up here. It uses an Action "class" coupled with key event triggers.
Action "class"
function Actions(){
this.count = 0;
this.running = {};
this.interval = undefined;
}
Actions.prototype.start = function(action){
if( typeof(this.running[action]) == "undefined"){
this[action]();
this.running[action] = action;
this.count++;
}
var me = this;
if( typeof(this.interval) == "undefined"){
this.interval = setInterval(function(){
for( var act in me.running ){
me[act]();
}
},50);
}
};
Actions.prototype.stop = function(action){
this.running[action] = void 0;
delete this.running[action];
this.count--;
if( this.count == 0 ){
clearInterval(this.interval);
this.interval = void 0;
};
};
Actions.prototype.left = function(){
cc();
x -= xv;
if (x < r) {
circle(x + width, y, r);
if (x + width <= width - r) {
x = x + width;
}
}
circle(x, y, r);
};
Actions.prototype.right = function(){
cc();
x += xv;
if (x >= width - r) {
circle((x - r) - (width - r), y, r);
if ((x - r) - (width - r) > r) {
x = (x - r) - (width - r);
}
}
circle(x, y, r);
};
Actions.prototype.space = function(){
cc();
y -= yv;
circle(x, y, r);
};
key event triggers
document.onkeydown = checkKeyDown;
function checkKeyDown(e) {
e = e || window.event;
if (e.keyCode == '37') {
// left arrow
actions.start("left");
}
if (e.keyCode == '39') {
// right arrow
actions.start("right");
}
if (e.keyCode == '32') {
// space bar
actions.start("space");
}
}
document.onkeyup = checkKeyUp;
function checkKeyUp(e) {
e = e || window.event;
if (e.keyCode == '37') {
// left arrow
actions.stop("left");
}
if (e.keyCode == '39') {
// right arrow
actions.stop("right");
}
if (e.keyCode == '32') {
// space bar
actions.stop("space");
}
}

Jump Animation in JavaScript

My newest Hobby Project is a very simple Jump'n'Run Game using JavaScript. I already wrote some code (with the help of a tutorial at lostdecadegames) and read everything about the GameLoop.
var start = true;
// Create the canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 1200;
canvas.height = 480;
document.body.appendChild(canvas);
var jumping = false;
var gravity = 1.5;
var pressed = true;
// Background image
var bgReady = false;
var bgImage = new Image();
bgImage.onload = function () {
bgReady = true;
};
bgImage.src = "background.png";
// Hero image
var heroReady = false;
var heroImage = new Image();
heroImage.onload = function () {
heroReady = true;
};
heroImage.src = "hero.png";
// Monster image
var monsterReady = false;
var monsterImage = new Image();
monsterImage.onload = function () {
monsterReady = true;
};
monsterImage.src = "monster.png";
// Game objects
var hero = {
speed_x: 50,
speed_y_up: 50,
speed_y_down: 50, // movement in pixels per second
velocity_x: 50,
velocity_y: 50
};
// Handle keyboard controls
var keysDown = {};
addEventListener("keydown", function (e) {
keysDown[e.keyCode] = true;
}, false);
addEventListener("keyup", function (e) {
delete keysDown[e.keyCode];
}, false);
// Update game objects
var update = function (modifier) {
if(38 in keysDown) { // Player holding up
jumping = true;
//hero.y -= hero.speed_y_up * modifier;
}
if (40 in keysDown) { // Player holding down
hero.y += hero.speed_y_down * modifier;
}
if (37 in keysDown) { // Player holding left
hero.x -= hero.speed_x * modifier;
}
if (39 in keysDown) { // Player holding right
hero.x += hero.speed_x * modifier;
}
};
// Draw everything
var render = function () {
if (bgReady) {
ctx.drawImage(bgImage, 0, 0);
}
if (heroReady) {
if(hero.y > 0 && hero.y < 480 && hero.x <= -32)
{
hero.x = hero.x + 1232;
ctx.drawImage(heroImage, hero.x, hero.y);
}
else if(hero.y > 0 && hero.y < 480 && hero.x >= 1200)
{
hero.x = hero.x - 1232;
ctx.drawImage(heroImage, hero.x, hero.y);
}
else if(jumping)
{
ctx.drawImage(heroImage, hero.x, hero.y-100);
jumping = false;
}
else ctx.drawImage(heroImage, hero.x, hero.y);
}
if (monsterReady) {
ctx.drawImage(monsterImage, monster.x, monster.y);
}
};
// The main game loop
var main = function () {
var now = Date.now();
var delta = now - then;
update(delta / 500);
render();
then = now;
};
// Starting the game!
reset();
var then = Date.now();
setInterval(main, 1); // Execute as fast as possible
As you can see, I already added a fix gravity var and some speed vars. The Hero moves very smooth, so this is no problem.
I have 2 problems with the jump-Animation:
The Hero stays in the air, when the Up-Key is keep being pressed. I tried to fix this with some boolean vars, but I couldn't figure it out how to get the Hero down again.
Right now, I implemented a "dirty hack" which causes the Hero to be repainted 50px higher, but I want a smooth Jump, so that the Hero gets slower while going up and speeds up while falling. I looked up so many Tutorials and so much Example Code, but I'm too stupid to figure it out, how I get my desired Animation.
Hope you guys can give me some advice for my problem (I'm not asking for the final code, I just need some tips).
It's hard to understand exactly what the if statements inside of if (heroReady) are doing because the numbers don't mean anything to me, but it seems to me like your problem is in there.
First of all, it seems to me like jumping should the first condition checked. If one of the first conditions is true, then it doesn't matter whether or not he's jumping. I can't easily tell when each condition is true, though, so I'm going to assume that when the player is holding up,
else if(jumping)
{
ctx.drawImage(heroImage, hero.x, hero.y-100);
jumping = false;
}
gets executed like normal.
Now, assuming that, I think your issue is that jumping is determined solely by whether or not the player is holding up, because as soon as jumping is true, it becomes false. This is incorrect.
Jumping should be set to true when the player presses the up key, but it should be set to false when they remove it. It should be set to false when the animation hits the ground.
Another issue that you have is the fact that you aren't actually using the hero's attributes to render its jumping location, you're simply offsetting it. Perhaps that is just your workaround until the problem is solved, but it makes it hard to tell when the character hits the ground, because you can't start lower the character (increasing the y value) after they jump, since you never raised them by decreasing the y value.
So how do we fix this?
Here are my recommendations. You might find more elegant ways to do it by the time you're done due to refactoring, but the way you have it set up right now I think it will work fine:
Set jumping as soon as they press up, like you're doing, but only if jumping == false, because presumably your hero can't do mid-air jumps.
Immediately after you set jumping (and inside the same if statement), update their velocity.
In your update section, add another if for whether or not the player is jumping, regardless of whether or not they are pressing any keys. If they are, decrease their momentum based on gravity. Then, add a check for if their momentum is the opposite of how much you increase it when they start jumping. In other words, check if they are moving down at exactly the same rate they were moving up when they started jump. This happens at exactly the y-coordinate that they began the jump from. (This is more reliable that just checking their position, because it will work from multiple y-locations.) The alternative would be to store a variable with the y-coordinate they were at when they jumped. Either way, if their jump has ended, set jumping to false.
Since you're updating their coordinates based on jumping, in your render function, you can eliminate any jumping logic and just draw the image based on the coordinates.
Does that help at all?

JavaScript move delay and multiple keystrokes

Here is my problem: http://testepi.kvalitne.cz/test/
I do not want the delay between a keypress and the movement of the square. I would also like to know how to move diagonally (pressing two keys at same time).
My code:
$(function(){
document.addEventListener("keydown", move, false);
var x = 0;
var y = 0;
function move(event){
if(event.keyCode==37){
x -= 10;
$("#square").css("left", x);
}
if(event.keyCode==39){
x += 10;
$("#square").css("left", x);
}
if(event.keyCode==38){
y -= 10;
$("#square").css("top", y);
}
if(event.keyCode==40){
y += 10;
$("#square").css("top", y);
}
}
});
First, to avoid the keypress/repeat delay, you have to wrap your program in a loop, and make the state of the keyboard available inside the scope of that loop, secondly to monitor multiple keypresses you need to keep track of individual keydown and keyup events:
var x = 0;
var y = 0;
// store the current pressed keys in an array
var keys = [];
// if the pressed key is 38 (w) then keys[38] will be true
// keys [38] will remain true untill the key is released (below)
// the same is true for any other key, we can now detect multiple
// keypresses
$(document).keydown(function (e) {
keys[e.keyCode] = true;
});
$(document).keyup(function (e) {
delete keys[e.keyCode];
});
// we use this function to call our mainLoop function every 200ms
// so we are not relying on the key events to move our square
setInterval( mainLoop , 200 );
function mainLoop() {
// here we query the array for each keyCode and execute the required actions
if(keys[37]){
x -= 10;
$("#square").css("left", x);
}
if(keys[39]){
x += 10;
$("#square").css("left", x);
}
if(keys[38]){
y -= 10;
$("#square").css("top", y);
}
if(keys[40]){
y += 10;
$("#square").css("top", y);
}
}
If you are trying to implement game-like 2d sprite movement, I suggest you have a notion of x and y velocity, rather than moving the sprite a fixed amount on keypress.
So on keypress, add or subtract from x or y velocity.
var xvel = 0,
yvel = 0,
x = 0,
y = 0;
setInterval(function () {
y += yvel;
x += xvel;
$("#square").css("left", x);
$("#square").css("top", y);
}, 16); //run an update every 16 millis
document.addEventListener("keydown", move, false);
function move(event){
if(event.keyCode==37){
xvel -= 10;
}
if(event.keyCode==39){
xvel += 10;
}
if(event.keyCode==38){
yvel -= 10;
}
if(event.keyCode==40){
yvel += 10;
}
}
You would also need to worry about a keyup event, however, as the velocity would stay until you cancelled it out.
You can use setInterval to update the position of the sprite every x milliseconds. (Game tick)
To move diagonally, just add/subtract from the velocity of both x and y simultaneously.
This is just an example, but there are more examples out there on sprite movement.
have you looked here? you should be able to do diagonal moving by checking if multiple keys have been pressed down without being released.

Categories