Keyboard Arrow Key Controls in Javascript - javascript

function control()
{
var ship = document.getElementById("ship");
document.onkeydown = function(e) {
switch (e.keyCode) {
case 38:
ship.style.top += "5%";
break;
case 40:
ship.style.top -= "5%";
break;
default:
break;
}
}
}
setInterval(control,1000);
This code is not working.
The object I'm trying to move is not moving when I'm pressing the Up & Down Arrow Key.

You can't do
ship.style.top += "5%";
because ship.style.top value is not a number but a string. the += opérator is concatening strings here.

You should do something like that:
const ship = document.getElementById("ship");
document.onkeydown = function (e) {
let winHeigth = window.innerHeight;
let top = ship.style.top;
switch (e.code) {
case "ArrowUp":
ship.style.top = (Number(top.substring(0, top.length - 2)) - (winHeigth / 20)) + "px";
break;
case "ArrowDown":
ship.style.top = (Number(top.substring(0, top.length - 2)) + (winHeigth / 20)) + "px";
break;
default:
break;
}
}
The position attribute of the "ship" must be like "relative".
By the way, e.keyCode is deprecated, you can use e.code instead ^^

Related

JavaScript game - Object that can not be crossed

I have a project to do as I learn JavaScript.
This is a simple game. You have to go from the bottom to the top of the Canvas.
I would like to place a rock on the canvas what can not be crossed and the player needs to go around it.
Could you help me how to solve this problem?
This is how I control the player
Player.prototype.handleInput = function () {
var self = this;
console.log(self);
document.addEventListener('keyup', function (event) {
var keyName = event.which || event.keyCode;
switch (keyName) {
case true:
return self.x = 0, self.y = 0;
case 37:
case 65:
case 100:
return self.x -= 20;
case 38:
case 87:
case 104:
return self.y -= 20;
case 39:
case 68:
case 102:
return self.x += 20;
case 40:
case 83:
case 101:
return self.y += 20;
}
})
}
This is the rock constructor
Rock = function(){
this.x = getRandomInt(50, 700);
this.y = getRandomInt(50, 400);
this.width = 101;
this.height = 171;
}
I have a collision detection as well what is from the MDN site
function objectCollision(obj1, obj2) {
var rect1 = obj1;
var rect2 = obj2;
if (rect1.x < rect2.x + rect2.width &&
rect1.x + rect1.width > rect2.x &&
rect1.y < rect2.y + rect2.height &&
rect1.height + rect1.y > rect2.y) {
return true;
}
return false;
}
I have tried to solve different ways but I can not figure it out.
I need a solution when the player hit the rock from any sides than it can not move further that way.
Thank you
In your keyup event handler, try something like the following around the existing switch:
var old_x = self.x;
var old_y = self.y;
switch (keyName) {
...
}
for (var i in obstacles) {
if (obstacles[i] != self && objectCollision(self, obstacles[i])) {
self.x = old_x;
self.y = old_y;
break;
}
}
I'm assuming you'll have an array of obstacles rather than just a single rock.

How to make this object move faster

