I am trying to make me character moving left and up and I think jump() and slideLeft()
functions are working properly and the problem is in the controller(e) function (else if (e.KeyCode===37)) . The first function is avaible but it isn't able to acces the second conditon function. Also, I would want to make the grid solid after I will make an slideRight() similar function ,so if my character is jumping on it, the platform would sustain the square . Has anyone any ideea for either of my questions ?
Code snippet:
var square = document.querySelector('.square');
var grid = document.querySelector('.grid');
var bottom = 0;
let isJumping = false;
let isGoingLeft = false;
var newBottom;
let left = 0;
let leftTimerId;
function jump() {
if (isJumping) return
let timerUpId = setInterval(function() {
if (bottom > 250) {
clearInterval(timerUpId);
let timerDownId = setInterval(function() {
if (bottom < 0) {
clearInterval(timerDownId);
isJumping = false;
}
bottom -= 5;
square.style.bottom = bottom + 'px';
}, 20)
}
isJumping = true;
bottom += 30;
square.style.bottom = bottom + 'px';
}, 20)
}
function slideLeft() {
console.log('da');
isGoingLeft = true;
leftTimerId = setInterval(function() {
left -= 5;
square.style.left = left + 'px';
}, 20)
}
function controller(e) {
if (e.keyCode === 32)
jump();
else if (e.KeyCode === 37)
slideLeft();
}
document.addEventListener('keydown', controller);
.grid {
position: absolute;
background-color: chartreuse;
height: 20px;
width: 500px;
bottom: 100px;
left: 100px;
}
.square {
position: absolute;
background-color: darkblue;
height: 100px;
width: 100px;
bottom: 0px;
left: 150px;
}
`
<div class="grid"></div>
<div class="square"></div>
EDIT:
There is a typo:
The second time you've written KeyCode
function controller(e) {
if(e.keyCode===32) {
jump();
}
else if(e.keyCode===37) {
slideLeft();
}
}
I don't really understand what you mean by the second part of your question. If you want a character to have the ability to jump on a square, you'll have to implement a collision detection. Something like this:
if ( isNotOnGround() ) {
fall()
}
Related
I want my code to do the following:
when the right arrow key is pressed, move the circle to the right
when the down arrow key is pressed, move the circle to the bottom
But instead it does the following:
When one of these keys is pressed, it moves only once and than no more. What am I doing wrong?
document.onkeydown = function(event) {
var circle = document.getElementById("circle");
if (event.keyCode == 39) {
circle.style.left += 100;
console.log("right")
} else if (event.keyCode == 40) {
circle.style.top += 100;
console.log("bottom")
}
}
#circle {
width: 50px;
height: 50px;
border-radius: 25px;
background: red;
position: absolute;
}
<div id="circle"></div>
You forgot about the units!
I changed your snippet to keep the actual values in 2 variables and added a function to update the circles style properties by using those vars and appending the units.
<html>
<head>
<title>HTML Test</title>
<style>
#circle {
width: 50px;
height: 50px;
border-radius: 25px;
background: red;
position: absolute;
}
</style>
</head>
<body>
<div id="circle"></div>
</body>
<script>
var circle = document.getElementById("circle");
var circleLeft = 0;
var circleTop = 0;
var updatePosition = function(left, top) {
circle.style.left = left + 'px';
circle.style.top = top + 'px';
};
// once at the start
updatePosition(circleLeft, circleTop);
document.onkeydown = function (event) {
if (event.keyCode == 39) {
circleLeft += 100;
console.log("right");
} else if (event.keyCode == 40) {
circleTop += 100;
console.log("bottom");
}
updatePosition(circleLeft, circleTop);
}
</script>
</html>
There is probably a more elegant way of doing this, but as
Rene said in the comments, you are dealing with strings not numbers and therefore will have trouble actually preforming simple operations like += 100. You instead need to substring the style string, parse the number from it and then add your number, then re-add the "px" to the end (actually might not be necessary since it seems to infer that 100 == 100px in HTML, but not the other way around.)
Here is a fix that worked for moving it left!
<script>
circle.style.left = "0px";
document.onkeydown = function (event) {
var circle = document.getElementById("circle");
if (event.keyCode == 39) {
console.log(circle.style.left.substring(0,circle.style.left.length -2))
circle.style.left = (parseInt(circle.style.left.substring(0,circle.style.left.length -2)) + 100) + "px"
console.log(circle.style.left)
} else if (event.keyCode == 40) {
circle.style.top += 100;
console.log("bottom")
}
}
</script>
Here is the working example. I have set the 10px move position instead of 100px.
Here you can move the circle infinite times as well instead of the single move.
document.onkeydown = function (event) {
var circle = document.getElementById("circle");
if (event.keyCode == 39) {
for (let i = 0; i < 10; i++) {
(i => {
setTimeout(() => {
const left = window.getComputedStyle(circle).left;
circle.style.left = `${(+left.replace("px", "") + i * 2) %
window.innerWidth}px`;
}, 500);
})(i);
}
} else if (event.keyCode == 40) {
for (let j = 0; j < 10; j++) {
(i => {
setTimeout(() => {
const top = window.getComputedStyle(circle).top;
circle.style.top = `${(+top.replace("px", "") + j * 2) %
window.innerWidth}px`;
}, 500);
})(j);
}
}
}
#circle {
width: 50px;
height: 50px;
border-radius: 25px;
background: red;
position: absolute;
}
<div id="circle"></div>
What I am trying to do is make a drawer where drawer can be opened with left swipe from the edge and can be closed from right swipe from anywhere, if swipe is more than 150px.
I have achieved everything, however, the drawer becomes laggy and ultimately the browser freezes. The code for the following is as below.
let drawer = document.getElementsByClassName('drawer')[0];
function openDrawer(start) {
document.addEventListener('touchend', function() {
let end = event.changedTouches[0].pageX;
if ((end > start) && ((end - start) > 150)) {
drawer.classList.add('tra')
drawer.style.transform = `translateX(0px)`;
}
});
}
function closeDrawer(start) {
document.addEventListener('touchend', function() {
let end = event.changedTouches[0].pageX;
if ((end < start) && ((start - end) > 150)) {
drawer.classList.add('tra')
drawer.style.transform = `translateX(-104%)`;
}
});
}
document.addEventListener('touchstart', function() {
drawer.classList.remove('tra')
let start = event.changedTouches[0].pageX;
if (start < 50) {
document.addEventListener('touchmove', function() {
let change = event.changedTouches[0].pageX;
let drawerWidth = drawer.offsetWidth;
let move = change - drawerWidth;
let min = 0;
let max = -drawerWidth;
if (move < max) {
move = max;
}
if (move > min) {
move = min;
}
drawer.style.transform = `translateX(${move}px)`;
document.addEventListener('touchmove', function() {
document.addEventListener('touchend', function() {
if (change >= drawerWidth / 2) {
drawer.classList.add('tra');
drawer.style.transform = `translateX(0%)`;
} else {
drawer.classList.add('tra');
drawer.style.transform = `translateX(-104%)`;
}
});
})
})
openDrawer(start)
} else {
closeDrawer(start)
}
}, 500);
html,
body {
margin: 0px;
padding: 0px;
background: lightgrey;
}
.drawer {
position: fixed;
top: 0px;
left: 0px;
bottom: 0px;
width: 80%;
background: hotpink;
transform: translateX(-104%);
}
.tra {
transition: 500ms ease;
}
<div class="drawer" id="drawer">
</div>
Here is the jsFiddle: https://jsfiddle.net/0xre4uo5/5/
Below is an example of a box moving left,right,up or down based
on pressing the arrow keys. However when I added a "laser" and used
the exact same principal/code to move the laser from left to right using "laserLeft++;" with the space bar, it does not move. I have very
carefully duplicated the code from the "square" to apply to the laser and
I cannot find why there is no movement. (I did not copy and paste the entire view source since it isn't relevant to problem).
the specific function is question is fireLaser().
#square {
position: absolute;
top: 0px;
left: 0px;
height: 5px;
width: 5px;
background-color: white;
}
#laser {
postion: absolute;
top: 0px;
left 0px;
height: 2px;
width: 5px;
background-color: red;
}
<script>
document.addEventListener("keydown", keyBoardInput);
var boxTop = 0;
var boxLeft = 0;
var laserTop = 0;
var laserLeft = 0;
function moveBoxUp(){
var square = document.getElementById("square");
boxTop--;
square.style.top = boxTop;
};
function moveBoxDown(){
var square = document.getElementById("square");
boxTop++;
square.style.top = boxTop;
};
function moveBoxLeft(){
var square = document.getElementById("square");
boxLeft--;
square.style.left = boxLeft;
};
function moveBoxRight(){
var square = document.getElementById("square");
boxLeft++;
square.style.left = boxLeft;
};
function fireLaser(){
var laser = document.getElementById("laser");
laserLeft++;
laser.style.left = laserLeft;
};
var i = event.keyCode;
if(i == 38){
moveBoxUp();
};
if(i == 40){
moveBoxDown();
};
if(i == 37){
moveBoxLeft();
};
if(i == 39){
moveBoxRight();
};
if (i == 32){
fireLaser();
};
};
</script>
I found my error!!! it was incorrectly typed "postion: absolute;" now it works perfectly!!!
I've created a snake game, and when the snake hit the wall or itself, it still wont stop moving. I figured out if I used the clearTimeout(), it would help. but it didn't.
Is there a way to stop the loop? or it is another issue?
jQuery(document).ready(function($) {
init();
});
var move;
function init() {
board.initBoard();
drawSnake();
food.createFood();
}
function play() {
$('.newGame').css('visibility', 'hidden');
$('.playgame').css('visibility', 'hidden');
moveSnake();
getSnakeDir();
}
function gameover() {
clearTimeout(move);
$('.newGame').css('visibility', 'visible');
}
function playGame() {
$('#gameboard').empty();
$('.newGame').hide();
init();
play();
}
var board = {
DIM: 20,
initBoard: function() {
for (var i = 0; i < board.DIM; i++) {
var row = $('<div class="row-' + i + '"></div>');
for (var j = 0; j < board.DIM; j++) {
var col = ('<div class="col-' + j + '-' + i + '"></div>');
$(row).append(col);
}
$("#gameboard").append(row);
}
}
}
var snake = {
position: ['10-10', '10-11', '10-12'],
direction: 'r',
speed: 200,
};
function drawSnake() {
$('.col-10-10').addClass('snake');
$('.col-11-10').addClass('snake');
}
function getSnakeDir() {
$(document).keydown(function(event) {
//event.preventDefault();
if (event.which == 38) {
snake.direction = 'u';
} else if (event.which == 39) {
snake.direction = 'r';
} else if (event.which == 40) {
snake.direction = 'd';
} else if (event.which == 37) {
snake.direction = 'l';
}
});
}
function moveSnake() {
var tail = snake.position.pop();
$('.col-' + tail).removeClass('snake');
var coords = snake.position[0].split('-');
var x = parseInt(coords[0]);
var y = parseInt(coords[1]);
if (snake.direction == 'r') {
x = x + 1;
} else if (snake.direction == 'd') {
y = y + 1;
} else if (snake.direction == 'l') {
x = x - 1;
} else if (snake.direction == 'u') {
y = y - 1;
}
var currentcoords = x + '-' + y;
snake.position.unshift(currentcoords);
$('.col-' + currentcoords).addClass('snake');
//when snake eats food
if (currentcoords == food.coords) {
console.log('true');
$('.col-' + food.coords).removeClass('food');
snake.position.push(tail);
food.createFood();
}
//game over
if (x < 0 || y < 0 || x > board.DIM || y > board.DIM) {
gameover();
}
//if snake touch itself
if (hitItself(snake.position) == true) {
gameover();
}
move=setTimeout(moveSnake, 200);
}
var food = {
coords: "",
createFood: function() {
var x = Math.floor(Math.random() * (board.DIM-1)) + 1;
var y = Math.floor(Math.random() * (board.DIM-1)) + 1;
var fruitCoords = x + '-' + y;
$('.col-' + fruitCoords).addClass('food');
food.coords = fruitCoords;
},
}
function hitItself(array) {
var valuesSoFar = Object.create(null);
for (var i = 0; i < array.length; ++i) {
var value = array[i];
if (value in valuesSoFar) {
return true;
}
valuesSoFar[value] = true;
}
return false;
}
.buttonnewgame {
position: relative;
}
.newGame {
position: absolute;
top: 45%;
left: 25%;
padding: 15px;
font-size: 1em;
font-family: arial;
visibility: hidden;
}
.gameContainer{
width: 100%;
}
#gameboard {
background-color:#eee;
padding:3px;
}
.playgame {
position: absolute;
top: 45%;
left: 20%;
padding: 15px;
font-size: 1em;
font-family: arial;
}
/* styling the board */
div[class^='row'] {
height: 15px;
text-align: center;
}
div[class*='col']{
display: inline-block;
border: 1px solid grey;
width: 15px;
height: 15px;
}
/*display the snake*/
.snake {
background-color: blue;
z-index: 99;
}
.food {
background: red;
z-index: 99;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="game">
<div class="buttonnewgame">
<input type="button" name="new game" value="new game" class="newGame" onclick="playGame()" />
<button class="playgame" onclick="play()">Play Game</button>
<div class="gameContainer">
<div id="gameboard">
<!-- snake game in here -->
</div>
</div>
</div>
</div>
There were a few problems, but here is the 'working version' (there are more bugs).
1) I renamed drawSnake to createSnake. You weren't fully reinitializing the snake when you called init(). The snakes position was not being reset in the previous drawSnake method, so it would seem like the game was not playable.
After that there were 2 more bugs.
2) You have to return after you call gameOver or the game never really ends does it? Once you clear the timeout in gameover, you immediately set another Timeout for on the last line of moveSnake() because you didn't return once the game was over. That lead to weird results that made it seem like the game was unresponsive.
3) You were using a combination of visibility none or visible and $.hide(). $.hide() uses display: none, so when you tried to show it again with the visibility style change, its still display: none so the new game button would stop appearing.
My advice to any game coder is to learn how to separate the code that handles how the game works (logic of the game, how the clock ticks, initialization of game state, etc) , and how it is displayed (the html and css). Modeling the game logic after a cleanly written system is easy to read and debug. The code becomes harder to understand and modify when the display code is mixed in with game logic. In theory, our game should work perfectly without any kind of rendering. Then we could write a renderer that produces an HTML canvas, html DOM, text in the command line, or OpenGL.
Heres an old project I never finished that should illustrate a separation between model and view.
http://tando.us/ganix/ganix.htm
jQuery(document).ready(function($) {
init();
});
var move;
function init() {
board.initBoard();
createSnake();
food.createFood();
}
function play() {
$('.newGame').hide();
$('.playgame').hide();
moveSnake();
getSnakeDir();
}
function gameover() {
clearTimeout(move);
$('.newGame').show();
}
function playGame() {
$('#gameboard').empty();
$('.newGame').hide();
init();
play();
}
var board = {
DIM: 20,
initBoard: function() {
for (var i = 0; i < board.DIM; i++) {
var row = $('<div class="row-' + i + '"></div>');
for (var j = 0; j < board.DIM; j++) {
var col = ('<div class="col-' + j + '-' + i + '"></div>');
$(row).append(col);
}
$("#gameboard").append(row);
}
}
}
var snake = {
position: ['10-10', '10-11', '10-12'],
direction: 'r',
speed: 200,
};
function createSnake() {
$('.col-10-10').addClass('snake');
$('.col-11-10').addClass('snake');
snake.position = ['10-10', '10-11', '10-12'];
}
function getSnakeDir() {
$(document).keydown(function(event) {
//event.preventDefault();
if (event.which == 38) {
snake.direction = 'u';
} else if (event.which == 39) {
snake.direction = 'r';
} else if (event.which == 40) {
snake.direction = 'd';
} else if (event.which == 37) {
snake.direction = 'l';
}
});
}
function moveSnake() {
var tail = snake.position.pop();
$('.col-' + tail).removeClass('snake');
var coords = snake.position[0].split('-');
var x = parseInt(coords[0]);
var y = parseInt(coords[1]);
if (snake.direction == 'r') {
x = x + 1;
} else if (snake.direction == 'd') {
y = y + 1;
} else if (snake.direction == 'l') {
x = x - 1;
} else if (snake.direction == 'u') {
y = y - 1;
}
var currentcoords = x + '-' + y;
snake.position.unshift(currentcoords);
$('.col-' + currentcoords).addClass('snake');
//when snake eats food
if (currentcoords == food.coords) {
console.log('true');
$('.col-' + food.coords).removeClass('food');
snake.position.push(tail);
food.createFood();
}
//game over
if (x < 0 || y < 0 || x > board.DIM || y > board.DIM) {
gameover();
return;
}
//if snake touch itself
if (hitItself(snake.position) == true) {
gameover();
return;
}
move=setTimeout(moveSnake, 200);
}
var food = {
coords: "",
createFood: function() {
var x = Math.floor(Math.random() * (board.DIM-1)) + 1;
var y = Math.floor(Math.random() * (board.DIM-1)) + 1;
var fruitCoords = x + '-' + y;
$('.col-' + fruitCoords).addClass('food');
food.coords = fruitCoords;
},
}
function hitItself(array) {
var valuesSoFar = Object.create(null);
for (var i = 0; i < array.length; ++i) {
var value = array[i];
if (value in valuesSoFar) {
return true;
}
valuesSoFar[value] = true;
}
return false;
}
.buttonnewgame {
position: relative;
}
.newGame {
position: absolute;
top: 45%;
left: 25%;
padding: 15px;
font-size: 1em;
font-family: arial;
}
.gameContainer{
width: 100%;
}
#gameboard {
background-color:#eee;
padding:3px;
}
.playgame {
position: absolute;
top: 45%;
left: 20%;
padding: 15px;
font-size: 1em;
font-family: arial;
}
/* styling the board */
div[class^='row'] {
height: 15px;
text-align: center;
}
div[class*='col']{
display: inline-block;
border: 1px solid grey;
width: 15px;
height: 15px;
}
/*display the snake*/
.snake {
background-color: blue;
z-index: 99;
}
.food {
background: red;
z-index: 99;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="game">
<div class="buttonnewgame">
<input type="button" name="new game" value="new game" class="newGame" style="display:none;" onclick="playGame()" />
<button class="playgame" onclick="play()">Play Game</button>
<div class="gameContainer">
<div id="gameboard">
<!-- snake game in here -->
</div>
</div>
</div>
You could try not to initiate a new setTimeout call at the and of the moveSnake function, but instead using.
function play() {
$('.newGame').css('visibility', 'hidden');
$('.playgame').css('visibility', 'hidden');
move = setInterval(moveSnake, 200);
getSnakeDir();
}
and remove the
move = setTimeout(moveSnake, 200)
from the moveSnake function and do
function gameover() {
clearInterval(move);
$('.newGame').css('visibility', 'visible');
}
All I'm trying to do is to simply move a div around the screen using my arrow keys. I am completely newbie to JavaScript and what I wrote seems like it should be working but it's not. Every keyUp is moving the div based on it's original position and not the current position of the div. Is there something I'm missing?
CSS:
#pawn {
position: absolute;
left: 0;
top: 0;
width: 50px;
height: 50px;
}
JavaScript
function showKeyCode(e) {
var pawn = document.getElementById("pawn");
if(e.keyCode == "37") {
console.log("left");
pawn.style.left = -50+"px";
}
if(e.keyCode == "38") {
console.log("up");
pawn.style.top = -50+"px";
}
if(e.keyCode == "39") {
console.log("right");
pawn.style.left = +50+"px";
}
if(e.keyCode == "40") {
console.log("down");
pawn.style.top = +50+"px";
}
}
HTML:
<body onKeyUp="showKeyCode(event);">
<div id="pawn"></div>
</body>
Can anyone shine some light on this? I've been stuck for hours.
The pawn.style.left properties are text, so you're not actually incrementing the value at all. Essentially the assignments say "set it to positive/negative 50+"px"; every time.
You'll need to convert the values to integers and then add the new value, and then set it as the px value.
A very basic demo in jQuery:
$(function(){
$('body').on('keyup', function(e){
var pawn = $('#pawn');
var newLeft = parseInt(pawn.css('left')) + 50;
pawn.css('left',newLeft+'px');
});
});
Codepen
You can infer how to add support for the different directions/arrow keys.
You need to increment the position value but also take in count that the value you save is a string so you need to convert that back to a number so you can increment it again.
var pawn = document.getElementById("pawn");
var move = 50;
document.body.addEventListener('keyup', showKeyCode);
function showKeyCode(e) {
var num = 0;
if(e.keyCode === 37) {
num = parseInt(pawn.style.left, 10) || 0;
num -= move;
pawn.style.left = num + "px";
}
if(e.keyCode === 38) {
num = parseInt(pawn.style.top, 10) || 0;
num -= move;
pawn.style.top = num + "px";
}
if(e.keyCode === 39) {
num = parseInt(pawn.style.left, 10) || 0;
num += move;
pawn.style.left = num + "px";
}
if(e.keyCode === 40) {
num = parseInt(pawn.style.top, 10) || 0;
num += move;
pawn.style.top = num + "px";
}
}
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
font-family: "Trebuchet MS", sans-serif;
background-color: #ECEFF1;
}
#pawn {
background-color: #B0BEC5;
color: white;
width: 100px;
display: block;
text-align: center;
padding: 20px;
position: absolute;
left: 0;
top: 0;
}
<div id="pawn">pawn</div>