I'm making a snake game in JS. Right now I'm trying to write a condition that compares the position of the snake head and the position of the food to see if the snake has made contact with it. If so I want to alert the user. Except the condition isn't working for some reason. I've made another version of this game and I used the same condition in that one, so this is really confusing Any ideas?
//declare global variables
const canvas = document.querySelector('#canvas');
//set canvas context
const ctx = canvas.getContext('2d');
//put canvas dimensions into variables
const cvsW = canvas.width;
const cvsH = canvas.height;
//create snake unit
const unit = 16;
//create snake and set starting position
let snake = [{
x : cvsW/2,
y : cvsH/2
}]
//create food object and set its position somewhere on board
let food = {
//Math.floor(Math.random()*cvsW + 1)---number from 1 to 784
//Math.floor(Math.random()*cvsW/unit + 1)---number from 1 to 79
//Math.floor(Math.random()*cvsW/unit + 1)*unit---number from 1 to 784(but it's a multiple of unit)
//Math.floor(Math.random()*(cvsW/unit - 1)+1)*unit---same as above but -1 keeps food inside canvas
x : Math.floor(Math.random()*(cvsW/unit - 1)+1)*unit,
y : Math.floor(Math.random()*(cvsH/unit - 1)+1)*unit
}
//create a variable to store the direction of the snake
let direction;
//add event to read users input then change direction
document.addEventListener('keydown', (e) => {
if(e.keyCode == 37 && direction != 'right') direction = 'left';
else if (e.keyCode == 38 && direction != 'down') direction = 'up';
else if (e.keyCode == 39 && direction != 'left') direction = 'right';
else if (e.keyCode == 40 && direction != 'up') direction = 'down';
})
function draw() {
//clear canvas and redraw snake and food
ctx.clearRect(0, 0, cvsW, cvsH);
ctx.fillStyle = 'limegreen';
ctx.fillRect(snake[0].x-unit/2, snake[0].y-unit/2, unit, unit);
ctx.fillStyle = 'red';
ctx.fillRect(food.x, food.y, unit, unit);
//move snake in chosen direction
changeDirection();
//check to see if snakes eaten
if(snake[0].x === food.x && snake[0].y === food.y) {
alert('yo');
}
//check to see if snake has hit a wall
collision(snake[0].x, snake[0].y);
}
let runGame = setInterval(draw, 70);
function changeDirection() {
if(direction == 'left') snake[0].x -= unit;
else if(direction == 'right') snake[0].x += unit;
else if(direction == 'up') snake[0].y -= unit;
else if(direction == 'down') snake[0].y += unit;
}
function collision(x, y) {
if(x < 0 || x > cvsW || y < 0 || y > cvsH) {
clearInterval(runGame);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Snake</title>
<style>
body {
background-color: #333;
}
#canvas {
background-color: #4d4d4d;
display: block;
margin: auto;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
</style>
</head>
<body>
<canvas id="canvas" width="784" height="528"></canvas>
<script src="script.js"></script>
</body>
</html>
The issue seems to be here
let direction;
//add event to read users input then change direction
document.addEventListener('keydown', (e) => {
if(e.keyCode == 37 && direction != 'right') direction = 'left';
else if (e.keyCode == 38 && direction != 'down') direction = 'up';
else if (e.keyCode == 39 && direction != 'left') direction = 'right';
else if (e.keyCode == 40 && direction != 'up') direction = 'down';
})
In this case the direction is undefined so no value will be assigned the direction
Related
I want the movement to be smooth upon pressing a key, the object does an initial movement and then starts moving completely when holding down the button.
//movement speed
var xSpeed = 0.5;
var zSpeed = 0.5;
document.addEventListener("keydown", onDocumentKeyDown, false);
function onDocumentKeyDown(event) {
var keyCode = event.which;
if (keyCode == 87) { //W KEY
car.position.z -= zSpeed;
} else if (keyCode == 83) { //S KEY
car.position.z += zSpeed;
} else if (keyCode == 65) { //A KEY
car.position.x -= xSpeed;
} else if (keyCode == 68) { //D KEY
car.position.x += xSpeed;
} else if (keyCode == 32) {
car.position.set(0, 0, 0);
}
};
Trying to get a GLTF imported model to be controlled on a plane with keyboard controls smoothly.
Tried wrapping the program in a loop and made the state of the keyboard available inside the scope of that loop but couldn't get it working
You could try an approach where the velocity is modified upon keyup/keydown, and the loop just modifies the car's position based on the velocity.
// initial movement speed
var xSpeed = 0;
var zSpeed = 0;
document.addEventListener("keydown", onDocumentKeyDown, false);
document.addEventListener("keydown", onDocumentKeyUp, false);
function onDocumentKeyDown(event) {
var keyCode = event.which;
if (keyCode == 87) { //W KEY
zSpeed = -0.5;
} ... // do so for the rest of the keys
};
function onDocumentKeyUp(event) {
var keyCode = event.which;
if (keyCode == 87) { //W KEY
zSpeed = 0;
} ... // do so for the rest of the keys
};
function loop() {
car.position.z += zSpeed;
car.position.x += xSpeed;
window.requestAnimationFrame(loop);
}
If you are interested in more eased movement, e.g. the car doesn't just start moving at constant velocity but ramps up and slows down, consider having the keyup/keydown modify an acceleration factor, and the loop modifies the velocity.
This is a good in-depth article by Daniel Shiffman about attempting to represent the real world with code:
https://natureofcode.com/book/chapter-1-vectors/
I am trying to control a Sprite using the arrow keys (UP/DOWN for Translation & LEFT/RIGHT for Rotation).
I need the sprite to translate in the direction it has been rotated in.
The issue is that when the sprite is rotated after the sprite has been translated, the position of the sprite resets to where it was originally. I have tried using one div for rotation and one div for translation to no success.
The problem I am facing is a little different to the usual "moving div around screen" issue because I need to move the div at angles and continue to move at that angle.
I feel I am overlooking a simple solution, I would really appreciate if someone could point me in the right direction! Is there an easier alternative to what I am attempting to do that someone could make me aware of?
I have created a JSFiddle to demonstrate what is going on:
CSS transform sprite fiddle
var r = document.getElementById("image2");
document.addEventListener("keyup", checkKeyUp);
document.addEventListener("keydown", checkKey);
var trany = 0;
var rotate = 0;
function checkKey(e) {
e = e || window.event;
if (e.keyCode == '38') {
// up arrow
trany = trany-1;
r.style.transform = 'rotate('+rotate+'deg)translateY('+trany+'vmin)';
}
else if (e.keyCode == '40') {
// down arrow
trany = trany+1;
r.style.transform = 'rotate('+rotate+'deg)translateY('+trany+'vmin)';
}
else if (e.keyCode == '37') {
// left arrow
rotate = rotate-.8;
r.style.transform = 'translateY('+trany+'vmin)rotate('+rotate+'deg)';
}
else if (e.keyCode == '39') {
// right arrow
rotate = rotate+.8;
r.style.transform = 'translateY('+trany+'vmin)rotate('+rotate+'deg)';
}
}
function checkKeyUp(e) {
e = e || window.event;
if (e.keyCode == '38') {
// up arrow
}
else if (e.keyCode == '40') {
// down arrow
}
else if (e.keyCode == '37') {
// left arrow
r.style.transform = 'translateY('+trany+'vmin)rotate('+rotate+'deg)';
}
else if (e.keyCode == '39') {
// right arrow
r.style.transform = 'translateY('+trany+'vmin)rotate('+rotate+'deg)';
}
}
#myAnimation {
top:250px;
left:250px;
position: absolute;
}
#image2 {
width:40%
}
img {
width: 30%;
}
<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<body>
<div id ="myContainer">
<div id="image1" style="height:300px;width:500px; background-
color:red;"></div>
</div>
<div id ="myAnimation">
<image id="image2" src="https://banner2.kisspng.com/20180415/pge/kisspng-arrow-desktop-wallpaper-symbol-clip-art-up-arrow-5ad37ddc82f384.4572004515238097565364.jpg" style="bottom:0px;width:10%"></image>
</div>
</body>
</html>
what you want to achieve is to move your element independently from its previous state and this cannot be achieved using only transform since transform always consider the initial state in order to move your element.
An idea is to consider using bottom/left to move the element and use only transform to rotate the element. The angle of rotation will define how you will adjust the bottom and left properties:
var r = document.getElementById("image2");
document.addEventListener("keydown", checkKey);
var rotate = 0;
var left=0;
var bottom= 0;
function checkKey(e) {
e = e || window.event;
if (e.keyCode == '38') {
// up arrow
r.style.left = left + Math.sin(rotate*Math.PI/180) + 'px';
r.style.bottom = bottom + Math.cos(rotate*Math.PI/180) + 'px';
} else if (e.keyCode == '40') {
// down arrow
r.style.left = left - Math.sin(rotate*Math.PI/180) + 'px';
r.style.bottom = bottom - Math.cos(rotate*Math.PI/180) + 'px';
} else if (e.keyCode == '37') {
// left arrow
rotate = rotate - .8;
r.style.transform = 'rotate(' + rotate + 'deg)';
} else if (e.keyCode == '39') {
// right arrow
rotate = rotate + .8;
r.style.transform = 'rotate(' + rotate + 'deg)';
}
left = parseFloat(r.style.left);
bottom = parseFloat(r.style.bottom);
}
#image2 {
width: 40px;
position: absolute;
}
<img id="image2" src="https://banner2.kisspng.com/20180415/pge/kisspng-arrow-desktop-wallpaper-symbol-clip-art-up-arrow-5ad37ddc82f384.4572004515238097565364.jpg" style="left:0;bottom:0;">
To fix this problem we need to understand how transform works. It does each step one by one. If we want, for example to move diagonally, first we need to rotate, then translate. If we want to make the next move, our previous steps need to be saved. If we don't remember them, the arrow will be animated from the beginning.
So, on each animation end (key up) we need to save all the previous steps.
The next step is all the previous steps + translate/rotate.
Here is your code that I think is working correctly:
var r = document.getElementById("image2");
document.addEventListener("keyup", checkKeyUp);
document.addEventListener("keydown", checkKey);
var saved_moves = '';
var trany = 0;
var rotate = 0;
function checkKey(e) {
e = e || window.event;
if (e.keyCode == '38') {
// up arrow
trany = trany-1;
r.style.transform = saved_moves + 'translateY('+trany+'vmin)';
}
else if (e.keyCode == '40') {
// down arrow
trany = trany+1;
r.style.transform = saved_moves + 'translateY('+trany+'vmin)';
}
else if (e.keyCode == '37') {
// left arrow
rotate = rotate-2;
r.style.transform = saved_moves + 'rotate('+rotate+'deg)';
}
else if (e.keyCode == '39') {
// right arrow
rotate = rotate+2;
r.style.transform = saved_moves + 'rotate('+rotate+'deg)';
}
}
function checkKeyUp(e) {
e = e || window.event;
if (e.keyCode == '37' || e.keyCode == '38' || e.keyCode == '39' || e.keyCode == '40') {
// every arrow
saved_moves = r.style.transform;
// reset trany and rotate values
trany = 0;
rotate = 0;
}
}
You can check this jsfiddle https://jsfiddle.net/cyv0j1du/49/
EDIT
Becouse the solution above would create a very long transform, I've came up with different solution. When you release the key, app is reading the matrix value, and then it changes the arrow top and left value. Now only rotate value is remembered.
// Based on the absolute position you've chosen
var left = 250;
var top = 250;
function checkKeyUp(e) {
e = e || window.event;
if (e.keyCode == '37' || e.keyCode == '38' || e.keyCode == '39' || e.keyCode == '40') {
var matrix = window.getComputedStyle(r).getPropertyValue('transform');
matrix = matrix.slice(0, -1);
var values = matrix.split(',');
var x = values[4];
var y = values[5];
top += parseInt(y);
left += parseInt(x);
r.style.top = top + 'px';
r.style.left = left + 'px';
r.style.transform = 'rotateZ('+rotate+'deg)';
trany = 0;
}
}
I've also deleted #myAnimation
#image2 {
width: 20%;
position: absolute;
top: 250px;
left: 250px;
}
so I've deleted the div
<image id="image2" src="https://banner2.kisspng.com/20180415/pge/kisspng-arrow-desktop-wallpaper-symbol-clip-art-up-arrow-5ad37ddc82f384.4572004515238097565364.jpg" style="bottom:0px;width:10%"></image>
You can check how it works here:
https://jsfiddle.net/w1ox240m/57/
This question already has answers here:
How to detect if multiple keys are pressed at once using JavaScript?
(19 answers)
Closed 5 years ago.
So i am making a html5 game where i was working in movement. Player can move with w, a, s ,d in key. That is working well but i wanted to add a power ..like if player press a + space-bar or d + space-bar an ability will trigger.
i used and operator and it should have worked in my theory but it's not working.
I am new in html5 and any help will be appreciated. thanks in advance.
Here is my code... Just copy paste on html note.
<canvas id="canvas" width="800" height="500" style="border:1px solid #000000;"></canvas>
<script>
var c = document.getElementById("canvas").getContext("2d");
var WIDTH = 800;
var HEIGHT = 500;
var player = {
x: Math.random() * WIDTH,
y: Math.random() * HEIGHT,
width: 30,
height: 30,
color: 'black',
pressingDown: false,
pressingUp: false,
pressingLeft: false,
pressingRight: false,
pressinpowerRight: false,
pressinpowerLeft: false,
};
drawEntity = function(e) {
c.fillStyle = e.color;
c.fillRect(e.x - e.width / 2, e.y - e.height / 2, e.width, e.height);
}
document.onkeydown = function(event) {
if (event.keyCode === 68) //d
player.pressingRight = true;
else if (event.keyCode === 83) //s
player.pressingDown = true;
else if (event.keyCode === 65) //a
player.pressingLeft = true;
else if (event.keyCode === 87) // w
player.pressingUp = true;
else if (event.keyCode === 68 && event.keyCode === 32) // this statement is not working
player.pressinpowerRight = true;
else if (event.keyCode === 65 && event.keyCode === 32) // this statement is not working
player.pressinpowerLeft = true;
}
document.onkeyup = function(event) {
if (event.keyCode === 68) //d
player.pressingRight = false;
else if (event.keyCode === 83) //s
player.pressingDown = false;
else if (event.keyCode === 65) //a
player.pressingLeft = false;
else if (event.keyCode === 87) // w
player.pressingUp = false;
else if (event.keyCode === 68 && event.keyCode === 32) // not working
player.pressinpowerRight = false;
else if (event.keyCode === 65 && event.keyCode === 32) // not working
player.pressinpowerLeft = false;
}
updatePlayerPosition = function() {
if (player.pressingRight)
player.x += 5;
if (player.pressingLeft)
player.x -= 5;
if (player.pressingDown)
player.y += 5;
if (player.pressingUp)
player.y -= 5;
if (player.pressingpowerRight)
player.x += 50;
if (player.pressingpowerLeft)
player.x -= 50;
}
update = function() {
c.clearRect(0, 0, WIDTH, HEIGHT);
updatePlayerPosition();
drawEntity(player);
}
setInterval(update, 40);
</script>
Try creating a previousButtonKey global variable and always record the last key, then check the previousButtonKey with another key to combine two keys on your condition.
Ex. First key is to be pressed is 'Shift', store it to a variable, then once another key event happens, check the previous and the new key. If it is valid, then do the action that you want.
I have element
<div id="square"></div>
He has a property to move on document
var square = document.getElementById("square");
document.body.onkeydown = function(e) {
if (e.keyCode == 37) {left()}
if (e.keyCode == 38) {up()}
if (e.keyCode == 39) {right()}
if (e.keyCode == 40) {down()}
}
How I make a function, which not allowed movement, if square element is closest to document border?
JSFiddle: https://jsfiddle.net/zutxyLsq/
You need to check if left is outside of boundaries like this:
function left() {
console.log('Left');
var left = parseInt(square.style.left || getComputedStyle(square)['left'], 10);
if (left >= 50) {
square.style.left = (left - 50) + 'px';
}
}
function right() {
console.log('Right');
var left = parseInt(square.style.left || getComputedStyle(square)['left'], 10);
if (left+50+square.offsetWidth < window.innerWidth) {
square.style.left = (left + 50) + 'px';
}
}
https://jsfiddle.net/zutxyLsq/3/
and the same for up and down.
I've scoured the web for this answer. If it is buried in a StackOverflow answer somewhere I apologize.
I am working on a 2d canvas JavaScript game.
I am handling arrow key input with onkeydown and onkeyup events.
I store this input in an object called Keys.
var Keys = {
up: false,
down: false,
left: false,
right: false
};
This is what my event handlers look like:
window.onkeydown = function(e){
var kc = e.keyCode;
e.preventDefault();
if(kc === 37) Keys.left = true;
else if(kc === 38) Keys.up = true;
else if(kc === 39) Keys.right = true;
else if(kc === 40) Keys.down = true;
move();
};
window.onkeyup = function(e){
var kc = e.keyCode;
e.preventDefault();
if(kc === 37) Keys.left = false;
else if(kc === 38) Keys.up = false;
else if(kc === 39) Keys.right = false;
else if(kc === 40) Keys.down = false;
};
Then each time the keydown event occurs, I call my move() function:
var move = function(){
if(Keys.up){
hero.y -= 10;
}
else if(Keys.down){
hero.y += 10;
}
if(Keys.left){
hero.x -= 10;
}
else if(Keys.right){
hero.x += 10;
}
main();
}
The move() function calls my main() function which just draws the map again.
I'm trying to avoid looping the game, and instead update the map each time the player moves.
So my problem arises when I try to move diagonally. I am able to do it, however once I release the second key pressed, my character stops.
For example:
Right key pressed and then up key pressed, character moves northeast.
Up key released, player stops.
However, if I release the right key, the character continues moving up.
Another glitch is when I hold both left and right, the character will move left,
but I want it to stop moving.
Quickly sketched an example, jsfiddle: http://jsfiddle.net/ofnp4vj4/
HTML: <div id="log"></div>
JS:
var Keys = {
up: false,
down: false,
left: false,
right: false
};
var hero = {
x: 0,
y: 0
};
var log = document.getElementById("log");
window.onkeydown = function(e){
var kc = e.keyCode;
e.preventDefault();
if(kc === 37) Keys.left = true;
if(kc === 38) Keys.up = true;
if(kc === 39) Keys.right = true;
if(kc === 40) Keys.down = true;
};
window.onkeyup = function(e){
var kc = e.keyCode;
e.preventDefault();
if(kc === 37) Keys.left = false;
if(kc === 38) Keys.up = false;
if(kc === 39) Keys.right = false;
if(kc === 40) Keys.down = false;
};
function main() {
/* body */
move();
log.innerHTML = "x: "+hero.x+", y: "+hero.y;
};
function move(){
if(Keys.up){
hero.y -= 10;
}
if(Keys.down){
hero.y += 10;
}
if(Keys.left) {
hero.x -= 10;
}
if(Keys.right){
hero.x += 10;
}
}
setInterval(main, 100);
You mention that you want the player to stop moving when you press the left and right keys simultaneously. It appears you should be able to easily do this by replacing the else if statements in move with if statements, resulting in a move function similar to:
var move = function(){
if(Keys.up){
hero.y -= 10;
}
if(Keys.down){
hero.y += 10;
}
if(Keys.left){
hero.x -= 10;
}
if(Keys.right){
hero.x += 10;
}
main();
}