Moving an image on a canvas with arrow keys - javascript

I'm trying to get a block I've called "Sword" to move up and down when using the arrow keys, I have event listeners and handlers but for some reason they're just not talking to each other and I dunno why.
Here is the HTML, it's very simple, just draws a canvas to use.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>17013455_assignment_2</title>
</head>
<body>
<canvas id="canvas"></canvas>
<script src="17013455_ass2_task1.js"></script>
</html>
This is the Javascript, the canvas has a background drawn on, and the "sword" is drawn as a box, my key handlers should move the sword on the Y axis depending on the sword's height and it's space in the Y axix.
window.onload=function () {
var canvas = document.getElementById("canvas");
var gc = canvas.getContext("2d");
canvas.width = 640;
canvas.height = 448;
gc.clearRect(0, 0, canvas.width, canvas.height);
var background = new Image();
background.src = "https://i.imgur.com/9mPYXqC.png";
//sword dimentions
var swordHeight = 50;
var swordWidth = 25;
var swordX = 50;
var swordY = 220;
//controls for player
var upPressed = false;
var downPressed = false;
if (downPressed && swordY < canvas.height - swordHeight) {
swordY += 10;
}
else if (upPressed && swordY > 0) {
swordY -= 10;
}
function keyUpHandler(e) {
if (e.keyCode === 38) {
upPressed = false;
}
else if (e.keyCode === 40) {
downPressed = false;
}
}
function drawSword() {
/*Make a box to represent a sword until sprites are used*/
gc.beginPath();
gc.rect(swordX, swordY, swordWidth, swordHeight);
gc.fillStyle = "#000000";
gc.fill();
gc.closePath();
}
function keyDownHandler(e) {
if (e.keyCode === 38) {
upPressed = true;
}
else if (e.keyCode === 40) {
downPressed = true;
}
}
function render() {
background.onload = function () {
gc.drawImage(background, 0, 0)};
drawSword();
}
document.addEventListener("keydown", keyDownHandler, "false");
document.addEventListener("keyup", keyUpHandler, "false");
render();
setInterval(render, 10);
};

Move this part of code
if (downPressed && swordY < canvas.height - swordHeight) {
swordY += 10;
}
else if (upPressed && swordY > 0) {
swordY -= 10;
}
to render() function.
Your function should look like this:
function render() {
if (downPressed && swordY < canvas.height - swordHeight) {
swordY += 10;
}
else if (upPressed && swordY > 0) {
swordY -= 10;
}
gc.drawImage(background, 0, 0)};
drawSword();
}
and this part
background.onload = function () {
gc.drawImage(background, 0, 0)};
to window.onload = function(){} scope

Related

How do you code jumping in a javascript game?

I am writing a game in javascript for the first time most of my code is not efficient. I am stuck on how to code a jumping method for my cube(the character for my game). The jump works but the player can double jump. The double jump occurs on the way down if the user presses the jump key again. I have tried setting a variable which will be modified when the player is on the ground and if it is true then your only allowed to jump but it hasn't worked. Here is the code:
//setting screen up
const canvas = document.getElementById('canvas');
const c = canvas.getContext('2d');
canvas.width = innerWidth;
canvas.height = innerHeight;
//ground
gHeight = canvas.height/1.3
function ground(){
c.fillStyle = 'white';
c.fillRect(0,gHeight,canvas.width,canvas.height-gHeight);
}
//player
class Player{
constructor(x,y,w,h){
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = 'rgb(92,168,255)';
this.l = false;
this.r = false;
this.speed = 10
this.hp = 100;
this.jump = false;
this.jumpC = 0;
}
draw(){
c.fillStyle = this.color;
c.fillRect(this.x,this.y,this.w,this.h);
}
update(){
this.draw();
//gravity
if(this.y < gHeight - this.h){
this.y += 5;
}
//movement
if(this.l == true){
this.x -= this.speed;
}
if(this.r == true){
this.x += this.speed;
}
//jump
if(this.jump == true){
this.y -= 10;
this.jumpC += 5;
}
if (this.jumpC >= 100){
this.jump = false;
this.jumpC = 0;
}
}
}
var player = new Player(100, 100,50,50);
//main loop
var animationId;
function animate(){
c.fillStyle = 'rgba(0,0,0,0.7)';
c.fillRect(0,0, canvas.width, canvas.height);
animationId = requestAnimationFrame(animate);
//drawing the ground
ground();
//drawing the player
player.update();
//ending game
if(player.hp == 0){
cancelAnimationFrame(animationId);
}
}
//keypress
addEventListener('keydown', (event)=>{
if(event.keyCode == 37) {
player.l = true;
}
if(event.keyCode == 39) {
player.r = true;
}
if(event.keyCode == 38 && player.jump == false){
player.jump = true;
}
});
//keyup
addEventListener('keyup', (event)=>{
if(event.keyCode == 37 ) {
player.l = false;
}
if(event.keyCode == 39) {
player.r = false;
}
});
animate();
tell me if more info is needed
After the jump make it impossible to jump until the player reaches the ground.
if(event.keyCode == 38 && player.jump == false){ player.jump = true; }
I would add another comparison in this if like this:
if(event.keyCode == 38 && player.jump == false && player.isOnGround()){ player.jump = true; }
To check if the user landed

