Preventing key event delay [duplicate] - javascript

The "spaceShip" in the following code isn't moving smoothly at the beginning of holding any arrow key down. It moves one step, freezes for a split second, and then moves "smoothly". How can I make it move smoothly right from the beginning, with not "freezing"?
My code:
<!doctype html>
<html>
<head>
<meta http-content="Content-type" charset="utf-8">
<title>Make body move smoothly</title>
<style type="text/css">
body {
}
canvas {
margin: auto;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
border: 1px solid black;
}
</style>
</head>
<body>
<canvas id="canvas" width="400" height="600"></canvas>
<script type="text/javascript">
// Set up requestAnimationFrame and cancelAnimationFrame
(function() {
var lastTime =0;
var vendors=['ms', 'moz', 'webkit', 'o'];
for(var x=0; x<vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame=window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame =
window[vendors[x]+ 'CancelAnimationFrame'] ||
window[vendors[x] +'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame=function(callback, element) {
var currTime =new Date().getTime();
var timeToCall =Math.max(0, 16 - (currTime - lastTime));
var id =window.setTimeout(function() { callback(currTime+timeToCall); },
timeToCall);
lastTime =currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame=function(id) {
clearTimeout(id);
};
}());
var canvas;
var ctx;
// ship data
var shipPositionX = document.getElementById('canvas').width/2;
var shipPositionY = document.getElementById('canvas').height - 30;
var deltaShipPositionX = 10;
var deltaShipPositionY = 10;
function init() {
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
draw();
}
function draw(){
clear();
createRectangleToCoverCanvas();
createSpaceShip(shipPositionX, shipPositionY, 10);
requestAnimationFrame(draw);
}
function clear(){
ctx.clearRect(0, 0, document.getElementById('canvas').width, document.getElementById('canvas').height);
}
function createRectangleToCoverCanvas(){
ctx.fillStyle = 'black';
ctx.strokeStyle = 'black';
ctx.beginPath();
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.closePath();
ctx.fill();
ctx.stroke();
}
function createSpaceShip(x, y, radius) {
ctx.fillStyle = 'white'
ctx.strokeStyle = 'white'
ctx.beginPath();
ctx.rect(x, y, 20, 20);
ctx.closePath();
ctx.fill();
ctx.stroke();
}
function moveSpaceShip(event){
switch(event.keyCode){
// left
case 37:
if(shipPositionX - deltaShipPositionX + 15 > 0){
shipPositionX -= deltaShipPositionX;
}
break;
// up
case 38:
if(shipPositionY - deltaShipPositionY + 15 > 0){
shipPositionY -= deltaShipPositionY;
}
break;
// right
case 39:
if(shipPositionX + deltaShipPositionX < document.getElementById('canvas').width){
shipPositionX += deltaShipPositionX;
}
break;
//down
case 40:
if(shipPositionY + deltaShipPositionY < document.getElementById('canvas').height){
shipPositionY += deltaShipPositionY;
}
break;
}
}
window.addEventListener('load', init);
window.addEventListener('keydown', moveSpaceShip, true);
</script>
</body>
</html>
Notice the difference between my code and this example: http://atomicrobotdesign.com/blog_media/sprite_sheet/spritesheet.html
See how the example's is smooth, but my "spaceShip" isn't?
Why is it happening and how can I fix it? Is it because the example uses a sprite (but this doesn't seem to make much sense)?

The problem is that you wait for each keydown event to update the ship position.
The keydown event has a delay before it triggers again : the delay you are experiencing at beginning and the jump you face at each redraw.
The solution here is to trigger the movement on keydown and release it on keyup. This way, your ship will move smoothly as soon as you push the button.
// Im' assuming most of visitors here have recent browsers, so I removed the rAF polyfill for readibility
// If you wrap it after the canvas element decalaration, you can already populate this variable, it will avoid that you make a lot of calls to document.getElementById()
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// ship data
var shipPositionX = canvas.width / 2;
// Just for the snippet height
var shipPositionY = 0;
var deltaShipPositionX = 10;
var deltaShipPositionY = 10;
//Removed the init() function, since our elements are loaded.
function draw() {
clear();
createRectangleToCoverCanvas();
createSpaceShip(shipPositionX, shipPositionY, 10);
}
function clear() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function createRectangleToCoverCanvas() {
ctx.fillStyle = 'black';
ctx.strokeStyle = 'black';
ctx.beginPath();
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.fill();
ctx.stroke();
}
function createSpaceShip(x, y, radius) {
ctx.fillStyle = 'white'
ctx.strokeStyle = 'white'
ctx.beginPath();
ctx.rect(x, y, 20, 20);
ctx.fill();
ctx.stroke();
}
// instantiate a variable that will store our animationFrame id, so we can cancel it further
var raf,
// the direction object, with an x and y values
direction = {
x: 0,
y: 0
};
// we can set a speed variable
var speed = 2.5;
function triggerMoveSpaceShip(event) {
switch (event.keyCode) {
// left
case 37:
// update the direction object
direction.x = -speed;
// avoid the scroll in the snippet
event.preventDefault();
break;
// up
case 38:
direction.y = -speed;
event.preventDefault();
break;
// right
case 39:
direction.x = speed;
event.preventDefault();
break;
//down
case 40:
direction.y = speed;
event.preventDefault();
break;
}
// if we haven't initiated the animation yet, and that our direction is not 0, then do it now
if (!raf && (direction.x || direction.y)) moveSpaceShip();
}
function releaseMoveSpaceShip(event) {;
switch (event.keyCode) {
// left
case 37:
//reset this direction
direction.x = 0;
break;
// up
case 38:
direction.y = 0;
break;
// right
case 39:
direction.x = 0;
break;
//down
case 40:
direction.y = 0;
break;
}
if (!direction.x && !direction.y) {
// if none of the directions is set, stop the animation
cancelAnimationFrame(raf);
raf = undefined;
}
}
function moveSpaceShip() {
// declare our animation function
var move = function() {
// update the positions without going out of the screen
// Sorry, this is dirty...
if(direction.x){
if(
(shipPositionX > 0 && shipPositionX < canvas.width-20) ||
(shipPositionX <= 0 && direction.x > 0) ||
(shipPositionX >= canvas.width-20 && direction.x < 0))
shipPositionX += direction.x;
}
if(direction.y){
if(
(shipPositionY > 0 && shipPositionY < canvas.height-20) ||
(shipPositionY <= 0 && direction.y > 0) ||
(shipPositionY >= canvas.width-20 && direction.y < 0))
shipPositionY += direction.y;
}
// finally draw ou ship
draw();
// update our raf id
raf = requestAnimationFrame(move);
};
// let's go !
raf = requestAnimationFrame(move);
}
draw();
window.addEventListener('keydown', triggerMoveSpaceShip, true);
window.addEventListener('keyup', releaseMoveSpaceShip, true);
canvas {
margin: auto;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
border: 1px solid black;
}
body{
overflow: none;
}
<canvas id="canvas" width="400" height="200"></canvas>
uncommented fiddle

Related

Create bullets for a game at an interval

I have a game, and in it there is a main, controllable character and then enemies that shoot back at the character. For the enemies, when they shoot back I want them to shoot at intervals so that it isn't just one massive block of bullets, and it worked with a setInterval for one, but when a second enemy comes in they don't shoot. Only one of the two will. If anybody has a solution that would be great!
function enemies() {
if (enemy_soldiers.length == 0) {
level += 0.2;
for (var i = 0; i<(1 + Math.floor(Math.round(level))); i++) {
var gx = 1450
var gy = getRandom(430, 630);
enemy_soldiers.push({
x: gx,
y: gy,
l: gl,
d: getRandom(350, 600),
shooting: false,
interval: setInterval (function() {enemy.shooting = true;},fire_rate),
shoot: function() {
enemy_bullets.push({
x: enemy.x+40,
y: enemy.y+87,
vel: 10,
});
}
});
}
}
var enemy;
gctx.clearRect(0, 0, 1400, 800);
for (var i in enemy_soldiers) {
enemy = enemy_soldiers[i];
drawenemy(enemy.x, enemy.y, enemy.l);
//ai
if (distance(enemy.x, enemy.y, cx, cy) >= enemy.d && enemy.x>cx) {
enemy.x-=vel;
}
else if (distance(enemy.x, enemy.y, cx, cy) >= enemy.d && enemy.x<cx) {
enemy.x+=vel;
}
if (distance(enemy.x, enemy.y, cx, cy) <= 600) {
if (enemy.shooting == true) {
enemy.shoot(enemy.x,enemy.y);
enemy.shooting = false;
}
gbctx.clearRect(0, 0, 1400, 800);
for (var j in enemy_bullets) {
enemy_bullet = enemy_bullets[j];
enemy_bullet.x -= enemy_bullet.vel;
if (enemy_bullet.x > 1400 || enemy_bullet.x < -5 || enemy_bullet.y > 800 || enemy_bullet.y < -5) {
enemy_bullets.splice(j,1);
}
drawEnemyBullet(enemy_bullet.x, enemy_bullet.y);
}
}
}}
This solution relies on the function Date.now() which returns the current time in milliseconds. It's possible for each enemy to keep track of when they have to fire next and each one can have a different delay between shots.
I've only added a graphic to show when they are firing their weapons, but this can be easily altered to something like a raycast or spawn a projectile particle.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: black;
}
canvas {
position: absolute;
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
border: solid 1px white;
border-radius: 1px;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="application/javascript">
// Enemy constructor
function Enemy(x,y) {
this.x = x;
this.y = y;
this.isFiring = false;
this.fireDelay = (500 + Math.random() * 500) | 0; // Time between shots
this.lastFired = Date.now(); // Last time at which the enemy fired
}
/*
Enemy prototype
(All objects created using the constructor share these properties)
E.G.
var e1 = new Enemy(10,0);
var e2 = new Enemy(20,0);
if (e1.__proto__ === e2.__proto__) {
console.log("Match");
}
prints "Match"
*/
Enemy.prototype = {
WIDTH: 10,
HEIGHT: 20,
FIRE_DURATION: 100, // Amount of time 'fire' graphic is shown
FIRE_WIDTH: 10,
FIRE_HEIGHT: 10,
update: function() {
// If current time - time when I last fired > the amount of time between shots
if (Date.now() - this.lastFired > this.fireDelay) {
this.lastFired = Date.now();
this.isFiring = true;
// If you were using projectile particles, this is where you would spawn one
}
if (this.isFiring && Date.now() - this.lastFired > this.FIRE_DURATION) {
this.isFiring = false;
}
},
render: function(ctx) {
ctx.fillStyle = "darkred";
ctx.strokeStyle = "black";
ctx.lineWidth = 2;
ctx.beginPath();
ctx.rect(
this.x,
this.y,
this.WIDTH,
this.HEIGHT
);
ctx.fill();
ctx.stroke();
if (this.isFiring) {
ctx.fillStyle = "yellow";
ctx.strokeStyle = "darkyellow";
ctx.lineWidth = 3;
ctx.beginPath();
ctx.rect(
this.x + this.WIDTH,
this.y + this.HEIGHT * 0.5 - this.FIRE_HEIGHT * 0.5,
this.FIRE_WIDTH,
this.FIRE_HEIGHT
);
ctx.fill();
ctx.stroke();
}
}
};
var canvasWidth = 180;
var canvasHeight = 160;
var canvas = null;
var ctx = null;
var enemies = [];
window.onload = function() {
canvas = document.getElementById("canvas");
canvas.width = canvasWidth;
canvas.height = canvasHeight;
ctx = canvas.getContext("2d");
for (var i = 0; i < 5; ++i) {
enemies[i] = new Enemy(20 + i * 3,10 + i * 30);
}
loop();
}
function loop() {
// Update
for (var i = 0; i < enemies.length; ++i) {
enemies[i].update();
}
// Render
ctx.fillStyle = "gray";
ctx.fillRect(0,0,canvasWidth,canvasHeight);
for (var i = 0; i < enemies.length; ++i) {
enemies[i].render(ctx);
}
//
requestAnimationFrame(loop);
}
</script>
</body>
</html>

HTML Canvas & Javascript - Emulating a Scroll-On-Hover Event

I am trying to write a scroll-on-hover function in an HTML canvas by defining a hover variable, detecting mouse events over the designated hover area and (on doing so) adding or subtracting to this hover variable depending on which area is hovered over. This hover variable is connected to the position of a series of selection buttons which, for the purposes of this example, contain the numbers 0 to 30. When either end of this series of selection buttons is hovered over they all move up or down as if scrolled, but to make it act like a scroll you must keep the mouse moving as the canvas is only rendered on each new mousemove event.
My question is how can I trigger the event on mouseover such that if (lowerHoverBoxHitTest(x, y)) or (upperHoverBoxHitTest(x, y)) (i.e if the mouse is hovered over either of the hit boxes defined in the script below) the hover variable keeps being added to by the set increment (0.1) until the mouse leaves that area. I have tried replacing the if/else statement in the function mouseMove with a while loop (as it would seem this is logically akin to what I am asking) as so
while (lowerHoverBoxHitTest(x, y)) {
if (hover < 750) {
hover-=0.1;
}
}
while (upperHoverBoxHitTest(x, y)) {
if (hover > 0) {
hover+=0.1;
}
}
but this just causes the page to crash (presumably it triggers an infinite loop?). There isn't much on Stack Overflow about this besides this but this solution is not useful if you have a lot of other things in your canvas that you don't want to scroll (unless you were to define their position absolutely which I don't want to) which I do in my full project. Any help will be appreciated.
var c=document.getElementById('game'),
canvasX=c.offsetLeft,
canvasY=c.offsetTop,
ctx=c.getContext('2d');
var hover=0;
function upperHoverBoxHitTest(x, y) {
return (x >= 0) && (x <= 350) && (y >= 0) && (y <= 50);
}
function lowerHoverBoxHitTest(x, y) {
return (x >= 0) && (x <= 350) && (y >= 450) && (y <= 500);
}
var selectionForMenu = function(id, text, y) {
this.id = id;
this.text = text;
this.y = y;
}
selectionForMenu.prototype.makeSelection = function() {
ctx.beginPath();
ctx.fillStyle='#A84FA5';
ctx.fillRect(0, this.y+hover, 350, 30)
ctx.stroke();
ctx.font='10px Noto Sans';
ctx.fillStyle='white';
ctx.textAlign='left';
ctx.fillText(this.text, 10, this.y+hover+19);
}
var Paint = function(element) {
this.element = element;
this.shapes = [];
}
Paint.prototype.addShape = function(shape) {
this.shapes.push(shape);
}
Paint.prototype.render = function() {
ctx.clearRect(0, 0, this.element.width, this.element.height);
for (var i=0; i<this.shapes.length; i++) {
this.shapes[i].makeSelection();
}
}
var paint = new Paint(c);
for (i=0; i<30; i++) {
paint.addShape(new selectionForMenu(i+1, i, i*30));
}
paint.render();
function mouseMove(event) {
var x = event.x - canvasX;
var y = event.y - canvasY;
paint.render();
if (lowerHoverBoxHitTest(x, y)) {
hover+=1;
} else if (upperHoverBoxHitTest(x, y)) {
hover-=1;
}
}
c.addEventListener('mousemove', mouseMove);
canvas {
z-index: -1;
margin: 1em auto;
border: 1px solid black;
display: block;
background: #9F3A9B;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>uTalk Demo</title>
<link rel='stylesheet' type='text/css' href='wordpractice.css' media='screen'>
</head>
<body>
<canvas id="game" width = "350" height = "500"></canvas>
</body>
</html>
Animation via animation loops.
You need to have an animation loop that will increment/decrement the value if the conditions are met. This loop can be part of another if you have one (which is better than adding an animation loop for each animated object) or as its own function.
The animation loop does all the rendering, and only if needed (no point rendering something that is already rendered).
Demo
Demo is a copy of the OP's code with modifications to animate the scrolling and give a little user feed back. Though not complete as a scrolling selection box, it will need some tweaking to be useful.
var c = document.getElementById('game'),
canvasX = c.offsetLeft,
canvasY = c.offsetTop,
ctx = c.getContext('2d');
var hover = 0;
const overTypes = {
lower : 1,
raise : 2,
none : 0,
}
var overBox = 0;
var overDist = 0;
const maxSpeed = 4;
const shapeSize = 30;
const hoverScrollSize = 50;
const gradUp = ctx.createLinearGradient(0, 0, 0, hoverScrollSize);
const gradDown = ctx.createLinearGradient(0, ctx.canvas.height - hoverScrollSize, 0, ctx.canvas.height);
gradUp.addColorStop(0, `rgba(${0xA8},${0x4F},${0xB5},1)`);
gradUp.addColorStop(1, `rgba(${0xA8},${0x4F},${0xB5},0)`);
gradDown.addColorStop(1, `rgba(${0xB8},${0x5F},${0xB5},1)`);
gradDown.addColorStop(0, `rgba(${0xB8},${0x5F},${0xB5},0)`);
c.addEventListener('mousemove', mouseMove)
c.addEventListener('mouseout', () => {
overBox = overTypes.none
}); // stop scroll when mouse out of canvas
// start the first frame
requestAnimationFrame(() => {
paint.render(); // paint first frame
requestAnimationFrame(mainLoop); // start main loop
});
function mainLoop() {
if (overBox !== overTypes.none) {
hover += overDist / hoverScrollSize * (overBox === overTypes.lower ? maxSpeed : -maxSpeed);
var bottom = - (paint.shapes.length - ctx.canvas.height / shapeSize) * shapeSize;
hover = hover > 0 ? 0 : hover < bottom ? bottom : hover;
paint.render();
}
requestAnimationFrame(mainLoop); // wait for next animation frame
}
function mouseMove(event) {
var x = event.clientX - canvasX;
var y = event.clientY - canvasY;
if (lowerHoverBoxHitTest(x, y)) {
overBox = overTypes.lower;
} else if (upperHoverBoxHitTest(x, y)) {
overBox = overTypes.raise;
} else {
overBox = overTypes.none;
}
}
function upperHoverBoxHitTest(x, y) {
overDist = hoverScrollSize - y;
return (x >= 0) && (x <= 350) && (y >= 0) && (y <= hoverScrollSize);
}
function lowerHoverBoxHitTest(x, y) {
overDist = y - (ctx.canvas.height - hoverScrollSize);
return (x >= 0) && (x <= 350) && (y >= ctx.canvas.height - hoverScrollSize) && (y <= ctx.canvas.height);
}
var selectionForMenu = function (id, text, y) {
this.id = id;
this.text = text;
this.y = y;
}
selectionForMenu.prototype.makeSelection = function () {
ctx.beginPath();
ctx.fillStyle = '#A84FA5';
ctx.fillRect(0, this.y + hover, 350, shapeSize)
ctx.stroke();
ctx.font = '10px Noto Sans';
ctx.fillStyle = 'white';
ctx.textAlign = 'left';
ctx.fillText(this.text, 10, this.y + hover + 19);
}
var Paint = function (element) {
this.element = element;
this.shapes = [];
}
Paint.prototype.addShape = function (shape) {
this.shapes.push(shape);
}
Paint.prototype.render = function () {
ctx.clearRect(0, 0, this.element.width, this.element.height);
for (var i = 0; i < this.shapes.length; i++) {
this.shapes[i].makeSelection();
}
if (overBox !== overTypes.none) {
ctx.globalAlpha = 0.4 * (overDist / 50);
ctx.globalCompositeOperation = "lighter";
if (overBox === overTypes.raise) {
ctx.fillStyle = gradUp;
ctx.fillRect(0, 0, ctx.canvas.width, hoverScrollSize);
} else if (overBox === overTypes.lower) {
ctx.fillStyle = gradDown;
ctx.fillRect(0, ctx.canvas.height - hoverScrollSize, ctx.canvas.width, hoverScrollSize);
}
ctx.globalCompositeOperation = "source-over";
ctx.globalAlpha = 1;
}
}
var paint = new Paint(c);
for (i = 0; i < 30; i++) {
paint.addShape(new selectionForMenu(i + 1, i, i * 30));
}
paint.render();
canvas {
z-index: -1;
margin: 1em auto;
border: 1px solid black;
display: block;
background: #9F3A9B;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>uTalk Demo</title>
<link rel='stylesheet' type='text/css' href='wordpractice.css' media='screen'>
</head>
<body>
<canvas id="game" width = "350" height = "150"></canvas>
</body>
</html>

Grid system needed to fix a position issue on canvas?

I am trying to create a simple snake game. My problem is, most of the times when the snake meets the food, the position of the snake is not how it should be.
For a better understanding, please look at this screenshot where the snake (white) meets the food (green):
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
x = 0,
y = 0,
speed = 3;
x_move = speed,
y_move = 0,
food_position_x = Math.floor(Math.random() * canvas.width) - 20;
food_position_y = Math.floor(Math.random() * canvas.height) - 20;
// Drawing
function draw() {
requestAnimationFrame(function() {
draw();
});
// Draw the snake
ctx.beginPath();
ctx.rect(x, y, 20, 20);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#ffffff';
ctx.fill();
ctx.closePath();
// Draw the food
ctx.beginPath();
ctx.rect(food_position_x, food_position_y, 20, 20);
ctx.fillStyle = "lightgreen";
ctx.fill();
ctx.closePath();
// Increase the value of x and y in order to animate
x = x + x_move;
y = y + y_move;
}
draw();
// Key Pressing
document.addEventListener('keydown', function(event) {
switch(event.keyCode) {
case 40: // Moving down
if (x_move != 0 && y_move != -1) {
x_move = 0;
y_move = speed;
}
break;
case 39: // Moving right
if (x_move != -1 && y_move != 0) {
x_move = speed;
y_move = 0;
}
break;
case 38: // Moving top
if (x_move != 0 && y_move != 1) {
x_move = 0;
y_move = -speed;
}
break;
case 37: // Moving left
if (x_move != 1 && y_move != 0) {
x_move = -speed;
y_move = 0;
}
break;
}
});
canvas { background-color:red }
<canvas id="canvas" width="600" height="400"></canvas>
So it seems like I would need a simple grid system but how would I go ahead on this to fix this issue?
I can't see the code for your collision. But I think you have a mistake in your origin. The origin of your squares is not in the middle, it is on the top left corner.

How to set a delay in each penalty shot in HTML5 JS Canvas football penalty game

I am trying to make a simple football penalty game using HTML5/JS Canvas. The aim is to make a game where you control the goal keeper and you have three attempts to save the ball.
I have most of the functionality done, I have a score system and collision detection.
Currently I have a delay on the first attempt. I am however finding difficulty in adding a delay before the ball is shot into the goal in the second and third attempt.
I am using the method requestAnimationFrame() to paint my shapes on my canvas. If there is still attempts available, the ball is positioned to its original location but then there is no delay and fires the ball immediately.
Any advice ? Thanks!
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Football</title>
<style>
* { padding: 0; margin: 0; }
canvas { background: #a5bd7b; display: block; margin: 0 auto; }
</style>
</head>
<body>
<canvas id="myCanvas" width="300" height="250"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext("2d");
//Sets the original position of the ball
var x = canvas.width/2;
var y = 50;
// Defines values that will be added to the position of x and y values
// List of possible values for the x position
var x_options = [3.5, 3, 2.5, 2, 1.5, 1, 0.5, 0, -0.5, -1, -1.5, -2, -2.5, -3, -3.5];
// Gets a random value from the x_options array
var dx = x_options[Math.floor(Math.random() * x_options.length)];
var dy = 5;
var ballRadius = 10;
// Defines the height and width of the goal
var goal_height = 40;
var goal_width = 200
// Defines the height, width and position of goalie
var goalieHeight = 20;
var goalieWidth = 40;
var goalieX = (canvas.width-goalieWidth)/2;
var goalieY = (canvas.height - goal_height) - 30;
// Set to false by default
var rightPressed = false;
var leftPressed = false;
var goalkeeper_blocked = 0;
var goalkeeper_missed = 0;
var attempts_left = 3;
var attempt1 = true;
var attempt2 = false;
var attempt3 = false;
var footBall = {
shapes : {
ball: function (){
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI*2, false);
ctx.fillStyle = "red";
ctx.fill();
ctx.closePath();
},
goal : function (){
ctx.beginPath();
ctx.rect((canvas.width - goal_width) / 2 , canvas.height - goal_height, goal_width, goal_height);
ctx.strokeStyle = "#000000";
ctx.stroke();
ctx.closePath();
},
goalie : function(){
ctx.beginPath();
ctx.rect(goalieX, goalieY, goalieWidth, goalieHeight);
ctx.fillStyle = "#666666";
ctx.fill();
ctx.closePath();
},
score : function(){
ctx.font = "16px Arial";
ctx.fillStyle = "#ffffff";
ctx.fillText("Score: "+goalkeeper_blocked, 8, 20);
},
missed : function(){
ctx.font = "16px Arial";
ctx.fillStyle = "#ffffff";
ctx.fillText("Missed: "+goalkeeper_missed, 8, 40);
},
attempts : function(){
ctx.font = "16px Arial";
ctx.fillStyle = "#ffffff";
ctx.fillText("Attempts left: "+attempts_left, canvas.width-110, 20);
}
},
controls : {
keyDownHandler : function (e){
if(e.keyCode == 39) {
rightPressed = true;
}
else if(e.keyCode == 37) {
leftPressed = true;
}
},
keyUpHandler : function(e){
if(e.keyCode == 39) {
rightPressed = false;
}
else if(e.keyCode == 37) {
leftPressed = false;
}
}
},
calculateScore : function(){
if(goalkeeper_missed > goalkeeper_blocked){
alert("GAME OVER! YOU HAVE LOST!");
document.location.reload();
} else {
alert("GAME OVER! YOU HAVE WON!");
document.location.reload();
}
},
animateBall : function (){
// Sets a delay of 3 second before it shoots
setTimeout(function(){
x += dx;
y += dy;
}, 3000);
},
resetShapePositions : function(){
//Sets the original position of the ball
x = canvas.width/2;
y = 50;
// Sets a new shooting path
dx = x_options[Math.floor(Math.random() * x_options.length)];
dy = 5;
// Resets the goalie to the middle
goalieX = (canvas.width-goalieWidth)/2;
},
draw : function(){
// This ensures that the ball doesn't leave a trail
// Clears the canvas of this shape each frame
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draws shapes on the canvas
footBall.shapes.ball();
footBall.shapes.goal();
footBall.shapes.goalie();
footBall.shapes.score();
footBall.shapes.missed();
footBall.shapes.attempts();
// adds values to the balls x and y position every frame
footBall.animateBall();
// Ball hits the goal
if(y + dy > canvas.height - goal_height) {
attempts_left--;
goalkeeper_missed++;
if (!attempts_left){
footBall.calculateScore();
}
else {
footBall.resetShapePositions();
}
} // Ball saved by goalie
else if (x > goalieX && x < goalieX + goalieWidth && y + dy > goalieY - ballRadius){
attempts_left--;
goalkeeper_blocked++;
if (!attempts_left){
footBall.calculateScore();
}
else {
footBall.resetShapePositions();
}
}
// makes paddle move left and right and only within the canvas
if(rightPressed && goalieX < canvas.width-goalieWidth) {
goalieX += 7;
}
else if(leftPressed && goalieX > 0) {
goalieX -= 7;
}
requestAnimationFrame(footBall.draw);
}
}
footBall.draw();
// Defines what functions are fired when keydown or keyup event triggers
document.addEventListener("keydown", footBall.controls.keyDownHandler, false);
document.addEventListener("keyup", footBall.controls.keyUpHandler, false);
</script>
</body>
</html>
Add some properties to football that control if/when a shot is occuring:
// is a shot in progress?
isShooting:false,
// the time when next shot will start
nextShotTime:0,
// delay between shots
delayUntilNextShot:3000,
Then in the animation loop, use these properties to appropriately delay the next shot:
If isShooting, process the shot,
If not isShooting, see if the required delay has elapsed between shots. If yes, set isShooting=true,
When the goalie blocks or misses the shot, set isShooting=false and set nextShotTime=currentTime+delayUntilNextShot,
Example code and a Demo:
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext("2d");
//Sets the original position of the ball
var x = canvas.width/2;
var y = 50;
// Defines values that will be added to the position of x and y values
// List of possible values for the x position
var x_options = [3.5, 3, 2.5, 2, 1.5, 1, 0.5, 0, -0.5, -1, -1.5, -2, -2.5, -3, -3.5];
// Gets a random value from the x_options array
var dx = x_options[Math.floor(Math.random() * x_options.length)];
var dy = 5;
var ballRadius = 10;
// Defines the height and width of the goal
var goal_height = 40;
var goal_width = 200
// Defines the height, width and position of goalie
var goalieHeight = 20;
var goalieWidth = 40;
var goalieX = (canvas.width-goalieWidth)/2;
var goalieY = (canvas.height - goal_height) - 30;
// Set to false by default
var rightPressed = false;
var leftPressed = false;
var goalkeeper_blocked = 0;
var goalkeeper_missed = 0;
var attempts_left = 3;
var attempt1 = true;
var attempt2 = false;
var attempt3 = false;
var footBall = {
// is a shot in progress
isShooting:false,
// time when next shot will run
nextShotTime:0,
// delay until next shot will run
delayUntilNextShot:3000,
shapes : {
ball: function (){
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI*2, false);
ctx.fillStyle = "red";
ctx.fill();
ctx.closePath();
},
goal : function (){
ctx.beginPath();
ctx.rect((canvas.width - goal_width) / 2 , canvas.height - goal_height, goal_width, goal_height);
ctx.strokeStyle = "#000000";
ctx.stroke();
ctx.closePath();
},
goalie : function(){
ctx.beginPath();
ctx.rect(goalieX, goalieY, goalieWidth, goalieHeight);
ctx.fillStyle = "#666666";
ctx.fill();
ctx.closePath();
},
score : function(){
ctx.font = "16px Arial";
ctx.fillStyle = "#ffffff";
ctx.fillText("Score: "+goalkeeper_blocked, 8, 20);
},
missed : function(){
ctx.font = "16px Arial";
ctx.fillStyle = "#ffffff";
ctx.fillText("Missed: "+goalkeeper_missed, 8, 40);
},
attempts : function(){
ctx.font = "16px Arial";
ctx.fillStyle = "#ffffff";
ctx.fillText("Attempts left: "+attempts_left, canvas.width-110, 20);
}
},
controls : {
keyDownHandler : function (e){
if(e.keyCode == 39) {
rightPressed = true;
}
else if(e.keyCode == 37) {
leftPressed = true;
}
},
keyUpHandler : function(e){
if(e.keyCode == 39) {
rightPressed = false;
}
else if(e.keyCode == 37) {
leftPressed = false;
}
}
},
calculateScore : function(){
if(goalkeeper_missed > goalkeeper_blocked){
alert("GAME OVER! YOU HAVE LOST!");
document.location.reload();
} else {
alert("GAME OVER! YOU HAVE WON!");
document.location.reload();
}
},
resetShapePositions : function(){
//Sets the original position of the ball
x = canvas.width/2;
y = 50;
// Sets a new shooting path
dx = x_options[Math.floor(Math.random() * x_options.length)];
dy = 5;
// Resets the goalie to the middle
goalieX = (canvas.width-goalieWidth)/2;
},
drawField: function(){
// This ensures that the ball doesn't leave a trail
// Clears the canvas of this shape each frame
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draws shapes on the canvas
footBall.shapes.ball();
footBall.shapes.goal();
footBall.shapes.goalie();
footBall.shapes.score();
footBall.shapes.missed();
footBall.shapes.attempts();
},
draw : function(currentTime){
// makes paddle move left and right and only within the canvas
if(rightPressed && goalieX < canvas.width-goalieWidth) {
goalieX += 7;
}
else if(leftPressed && goalieX > 0) {
goalieX -= 7;
}
// draw the scene
footBall.drawField();
// delay until next shot time is due
if(!footBall.isShooting){
// time has elapsed, let's shoot again
if(currentTime>footBall.nextShotTime){
footBall.isShooting=true;
}else{
// time has not elapsed, just request another loop
requestAnimationFrame(footBall.draw);
return;
}
}
// adds values to the balls x and y position every frame
x += dx;
y += dy;
// Ball hits the goal
if(y + dy > canvas.height - goal_height) {
// end the shot
footBall.isShooting=false;
// delay the next shot
footBall.nextShotTime=currentTime+footBall.delayUntilNextShot;
attempts_left--;
goalkeeper_missed++;
if (!attempts_left){
footBall.calculateScore();
}
else {
footBall.resetShapePositions();
}
} // Ball saved by goalie
else if (x > goalieX && x < goalieX + goalieWidth && y + dy > goalieY - ballRadius){
// end the shot
footBall.isShooting=false;
// delay the next shot
footBall.nextShotTime=currentTime+footBall.delayUntilNextShot;
attempts_left--;
goalkeeper_blocked++;
if (!attempts_left){
footBall.calculateScore();
}
else {
footBall.resetShapePositions();
}
}
requestAnimationFrame(footBall.draw);
}
}
footBall.drawField();
footBall.nextShotTime=footBall.delayUntilNextShot;
requestAnimationFrame(footBall.draw);
// Defines what functions are fired when keydown or keyup event triggers
document.addEventListener("keydown", footBall.controls.keyDownHandler, false);
document.addEventListener("keyup", footBall.controls.keyUpHandler, false);
* { padding: 0; margin: 0; }
canvas { background: #a5bd7b; display: block; margin: 0 auto; }
<canvas id="myCanvas" width="300" height="250"></canvas>

object moves through keyboard arrow keys using html5 and javascript

how can i move the object with keyboard keys using html5 and javascript. Here i tried it with below code but it is not moving can any one help to move the object using keyboard arrow keys?
<!DOCTYPE html>
<html>
<head>
</head>
<body onLoad="gameLoop()" onkeydown="keyDown(event)" onkeyup="keyUp(event)" bgcolor='green'>
<canvas id="mycanvas"></canvas>
<script>
var canvas = document.getElementById('mycanvas');
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.arc(100, 100, 50, 0.25 * Math.PI, 1.25 * Math.PI, false);
ctx.fillStyle = "rgb(255, 255, 0)";
ctx.fill();
ctx.beginPath();
ctx.arc(100, 100, 50, 0.75 * Math.PI, 1.75 * Math.PI, false);
ctx.fill();
ctx.beginPath();
ctx.arc(100, 75, 10, 0, 2 * Math.PI, false);
ctx.fillStyle = "rgb(0, 0, 0)";
ctx.fill();
//moves//
var xpos=500;
var ypos=550;
var xspeed=1;
var yspeed=0;
var maxspeed=5;
//boundaries//
var minx=500;
var miny=200;
var maxx=990;
var maxy=400;
//controller
var upPressed=0;
var downPressed=1;
var leftPressed=0;
var rightPressed=0;
function slowDownX()
{
if(xspeed > 0) xspeed=xspeed-1; if(xspeed<0) xspeed=xspeed+1;
}
function slowDownY()
{
if(yspeed > 0)
yspeed = yspeed-1;
if(yspeed < 0)
yspeed = yspeed+1;
}
function gameLoop()
{
xpos=Math.min(Math.max(xpos+xspeed,minx),maxx); ypos=Math.min(Math.max(ypos+yspeed,miny),maxy);
xpos = document.getElementById('mycanvas').style.left;
ypos = document.getElementById('mycanvas').style.top;
if (upPressed == 1)
yspeed = Math.max(yspeed - 3,-3*maxSpeed);
if (downPressed == 1)
yspeed = Math.min(yspeed + 3,3*maxSpeed)
if (rightPressed == 1)
xspeed = Math.min(xspeed + 1,1*maxSpeed);
if (leftPressed == 1)
xspeed = Math.max(xspeed - 1,-1*maxSpeed);
if (upPressed == 0 && downPressed == 0)
slowDownY();
if (leftPressed == 0 && rightPressed == 0)
slowDownX();
return setTimeout("gameLoop()",10);
}
function keyDown(e)
{
var code = e.keyCode ? e.keyCode : e.which;
if (code == 38)
upPressed = 1;
if (code == 40)
downPressed = 1;
if (code == 37)
leftPressed = 1;
if (code == 39)
rightPressed = 1;
}
function keyUp(e)
{
var code = e.keyCode ? e.keyCode : e.which;
if (code == 38)
upPressed = 0;
if (code == 40)
downPressed = 0;
if (code == 37)
leftPressed = 0;
if (code == 39)
rightPressed = 0;
}
</script>
</body>
</html>
Here are the basics of drawing a shape on the html canvas and moving it with arrowkeys
Disclaimer: this code is not best game technique, it’s meant for clear instruction. ;)
First create a few variables that define a ball:
// the ball will be at coordinates 70,75
var ballX=70;
var ballY=75;
// the ball will have a radius of 15;
var ballRadius=15;
Next create a function that will draw that ball at the specified coordinates
function draw(){
// clear the canvas for the next frame
ctx.clearRect(0,0,canvas.width,canvas.height);
// draw a ball that the use can move with left/right arrow keys
// the ball's center will be at BallX / BallY
// the ball will have a radius of BallRadius
ctx.beginPath();
ctx.arc(ballX,ballY,ballRadius,0,Math.PI*2,false);
ctx.closePath();
ctx.fill();
}
Now listen for user’s keystrokes.
// Listen for when the user presses a key down
window.addEventListener("keydown", keyDownHandler, true);
When the user presses a key down:
If the user presses the left or right arrows, move the ball by changing it’s “ballX” coordinate.
After changing the balls position, redraw the canvas
This code handles when a key is down (called by the addEventListener):
// Here we just handle command keys
function keyDownHandler(event){
// get which key the user pressed
var key=event.which;
// Let keypress handle displayable characters
if(key>46){ return; }
switch(key){
case 37: // left key
// move the ball 1 left by subtracting 1 from ballX
ballX -= 1;
break;
case 39: // right key
// move the ball 1 right by adding 1 to ballX
ballX += 1;
break;
default:
break;
}
// redraw the ball in its new position
draw();
}
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/TsXmx/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; padding:20px;}
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
ctx.strokeStyle="blue";
ctx.fillStyle="red";
var ballX=70;
var ballY=75;
var ballRadius=15;
var leftWall=30;
var rightWall=120;
draw();
function draw(){
// clear the canvas for the next frame
ctx.clearRect(0,0,canvas.width,canvas.height);
// tell canvas to start a new path
// draw walls on left and right
ctx.beginPath();
ctx.moveTo(leftWall,0);
ctx.lineTo(leftWall,canvas.height);
ctx.moveTo(rightWall,0);
ctx.lineTo(rightWall,canvas.height);
ctx.lineWidth=2;
ctx.stroke();
// draw a ball that the use can move with left/right arrow keys
ctx.beginPath();
ctx.arc(ballX,ballY,ballRadius,0,Math.PI*2,false);
ctx.closePath();
ctx.fill();
}
// Here we just handle command keys
function keyDownHandler(event){
// get which key the user pressed
var key=event.which;
// Let keypress handle displayable characters
if(key>46){ return; }
switch(key){
case 37: // left key
// move the ball 1 left by subtracting 1 from ballX
ballX -= 1;
// calc the ball's left edge
var ballLeft=ballX-ballRadius;
// Keep the ball from moving through the left wall
if(ballLeft<=leftWall){ ballX=leftWall+ballRadius; }
break;
case 39: // right key
// move the ball 1 right by adding 1 to ballX
ballX += 1;
// calc the ball's right edge
var ballRight=ballX+ballRadius;
// Keep the ball from moving through the right wall
if(ballRight>=rightWall){ ballX=rightWall-ballRadius; }
break;
default:
break;
}
// redraw everything
draw();
}
// Listen for when the user presses a key down
window.addEventListener("keydown", keyDownHandler, true);
}); // end $(function(){});
</script>
</head>
<body>
<p>Click in the red box to get keyboard focus</p>
<p>Then Move ball with left and right arrow keys</p>
<canvas id="canvas" width=200 height=150></canvas>
</body>
</html>
two ball are move diff. side on key board .
first ball to move to keyboard to up, down , right, left key
second ball move to A(left side), W(up side) ,D(right side) and S(down side).
just copy and past in your screen.
<html>
<head>
<title> game</title>
</head>
<body>
<canvas id="canvas" width="307" height= "211" style= "border:1px solid #ff0000 ;" mxrgin = right >
</canvas>
<script>
var x = 10;
var x1= 280;
var y = 10;
var y1 = 10;
var dx = 2;
var dx1 = 3;
var dy = 1;
var dy1 =1;
var ctx;
var ctx1;
var WIDTH=300;
var HEIGHT=200;
var a="";
var b="";
var sp= 500;
var timer=[];
var down = [];
var up;
document.onkeydown=k_down;
document.onkeyup=k_up;
var left=false;
var right=false;
var up1=false;
var down1=false;
var flag=false;
var aa=false;
init();
function k_down(e)
{
down[e.keyCode]=true;
clearInterval(timer);
//sp=10;
if(down[37])
{
if(sp>2)
{
sp++;
}
dy=0;
dx=-3;
left=true;
flag=false;
//down=[];
}
else if(down[38])
{
if(sp>2)
{
sp++;
}
dx=0;
dy=-4;
up1=true;
flag=false;
//down=[];
}
else if(down[39])
{
if(sp>2)
{
sp++;
}
dy=0;
dx=3;
right=true;
flag=false;
//down=[];
}
else if(down[40])
{
if(sp>2)
{
sp++;
}
dx=0;
dy=4;
down1=true;
flag=false;
//down=[];
}
if(down[65])
{
dy1=0;
dx1=-3;
}
else if(down[87])
{
dx1=0;
dy1=-4;
}
else if(down[68])
{
dy1=0;
dx1=3;
}
else if(down[83])
{
dx1=0;
dy1=4;
}
//console.log("speed++>"+sp);
timer=setInterval(draw,sp);
down[e.keyCode]=false;
}
function k_up(e)
{
up=e.keyCode;
//alert(sp);
if(sp<10)
{
sp=10;
clearInterval(timer);
timer=setInterval(draw,10);
}
//console.log("upp->>"+down);
if(left==true && up1==true)
{
//console.log("1");
sp=2;
clearInterval(timer);
timer=setInterval(draw,sp);
dx=-3;
dy=-4;
flag=true;
}
else if(left==true && down1==true)
{
//console.log("2");
sp=2;
clearInterval(timer);
timer=setInterval(draw,sp);
dx=-3;
dy=4;
flag=true;
}
else if(right==true && up1==true)
{
//console.log("3");
sp=2;
clearInterval(timer);
timer=setInterval(draw,sp);
dx=3;
dy=-4;
flag=true;
}
else if(right==true && down1==true)
{
//console.log("4");
sp=2;
clearInterval(timer);
timer=setInterval(draw,sp);
dx=3;
dy=4;
flag=true;
}
if(left==true)
{
if(flag==false){
dy=0;
dx=-3;
}
}
else if(up1==true)
{
if(flag==false){
dx=0;
dy=-4;
}
}
else if(right==true)
{
if(flag==false){
dy=0;
dx=3;
}
}
else if(down1==true)
{
if(flag==false){
dx=0;
dy=4;
}
}
if (up==37)
{
left=false;
}
else if (up==38)
{
up1=false;
}
else if (up==39)
{
right=false;
}
else if (up==40)
{
down1=false;
}
}
function circle(x,y,r) {
ctx.beginPath();
ctx.arc(x, y, r, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
}
function rect(x,y,w,h) {
ctx.beginPath();
ctx.rect(x,y,w,h);
ctx.closePath();
ctx.fill();
}
function clear() {
ctx.clearRect(0, 0, 307, 211);
}
function init() {
//ctx = $("#canvas").getContext("2d");
ctx = document.getElementById('canvas').getContext("2d");
//WIDTH = $("#canvas").width()
//HEIGHT = $("#canvas").height()
//canvas.addEventListener("click", getPosition, false);
return setInterval(draw, 10);
}
/*
function getPosition(event)
{
// var canvas = document.getElementById("canvas");
// var x = event.x;
//var y = event.y;
// x -= canvas.offsetLeft;
// y -= canvas.offsetTop;
//alert("x: " + x + " y: " + y);
}
*/
function draw() {
clear();
circle(x, y, 10);
circle(x1, y1, 10);
if (x + dx > WIDTH || x + dx < 0)
dx = -dx;
if (y + dy > HEIGHT || y + dy < 0)
dy = -dy;
x += dx;
y += dy;
console.log("x->"+x)
if (x==10){
dx = -dx;
x += dx;
y += dy;
}
if (y==10){
dy = -dy;
x += dx;
y += dy;
}
if (x1 + dx1 > WIDTH || x1 + dx1 < 0)
dx1 = -dx1;
if (y1 + dy1 > HEIGHT || y1 + dy1 < 0)
dy1 = -dy1;
x1 += dx1;
y1 += dy1;
console.log("x1->"+x1)
if (x1==10){
dx1 = -dx1;
x1 += dx1;
y1 += dy1;
}
if (y1==10){
dy1 = -dy1;
x1 += dx1;
y1 += dy1;
}
}
</script>
</body>
</html>

Categories

Resources