div element onkeypress isn't working properly - javascript

I'm attempting to create a classic "Snake game" using only vanilla Javascript. I got an issue with the snake movements when arrow keys are pressed. It didn't work as supposed to.
The entire code is look like this.
HTML
<div class="canvas" id="canvas">
<div class="snake" id="snake"></div>
<div class="food-item" id="food-item"></div>
</div>
CSS
.canvas {
position: relative;
width: 500px;
height: 500px;
background-color: rgba(203, 200, 200, 0.51);
}
.snake {
width: 18px;
height: 18px;
transform: translate(215px, 246px);
background-color: rgba(180, 9, 180, 0.808);
border-radius: 25px;
}
JS
//the position of element before movement
var pos = 0;
let ele = document.getElementById("snake");
//Add an event for button press
window.addEventListener("keydown", (key) => {
var keycode = key.key;
return {
keycode: keycode,
start: start(keycode),
};
});
//movement of the element
function start(key) {
let keys = key;
function automove() {
try {
if (pos === 380) {
clearInterval(movement);
} else if (keys === "ArrowRight") {
pos++;
ele.style.transform = "translate(" + pos + "px)";
} else if (keys === "ArrowLeft") {
pos++;
ele.style.transform = "translate(" + -pos + "px)";
} else if (keys === "ArrowUp") {
pos++;
ele.style.transform = "translateY(" + pos + "px)";
} else if (keys === "ArrowDown") {
pos++;
ele.style.transform = "translateY(" + -pos + "px)";
} else {
console.log("invalid command: " + Error);
}
} catch (error) {
console.log("Error: " + error);
}
}
const movement = setInterval(automove, 1000);
return movement;
}
the behavior of the code is this
What I'm doing wrong here... is there any alternative way of doing this ?
It would be great if you can support with a vanillaJs answer.

For a snake game, you want the character to move even when no key is pressed.
So you need to store the direction somehow.
here's an updated version:
https://jsfiddle.net/wmvqgku4/1/
JS:
var posX = 200;
var posY = 160;
var ele = document.getElementById("snake");
const UP =0;
const RIGHT =1;
const DOWN =2;
const LEFT =3;
var dir = 1;
window.addEventListener("keydown", (key) => {
keyhandler(key.key)
});
window.onload = function () {
ele = document.getElementById("snake");
ele.style.top = posY + "px";
ele.style.left = posX + "px";
setInterval( automove, 300);
console.log("Started.");
}
function keyhandler(keys) {
try {
if (posX >= 380) {
clearInterval(movement);
}
if (keys === "ArrowRight") {
dir = RIGHT;
} else if (keys === "ArrowLeft") {
dir = LEFT;
} else if (keys === "ArrowUp") {
dir = UP;
} else if (keys === "ArrowDown") {
dir = DOWN;
} else {
console.log("invalid command: " + keys);
}
} catch (error) {
console.log("Error: " + error);
}
}
function automove() {
switch ( dir ) {
case UP: posY--; break;
case DOWN: posY++; break;
case LEFT: posX--; break;
case RIGHT: posX++; break;
}
console.log(dir);
ele.style.top = posY + "px";
ele.style.left = posX + "px";
}
CSS:
.canvas {
position: relative;
width: 500px;
height: 500px;
background-color: rgba(203, 200, 200, 0.51);
}
.snake {
width: 18px;
height: 18px;
position: absolute;
background-color: rgba(180, 9, 180, 0.808);
border-radius: 25px;
}
I made the snake position absolute, and als kept track of the x/y position, so you can add checks for the bounds.
I also changed it a bit, the keyhandler checks the keys and updates the direction variable.
the automove now only checks the direction, and updates the position.
Hope this helps.

Related

How to stop an element in JavaScript at the screen border?

