So the operating system has a delay when you hold down a key. It will execute the command once, delay, then repeat. I tried to bypass this with setting a variable to true or false based on when the key has "keydown" and "Keyup." I am not sure why it is not working though. I am not sure if I am forgetting about something, but If someone could explain why my code is still not fixing the issue.
Variables
var keyPressed = {Kleft: 37, Kright: 39, Kup: 38, Kdown: 40, Kspace: 32};
key = {K37: false, K39: false, K38: false, K40: false, K32: false};
detect for key being pressed
//to detect multiple keys being pressed
$(document).keydown(function(e) {
if(keyPressed.Kleft) //left arrow
{
console.log('test');
key.K37 = true;
airplane.performAction();
}
if(keyPressed.Kright) //right arrow
{
key.K37 = true;
// airplane.performAction();
}
if(keyPressed.Kup) //up arrow
{
key.K37 = true;
// airplane.performAction();
}
if(keyPressed.Kdown) //down arrow
{
key.K37 = true;
// airplane.performAction();
}
if(keyPressed.Kspace) //space key
{
key.K37 = true;
bullet = new Bullet({x: airplane.position.x+32, y: airplane.position.y-12}, bullets_total++); //create a new bullet
bullets.push(bullet); //store the bullet in the bullets array
}
}).keyup(function(e) {
key.K37 = false; //testing just one key for now
console.log('ehhlo');
// console.log(key['K'+toString(e)]);
// key['K'+toString(e)] = false;
});
the executed function on Keypress
function MyAirplane()
{
this.performAction = function(action)
{
if(key.K37 === true){
console.log('left');
this.position.x -= 10;
}
if(key.K37 == true){
this.position.x += 10;
}
if(key.K37 == true){
this.position.y -= 10;
}
if(key.K37 == true){
this.position.y += 10;
}
}
}
Just an idea, try not automatically calling performAction.
//to detect multiple keys being pressed
$(document).keydown(function(e) {
if(keyPressed.Kleft) //left arrow
{
key.K37 = true;
}
if(keyPressed.Kright) //right arrow
{
key.K37 = true;
}
if(keyPressed.Kup) //up arrow
{
key.K37 = true;
}
if(keyPressed.Kdown) //down arrow
{
key.K37 = true;
}
if(keyPressed.Kspace) //space key
{
key.K37 = true;
bullet = new Bullet({x: airplane.position.x+32, y: airplane.position.y-12}, bullets_total++); //create a new bullet
bullets.push(bullet); //store the bullet in the bullets array
}
}).keyup(function(e) {
key.K37 = false; //testing just one key for now
console.log('ehhlo');
// console.log(key['K'+toString(e)]);
// key['K'+toString(e)] = false;
});
And create an event timer:
function MyAirplane()
{
this.performAction = function(action)
{
if(key.K37 === true){
console.log('left');
this.position.x -= 10;
}
if(key.K37 == true){
this.position.x += 10;
}
if(key.K37 == true){
this.position.y -= 10;
}
if(key.K37 == true){
this.position.y += 10;
}
}
// 60 frames per second event checker.
var eventLoop = setInterval(this.performAction.bind(this), 1000 / 60);
}
Related
I am trying to make a 2D platforming game and I am missing an essential part of it, gravity.
I have tried everything from look at questions on this website to looking at online tutorials and you-tube videos.
I really need help with getting gravity into this game as I am out of ideas.
As I said I have already tried looking at multiple tutorials and videos, including this one:
http://www.somethinghitme.com/2013/01/09/creating-a-canvas-platformer-tutorial-part-one/
but this one uses shapes created in canvas rather than images.
I already know that you have to use a velocity function as well as variable for the gravity. Then you have to put this all inside the key handler function so that it can get executed.
//spaceman variables
var sx = canvasWidth / 2; // start the spaceman in the centre
var sy = canvasHeight / 2;
var sdx = 0; // set initial speed to 0
var sdy = 0;
var sspeed = 3; // create a variable for speed
var gravity = 0.2;
var svX = 0;
var svY = (Math.random() * -10) - 5;
//set variables to use for key presses
//these are Boolean variables
//they can only be true or false
var rightPressed = false;
var leftPressed = false;
var upPressed = false;
var downPressed = false;
function keyDownHandler(e) {
if (e.keyCode == 39) {
rightPressed = true;
} else if (e.keyCode == 37) {
spaceman2Ready = true;
spacemanReady = false;
leftPressed = true;
} else if (e.keyCode == 38) {
upPressed = true;
} else if (e.keyCode == 40) {
downPressed = true;
}
}
function keyUpHandler(e) {
if (e.keyCode == 39) {
rightPressed = false;
sdx--;
} else if (e.keyCode == 37) {
spaceman2Ready = false;
spacemanReady = true;
leftPressed = false;
sdx--;
} else if (e.keyCode == 38) {
upPressed = false;
sdx--;
} else if (e.keyCode == 40) {
downPressed = false;
sdx--;
}
}
// add something to "listen" for an event
//an event is keypress, mouse movement, mouse click etc.
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (rightPressed == true) {
sdx = sspeed;
} else if (leftPressed == true) {
sdx = -sspeed;
} else if (upPressed == true) {
sdy = -sspeed;
} else if (downPressed == true) {
sdy = sspeed
}
if (rightPressed == false && leftPressed == false && upPressed == false && downPressed == false) {
sdx = 0;
sdy = 0;
}
sx = sx + sdx;
sy = sy + sdy;
}
if (spacemanReady) {
ctx.drawImage(spacemanImage, sx, sy);
if (spaceman2Ready) {
ctx.drawImage(spaceman2Image, sx, sy);
}
// basically the setTimeout part, but this time its requesting the function that we made at the top
requestAnimationFrame(draw);
}
// this is to get the loop for the animation to start going
window.addEventListener("load",
function() {
draw();
});
< /script>
</body >
</html>/
You should be using gravity to update your position every frame (in the draw function). This would look like:
if(sy > 0){
sdy += gravity
}
I have created a codepen with your game with gravity. I hope this helps!
I'm making a game in which a player character moves left and right.
Since simply using an onKeyDown eventListener had my character move in a choppy fashion, and with a slight delay, I tried using requestAnimationFrame to call the movement function as often as possible, as suggested by another answer(How can I move my JS objects smoothly using keyboard input?)
however, that has changed nothing.
Here is my Javascript Code
var NodoCampo = document.getElementById("campo");
var NodoGiocatore = null;
var Left = false;
var Right = false;
var FRAMERATE = 20;
//cache giocatore
var LARG_GIOCATORE = 30;
var ALT_GIOCATORE = 30;
var X_GIOCATORE = 300;
var Y_GIOCATORE = 1100;
var VEL_GIOCATORE = 10;
function mostra_giocatore() {
if (NodoGiocatore === null) {
NodoGiocatore = document.createElement('div');
NodoGiocatore.setAttribute ('id', 'player');
NodoCampo.appendChild (NodoGiocatore);
}
NodoGiocatore.style.marginLeft = (X_GIOCATORE - LARG_GIOCATORE) + 'px';
NodoGiocatore.style.marginTop = (Y_GIOCATORE - ALT_GIOCATORE) + 'px';
}
function muovi() {
if (Left) {
X_GIOCATORE = X_GIOCATORE - VEL_GIOCATORE;
//aggiorno immagine
mostra_giocatore();
}
else if (Right) {
X_GIOCATORE = X_GIOCATORE + VEL_GIOCATORE;
//aggiorno immagine
mostra_giocatore();
}
}
function stop() {
Left = false;
Right = false;
}
function interfaccia(e) {
//freccia sinstra
if (e.keyCode === 37) {
X_GIOCATORE = X_GIOCATORE - VEL_GIOCATORE;
//aggiorno immagine
mostra_giocatore();
}
//freccia destra
else if (e.keyCode === 39) {
X_GIOCATORE = X_GIOCATORE + VEL_GIOCATORE;
//aggiorno immagine
mostra_giocatore();
}
}
function inizia() {
mostra_giocatore();
requestAnimationFrame(muovi);
}
window.document.onkeypress = interfaccia;
window.document.onkeyup = stop;
Your choppy movement is likely a result of the amount you are moving the player on each frame with VEL_GIOCATORE. Try reducing this amount to observe smoother movement.
The delay you are experiencing is likely due to your operating system or browsers individual settings on how key presses should repeat. You can work around this by implementing your own key tracking -- it looks like you've started to experiment with this. Track the state of your left and right keys by updating a boolean value in onkeydown and onkeyup event listeners.
var keys = {
left: false,
right: false
};
window.document.onkeydown = function (e) {
if (e.keyCode === 37) {
keys.left = true;
} else if (e.keyCode === 39) {
keys.right = true;
}
window.document.onkeyup = function (e) {
if (e.keyCode === 37) {
keys.left = false;
} else if (e.keyCode === 39) {
keys.right = false;
}
Then, in your muovi function, check the state of these variables to determine if you should update the position of the player.
I'm recreating the classic pong game in Javascript and I have a loop that updates the game state then redraws the whole game.
Setting the height of the game:
var leftHeight = 225;
var rightHeight = 225;
the paddle state and the key to change their state:
var keyWPressed = false;
var keySPressed = false;
var keyArrowUpPressed = false;
var keyArrowDownPressed = false;
window.addEventListener('keydown', function (evt) {
if (evt.keyCode === 87) {
keyWPressed = true;
keySPressed = false; // the player can hold down both keys at once, but
// we want the last pressed key to take precedence
} else if (evt.keyCode === 83) {
keySPressed = true;
keyWPressed = false; // last keypress takes precedence
} else if (evt.keyCode === 38) { // up arrow
keyArrowUpPressed = true;
keyArrowDownPressed = false; // last keypress takes precedence
} else if (evt.keyCode === 40) { // down arrow
keyArrowDownPressed = true;
keyArrowUpPressed = false; // last keypress takes precedence
} else if (evt.keyCode === 82) { // 'r'
// when a player has won, hitting 'r' resets the game
if (winner) {
restartGame();
}
}
});
updating the paddle state and looping the game:
function update(){
if (keyWPressed && leftHeight != 0){
leftHeight = leftHeight - 5;
}else if (keySPressed && leftHeight != 450){
leftHeight = leftHeight + 5;
}
if (keyArrowUpPressed && rightHeight != 0){
rightHeight = rightHeight - 5;
}else if (keyArrowDownPressed && rightHeight != 450){
rightHeight = rightHeight + 5;
}
}
function gameloop(){
update();
draw();
window.requestAnimationFrame(gameloop);
}
the problem is, whenever I press a key, for example, the W key, the paddle moves up at a single press when what I really want is for it to move only when the player is pressing and holding on to the W key.
Hi I've taken the code (to move objects with arrow keys) from some internet template. Since then, I've limited the area that the object can be moving around but I still have a problem that when I press an arrow key the object moves more than necessary, I just want to move it 20px in the appropriate direction, regardless how long the key is pressed.
Here are the functions:
var GameInput = (function() {
var pressedKeys = {};
function setKey(event, status) {
var code = event.keyCode;
var key;
switch(code) {
case 32:
key = 'SPACE'; break;
case 37:
key = 'LEFT'; break;
case 38:
key = 'UP'; break;
case 39:
key = 'RIGHT'; break;
case 40:
key = 'DOWN'; break;
default:
// Convert ASCII codes to letters
key = String.fromCharCode(event.keyCode);
}
pressedKeys[key] = status;
}
document.addEventListener('keydown', function(e) {
setKey(e, true);
});
document.addEventListener('keyup', function(e) {
setKey(e, false);
});
function isDown(key) {
return pressedKeys[key];
}
return {
isDown: isDown
};
})();
And the function calling it:
function update() {
if(GameInput.isDown('DOWN')) {
if(player.y < canvas.height - player.sizeY) {
player.y += 20;
}
}
if(GameInput.isDown('UP')) {
if(player.y > 0) {
player.y -= 20;
}
}
if(GameInput.isDown('LEFT')) {
if(player.x > 0) {
player.x -= 20;
}
}
if(GameInput.isDown('RIGHT')) {
// Don't go out of canvas
if(player.x < canvas.width - player.sizeX) {
player.x += 20;
}
}
// You can pass any letter to `isDown`, in addition to DOWN,
// UP, LEFT, RIGHT, and SPACE:
// if(GameInput.isDown('a')) { ... }
}
I understand why it does what it does but I have not been able to modify it to only move 20px regardless how much time a key is pressed.
Thank you
How about using the keyup event to allow the operation to repeat only when a new key is pressed. Something like:
var allowRepeat = true;
document.addEventListener('keydown', function(e) {
if (allowRepeat) {
setKey(e, true);
}
allowRepeat = false;
});
document.addEventListener('keyup', function(e) {
allowRepeat = true;
setKey(e, false);
});
I think your logic is a little reverted, what you want is to disallow update 'before key up is fired', from your code, as long as the keyUp event is not fired, isDown('XXX') is still true..
So this is what you need: (you should do some refactoring, but this should work)
var GameInput = (function() {
....
var _allowUpdate = {};
function setKey(event, status) {
var code = event.keyCode;
var key;
switch(code) {
case 32:
key = 'SPACE'; break;
case 37:
key = 'LEFT'; break;
case 38:
key = 'UP'; break;
case 39:
key = 'RIGHT'; break;
case 40:
key = 'DOWN'; break;
default:
// Convert ASCII codes to letters
key = String.fromCharCode(event.keyCode);
}
// This checks whether it's the first time the key being pressed.
allowUpdate[key] = !pressedKeys[key] && status;
pressedKeys[key] = status;
}
function allowUpdate(key) {
_allowUpdate[key] ;
}
return {
allowUpdate: allowUpdate
};
}
function update() {
if(GameInput.allowUpdate('DOWN')) {
if(player.y < canvas.height - player.sizeY) {
player.y += 20;
}
}
.....
}
I am making a Snake game so I'm trying to move my snake. It is moving with keys but it should move automatically on the screen. I tried doing that with while loops like in the code below but because of break; I have to press a key every time I want it to move. How can I make it move automatically? I tried removing break; an using an if statement but I didn't succeed.
Any other solutions or something else?
I'm new to programming so any advices would be helpful.
var main = function() {
var i = 0;
var j = 0;
$(document).keyup(function(event) {
var e = event.which;
while(i == 1) {
$('.snake').animate({left: '+=10px'}, 10);
break;
}
while(i == 2) {
$('.snake').animate({left: '-=10px'}, 10);
break;
}
while(i == 3) {
$('.snake').animate({top: '-=10px'}, 10);
break;
}
while(i == 4) {
$('.snake').animate({top: '+=10px'}, 10);
break;
}
//Which key is preesed
//D
if(e == 68) {
i = 1;
}
//A
else if(e == 65) {
i = 2;
}
//W
else if(e == 87) {
i = 3;
}
//S
else if(e == 83) {
i = 4;
}
//Any other key
else {
i = 0;
}
});
};
$(document).ready(main);
I think you just have to organize a little bit your code.
First. You must put your code inside a function. You really don't need a while. You can use a simple if.
function move(i) {
if(i == 1) {
$('.snake').animate({left: '+=10px'}, 10);
break;
}
if(i == 2) {
$('.snake').animate({left: '-=10px'}, 10);
break;
}
if(i == 3) {
$('.snake').animate({top: '-=10px'}, 10);
break;
}
if(i == 4) {
$('.snake').animate({top: '+=10px'}, 10);
break;
}
}
Now you have to change the event, using keydown instead of keyup
function main() {
var interval;
$(document).keydown(function(event) {
if(interval) clearInterval(interval); // Clear the previous interval
var e = event.which;
var i;
//Which key is pressed
//D
if(e == 68) {
i = 1;
}
//A
else if(e == 65) {
i = 2;
}
//W
else if(e == 87) {
i = 3;
}
//S
else if(e == 83) {
i = 4;
}
//Any other key
else {
i = 0;
}
interval = setInterval(function() {
move(i)
},1000); // repeat every 1 second
});
}
$(document).ready(main);