My Javascript ball moving code isn't working

I created a ball and some Javascript code that is supposed to make it move. But my code isn't working and I don't know why. Could someone please look over my code and help me out.
Code
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var xPos = canvas.width/2;
var yPos = canvas.height-30;
var ballRadius = 10;
var leftPressed = false;
var rightPressed = false;
var upPressed = false;
var downPressed = false;
function drawBall() {
ctx.beginPath();
ctx.arc(xPos, yPos, ballRadius, 0, Math.PI*2, false);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall();
}
setInterval(draw, 10);
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
function keyDownHandler(e) {
if(e.keyCode == 37) {
leftPressed = true;
}
else if(e.keyCode == 39) {
rightPressed = true;
}
else if(e.keyCode == 38) {
upPressed == true;
}
else if(e.keyCode == 40) {
downPressed = true;
}
}
function keyUpHandler(e) {
if(e.keyCode == 37) {
leftPressed = false;
}
else if(e.keyCode == 39) {
rightPressed = false;
}
else if(e.keyCode == 38) {
upPressed == false;
}
else if(e.keyCode == 40) {
downPressed = false;
}
}
if(leftPressed = true) {
xPos -= 7;
} else if(rightPressed = true) {
xPos += 7;
} else if(upPressed = true) {
yPos -= 7;
} else if(downPressed = true) {
yPos += 7;
}
* { padding: 0; margin: 0; }
canvas { background: #eee; display: block; margin: 0 auto; }
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Breakout</title>
<style>
* { padding: 0; margin: 0; }
canvas { background: #eee; display: block; margin: 0 auto; }
</style>
</head>
<body>
<canvas id="myCanvas" width="480" height="320"></canvas>
<script src="gameJS.js"></script>
</body>
</html>
You're only updating the boolean values during keypress. You're not updating the position dynamically. Your position update code runs first during load and that's it.
To move during keypress, you need to update the position during each keypress and you need to draw the ball.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var xPos = canvas.width/2;
var yPos = canvas.height-30;
var ballRadius = 10;
var leftPressed = false;
var rightPressed = false;
var upPressed = false;
var downPressed = false;
function drawBall() {
ctx.beginPath();
ctx.arc(xPos, yPos, ballRadius, 0, Math.PI*2, false);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall();
}
setInterval(draw, 10);
document.addEventListener("keydown", keyDownHandler, false);
//document.addEventListener("keyup", keyUpHandler, false);
function keyDownHandler(e) {
if(e.keyCode == 37) {
xPos -= 7;
//draw the ball with new position
}
else if(e.keyCode == 39) {
xPos += 7;
//draw the ball with new position
}
else if(e.keyCode == 38) {
yPos -= 7;
//draw the ball with new position
}
else if(e.keyCode == 40) {
yPos += 7;
//draw the ball with new position
}
}
* { padding: 0; margin: 0; }
canvas { background: #eee; display: block; margin: 0 auto; }
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Breakout</title>
<style>
* { padding: 0; margin: 0; }
canvas { background: #eee; display: block; margin: 0 auto; }
</style>
</head>
<body>
<canvas id="myCanvas" width="480" height="320"></canvas>
<script src="gameJS.js"></script>
</body>
</html>
You are using assignment operators (single equal signs) in your check for keypresses, rather than comparator operators (double equal signs). Essentially, you're saying that they should equal true, rather than checking if they are true:
if (leftPressed = true) {}
else if (rightPressed = true) {}
else if (upPressed = true) {}
else if (downPressed = true) {}
These should be written as:
if (leftPressed == true) {}
else if (rightPressed == true) {}
else if (upPressed == true) {}
else if (downPressed == true) {}
Having said that, you don't need to make use of these four variables at all, and can instead simply modify the positions directly on checking against the keyCode values:
if (e.keyCode == 37) {
xPos -= 7;
}
Hope this helps! :)
There are a few errors in your code.
In your up/down key handlers you compare the value of upPressed instead of setting it.
e.g.
upPressed == true;
should be
upPressed = true;
In your if conditions at the end, you set the value instead of comparing.
e.g.
if(leftPressed = true)
should be
if(leftPressed)
I've moved the ball position code into the moveBall function and called that when the key handler is called so that the position is updated on key press.
This is the fixed version.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var xPos = canvas.width / 2;
var yPos = canvas.height - 30;
var ballRadius = 10;
var leftPressed = false;
var rightPressed = false;
var upPressed = false;
var downPressed = false;
function drawBall() {
ctx.beginPath();
ctx.arc(xPos, yPos, ballRadius, 0, Math.PI * 2, false);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall();
}
setInterval(draw, 10);
document.addEventListener("keydown", keyDownHandler, false);
function keyDownHandler(e) {
leftPressed = false;
rightPressed = false;
upPressed = false;
downPressed = false;
if (e.keyCode == 37) {
leftPressed = true;
} else if (e.keyCode == 39) {
rightPressed = true;
} else if (e.keyCode == 38) {
upPressed = true;
} else if (e.keyCode == 40) {
downPressed = true;
}
moveBall();
}
function moveBall() {
if (leftPressed) {
xPos -= 7;
} else if (rightPressed) {
xPos += 7;
} else if (upPressed) {
yPos -= 7;
} else if (downPressed) {
yPos += 7;
}
}
* {
padding: 0;
margin: 0;
}
canvas {
background: #eee;
display: block;
margin: 0 auto;
}
<canvas id="myCanvas" width="480" height="320"></canvas>
Since keyDownHandler is called whenever a keydown event occurs, you'll want to move your position variables updating code to within that function, and you can remove the keyDownHandler as it doesn't do anything in this example:
function keyDownHandler(e) {
//left
if(e.keyCode === 37){
xPos -= 7
}
//right
else if (e.keyCode === 39) {
xPos += 7
}
//up
else if (e.keyCode === 38) {
yPos -= 7
}
//down
else if (e.keyCode === 40) {
yPos += 7
}
}
In addition, you can make your code slightly more readable with a switch statement rather than cascading else if
function keyDownHandler(e) {
switch(e.keyCode){
case 37: //left
xPos -= 7
break;
case 39: //right
xPos += 7
break;
case 38: //up
yPos -= 7
break;
case 40: //down
yPos += 7
break;
}
}
Note: as Obsidian Age correctly pointed out, you are using assignment operators and not comparison operators in your update code, so you might want to double check that in the future. In my example I used the triple equal === operator because it checks both type and value, which is recommended in JavaScript. See W3Schools reference for JavaScript Operators
Just update your javascript as below will do the trick.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var xPos = canvas.width/2;
var yPos = canvas.height-30;
var ballRadius = 20;
var leftPressed = false;
var rightPressed = false;
var upPressed = false;
var downPressed = false;
function drawBall() {
ctx.beginPath();
ctx.arc(xPos, yPos, ballRadius, 0, Math.PI*2, false);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if(leftPressed == true) {
xPos -= 7;
}
else if(rightPressed == true) {
xPos += 7;
}
else if(upPressed == true) {
yPos -= 7;
}
else if(downPressed == true) {
yPos += 7;
}
drawBall();
}
function keyDownHandler(e) {
var keyCode = e.keyCode;
if(keyCode == 37) {
leftPressed = true;
}
else if(keyCode == 39) {
rightPressed = true;
}
else if(keyCode == 38) {
upPressed = true;
}
else if(keyCode == 40) {
downPressed = true;
}
}
function keyUpHandler(e) {
var keyCode = e.keyCode;
if(keyCode == 37) {
leftPressed = false;
}
else if(keyCode == 39) {
rightPressed = false;
}
else if(keyCode == 38) {
upPressed = false;
}
else if(keyCode == 40) {
downPressed = false;
}
}
Use assignment operator = instead of comparison operator == for upPressed variable within keyUpHandler and keyDownHandler methods.
Don't set leftPressed, rightPressed, upPressed and downPressed values using by = operator within if...else conditions. Use comparison operator or logical values directly instead.
Update xPos and yPos values each time before drawBall method calling.
The working code below.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var xPos = canvas.width / 2;
var yPos = canvas.height - 30;
var ballRadius = 10;
var leftPressed = false;
var rightPressed = false;
var upPressed = false;
var downPressed = false;
function drawBall() {
ctx.beginPath();
ctx.arc(xPos, yPos, ballRadius, 0, Math.PI * 2, false);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
SetPos();
drawBall();
}
setInterval(draw, 10);
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
function keyDownHandler(e) {
if (e.keyCode == 37) {
leftPressed = true;
} else if (e.keyCode == 39) {
rightPressed = true;
} else if (e.keyCode == 38) {
upPressed = true;
} else if (e.keyCode == 40) {
downPressed = true;
}
}
function keyUpHandler(e) {
if (e.keyCode == 37) {
leftPressed = false;
} else if (e.keyCode == 39) {
rightPressed = false;
} else if (e.keyCode == 38) {
upPressed = false;
} else if (e.keyCode == 40) {
downPressed = false;
}
}
function SetPos() {
if (leftPressed) {
xPos -= 7;
} else if (rightPressed) {
xPos += 7;
} else if (upPressed) {
yPos -= 7;
} else if (downPressed) {
yPos += 7;
}
}
* {
padding: 0;
margin: 0;
}
canvas {
background: #eee;
display: block;
margin: 0 auto;
}
<canvas id="myCanvas" width="480" height="320"></canvas>

Javascript game - cannot read "y" property of undefined

So I was making this game today, and everything works perfectly, but sometimes this error shows up. I know what it means, and I've had it before, but this time it makes no sense. The game works perfectly fine, but sometimes when the bullet collides with the enemy the game freezes. I don't even know what to try anymore. Btw, if the error doesn't show up right away, just keep playing. Here's the code:
<html>
<head>
<title>Space shooter</title>
<style>
* {
margin:0;
}
canvas {
background: url("http://www.ufointernationalproject.com/wp-content/uploads/2017/03/space-03.jpg");
}
</style>
</head>
<body>
<canvas id="canvas" width="1350" height="630"></canvas>
<script>
var ctx = document.getElementById("canvas").getContext("2d"),
lastShot = Date.now(),
fireRate = 120,
bullets = [],
enemies = [],
enemySpeed = 1.5,
bulletSpeed = 20,
player = {
x: 600,
y: 250,
leftPressed: false,
rightPressed: false,
upPressed: false,
downPressed: false,
spacePressed: false,
speed: 5
};
var playerImage = new Image();
playerImage.src = "https://3.bp.blogspot.com/-jGC08Dy0zg8/U405cNq1-MI/AAAAAAAABqU/38d5rmV1S8Y/s1600/redfighter0006.png";
var enemyImage = new Image();
enemyImage.src = "https://a.fsdn.com/con/app/proj/partartspace/screenshots/Spaceship14.png/1";
function spawnEnemes() {
enemies.push({
x:Math.floor(Math.random() * 1250) + 1,
y:-100
})
}
setInterval(spawnEnemes, 500);
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(playerImage, player.x,player.y, 100, 100);
if (player.leftPressed) {
player.x -= player.speed;
}
if (player.rightPressed) {
player.x += player.speed;
}
if (player.upPressed) {
player.y -= player.speed;
}
if (player.downPressed) {
player.y += player.speed;
}
if (player.spacePressed && Date.now() - lastShot > fireRate) {
bullets.push({
x: player.x+50,
y: player.y
});
lastShot = Date.now();
}
bullets.forEach(function(bullet){
ctx.beginPath();
ctx.arc(bullet.x, bullet.y, 5, 0, 2 * Math.PI);
ctx.fillStyle = "red";
ctx.fill();
bullet.y -= bulletSpeed;
});
enemies.forEach(function(enemy){
ctx.drawImage(enemyImage, enemy.x, enemy.y, 100,100);
enemy.y += enemySpeed;
});
for (var enemy = 0; enemy < enemies.length; enemy ++){
if(player.x < enemies[enemy].x + 80 &&
player.x + 80 > enemies[enemy].x &&
player.y < enemies[enemy].y + 65 &&
player.y + 100 > enemies[enemy].y)
{
document.location.reload();
}
for (var bullet = 0; bullet < bullets.length; bullet ++) {
if(bullets[bullet].y < enemies[enemy].y + 70 &&
bullets[bullet].y > enemies[enemy].y &&
bullets[bullet].x < enemies[enemy].x + 100 &&
bullets[bullet].x > enemies[enemy].x)
{
bullets.splice(bullet, 1);
enemies.splice(enemy, 1);
}
}
}
requestAnimationFrame(draw);
}
draw();
document.body.addEventListener("keydown", function(e) {
if (e.keyCode === 37) {
player.leftPressed = true;
}
else if (e.keyCode === 39) {
player.rightPressed = true;
}
else if (e.keyCode === 38) {
player.upPressed = true;
}
else if (e.keyCode === 40) {
player.downPressed = true;
}
else if (e.keyCode === 32) {
player.spacePressed = true;
}
});
document.body.addEventListener("keyup", function(e) {
if (e.keyCode === 37) {
player.leftPressed = false;
}
else if (e.keyCode === 39) {
player.rightPressed = false;
}
else if (e.keyCode === 38) {
player.upPressed = false;
}
else if (e.keyCode === 40) {
player.downPressed = false;
}
else if (e.keyCode === 32) {
player.spacePressed = false;
}
});
</script>
</body>
</html>
The problem seems to be when you splice. As you don't exit the loops, you end up accessing invalid positions after a removal.

javascript jumping character not working

I'm having a few issues with my code. Can't get my cube to jump. Take a look at my code and let me know if you can help please.
My left, right and duck abilities all currently work at desired level, but I cannot get my cube to jump. I've been trying for three days and can't find anything online. My javascript is embedded within a tag in a html page.
var canvas = document.getElementById("gameCanvas");
var ctx = canvas.getContext("2d");
var coinRad = 8;
var coinX = 40;
var coinY = 80;
var x = 20;
var y = 510;
var w = 30;
var h = 50;
var rightPressed = false;
var leftPressed = false;
var ducked = false;
var jumping = false;
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
function keyDownHandler(e) {
if (e.keyCode == 39) {
rightPressed = true;
} else if (e.keyCode == 37) {
leftPressed = true;
} else if (e.keyCode == 40) {
ducked = true;
} else if (e.keycode == 32) {
jumping = true;
}
}
function keyUpHandler(e) {
if (e.keyCode == 39) {
rightPressed = false;
} else if (e.keyCode == 37) {
leftPressed = false;
} else if (e.keyCode == 40) {
ducked = false;
} else if (e.keycode == 32) {
jumping = false;
}
}
function drawCube() {
ctx.beginPath();
ctx.rect(x, y, w, h);
ctx.fillStyle = "Green";
ctx.fill();
ctx.closePath();
}
function run() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (leftPressed) {
if (x > 0) {
x -= 2.5;
}
} else if (rightPressed) {
if (x < canvas.width - w) {
x += 2.5;
}
}
if (jumping) {
y -= 10;
h -= 10;
}
if (ducked) {
y = 535;
h = 25;
} else {
y = 510;
h = 50;
}
drawCube();
}
setInterval(run, 10);
<canvas id="gameCanvas"></canvas>
Additionally, your keyCode check is improperly capitalized for the jumping condition.
else if (e.keyCode == 40) {
ducked = false;
} else if (e.keycode == 32) { //should be keyCode
jumping = false;
}
because when the run method end, you do this.
if (jumping) {
y -= 10;
h -= 10;
}
if (ducked) {
y = 535;
h = 25;
} else {
y = 510;
h = 50;
}
even if you change the values from Y and H, their values always change to 510 and 50 respectively, because the else in ducked condition.
Remove this else or find another logic to do the same

canvas keyPress movement - broken

My keyPress movement seems to be broken, if I press arr.up/down twice then it gets broken and I can't move the element back. And the element doesn't even stop when I stop holding the arr.up/down, why?
rocket = new Image();
x = 50;
y = 185;
score = 0;
velY = 0;
speed = 2;
y += velY;
ctx.drawImage(rocket, x, y);
if(e.keyCode == 38) {
if(velY < speed) {
velY --;
}
}
if(e.keyCode == 40) {
if(velY < speed) {
velY ++;
}
}
Preview: http://game.stranger.tk/
I would have edited your code however your game via your link isn't working :(. I hope this code example I have provided helps you out.
jsFiddle : https://jsfiddle.net/w1z2c1cq/
javascript
var c = document.getElementById('myCanvas');
var ctx = c.getContext('2d');
var rocket = function()
{
this.Sprite = new Image();
this.Sprite.src = "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcS9zafp1ezdR2lSAxTdjZYe_nPhe6VeKKmAuK-GzWQCSs395WkzNA";
this.XPos = 100;
this.YPos = 100;
}
var player = new rocket();
setInterval(function()
{
ctx.fillRect(0,0,400,400);
ctx.drawImage(player.Sprite, player.XPos, player.YPos);
}, 3);
window.addEventListener("keydown", function(e){
// Left key
if(e.keyCode === 37) {
player.XPos -= 5;
}
// Right key
if(e.keyCode === 39) {
player.XPos += 5;
}
// Up key
if(e.keyCode === 38) {
player.YPos -= 5;
}
// Down key
if(e.keyCode === 40) {
player.YPos += 5;
}
});
Also in your code you are checking this same if statement for up and down if(velY < speed)
try
// Up
if(e.keyCode == 38) {
if(velY < speed) {
velY --;
}
}
// Down
if(e.keyCode == 40) {
if(velY > -speed) {
velY ++;
}
}

Categories