I am beginner in JavaScript and I'm trying to create a simple game. I'm looking for a way to stop the rectangle when it touches the screen border by stopping setInterval(), I can't get the value of the left screen border.
const element = document.querySelector('#rectangle');
let a = 1;
document.addEventListener('keydown', function (e) {
switch (e.keyCode) {
case 37:
let leftInterval = setInterval(moveLeft, 100);
break;
case 39:
let rightInterval = setInterval(moveRight, 100);
break;
}
});
window.addEventListener('load', () => {
rectangle.style.position = 'absolute';
rectangle.style.left = "44%";
});
let moveLeft = () => {
element.style.left = parseInt(element.style.left) - a + '%';
}
let moveRight = () => {
element.style.left = parseInt(element.style.left) + a + '%';
}
function clearinterval() {
if (element.style.left < 0)
clearinterval(leftInterval);
}
clearinterval();
body {
background-color: brown;
box-sizing: border-box;
width: 100%;
height: 100%;
}
#rectangle {
bottom: 2.5%;
background-color: burlywood;
width: 12%;
height: 14px;
}
<div id="rectangle"></div>
This will help you.
const element = document.querySelector('#rectangle');
let a = 1;
document.addEventListener('keydown', function (e) {
switch (e.keyCode) {
case 37:
let leftInterval = setInterval(moveLeft, 100);
break;
case 39:
let rightInterval = setInterval(moveRight, 100);
break;
}
});
window.addEventListener('load', () => {
rectangle.style.position = 'absolute';
rectangle.style.left = "44%";
});
let moveLeft = () => {
if (parseInt(window.getComputedStyle(element,null).getPropertyValue("left")) > 10) {
element.style.left = parseInt(element.style.left) - a + '%';
}
}
let moveRight = () => {
if (parseInt(window.getComputedStyle(element,null).getPropertyValue("right")) > 10) {
element.style.left = parseInt(element.style.left) + a + '%';
}
}
// function clearinterval() {
// // clearinterval(leftinterval);
// }
// clearinterval();

If my snake dies going downward or upward, it continues the upward/downward after restart. Why?

I am trying to make a snake game.
I made the movement and I added a die function so when the character hits the border, dies.
If the character dies going downward or upward, when it restart, the character continues the upward/downward movement.
When it dies going to the left or right, it restarts as it should.
HTML and Javascript:
var upDown = 0,
rightLeft = 0;
var k, move, character;
window.onload = function() {
move = setInterval(right, 10);
character = document.getElementById('character');
setInterval(die, 10);
}
document.onkeydown = function(event) {
k = event.keyCode;
}
function die() {
if (rightLeft > 1465 || rightLeft < 0 || upDown > 650 || upDown < 0) {
clearInterval(move);
upDown = 0;
rightLeft = 0;
character.style.left = 0 + "px";
character.style.top = 0 + "px";
move = setInterval(right, 10);
alert("You lost!");
}
}
function right() {
rightLeft++;
character.style.left = rightLeft + 'px';
if (k == 38) {
console.log(move);
clearInterval(move);
console.log(move);
move = setInterval(up, 10);
} else if (k == 40) {
clearInterval(move);
move = setInterval(down, 10);
}
}
function left() {
rightLeft--;
character.style.left = rightLeft + "px";
if (k == 38) {
clearInterval(move);
move = setInterval(up, 10);
} else if (k == 40) {
clearInterval(move);
move = setInterval(down, 10);
}
}
function down() {
upDown++;
character.style.top = upDown + "px";
if (k == 39) {
clearInterval(move);
move = setInterval(right, 10);
} else if (k == 37) {
clearInterval(move);
move = setInterval(left, 10);
}
}
function up() {
upDown--;
character.style.top = upDown + "px";
if (k == 39) {
clearInterval(move);
move = setInterval(right, 10);
} else if (k == 37) {
clearInterval(move);
move = setInterval(left, 10);
}
}
#character {
width: 50px;
height: 50px;
background-color: black;
position: absolute;
}
#playGround {
position: relative;
background-color: gray;
border-style: solid;
border-color: blue;
width: 1515px;
height: 700px;
}
<div id="playGround">
<div id="character"></div>
</div>
There is a lot of work to be done here, but as for your specific question: you forgot to reset the 'k' variable. Add the line k = 0 to the die() function.
Good luck!

Stop moving element when he outside of parent element