In my code I make an object (A man sprite) move 1 pixel every time an arrow key is pressed. When you hold down the arrow key, the man is very very slow. I tried increasing the amount each time the key is pressed but that is not smooth enough. Can somebody tell me how I can make him move one pixel each time but move one pixel every 100 milliseconds? Thanks I appreciate the help.
function moveLeft() {
var newLeft = left - 1;
left = newLeft;
myElement.style.left = newLeft + 'px';
}
function moveUp() {
var newTop = topStyle - 1;
topStyle = newTop;
myElement.style.top = newTop + 'px';
}
function moveRight() {
var newLeft2 = left + 1;
left = newLeft2;
myElement.style.left = newLeft2 + 'px';
}
function moveDown() {
var newTop2 = topStyle + 1;
topStyle = newTop2
myElement.style.top = newTop2 + 'px';
}
try it, i just re-write the whole code for you. now i use an interval for each 100 milliseconds
var myElement = document.getElementById("character");
var move_left = false;
var move_up = false;
var move_right = false;
var move_down = false;
setInterval(function (){
if (move_left) myElement.style.left = (getIntfromStyle(myElement.style.left) - 1) + 'px';
if (move_up) myElement.style.top = (getIntfromStyle(myElement.style.top) - 1) + 'px';
if (move_right) myElement.style.left = (getIntfromStyle(myElement.style.left) + 1) + 'px';
if (move_down) myElement.style.top = (getIntfromStyle(myElement.style.top) + 1) + 'px';
}, 100);
// with this function, you dont need topStyle & left variables to store previous positions
// you can get current positioin easilysily
function getIntfromStyle(in_style) {
return parseInt(in_style.replace('px', ''));
}
// i use keyboard to tell code when character should be moved and when must stop
document.onkeydown = function(e) {
e = e || window.event;
switch(e.which || e.keyCode) {
case 37: // left
move_left = true;
break;
case 38: // up
move_up = true;
break;
case 39: // right
move_right = true;
break;
case 40: // down
move_down = true;
break;
default: return; // exit this handler for other keys
}
e.preventDefault(); // prevent the default action (scroll / move caret)
}
document.onkeyup = function(e) {
e = e || window.event;
switch(e.which || e.keyCode) {
case 37: // left
move_left = false;
break;
case 38: // up
move_up = false;
break;
case 39: // right
move_right = false;
break;
case 40: // down
move_down = false;
break;
}
}
<div id="character" style="background:red;width:20px;height:20px;position:fixed;display:block;left:0;top:0"></div>

js move object with arrow keys (only once)

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;
}
}
.....
}

How to make a moving div restricted in an outside div?

So I have a div you move with your arrow keys, but how do I make it so it can't go outside the "border div"?
$(document).ready(function(){
$(document).keydown(function(e) {
switch (e.which) {
case 37: // Left
$("#cube").css("left", $("#cube").offset().left - 101);
break;
case 38: // Up
$("#cube").css("top", $("#cube").offset().top - 11);
break;
case 39: // Right
$("#cube").css("left", $("#cube").offset().left - 97);
break;
case 40: // Down
$("#cube").css("top", $("#cube").offset().top - 7);
break;
}
});
});
http://jsfiddle.net/SfKHN/
Here you go:- I tested in FF and Chrome and seems to be fine....
Demo
Probably this is not completely perfect but you can build on it. Key here is to get the margins of the parent right and make sure the cube's left/right/top/bottom doesn't go beyond it. Border width also should be considered. Another thing is your Step should be a multiple of its width/height(as it is a square)
$(document).ready(function(){
$(document).keydown(function(e) {
var cube = $("#cube");
var leftMargin = 0;
var rightMargin = $('#outside').position().left + $('#outside').width() - cube.width();
var topMargin =0;
var bottomMargin = $('#outside').position().top + $('#outside').height() - cube.height();
switch (e.which) {
case 37: // Left
var newLeft = parseInt(cube.position().left - 50);
if(leftMargin <= newLeft)
{
cube.css("left", newLeft);
}
break;
case 38: // Up
var newTop = parseInt(cube.position().top - 50);
if(topMargin <= newTop)
{
cube.css("top",newTop);
}
break;
case 39: // Right
var newRight = (cube.position().left + 50);
if(rightMargin > newRight)
{
cube.css("left", newRight);
}
break;
case 40: // Down
var newBottom = parseInt(cube.position().top + 50);
if(bottomMargin > newBottom)
{
cube.css("top", newBottom);
}
break;
}
});
});
You add simple if statements to make sure you haven't passed the border. Here's an example:
$(document).ready(function(){
$(document).keydown(function(e) {
switch (e.which) {
case 38: // Up
if( ( $("#cube").offset().top - 11 ) >= 0 )
$("#cube").css("top", $("#cube").offset().top - 11);
break;
case 40: // Down
if( ( $( "#cube" ).offset( ).top - 7 ) < ( 400 - 50 ) )
$("#cube").css("top", $("#cube").offset().top - 7 );
break;
}
});
});
You'd make similar changes to the left and right arrows
$(document).ready(function () {
var $out = $('#outside'),
w = $out.width(),
$cube = $('#cube'),
cw = $cube.outerWidth();
$(document).up(function (e) {
switch (e.which) {
case 37:
$cube.css('left', function (_, left) {
left = parseInt(left, 10);
if (left !== 0) return left - cw;
});
break;
case 38:
$cube.css('top', function (_, top) {
top = parseInt(top, 10);
if (top !== -1) return top - cw;
});
break;
case 39:
$cube.css('left', function (_, left) {
left = parseInt(left, 10);
if (left + cw < w) return left + cw;
});
break;
case 40:
$cube.css('top', function (_, top) {
top = parseInt(top, 10);
if (top !== 349) return top + cw;
});
break;
}
});
});
http://jsfiddle.net/QmBNC/

