JavaScript:"onkeydown"and "onkeypress" - javascript

I want to capture the event of onkeydown to move a box but when I press the key constantly,there existing a delay,that is,when I press a key constantly,the box will move after a while.Please help me eliminate the delay.

If I understand you correctly I believe the delay you are referring to might be the default functionality of your keyboard. For example if you open a text-editor and press and hold space you notice it will do:
(move over a little) (wait) (start moving)
Keyboard events also work in this way. If you defined moving of your box to something similar to this:
document.addEventListener("keydown", function(e) {
var key = e.which;
if( key == 37 ) X -= speed;
if( key == 38 ) Y -= speed;
if( key == 39 ) X += speed;
if( key == 40 ) Y += speed;
});
Here is an example of the code above
You will notice this "type-writer" like behavior. To fix this you can use Booleans to detect when a key is pressed (true), then to detect when the pressed key is let go (false). In your screen update function check these Booleans for movement.
var LEFT = false , RIGHT = false, UP = false, DOWN = false;
...
document.addEventListener("keydown", function(e) {
var key = e.which;
if( key == 37 ) LEFT = true;
if( key == 38 ) UP = true;
if( key == 39 ) RIGHT = true;
if( key == 40 ) DOWN = true;
});
document.addEventListener("keyup", function(e) {
var key = e.which;
if( key == 37 ) LEFT = false;
if( key == 38 ) UP = false;
if( key == 39 ) RIGHT = false;
if( key == 40 ) DOWN = false;
});
...
// In update function
if( LEFT ) X -= speed;
if( UP ) Y -= speed;
if( RIGHT ) X += speed;
if( DOWN ) Y += speed;
Here is an example
Notice in the second example the movement is much smoother.

<html>
<head>
<style>
.box {
width: 100px;
height: 100px;
background: #ccc;
position: absolute;
top: 0px;
left: 0px;
}
.clear {
clear: both;
}
p {
margin-top: 100px;
}
</style>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
<div class="box"></div>
<div class="clear"></div>
<p> Press Space Bar</p>
<script type="text/javascript">
$(document).ready(function(){
console.log("ready");
});
$(document).on('keydown', function(event){
var code = event.keyCode;
if (code == 32) {
var div = $('.box');
var left = div.position().left;
var new_left = left + 1;
console.log(new_left);
div.css({
'left': new_left + "px"
});
}
});
</script>
</body>
</html>
a JSfiddle Link
maybe this could give you a little help.
and try also to console.log on your event

Related

prevent snake from going in reverse direction