So, I have an event listener keydown on arrow right, when you push the square moving on xPX but my parent element this w and h
set a 100px for example, and I would like to stop moving and I can't, I try with element.offsetWidth > 0 so them you can move.
Please look this fiddle : FIDDLE
Few errors in your code. I've commented fixes. Here is how i made it for the right arrow - you can apply same logic to the rest of the moves...
Code:
const carre = document.querySelector('.carre');
const main = document.querySelector('.main');
const w = main.offsetWidth - carre.offsetWidth; // this was wrong in your code
carre.style.left="0px"; // set start position
document.addEventListener('keyup', (event) => {
const positionLeft = parseInt(carre.style.left); //i've used style.left, rather, it gives expected numbers (10,20,30....)
if(event.keyCode == '39') {
if (positionLeft < w) { // this was fixed too
carre.style.left = (positionLeft) + 10 + 'px';
} else {
carre.style.left = '0'
}
}
})
DEmo:
const carre = document.querySelector('.carre');
const main = document.querySelector('.main');
const w = main.offsetWidth - carre.offsetWidth; // this was wrong in your code
carre.style.left="0px"; // set start position
document.addEventListener('keyup', (event) => {
const positionLeft = parseInt(carre.style.left); //i've used style.left, rather, it gives expected numbers (10,20,30....)
if(event.keyCode == '39') {
if (positionLeft < w) { // this was fixed too
carre.style.left = (positionLeft) + 10 + 'px';
} else {
carre.style.left = '0'
}
}
})
* {
box-sizing:border-box;
}
.carre {
position:absolute;
left: 0;
width: 50px;
height: 50px;
background-color: red;
}
.main {
position: relative;
width: 100px;
height: 100px;
border: 1px solid #000;
}
<main class="main">
<div class="carre"></div>
</main>
I rebuild your code:
document.addEventListener('keydown', (event) => {
const w = main.getBoundingClientRect().right - carre.getBoundingClientRect().right;
const positionLeft = carre.getBoundingClientRect().left;
if(event.keyCode == '39') {
if (w >= 0) {
carre.style.left = (positionLeft) + 10 + 'px';
} else {
carre.style.left = '0'
}
}
if (event.keyCode == '37') {
if (w >= 0) {
carre.style.left = (positionLeft) - 10 + 'px';
}else {
carre.style.left = '0'
}
}
})

Less javascript code for this loop animation?

I've done this simple animation but i have a feeling i've writted to much lines of code for such a simple task. Is there a way to achieve the same result but with less code ?
https://jsfiddle.net/qw82Lwy0/1/
function myMove() {
var elem = document.getElementById("animate");
var pos = 0;
var id = setInterval(frame, 5);
var flag = true;
function frame() {
if (flag) {
pos++;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
if (pos == 350) {
flag = false;
}
} else if (!flag) {
pos--;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
if (pos == 0) {
flag = true;
}
}
}
}
P.S: No jquery or css animation, just javascript.
instead of using the flag and a seperate code for the 2 conditions you could just flip the incrementer like so:
function myMove() {
var elem = document.getElementById("animate");
var pos = 0;
var id = setInterval(frame, 5);
var changeVal = 1;
function frame() {
pos+=changeVal;
if ((pos >= 350) || (pos <= 0)) changeVal *= -1;
elem.style.top = elem.style.left = pos + 'px';
}
}
Animations can now be done in modern browsers using CSS. For example, your javascript animation can be condensed to just a few lines using a CSS transition.
See MDN for more details and examples of transitions and animations.
Run the code snippet below to try
window.ball.addEventListener('transitionend', toggle);
function toggle() {
window.ball.classList.toggle('move');
}
.animation {
position: relative;
background-color: lightyellow;
border: 1px solid gray;
height: 200px;
width: 200px;
}
#ball {
transition-property: left top background-color;
transition-duration: 2s;
position: absolute;
background-color: red;
border-radius: 12px;
height: 25px;
width: 25px;
left: 0;
top: 0;
}
#ball.move {
background-color: blue;
left: 175px;
top: 175px;
}
<button onclick="toggle()">Start</button>
<div class="animation"><div id="ball"></div></div>
Well, you could shorten your frame() function like so:
function myMove() {
var elem = document.getElementById("animate");
var pos = 0;
var id = setInterval(frame, 5);
var flag = true;
function frame() {
if (flag) {
pos++;
if (pos == 350) {
flag = false;
}
} else { // since you are checking if flag is true, the only other answer is false
pos--;
if (pos == 0) {
flag = true;
}
}
elem.style.top = pos + 'px'; // since this occurs in both cases
elem.style.left = pos + 'px'; // you can do it afterward
}
}
Use a function with 3 paraneters : posAdd, flagValue and posValue
function frame(posAdd,flagValue,posValue) {
if (flagValue) {
pos=pos+posAdd;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
if (pos == posValue) {
flag = !flagValue;
}
}
}
And call it twice : frame(1,true,350)
And frame(-1,false,0)