JQuery while keydown

How can i make a movement of a element while the user is "keydown" and then if he make "keyup" to stop the animation(movement), this is my code by now
$(document).ready(function(){
function checkKey(e){
switch (e.keyCode) {
case 40:
//alert('down');
$('#cube').animate({top: "+=20px"})
break;
case 38:
//alert('up');
$('#cube').animate({top: "-=20px"})
break;
case 37:
//alert('left');
$('#cube').animate({left: "-=20px"})
break;
case 39:
//alert('right');
$('#cube').animate({left: "+=20px"})
break;
default:
alert('???');
}
}
if ($.browser.mozilla) {
$(document).keydown (checkKey);
} else {
$(document).keydown (checkKey);
}
})
i want to move the cube while the user press the key (down, left, up, right), not with every press, is possible?
You need a simple 2D engine that will setup a game loop.
Simple demo: http://jsfiddle.net/kzXek/
Source: https://github.com/superrob/simple-2D-javascript-engine/blob/master/simple2d.html
Is that you are looking for?
$(document).on("keyup", function() {
$("#cube").stop(true);
});
DEMO: http://jsfiddle.net/LjGRe/
you can just change the checkKey function, and add this to it :
function checkKey(e){
$(document).keyup(return);
switch (e.keyCode) {
case 40:
//alert('down');
$('#cube').animate({top: "+=20px"})
break;
case 38:
//alert('up');
$('#cube').animate({top: "-=20px"})
break;
case 37:
//alert('left');
$('#cube').animate({left: "-=20px"})
break;
case 39:
//alert('right');
$('#cube').animate({left: "+=20px"})
break;
default:
alert('???');
}
}
I think using a timer to handle the animation is better.
You just start the timer when a key is pressed and stop it when the key is released ..
Here is a simple solution that handles multiple keypresses (can move diagonally)
var direction = {top:0,left:0},
animator = null,
cube = $("#cube");
function animate(){
cube.css({
top: '+=' + direction.top,
left: '+=' + direction.left
});
}
function setProperties(keyCode, unset){
switch (keyCode) {
case 40:
direction.top = (unset)?0:2;
break;
case 38:
direction.top = (unset)?0:-2;
break;
case 37:
direction.left = (unset)?0:-2;
break;
case 39:
direction.left = (unset)?0:2;
break;
}
}
function setKey(e) {
setProperties(e.keyCode);
if (animator === null){
animator = setInterval(animate, 10);
}
}
function unsetKey(e){
setProperties(e.keyCode, true);
if (direction.top === 0 && direction.left === 0){
clearTimeout(animator);
animator = null;
}
}
$(document)
.on("keyup", unsetKey)
.on('keydown', setKey);
Demo at http://jsfiddle.net/gaby/Cu6nW/

Categories

Resources