I am making a classic snake remake in JavaScript just for weekend fun, and I ran into this problem that if I press buttons quite fast - the snake (caterpillar in my case) is able to change direction to opposite and run into itself.
The way to recreate this situation is as follows:
direction is for example 'left'
press up(or down) and press right quickly after
now the caterpillar goes backwards. And my goal is it should make U-turn
I made the checks for opposite dir, but this doesn't prevent this
update = function() {
if (cat.direction != 'right' && key[37] === true) {
cat.direction = 'left';
}
if (cat.direction != 'left' && key[39] === true) {
cat.direction = 'right';
}
if (cat.direction != 'down' && key[38] === true) {
cat.direction = 'up';
}
if (cat.direction != 'up' && key[40] === true) {
cat.direction = 'down';
}
};
the full code
I was using normal addEventListener for the key listening, but I changed it for another approach (found somewhere), where I do update on keys very often and caterpillar moving is happening only from time to time, as I thought it might be a problem to directly associate drawing, changing direction and moving in the same time interval. I hope I am understandable, sorry if something isn't clear - I would be happy to provide more info if so.
One solution is to not process more than one key per move, but to allow more responsiveness you could implement a key buffer, instead of maintaining the key states as you do know. You would only collect arrow key presses in that buffer, and not push any repetitions of the same key into it.
Here are the relevant changes to the code:
Initialise the key buffer:
var keyBuffer = [];
Push arrow keys into the buffer when pressed:
var keyDown = function(e) {
var keyCode = e.which ? e.which : e.keyCode;
// *** Queue the arrow key presses
if (keyCode >= 37 && keyCode <= 40 &&
keyCode !== keyBuffer[keyBuffer.length-1] && ) {
keyBuffer.push(keyCode);
}
};
Process one key from the buffer at a time:
var update = function() {
// *** Extract next key from buffer, and only treat that one
// -- could be `undefined`, but that is not a problem:
var key = keyBuffer.shift();
if(cat.direction != 'right' && key === 37){
cat.direction = 'left';
} else if(cat.direction != 'left' && key === 39){
cat.direction = 'right';
} else if(cat.direction != 'down' && key === 38){
cat.direction = 'up';
} else if(cat.direction != 'up' && key === 40){
cat.direction = 'down';
}
};
Only process next key when about to move:
function loop() {
board.resetCanvas();
if(counter > 1000){
update(); // ***only process buffered keys when moving
cat.move();
counter = 0;
}
cat.draw();
counter += 5*cat.multiplier;
};
That's it. See fiddle below:
var canvas = document.getElementById("board");
var context = canvas.getContext("2d", {alpha:false});
var pieceSideLength = canvas.width / 40;
var key = [];
var keyBuffer = [];
window.addEventListener('keyup', function(e) {
this.keyUp.call(this, e);
}, false);
window.addEventListener('keydown', function(e) {
this.keyDown.call(this, e);
}, false);
function Piece(x,y){
this.x = x;
this.y = y;
}
board = {
leftBound: 0,
rightBound: canvas.width / pieceSideLength,
topBound: 0,
bottomBound: canvas.height / pieceSideLength,
drawPiece: function(x, y, color){
context.fillStyle = color;
context.fillRect(x*pieceSideLength,y*pieceSideLength,pieceSideLength,pieceSideLength);
context.strokeStyle = 'white';
context.strokeRect(x*pieceSideLength,y*pieceSideLength,pieceSideLength,pieceSideLength);
},
resetCanvas: function(){
context.clearRect(0,0,canvas.width,canvas.height);
}
};
//cat as for caterpillar
cat = {
x: canvas.width/pieceSideLength/2, //initial x
y: canvas.height/pieceSideLength/2, //initial y
pieces: [],
direction: 'up',
color: '#5da03c',
shouldGrow: false,
multiplier: 5,
init: function(){
cat.pieces.push(new Piece(this.x, this.y));
},
move: function(){
if(cat.pieces.length <= 10){
cat.shouldGrow = true;
}
var newX = cat.pieces[cat.pieces.length-1].x;
var newY = cat.pieces[cat.pieces.length-1].y;
if(cat.direction=='up'){
cat.makeNewHeadAt(newX,newY-1);
}
if(cat.direction=='down'){
cat.makeNewHeadAt(newX,newY+1);
}
if(cat.direction=='left'){
cat.makeNewHeadAt(newX-1,newY);
}
if(cat.direction=='right'){
cat.makeNewHeadAt(newX+1,newY);
}
cat.grow();
},
makeNewHeadAt: function(x,y){
cat.pieces.push(new Piece(x,y));
},
grow: function(){
if(cat.shouldGrow == false){
cat.pieces.shift();
} else {
cat.shouldGrow = false;
}
},
draw: function(){
for(i=0;i<cat.pieces.length;i++){
var p = cat.pieces[i];
board.drawPiece(p.x,p.y,cat.color);
}
}
};
cat.init();
update = function() {
// *** Extract next key from buffer, and only treat that one
// -- could be `undefined`, but that is not a problem:
var key = keyBuffer.shift();
if(cat.direction != 'right' && key === 37){
cat.direction = 'left';
} else if(cat.direction != 'left' && key === 39){
cat.direction = 'right';
} else if(cat.direction != 'down' && key === 38){
cat.direction = 'up';
} else if(cat.direction != 'up' && key === 40){
cat.direction = 'down';
}
};
keyUp = function(e) {
var keyCode = e.which ? e.which : e.keyCode;
this.key[keyCode] = false;
};
keyDown = function(e) {
var keyCode = e.which ? e.which : e.keyCode;
// *** Queue the key presses
if (keyCode >= 37 && keyCode <= 40 &&
keyCode !== keyBuffer[keyBuffer.length-1]) {
keyBuffer.push(keyCode);
}
this.key[keyCode] = true;
};
var counter = 0;
function loop() {
board.resetCanvas();
if(counter > 1000){
update(); // ***only process buffered keys when moving
cat.move();
counter = 0;
}
cat.draw();
counter += 5*cat.multiplier;
};
setInterval(loop, 1);
body { margin: 0px }
<div>
<canvas id="board" width="300" height="200" style="display: block; margin: 0 auto; background-color: #553300; border-style: solid; border-color: green;"></canvas>
</div>
Limiting the buffer size
You can limit the buffer size by replacing this:
keyBuffer.push(keyCode);
with:
keyBuffer = keyBuffer.slice(-2).concat(keyCode);
This will limit the size to 3. Adjust the slice argument as desired.
You can keep track of whether the snake has 'moved'. If you receive keyboard input, don't react to another keypress until the snake has moved. This way you're only allowing 1 key for each movement, so you can't change direction and run into yourself.
Modified example: link
update = function() {
if (moved = true) {
if(cat.direction != 'right' && key[37] === true){
and so forth

Adding a cool down to a javascript key press

I have a Jquery problem today using key Codes, my code dumb below
$(function() {
var distance = 0;
$('.right').click(function() {
distance -= 100;
$('#container').css('transform', 'translateX(' + distance + '%)')
console.log(distance);
});
$('.left').click(function() {
distance += 100;
$('#container').css('transform', 'translateX(' + distance + '%);')
console.log(distance);
});
$(window).keypress(function (e) {
var code = e.keyCode || e.which;
if(code == 13) {
$('.right').trigger('click')
}
if(code == 9) {
$('.right').trigger('click')
}
if(code == 32) {
$('.right').trigger('click')
}
if(code == 39) {
$('.right').trigger('click')
}
});
});
So I am having some trouble making the arrow key presses work.
if(code == 32) {
$('.right').trigger('click')
}
if(code == 39) {
$('.right').trigger('click')
}
Not only that but I can't seem to figure out a way to put a delay on it (1s) so it doesn't add a few hundred to the distance var when I only want it to do it once, so lets say instead of delay, a cool down.
UPDATE
While I'm at it I would like to ask if anyone has any solutions to putting a maximum and miniumum amount on
var distance = 0;
Look at debounce and throttle mechanisms described here. It should help you in achieving the delay/cool down.

How to detect when an enter is pressed using jQuery?

I am trying to detect what key is pressed and based on that I want to fire click() event.
My code work for all the key except for the enter.
for some reason when I press "enter" I do not get any messages on the screen as if the enter button was not pressed.
Here is my code
$(function(){
$(document).keypress(function(e) {
handleKeyPress(e);
});
function handleKeyPress( e ){
var key = e.which;
alert(key);
if( getIcwsTabIndex() != 1){
return;
}
if( key >= 48 && key <= 57){
var k = key - 48;
$('#icwsDialerNumber' + k).click();
}
if( key == 8){
e.preventDefault();
$('#icwsDialerScreenDel').click();
}
if( key == 13){
e.preventDefault();
$('#icwsDialerNumberDial').click();
}
}
});
what am I doing wrong here?
tested your code, it works on chrome besides the not defined getIcwsTabIndex
so verify it is ok on your side
here is a fiddle check the console
$(function(){
$(document).keypress(function(e) {
handleKeyPress(e);
});
function handleKeyPress( e ){
var key = e.which;
console.log(key);
// if( getIcwsTabIndex() != 1){
// return;
// }
if( key >= 48 && key <= 57){
var k = key - 48;
$('#icwsDialerNumber' + k).click();
}
if( key == 8){
e.preventDefault();
$('#icwsDialerScreenDel').click();
}
if( key == 13){
e.preventDefault();
console.log(key);
$('#icwsDialerNumberDial').click();
}
}
});
The problem with your code is that is not cross-browser. It should be:
var key = e.charCode || e.keyCode || 0;

How to make object move in js?

I'm trying to learn object oriented programming in javascript so I try to make a simple game. I would like to make a character that moves. There is the code in js:
function move(event)
{
var k=event.keyCode;
var chr = {
updown : function (){
var y=0;
if (k==38)
{--y;
}else if (k==40)
{++y;}
return y;
},
leftright : function (){
var x=0;
if (k==37)
{--x;
}else if (k==39)
{++x;}
return x;
}
};
chrId.style.top = (chr.updown())+"px";
chrId.style.left = (chr.leftright())+"px";
}
html:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="jumpOPP.css">
<script src="jumpOPP.js"></script>
</head>
<body onkeydown="move(event)">
<img id="chrId" src="TrackingDot.png" >
</body>
</html>
and CSS:
#chrId {
position: relative;
top: 0px;
left: 0px;
}
When I press and hold up, down, left, right the dot moves only for a one place. How to make it moving whole time I' m holding some key. I have made it without var char to move. I used function move(event) and then a switch, cases 38, 37, 39 and 40 and then it change style.top but I can't make it in one object.
Is it possible to make a object chr = {objekt movement, life, power...} and then a object ground = {some code that stops the chr} and other interacting objects ? Can somebody recomend a good tutorial for that? :)
Thank you
Here working jsfiddle - http://jsfiddle.net/t5ya4j26/
You error in define local variables in scopes that always will equal to 0. So for fix that, you must get current left and top of element, not define x = 0 and y = 0.
function move(event) {
var k = event.keyCode,
chrId = document.getElementById('test'),
chr = {
updown: function () {
var y = parseInt(getComputedStyle(chrId).top);
if (k == 38) {
--y;
} else if (k == 40) {
++y;
}
return y;
},
leftright: function () {
var x = parseInt(getComputedStyle(chrId).left);
if (k == 37) {
--x;
} else if (k == 39) {
++x;
}
return x;
}
};
chrId.style.top = (chr.updown()) + "px";
chrId.style.left = (chr.leftright()) + "px";
}
document.addEventListener('keydown', move);
I would recommend that you use the <canvas> element for stuff like this. But use window.setInterval(function, milliseconds) to have it repeatedly run your 'move' function and then when a key is released, window.onkeyup clear that interval.
clearInterval(intervalName);
This requires you to make a new event listener. Instead of having your event listener in body, use:
window.onkeydown = function(event) {
var k = event.which || event.keyCode; // This adds compatibilty across all browsers
// Code to be run
}
I know that you are looking for the function in an object, but moving an element is really quick and easy with this, I just made this today for my beginners game:
var change = (parseInt(chrId.style.left.replace('%',''),10) + 3).toString() + "%"
chrId.style.left = change
The % signs can be replaced with 'px' if you are using pixel values to move, and the ' + 3 ' is how many pixels or percentage points you want your element to move per execution.
The same can be done for up by changing the 'left' to 'top'.
My code might not be to your liking, but I'm just trying to demonstrate how I work around this problem, I am positively sure that there are hundreds of better ways, but this one seems to save me a lot of trouble for a lot of other stuff.
Hope I was able understand the question and help though, sorry if I couldn't :)
<!DOCTYPE html>
<html>
<head>
<meta charset = "utf-8">
<title> MOVEMENT </title>
</head>
<body>
<script type = "text/javascript">
//------------------------------------------------------------------------------
// VARIABLES are set here so they're GLOBAL (everything may access them)
//------------------------------------------------------------------------------
let lock_left = true
let lock_top = true
let lock_right = true
let lock_bottom = true
//------------------------------------------------------------------------------
let html; let htmls
let body; let bodys
let avatar; let avatars
//------------------------------------------------------------------------------
let avatar_x = 0
let avatar_y = 0
//------------------------------------------------------------------------------
// EVERY map will be an object, and every object needs a CREATE function that
// will happen only ONCE and an UPDATE function that will repeat itself
//------------------------------------------------------------------------------
const map_main =
{
create: function()
{
html = document.querySelector( "html" ); htmls = html.style
body = document.querySelector( "body" ); bodys = body.style
},
//--------------------------------------------------------------------------
update: function()
{
htmls.width = "100%"
htmls.height = "100%"
htmls.margin = "0"
bodys.width = "100%"
bodys.height = "100%"
bodys.margin = "0"
bodys.backgroundColor = "rgb( 120, 200, 80 )"
},
}
//------------------------------------------------------------------------------
const map_avatar =
{
create: function()
{
avatar = document.createElement( "div" ); avatars = avatar.style
body.appendChild( avatar )
},
//--------------------------------------------------------------------------
update: function()
{
avatars.width = "64px"
avatars.height = "64px"
avatars.backgroundColor = "rgb( 200, 80, 120 )"
avatars.position = "absolute"
avatars.top = avatar_y + "px"
avatars.left = avatar_x + "px"
},
}
//------------------------------------------------------------------------------
// BELOW are the 2 main gears of the engine
//------------------------------------------------------------------------------
// EVERY code that only needs to happen once is called here
const master_create = function()
{
map_main.create()
map_avatar.create()
}
//------------------------------------------------------------------------------
// EVERYTHING that needs constant updates is called here
const master_update = function()
{
map_main.update()
map_avatar.update()
movement()
window.requestAnimationFrame( master_update )
}
//------------------------------------------------------------------------------
// BELOW is showing how the keyboard affects the locks
//------------------------------------------------------------------------------
const press = function( pressed )
{
if( pressed.keyCode === 37 || pressed.keyCode === 69 ) lock_left = false
if( pressed.keyCode === 38 || pressed.keyCode === 82 ) lock_top = false
if( pressed.keyCode === 39 || pressed.keyCode === 70 ) lock_right = false
if( pressed.keyCode === 40 || pressed.keyCode === 68 ) lock_bottom = false
}
//------------------------------------------------------------------------------
const release = function( released )
{
if( released.keyCode === 37 || released.keyCode === 69 ) lock_left = true
if( released.keyCode === 38 || released.keyCode === 82 ) lock_top = true
if( released.keyCode === 39 || released.keyCode === 70 ) lock_right = true
if( released.keyCode === 40 || released.keyCode === 68 ) lock_bottom = true
}
//------------------------------------------------------------------------------
// BELOW will check the LOCKS and use them to change AVATAR_X and AVATAR_Y
//------------------------------------------------------------------------------
const movement = function()
{
if( lock_left === false ) avatar_x -= 10
if( lock_top === false ) avatar_y -= 10
if( lock_right === false ) avatar_x += 10
if( lock_bottom === false ) avatar_y += 10
}
//------------------------------------------------------------------------------
// BELOW we call the 2 gears and everything will work
//------------------------------------------------------------------------------
master_create() // will be called only ONCE
master_update() // will repeat forever due to "window.requestAnimationFrame()"
//------------------------------------------------------------------------------
// LISTENERS should go after the engine starts rolling
//------------------------------------------------------------------------------
body.addEventListener( "keydown", press, false )
body.addEventListener( "keyup", release, false )
//------------------------------------------------------------------------------
</script>
</body>
</html>

Javascript error: I have a unexpected end of input on my first line, with no apparent problems, but I'm getting a message and the whole canvas stops

I put in the entire thing just in case
I went into chrome and looked for errors, and it wasnt working either so I checked, apparently the first line has a problem. I kept the first 6 lines and deleted all else then it worked fine, so I went to SublimeText2 and searched for every ) and } in the code.
var canvasBg = document.getElementById('canvasBg');
var ctxBg = canvasBg.getContext('2d');
var canvasJet = document.getElementById('canvasJet');
var ctxJet = canvasJet.getContext('2d');
var jet1;
var fps = 17;
var drawInterval;
var imgSprite = new Image();
imgSprite.src = 'SpriteSheet.png'
imgSprite.addEventListener('load',init,false);
function init() {
drawBg();
startDrawing();
jet1 = new Jet();
document.addEventListener('keydown',checkKeyDown,false);
document.addEventListener('keyup',checKeyUp,false);
}
function draw() {
jet1.draw();
}
function startDrawing() {
stopDrawing();
drawInterval = setInterval(draw,fps);
}
function stopDrawing() {
clearInterval(setInterval);
}
Jet.prototype.draw = function() {
clearCtxJet();
ctxJet.drawImage(imgSprite,this.srcX,this.srcY,this.width,this.height,this.drawX,this.drawY,this.width,this.height);
};
function Jet() {
this.srcX = 0;
this.srcY = 0;
this.drawX = 200;
this.drawY = 200;
this.width = 96;
this.height = 30;
}
function drawJet() {
}
function drawBg() {
ctxBg.drawImage(imgSprite,96,0,800,500,0,0,800,500)
}
function clearCtxBg() {
ctxBg.clearRect(0,0,800,500);
}
function clearCtxJet() {
ctxJet.clearRect(0,0,800,500);
}
function checkKeyDown(e) {
var keyID = (e.keyCode) ? e.keyCode : e.which;
if (keyID === 38) { // 38 is up key
alert('up arrow was pressed');
e.preventDeafault();
}
if (keyID === 39) { // 39 is right key
e.preventDeafault();
}
if (keyID === 40) { // 40 is down key
e.preventDeafault();
}
if (keyID === 37) { // 37 is left key
e.preventDeafault();
}
function checkKeyup(e) {
var keyID = (e.keyCode) ? e.keyCode : e.which;
if (keyID === 38) { // 38 is up key
alert('up arrow was pressed');
e.preventDeafault();
}
if (keyID === 39) { // 39 is right key
e.preventDeafault();
}
if (keyID === 40) { // 40 is down key
e.preventDeafault();
}
if (keyID === 37) { // 37 is left key
e.preventDeafault();
}
}
I assume you're showing only parts of the code so there's no way of knowing whether this is the actual error, but both checkKeyup and checkKeydown are missing closing braces.
I recommend installing Package Control for Sublime Text 2 and then using it to install SublimeLinter which will be able to check your code for you and point out missing semicolons and braces.
It would be nice to see full code in http://jsfiddle.net

Categories