Document is not defined error for 'document.getElementById()'

Essentially, I keep getting the message "document is not defined" when I run my .js doc on command line. I'm trying to create a super basic game where the user helps the squirrel get to the chestnuts by using arrow keys. So far I can't move the squirrel yet, and I suspect it has to do with the document is not defined error that I'm getting (lines 1-3 and maybe also 52 in the link).
You can find my code (html, css and js) in the following jsfiddle link
(http://jsfiddle.net/8Lbkcsq2/)
var squirrelImg = document.getElementById("squirrelImg");
var forest = document.getElementById("forest");
var chestnutImg = document.getElementById("chestnutsImg");
var squirrel = {
name: "Mr. Squirrel",
has_chestnuts: false,
hungry: true
};
var chestnuts = {
name: "chestnuts"
};
var positionLeft = 0;
var positionTop = 0;
function move(e) {
// 39 for right arrow
if (e.keyCode === 39) {
if (positionLeft < 850) {
positionLeft += 50;
squirrelImg.style.left = positionLeft + "px";
}
}
// 40 for down arrow
if (e.keyCode === 40) {
if (positionTop < 600) {
positionTop += 50;
squirrelImg.style.top = positionTop + "px";
}
}
// 37 for left arrow
if (e.keyCode === 37) {
positionLeft -= 50;
if (positionLeft < 0) {
positionLeft += 50; // CHANGE TO +=50 LATER
}
squirrelImg.style.left = positionLeft + "px";
}
// 38 for up arrow
if (e.keyCode === 38) {
positionTop -= 100;
if (positionTop < 0) {
positionTop += 50; // CHANGE TO +=50 LATER
}
squirrelImg.style.top = positionTop + "px";
}
foundChestnuts();
}
document.onKeyDown = move();
function foundChestnuts() {
if ((squirrelImg.style.top == "300px") && (squirrelImg.style.left == "750px")) {
squirrel.has_chestnuts = true;
alert("Thank you for helping Mr. Squirrel find his chestnuts!");
var eat = confirm("Should Mr.Squirrel eat his chestnuts?");
if (eat === true) {
alert("Time to eat!");
alert("Yum! Mr. Squirrel isn't hungry anymore!");
} else {
alert("I guess Mr. Squirrel can wait a little longer...");
}
} else {
squirrel.has_chestnuts = false;
}
}
body {
background-color: #b5916c;
}
h3 {
font-weight: bold;
text-decoration: underline;
}
p {
font-family:'Dancing Script', cursive;
font-size: large;
}
#forest {
background-image: url(http://s21.postimg.org/jyht762hj/forestfloor.jpg);
width: 850px;
height: 600px;
position: relative;
/*opacity: 0.5;*/
}
#squirrelImg {
position: absolute;
background-image: url(http://s24.postimg.org/wkqh9by4x/squirrel.png);
height: 100px;
width: 100px;
left: 0;
top: 0;
}
#chestnutsImg {
position: absolute;
background-image: url(http://s28.postimg.org/kgiubxhnd/chestnuts.jpg);
height: 100px;
width: 100px;
left: 750px;
top: 300px;
}
<body>
<h3>A Plea from Mr. Squirrel:</h3>
<p>My dearest human,</p>
<p>I seem to have misplaced my chestnuts and I am quite famished.</p>
<p>Would you mind assisting me in locating them?</p>
<p>Much obliged!</p>
<div id="forest">
<div id="squirrelImg"></div>
<div id="chestnutsImg"></div>
</div>
</body>
The issue is that move() requires an event to be passed to it but when you do document.onKeyDown = move(); no event is passed.
Change document.onKeyDown = move(); to document.addEventListener("keydown", move, false);
working jsfiddle
Add a event listener document.body.addEventListener('keydown', function(e) {...} instead of document.onKeyDown = move().
Updated Fiddle
var squirrelImg = document.getElementById("squirrelImg");
var forest = document.getElementById("forest");
var chestnutImg = document.getElementById("chestnutsImg");
var squirrel = {
name: "Mr. Squirrel",
has_chestnuts: false,
hungry: true
};
var chestnuts = {
name: "chestnuts"
};
var positionLeft = 0;
var positionTop = 0;
document.body.addEventListener('keydown', function(e) {
// 39 for right arrow
if (e.keyCode === 39) {
if (positionLeft < 850) {
positionLeft += 50;
squirrelImg.style.left = positionLeft + "px";
}
}
// 40 for down arrow
if (e.keyCode === 40) {
if (positionTop < 600) {
positionTop += 50;
squirrelImg.style.top = positionTop + "px";
}
}
// 37 for left arrow
if (e.keyCode === 37) {
positionLeft -= 50;
if (positionLeft < 0) {
positionLeft += 50; // CHANGE TO +=50 LATER
}
squirrelImg.style.left = positionLeft + "px";
}
// 38 for up arrow
if (e.keyCode === 38) {
positionTop -= 100;
if (positionTop < 0) {
positionTop += 50; // CHANGE TO +=50 LATER
}
squirrelImg.style.top = positionTop + "px";
}
foundChestnuts();
});
// combined 3 functions previously separated for foundChestnuts, eatChestnuts and hungerLevel into the function below
function foundChestnuts() {
if ((squirrelImg.style.top == "300px") && (squirrelImg.style.left == "750px")) {
squirrel.has_chestnuts = true;
alert("Thank you for helping Mr. Squirrel find his chestnuts!");
var eat = confirm("Should Mr.Squirrel eat his chestnuts?");
if (eat === true) {
alert("Time to eat!");
alert("Yum! Mr. Squirrel isn't hungry anymore!");
} else {
alert("I guess Mr. Squirrel can wait a little longer...");
}
} else {
squirrel.has_chestnuts = false;
}
}
body {
background-color: #b5916c;
}
h3 {
font-weight: bold;
text-decoration: underline;
}
p {
font-family: 'Dancing Script', cursive;
font-size: large;
}
#forest {
background-image: url(http://s21.postimg.org/jyht762hj/forestfloor.jpg);
width: 850px;
height: 600px;
position: relative;
/*opacity: 0.5;*/
}
#squirrelImg {
position: absolute;
background-image: url(http://s24.postimg.org/wkqh9by4x/squirrel.png);
height: 100px;
width: 100px;
left: 0;
top: 0;
}
#chestnutsImg {
position: absolute;
background-image: url(http://s28.postimg.org/kgiubxhnd/chestnuts.jpg);
height: 100px;
width: 100px;
left: 750px;
top: 300px;
}
<body>
<h3>A Plea from Mr. Squirrel:</h3>
<p>My dearest human,</p>
<p>I seem to have misplaced my chestnuts and I am quite famished.</p>
<p>Would you mind assisting me in locating them?</p>
<p>Much obliged!</p>
<div id="forest">
<div id="squirrelImg"></div>
<div id="chestnutsImg"></div>
</div>
</body>
please place the script before </body>, or in window.onload callback function.
Because document object is not created when you call document.getElementById.
Yes, the problem is document.onKeyDown = move(). The right event handler isdocument.onkeydown, and handler should be a function move, not a function result move(). So just changed to document.onkeydown=move

Categories