How to make my keyup function work inside of my game - javascript

This is somewhat a long shot, but I have been recently working on a game, and I have been pretty proud of it. Although it is no Minecraft, for my level of expertise, it is looking pretty good. There is just one problem with it though. My character travels all over the place. I have never been able to get him to only move one block. If there is anyone out there with a high level of coding expertise, please look at this code. There is a lot of code, so it might take a while, but I appreciate all the help I can get. If you can spot the problem, please notify me. Thank you.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
setInterval(terrainJumpLoop, 100);
setInterval(playerLeftLoop, 100);
setInterval(playerRightLoop, 100);
canvas.width = 1500;
canvas.height = 500;
var highTerrain = [];
var middleTerrain = [];
var lowTerrain = [];
var oreTerrain = [];
var biome = "";
var biomeSelector = 0;
var playerBlock = 0;
var terrainLength = canvas.width/25;
var unevenTerrainLocator = 0;
var gravityVar = 0;
var gravityStrength = 0;
var touchingGround = false;
var canMove = true;
var gameOn = false;
window.onerror = function (msg, url, lineNo, columnNo, error) {
document.getElementById("paragraph").innerHTML = "Game has Stopped Abruptly Due to Error in Code";
document.getElementById("wrongCodeLine").innerHTML = msg;
document.getElementById("errorLineNo").innerHTML = "Line Number: " + lineNo.toString();
window.stop();
};
var Player = {
x:0,
y:0,
width:25,
height:25,
color:"gold"
};
function paintGameTrees(x, y){
alert(x);
alert(y);
}
function paintGameTerrain(){
var grassBlock = {
width:25,
height:25,
color:"green"
};
var dirtBlock = {
width:25,
height:25,
color:"brown"
};
var stoneBlock = {
width:25,
height:25,
color:"gray"
};
var coalBlock = {
width:25,
height:25,
color:"#383838"
};
var ironBlock = {
width:25,
height:25,
color:"#C0C0C0"
};
var lava = {
width:25,
height:25,
color:"red"
};
var snowBlock = {
width:25,
height:25,
color:"white"
};
for(i = 0; i < terrainLength; i++){
if(highTerrain[i] === 0){
paintGameItems(i*25, canvas.height - 100, grassBlock.width, grassBlock.height, grassBlock.color);
}
else if(highTerrain[i] === 7){
paintGameItems(i*25, canvas.height - 100, snowBlock.width, snowBlock.height, snowBlock.color);
}
}
for(i = 0; i < terrainLength; i++){
if(middleTerrain[i] === 0){
paintGameItems(i*25, canvas.height - 75, grassBlock.width, grassBlock.height, grassBlock.color);
}
else if(middleTerrain[i] === 1){
paintGameItems(i*25, canvas.height - 75, dirtBlock.width, dirtBlock.height, dirtBlock.color);
}
else if(middleTerrain[i] === 7){
paintGameItems(i*25, canvas.height - 75, snowBlock.width, snowBlock.height, snowBlock.color);
}
}
for(i = 0; i < terrainLength; i++){
if(lowTerrain[i] === 0){
paintGameItems(i*25, canvas.height - 50, grassBlock.width, grassBlock.height, grassBlock.color);
}
else if(lowTerrain[i] === 1){
paintGameItems(i*25, canvas.height - 50, dirtBlock.width, dirtBlock.height, dirtBlock.color);
}
else if(lowTerrain[i] === 2){
paintGameItems(i*25, canvas.height - 50, stoneBlock.width, stoneBlock.height, stoneBlock.color);
}
else if(lowTerrain[i] === 7){
paintGameItems(i*25, canvas.height - 50, snowBlock.width, snowBlock.height, snowBlock.color);
}
}
for(i = 0; i < terrainLength; i++){
if(oreTerrain[i] === 2){
paintGameItems(i*25, canvas.height - 25, stoneBlock.width, stoneBlock.height, stoneBlock.color);
}
else if(oreTerrain[i] === 4){
paintGameItems(i*25, canvas.height - 25, coalBlock.width, coalBlock.height, coalBlock.color);
}
else if(oreTerrain[i] === 5){
paintGameItems(i*25, canvas.height - 25, ironBlock.width, ironBlock.height, ironBlock.color);
}
else if(oreTerrain[i] === 6){
paintGameItems(i*25, canvas.height - 25, lava.width, lava.height, lava.color)
}
else if(oreTerrain[i] === 7){
paintGameItems(i*25, canvas.height - 25, lava.width, lava.height, lava.color)
}
}
}
function setItemAttributes(){
console.log("ItemAttributes Successfully Set");
paintGameItems(Player.x, Player.y, Player.width, Player.height, Player.color);
console.log("paintGameItems Successfully Called");
}
function randomTerrain(){
console.log("randomTerrain successfully called");
/*
If the number passed is 0, then the block will be grass
If the number 1 is passed, then the block will be dirt
If the number 2 is passed, then the block will be stone
If the number 3 is passed, then the block will be nothing
If the number 4 is passed, then the block will be coal
If the number 5 is passed, then the block will be iron
If the number 6 is passed, then the block will be lava
If the number 7 is passed, then the block will be snow
*/
var terrainVar = Math.random() * 10;
var oreVar = Math.random() * 10;
if(biome === "plains") {
if (terrainVar > 0 && terrainVar < 6) {
highTerrain.push(0);
middleTerrain.push(1);
lowTerrain.push(2)
} else if (terrainVar > 6 && terrainVar < 9) {
highTerrain.push(3);
middleTerrain.push(0);
lowTerrain.push(1);
} else {
highTerrain.push(3);
middleTerrain.push(3);
lowTerrain.push(0);
}
console.log("oreVar = " + oreVar);
if (oreVar < 6) {
oreTerrain.push(2);
} else if (oreVar > 6 && oreVar < 8) {
oreTerrain.push(4);
} else if (oreVar > 8 && oreVar < 9) {
oreTerrain.push(5);
} else if (oreVar > 9) {
oreTerrain.push(6)
}
}
else if(biome === "taiga") {
if (terrainVar > 0 && terrainVar < 6) {
highTerrain.push(7);
middleTerrain.push(7);
lowTerrain.push(2)
} else if (terrainVar > 6 && terrainVar < 9) {
highTerrain.push(3);
middleTerrain.push(7);
lowTerrain.push(7);
} else {
highTerrain.push(3);
middleTerrain.push(3);
lowTerrain.push(7);
}
console.log("oreVar = " + oreVar);
if (oreVar < 6) {
oreTerrain.push(2);
} else if (oreVar > 6 && oreVar < 8) {
oreTerrain.push(4);
} else if (oreVar > 8 && oreVar < 9) {
oreTerrain.push(5);
} else if (oreVar > 9) {
oreTerrain.push(6)
}
}
}
function paintGameItems(itemX, itemY, itemWidth, itemHeight, itemColor){
//console.log(itemX, itemY, itemWidth, itemHeight);
ctx.beginPath();
ctx.fillStyle = itemColor;
ctx.fillRect(itemX, itemY, itemWidth, itemHeight);
ctx.fill();
}
function selectBiome(){
biomeSelector = Math.random() * 10;
if(biomeSelector <= 7){
biome = "plains";
}
else if(biomeSelector > 7){
biome = "taiga";
}
}
function playerLocationTracker(){
console.log("Player.x = " + Player.x + ". canMove = " + canMove + ". playerBlock = " + playerBlock);
}
function playerJump(e){
addEventListener("keydown", function(e) {
if (e.keyCode === 32 || e.keyCode === 87 || e.keyCode === 38) {
if (touchingGround) {
for (i = 0; i < 1; i++) {
Player.y -= 1;
}
}
}
});
}
function playerLeft(e){
addEventListener("keydown", function(e) {
if(canMove) {
if (e.keyCode === 65 || e.keyCode === 37){
console.log("Left");
canMove = false;
playerBlock -= 0.04;
Player.x -= 0.4;
canMove = true;
e.keyCode = 0;
}
}
});
}
function playerRight(e){
addEventListener("keydown", function(e) {
if (canMove){
if (e.keyCode === 68 || e.keyCode === 39) {
console.log("Right");
canMove = false;
playerBlock += 0.04;
Player.x += 0.4;
canMove = true;
e.keyCode = 0;
}
}
});
}
function playerGravity(){
unevenTerrainLocator = Math.round(playerBlock);
if(highTerrain[unevenTerrainLocator] === 0 || highTerrain[unevenTerrainLocator] === 7){
gravityVar = canvas.height - 12;
}
else if(middleTerrain[unevenTerrainLocator] === 0 || middleTerrain[unevenTerrainLocator] === 7){
gravityVar = canvas.height - 100;
}
else if(lowTerrain[unevenTerrainLocator] === 0 || lowTerrain[unevenTerrainLocator] === 7){
gravityVar = canvas.height - 75
}
if(gravityVar <= Player.y){
Player.y = gravityVar;
gravityStrength = 0;
touchingGround = true;
}
else if(gravityVar > Player.y){
touchingGround = false;
gravityStrength +=5;
Player.y += gravityStrength;
}
}
function terrainJumpLoop(){
if(gameOn){
ctx.clearRect(0, 0, canvas.width, canvas.height);
playerGravity();
playerJump();
playerLocationTracker();
paintGameItems(Player.x, Player.y, Player.width, Player.height, Player.color);
paintGameTerrain();
}
}
function playerLeftLoop(){
playerLeft();
}
function playerRightLoop(){
playerRight();
}
function initializeGame(){
var treeX = (Math.round(Math.random()*(canvas.width/25)))*25;
var treeY = 0;
if(highTerrain[treeX/25] === 0){
treeY = canvas.height - 100;
}
else if(middleTerrain[treeX/25] === 0){
treeY = canvas.height - 75;
}
else if(lowTerrain[treeX/25]){
treeY = canvas.height - 50;
}
paintGameTrees(treeX, treeY);
if (biome === "plains") {
document.getElementById('mediaOverworld').play();
}
else if(biome === "taiga"){
document.getElementById('mediaGlaciers').play();
}
}
function startGameFunction() {
console.clear();
ctx.clearRect(0, 0, canvas.width, canvas.height);
document.getElementById('mediaOverworld').pause();
document.getElementById('mediaOverworld').currentTime = 0;
document.getElementById('mediaGlaciers').pause();
document.getElementById('mediaGlaciers').currentTime = 0;
highTerrain = [];
middleTerrain = [];
lowTerrain = [];
oreTerrain = [];
selectBiome();
Player.x = 0;
Player.y = 0;
document.getElementById("paragraph").innerHTML = "Music and Game Has Successfully Started";
console.log("Game Has Successfully Started");
setItemAttributes();
for(i = 0; i < terrainLength; i++){
randomTerrain();
console.log("Terrain Layer Successfully Generated")
}
console.log(highTerrain);
console.log(middleTerrain);
console.log(lowTerrain);
console.log(oreTerrain);
initializeGame();
paintGameTerrain();
document.getElementById("startBtn").innerHTML = "Reset the Game";
gameOn = true;
}
body{
background-color:black;
color:white;
}
canvas{
background-color:aqua;
margin:0 auto;
}
#ifError {
color: red;
font-family: "Arial Black";
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Simple 2D JavaScript Platformer</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas id="canvas"></canvas>
<br>
<button onclick="startGameFunction()" id="startBtn">Start The Game</button>
<p id="paragraph"></p>
<div id="ifError">
<p id="wrongCodeLine"></p>
<p id="errorLineNo"></p>
</div>
<audio id="mediaOverworld">
<source src="Audio/Overworld.mp3">
</audio>
<audio id="mediaGlaciers">
<source src="Audio/Glaciers.mp3">
</audio>
<script src="game.js"></script>
</body>
</html>
This is a lot of code to debug, but if you can do it, I will thank you a lot.

Related

Difficulty Adding a "Play Again!" Button to this snake game

I've been trying to figure out how I can add a play again button to refresh the page after a player has lost. This is a classic snake game. I followed a tutorial on it and but they never said anything about a Play Again button. Any help would be appreciated. Nothing too complicated though please, I'm still learning.
const ctx = canvas.getContext("2d");
class SnakePart {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
let speed = 7;
let tileCount = 20;
let tileSize = canvas.width / tileCount - 2;
let headX = 10;
let headY = 10;
const snakeParts = [];
let tailLength = 2;
let appleX = 5;
let appleY = 5;
let inputsXVelocity = 0;
let inputsYVelocity = 0;
let xVelocity = 0;
let yVelocity = 0;
let score = 0;
const gulpSound = new Audio("gulp.mp3");
//game loop
function drawGame() {
xVelocity = inputsXVelocity;
yVelocity = inputsYVelocity;
changeSnakePosition();
let result = isGameOver();
if (result) {
return;
}
clearScreen();
checkAppleCollision();
drawApple();
drawSnake();
drawScore();
if (score > 5) {
speed = 9;
}
if (score > 10) {
speed = 11;
}
setTimeout(drawGame, 1000 / speed);
}
function isGameOver() {
let gameOver = false;
if (yVelocity === 0 && xVelocity === 0) {
return false;
}
//walls
if (headX < 0) {
gameOver = true;
} else if (headX === tileCount) {
gameOver = true;
} else if (headY < 0) {
gameOver = true;
} else if (headY === tileCount) {
gameOver = true;
}
for (let i = 0; i < snakeParts.length; i++) {
let part = snakeParts[i];
if (part.x === headX && part.y === headY) {
gameOver = true;
break;
}
}
if (gameOver) {
ctx.fillStyle = "white";
ctx.font = "50px Verdana";
if (gameOver) {
ctx.fillStyle = "white";
ctx.font = "50px Verdana";
var gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
gradient.addColorStop("0", " magenta");
gradient.addColorStop("0.5", "blue");
gradient.addColorStop("1.0", "red");
// Fill with gradient
ctx.fillStyle = gradient;
ctx.fillText("Game Over!", canvas.width / 6.5, canvas.height / 2);
}
ctx.fillText("Game Over!", canvas.width / 6.5, canvas.height / 2);
}
return gameOver;
}
function drawScore() {
ctx.fillStyle = "white";
ctx.font = "10px Verdana";
ctx.fillText("Score " + score, canvas.width - 50, 10);
}
function clearScreen() {
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
function drawSnake() {
ctx.fillStyle = "green";
for (let i = 0; i < snakeParts.length; i++) {
let part = snakeParts[i];
ctx.fillRect(part.x * tileCount, part.y * tileCount, tileSize, tileSize);
}
snakeParts.push(new SnakePart(headX, headY)); //put an item at the end of the list next to the head
while (snakeParts.length > tailLength) {
snakeParts.shift(); // remove the furthet item from the snake parts if have more than our tail size.
}
ctx.fillStyle = "orange";
ctx.fillRect(headX * tileCount, headY * tileCount, tileSize, tileSize);
}
function changeSnakePosition() {
headX = headX + xVelocity;
headY = headY + yVelocity;
}
function drawApple() {
ctx.fillStyle = "red";
ctx.fillRect(appleX * tileCount, appleY * tileCount, tileSize, tileSize);
}
function checkAppleCollision() {
if (appleX === headX && appleY == headY) {
appleX = Math.floor(Math.random() * tileCount);
appleY = Math.floor(Math.random() * tileCount);
tailLength++;
score++;
gulpSound.play();
}
}
document.body.addEventListener("keydown", keyDown);
function keyDown(event) {
//up
if (event.keyCode == 38 || event.keyCode == 87) {
//87 is w
if (inputsYVelocity == 1) return;
inputsYVelocity = -1;
inputsXVelocity = 0;
}
//down
if (event.keyCode == 40 || event.keyCode == 83) {
// 83 is s
if (inputsYVelocity == -1) return;
inputsYVelocity = 1;
inputsXVelocity = 0;
}
//left
if (event.keyCode == 37 || event.keyCode == 65) {
// 65 is a
if (inputsXVelocity == 1) return;
inputsYVelocity = 0;
inputsXVelocity = -1;
}
//right
if (event.keyCode == 39 || event.keyCode == 68) {
//68 is d
if (inputsXVelocity == -1) return;
inputsYVelocity = 0;
inputsXVelocity = 1;
}
}
drawGame();```
The easiest way to refresh the page would be just:
window.location.reload(false)
Source:
https://www.freecodecamp.org/news/location-reload-method-how-to-reload-a-page-in-javascript/
I would suggest that simply reloading the page is not a great way to implement a play again feature but I appreciate the creativity of it.

How to make points in Javascript

I need help to make points every time the snake eats a piece of food. I am coding in Brackets.
I've watched The Coding Train and I was thinking the problem was that he was using p5.js when I was using Brackets. Could somebody please answer my question. Thank you! The link for the video that I have watched is: https://www.youtube.com/watch?v=AaGK-fj-BAM.
function Snake() { <- Javascript
this.x = 0;
this.y = 0;
this.xspeed = 1;
this.yspeed = 0;
this.total = 0;
this.tail = [];
this.eat = function(pos) {
var d = dist(this.x, this.y, pos.x, pos.y);
if (d < 1) {
this.total++;
return true;
} else {
return false;
}
}
this.dir = function(x, y) {
this.xspeed = x;
this.yspeed = y;
}
this.death = function() {
for (var i = 0; i < this.tail.length; i++) {
var pos = this.tail[i];
var d = dist(this.x, this.y, pos.x, pos.y);
if (d < 1) {
alert(' BAD LUCK ');
this.total = 0;
this.tail = [];
point.counterReset;
}
}
}
this.update = function() {
for (var i = 0; i < this.tail.length - 1; i++) {
this.tail[i] = this.tail[i + 1];
}
if (this.total >= 1) {
this.tail[this.total - 1] = createVector(this.x, this.y);
}
this.x = this.x + this.xspeed * scl;
this.y = this.y + this.yspeed * scl;
this.x = constrain(this.x, 0, width - scl);
this.y = constrain(this.y, 0, height - scl);
}
this.show = function() {
fill(89, 152, 47);
for (var i = 0; i < this.tail.length; i++) {
rect(this.tail[i].x, this.tail[i].y, scl, scl);
}
rect(this.x, this.y, scl, scl);
}
}
var s;
var point = 1;
var scl = 20;
var food;
var fool;
function setup() {
createCanvas(600,600);
s = new Snake();
frameRate(10);
pickLocation();
}
function pickLocation() {
var cols = floor(width / scl);
var rows = floor(height / scl);
food = createVector(floor(random(cols)), floor(random(rows)));
food.mult(scl);
fool = createVector(floor(random(cols)), floor(random(rows)));
fool.mult(scl);
}
function draw() {
background(120,6,6);
if (s.eat(food)) {
pickLocation();
point.total++;
if (Math.random() * 100 < 45) {
let name = prompt("What is 2 ÷ 4?");
alert ("Yes it is, " + name);
}
else if (Math.random() * 100 < 45) {
let name = prompt("What is the intergration of X²?");
alert ("Yes it is, " + name);
}
else if (Math.random() * 100 < 50) {
let name = prompt("What is Mass x Acceleration?");
alert ("Yes it is, " + name);
}
else if (Math.random() * 100 < 50) {
let name = prompt("How many elements are in the Periodic Table?");
alert ("Yes it is, " + name);
}
else if (Math.random() * 100 < 50 ) {
let name = prompt("What is 336 ÷ 84?");
alert ("Yes it is, " + name);
}
else if (Math.random() * 100 < 50 ) {
let name = prompt("(VERY RARE)Who was the captain of The First Fleet?");
alert ("Yes it is, " + name);
}
}
if (s.eat(fool)) {
pickLocation();
point.total++;
if (Math.random() * 100 < 45) {
let name = prompt("What is 2 ÷ 4?");
alert ("Yes it is, " + name);
}
else if (Math.random() * 100 < 45) {
let name = prompt("What is the intergration of X²?");
alert ("Yes it is, " + name);
}
else if (Math.random() * 100 < 50) {
let name = prompt("What is Mass x Acceleration?");
alert ("Yes it is, " + name);
}
else if (Math.random() * 100 < 50 ) {
let name = prompt("What is 336 ÷ 84?");
alert ("Yes it is, " + name);
}
else if (Math.random() * 100 < 50) {
let name = prompt("How many elements are in the Periodic Table?");
alert ("Yes it is, " + name);
}
else if (Math.random() * 100 < 50 ) {
let name = prompt("(VERY RARE)Who was the captain of The First Fleet?");
alert ("Yes it is, " + name);
}
}
s.death();
s.update();
s.show();
fill(255, 0, 100);
rect(food.x, food.y, scl, scl);
fill(255, 0, 100);
rect(fool.x, fool.y, scl, scl);
}
document.write("Score: " + point);
point.update();
point.show();
function keyPressed() {
if (keyCode === UP_ARROW) {
s.dir(0, -1);
} else if (keyCode === DOWN_ARROW) {
s.dir(0, 1);
} else if (keyCode === RIGHT_ARROW) {
s.dir(1, 0);
} else if (keyCode === LEFT_ARROW) {
s.dir(-1, 0)
}
}
html, body { <- css
margin: 0;
padding: 0;
background-color: #40E0D0;
}
canvas {
display: block;
}
<!DOCTYPE html> <-html
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/addons/p5.dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
<title>Snake Game</title>
</head>
<body>
<script src="sketch.js"></script>
<script src="snake.js"></script>
<script src="skin.js"></script>
</body>
</html>
I am counting points when snake eats apple with that code
if (cell.x === apple.x && cell.y === apple.y) snake.maxCells++;
And my snake-game:
var canvas = document.getElementById('game');
var context = canvas.getContext('2d');
var grid = 16;
var count = 0;
var snake = {
x: 160,
y: 160,
dx: grid,
dy: 0,
cells: [], //tail
maxCells: 4
};
var apple = {
x: 320,
y: 320
};
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
function loop() {
requestAnimationFrame(loop);
if (++count < 1) {
return;
}
count = -15; // speed
context.clearRect(0,0,canvas.width,canvas.height);
snake.x += snake.dx;
snake.y += snake.dy;
if (snake.x < 0) {
snake.x = canvas.width - grid;
}
else if (snake.x >= canvas.width) {
snake.x = 0;
}
if (snake.y < 0) {
snake.y = canvas.height - grid;
}
else if (snake.y >= canvas.height) {
snake.y = 0;
}
snake.cells.unshift({x: snake.x, y: snake.y});
if (snake.cells.length > snake.maxCells) {
snake.cells.pop();
}
context.fillStyle = 'red';
context.fillRect(apple.x, apple.y, grid-1, grid-1);
context.fillStyle = 'green';
snake.cells.forEach(function(cell, index) {
context.fillRect(cell.x, cell.y, grid-1, grid-1);
if (cell.x === apple.x && cell.y === apple.y) { // if our snake eat red apple, so you count points
// and adding one green cell to snake
snake.maxCells++;
// Drawing new apple
apple.x = getRandomInt(0, 25) * grid;
apple.y = getRandomInt(0, 25) * grid;
}
for (var i = index + 1; i < snake.cells.length; i++) {
if (cell.x === snake.cells[i].x && cell.y === snake.cells[i].y) {
snake.x = 160;
snake.y = 160;
snake.cells = [];
snake.maxCells = 4;
snake.dx = grid;
snake.dy = 0;
apple.x = getRandomInt(0, 25) * grid;
apple.y = getRandomInt(0, 25) * grid;
}
}
});
}
document.addEventListener('keydown', function(e) {
if (e.which === 37 && snake.dx === 0) {
snake.dx = -grid;
snake.dy = 0;
}
else if (e.which === 38 && snake.dy === 0) {
snake.dy = -grid;
snake.dx = 0;
}
else if (e.which === 39 && snake.dx === 0) {
snake.dx = grid;
snake.dy = 0;
}
else if (e.which === 40 && snake.dy === 0) {
snake.dy = grid;
snake.dx = 0;
}
});
requestAnimationFrame(loop);
html, body {
height: 100%;
margin: 0;
}
body {
background: black;
display: flex;
align-items: center;
justify-content: center;
}
canvas {
border: 1px solid white;
}
<!DOCTYPE html>
<html>
<body>
<canvas width="400" height="400" id="game"></canvas>
</body>
</html>

How can i make the bullet not move with the character when looking either right or left?

I am having a problem where when I fire either left or right, once i move the character the bullets direction will change while its still fired. I am using the protagonist picture as the condition to either shoot right or left but i would like the bullet to keep firing in the fired direction even if i change the movement of the character
I am a beginner in Javascript and I'm using canvas to create a game for a college project.
if (moveBullet) {
let s = heroPic.src.substring(heroPic.src.lastIndexOf("/") + 1);
//alert(s);
if (s == "Protagenist_Right_Jet.png" || s == "Protagenist_Stand_Jet.png") {
bulletX += 20;
}
if (s == "Protagenist_Left_Jet.png") {
bulletX -= 20;
}
if (bulletX >= canvas.width) {
moveBullet = false;
bulletX = canvas.width + 50
bulletY = canvas.height + 50;
}
if (bulletX <= 0) {
moveBullet = false;
bulletX = canvas.width + 50
bulletY = canvas.height + 50;
}
}
Full Code
<!DOCTYPE html>
<body>
<div id="canvasesdiv" style="text-align: center;">
<canvas id="canvas1" width="800" height="500" tabIndex="0" style="background: url('Level 1.png');position: relative; display: block;">
</div>
<script>
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
//get the animation frame depending on the browser engine
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
//Hero Attributes
var jetPackAudio = new Audio();
jetPackAudio.src = "Jetpack Sound.mp3";
var heroPic = new Image();
var heroX ;
var heroY ;
//Decides where the hero is looking
var heroRight = false;
var life = 3;
var heroWidth = 50 ;
var heroHeight = 50 ;
var gravity = 5;
heroX = 20;
heroY = 440;
heroPic.src = "Protagenist_Stand_Jet.png";
function drawHero(x,y)
{
ctx.drawImage(heroPic,x,y,heroWidth,heroHeight);
}
hitBottom = function() {
var rockbottom = canvas.height - heroHeight;
if (heroY > rockbottom) {
heroY = rockbottom;
}
}
// Key Attribute
var key = new Image();
key.src = "Key1.png"
var keyX ;
var keyY ;
var keyCounter = 0;
var keyWidth = 30 ;
var keyHeight = 30 ;
function drawKey()
{
ctx.drawImage(key,keyX,keyY,keyWidth,keyHeight);
}
var killCounter = 0 ;
var levelKillCounter;
// Monster 1 Attributes
var monster1 = new Image();
monster1.src = "Monster1_Left.png"
var m1MoveLeft = true;
var m1X ;
var m1Y ;
var m1Width = 50 ;
var m1Height = 50 ;
function drawMonster1()
{
ctx.drawImage(monster1,m1X,m1Y,m1Width,m1Height);
}
// Monster 2 Attributes
var monster2 = new Image();
monster2.src = "Monster 2_Right.png"
var m2MoveRight = true;
var m2X ;
var m2Y ;
var m2Width = 50 ;
var m2Height = 50 ;
function drawMonster2()
{
ctx.drawImage(monster2,m2X,m2Y,m2Width,m2Height);
}
// Monster 3 Attributes
var monster3 = new Image();
monster3.src = "Monster3_Right.png"
var m3MoveRight = true;
var m3X ;
var m3Y ;
var m3Width = 50 ;
var m3Height = 50 ;
function drawMonster3()
{
ctx.drawImage(monster3,m3X,m3Y,m3Width,m3Height);
}
// Hit Bottom
hitBottom = function() {
var rockbottom = canvas.height - heroHeight;
if (heroY > rockbottom) {
heroY = rockbottom;
}
}
//Bullet Attribute
var bulletX;
var bulletY;
const ammo = [];
var moveBullet = false;
var bulletImage = new Image();
bulletImage.src = 'Bullet.png';
function drawBullet(x,y)
{
ctx.drawImage(bulletImage,bulletX,bulletY);
}
//this function is used to detect a hit monster 1
function getDistanceHit1() {
var xRect = (m1X - bulletX);
var yRect = (m1Y - bulletY);
return Math.sqrt(Math.pow((xRect), 2) + Math.pow((yRect), 2));
}
//this function is used to detect a hit monster 2
function getDistanceHit2() {
var xRect = (m2X - bulletX);
var yRect = (m2Y - bulletY);
return Math.sqrt(Math.pow((xRect), 2) + Math.pow((yRect), 2));
}
//this function is used to detect a hit monster 3
function getDistanceHit3() {
var xRect = (m3X - bulletX);
var yRect = (m3Y - bulletY);
return Math.sqrt(Math.pow((xRect), 2) + Math.pow((yRect), 2));
}
//this function is used to detect if the player got the key
function getDistanceKey() {
var xRect = (keyX - heroX);
var yRect = (keyY - heroY);
return Math.sqrt(Math.pow((xRect), 2) + Math.pow((yRect), 2));
}
//configure the audio files
var fireAudio = new Audio();
fireAudio.src = "fire.mp3";
var hitAudio = new Audio();
hitAudio.src = "neck_snap.wav"
//Hero Movement
var rightPressed = false;
var leftPressed = false;
var upPressed = false;
var downPressed = false;
window.addEventListener("keydown", heroControl);
//Keyboard Cotrolls
function heroControl(event) { //event handler function
if (event.keyCode == 32) { //SPACE BAR PRESSED - fire gun
moveBullet = true;
fireAudio.play();
bulletX = heroX + 10;
bulletY = heroY + (heroHeight / 2);
console.log("BulletX = " + bulletX);
}
// 38 is up arrow, 87 is the W key
if (event.keyCode == 38 || event.keyCode == 87) { //Jump
upPressed = true;
console.log("HeroY = " + heroY);
}
// 39 is right arrow, 68 is thw D key
else if (event.keyCode == 39 || event.keyCode == 68) { //move Right
rightPressed = true;
console.log("Herox = " + heroX);
}
else if(event.keyCode == 37 || event.keyCode == 65) { // Move Left
leftPressed = true;
console.log("Herox = " + heroX);
}
else if(event.keyCode == 40 || event.keyCode == 83) { // Move Left
downPressed = true;
console.log("Heroy = " + heroY);
}
}
//Touch Controls
canvas.addEventListener("touchstart", handleTouchStart, false);
function handleTouchStart(touchEvent) { //event handler for touch events
var rect = canvas.getBoundingClientRect(); //to get canvas offsets
let touchX = touchEvent.changedTouches[0].clientX - rect.left;
let touchY = touchEvent.changedTouches[0].clientY - rect.top;
if (touchX <= canvas.width && touchX > canvas.width - 200) {
rightPressed = true;
}
if (touchX >= 0 && touchX < canvas.width - 600) {
leftPressed = true;
}
if (touchY >= 0 && touchY < canvas.height - 200) {
upPressed = true;
}
if (touchY <= canvas.height && touchY > canvas.height - 200) {
downPressed = true;
}
}
function moveHero() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if(rightPressed) {
if(heroX < canvas.width - 53){
heroPic.src = "Protagenist_Right_Jet.png"
heroRight = true;
heroX = heroX + 10;
heroRight = true;
rightPressed = false;
}
else
{
rightPressed = false;
heroRight = false;
}
}
if(leftPressed) {
if(heroX > 0){
heroX = heroX - 10;
heroLeft = true;
heroPic.src = "Protagenist_Left_Jet.png";
bulletImage.src = "left_bullet.png";
leftPressed = false;
}
else
{
leftPressed = false;
heroLeft = false;
}
}
if(upPressed) {
if(heroY > 0){
heroY = heroY - 20;
heroStand = true;;
jetPackAudio.play();
heroPic.src = "Protagenist_Stand_Jet.png";
upPressed = false;
}
else
{
upPressed = false;
heroStand = false;;
}
}
if(downPressed) {
if(heroY < canvas.height){
heroPic.src = "Protagenist_Stand_Jet.png"
heroStand = true;
heroY = heroY + 10;
downPressed = false;
}
else
{
downPressed = false;
heroStand = false;
}
}
displayScoreArea();
drawHero(heroX,heroY);
drawMonster1();
drawMonster2();
drawMonster3();
drawKey();
drawBullet(bulletX,bulletY);
requestAnimationFrame(moveHero);
}
//Level Setter
var level = 2;
function setLvl()
{
if(level == 1)
{
canvas.style = "background: url('Level 1.png')";
levelKillCounter = 3;
}
else if(level == 2)
{
canvas.style = "background: url('Level 2.png')";
monster1.src = "Monster3_Right.png"
monster2.src = "Monster3_Right.png"
}
else if(level == 3)
{
canvas.style = "background: url('Level 3.png')";
}
}
var gameAudio = new Audio();
gameAudio.src = "Dungeon Theme.mp3"
function animation()
{
setTimeout(() => {
//animation code goes into this anonymous function handler
requestAnimationFrame(animation);
//clear the whole canvas area
ctx.clearRect(0, 0, canvas.width, canvas.height);
moveHero();
drawMonster1();
drawMonster2();
drawMonster3();
drawKey();
drawBullet(bulletX,bulletY);
monsterAnimate();
setLvl();
heroY = heroY + gravity;
if(moveBullet)
{
let s = heroPic.src.substring(heroPic.src.lastIndexOf("/") + 1);
//alert(s);
if(s == "Protagenist_Right_Jet.png" || s == "Protagenist_Stand_Jet.png")
{
bulletX +=20;
}
if(s == "Protagenist_Left_Jet.png")
{
bulletX -=20;
}
if(bulletX >= canvas.width)
{
moveBullet = false;
bulletX = canvas.width + 50
bulletY = canvas.height +50;
}
if(bulletX <= 0)
{
moveBullet = false;
bulletX = canvas.width + 50
bulletY = canvas.height +50;
}
console.log(getDistanceHit1());
if (getDistanceHit1() <= 30 ||
getDistanceHit2() <= 30 ||
getDistanceHit3() <= 30 )
{
//Delete Monster
if(getDistanceHit1() <= 30)
{
m1X = 1000;
m1Y = 1000;
}
if(getDistanceHit2() <= 30)
{
m2X = 1000;
m2Y = 1000;
}
if(getDistanceHit3() <= 30)
{
m3X = 1000;
m3Y = 1000;
}
//increase the hit count
killCounter++;
//we have a hit
moveBullet = false;
//play the hitAudio
hitAudio.play();
//Reset Bullet
bulletX = canvas.width + 50
bulletY = canvas.height +50;
}
}
if(killCounter == 3)
{
keyX = canvas.width / 2;
keyY = 150;
}
if(getDistanceKey() <= 10)
{
keyCounter = 1;
keyX = 1000;
keyY = 1000;
}
//level progression flow - check of level objectives are met
if (level == 1 && keyCounter == 1 && heroX >= 700 & heroY >= 50) {
alert("Level 1 completed. Starting Level 2...");
level = 2;
killCounter = 0; //reset
keyCounter = 0;//reset
m1X = 700;
m1Y = 370;
m2X = 100;
m2Y = 320;
m3X = 100;
m3Y = 170;
}
else if (level == 2 && keyCounter == 1 && heroX == 700 & heroY == 50) {
alert("Level 2 completed. Starting Level 3...");
level = 3;
killCounter = 0; //reset
keyCounter = 0;//reset
}
else if (level == 3 && currentLevelHits == 4) {
//last level
var playAgain = confirm("Game completed. Play again?");
if (playAgain)
window.location.reload(true); //force reload
else
stopAnimation = true;
}
//gameAudio.play();
displayScoreArea();
hitBottom();
},100)
}
m1X = 700;
m1Y = 370;
m2X = 100;
m2Y = 320;
m3X = 100;
m3Y = 170;
function monsterAnimate()
{
//Movement for level 1
if(level == 1)
{
if(m1MoveLeft)
{
m1X -= 10
}
else if(!m1MoveLeft)
{
m1X += 10
}
if(m2MoveRight)
{
m2X += 10
}
else if(!m2MoveRight)
{
m2X -= 10
}
if(m3MoveRight)
{
m3X +=10
}
else if(!m3MoveRight)
{
m3X -= 10
}
if(m1X == 420)
{
m1MoveLeft = false;
monster1.src ="Monster 1_Right.png"
}
else if(m1X == 700)
{
m1MoveLeft = true;
monster1.src ="Monster1_Left.png"
}
if(m2X == 310)
{
m2MoveRight = false;
monster2.src ="Monster2_left.png"
}
else if(m2X == 100)
{
m2MoveRight = true;
monster2.src ="Monster 2_Right.png"
}
if(m3X == 310)
{
m3MoveRight = false;
monster3.src ="Monster 3_left.png"
}
else if(m3X == 100)
{
m3MoveRight = true;
monster3.src ="Monster3_Right.png"
}
}
//Movement for level 2
if(level == 2)
{
if(m1MoveLeft)
{
m1X -= 20
}
else if(!m1MoveLeft)
{
m1X += 20
}
if(m2MoveRight)
{
m2X += 20
}
else if(!m2MoveRight)
{
m2X -= 20
}
if(m3MoveRight)
{
m3X +=20
}
else if(!m3MoveRight)
{
m3X -= 20
}
if(m1X == 420)
{
m1MoveLeft = false;
monster1.src ="Monster 1_Right.png"
}
else if(m1X == 700)
{
m1MoveLeft = true;
monster1.src ="Monster1_Left.png"
}
if(m2X == 600)
{
m2MoveRight = false;
monster2.src ="Monster2_left.png"
}
else if(m2X == 100)
{
m2MoveRight = true;
monster2.src ="Monster 2_Right.png"
}
if(m3X == 500)
{
m3MoveRight = false;
monster3.src ="Monster 3_left.png"
}
else if(m3X == 100)
{
m3MoveRight = true;
monster3.src ="Monster3_Right.png"
}
}
}
// Create gradient
var gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
gradient.addColorStop("0", "black");
gradient.addColorStop("0.5", "red");
gradient.addColorStop("1.0", "white");
//Draw Score Area
function displayScoreArea() {
ctx.font = "40px Arial";
ctx.strokeStyle = gradient;
ctx.fillStyle = gradient;
ctx.strokeText(killCounter, 380, 60);
ctx.strokeText(life, 65, 45);
ctx.strokeText(keyCounter, 65, 90);
}
animation();
function moveup()
{
upPressed = true;
}
function movedown()
{
downPressed = true;
}
function moveright()
{
rightPressed = true;
}
function moveleft()
{
leftPressed = true;
}
function shootGun()
{
moveBullet = true;
fireAudio.play();
bulletX = heroX + 10;
bulletY = heroY + (heroHeight / 2);
console.log("BulletX = " + bulletX);
}
</script>
<div style="text-align:center;width:900px;">
<button style="width: 100px; height: 60px;" onclick="moveup()">UP</button><br><br>
<button style="width: 100px; height: 60px;" onclick="moveleft()">LEFT</button>
<button style="width: 100px; height: 60px; margin-left: 20px;" onclick="moveright()">RIGHT</button><br><br>
<button style="width: 100px; height: 60px;" onclick="movedown()">DOWN</button>
<button style="width: 100px; height: 60px;" onclick="shootGun()">SHOOT</button>
</div>
</body>
</html>
Using objects would be one (of many) steps in the right direction. Even without them, you could:
In your bullet variable creation
...
//Bullet Attribute
let bulletX;
let bulletY;
let bulletVelocity;
...
In your hero control function, where the firing action currently takes place, initialize your bullet properties once
...
//Keyboard Cotrolls
function heroControl(event) { //event handler function
if (event.keyCode == 32) { //SPACE BAR PRESSED - fire gun
moveBullet = true;
fireAudio.play();
bulletX = heroX + 10;
bulletY = heroY + (heroHeight / 2);
// Initialize bullet velocity
let s = heroPic.src.substring(heroPic.src.lastIndexOf("/") + 1);
//alert(s);
if (s == "Protagenist_Right_Jet.png" || s == "Protagenist_Stand_Jet.png") {
bulletVelocity = 20;
} else {
bulletVelocity = -20;
}
...
In your animation function, where this currently takes place, update your bullet position according to its velocity
...
if (moveBullet) {
bulletX += bulletVelocity;
if (bulletX >= canvas.width) {
...
There are lots of things I would refactor in your current setup, but this should get you moving on your current problem.
And a quick example of a very simple object:
// create with key: value pairs
let bullet = {
x: 0,
y: 0,
velocity: 0,
};
// Access or set properties using dot notation
bullet.x = heroX + 10;
bullet.y = heroY + (heroHeight / 2);

Javascript Collision (Not Collision Detection)

I'm trying to make a platforming game, and I've been working on the collision for the past 2 weeks. The collision detection is working, but the collision itself (as in, keeping the player out of the tile) is not, no matter what I try. I've tried looking up how to do this, but all I'm finding is how to do the detection part, which I already have done. What do I do after I detect collision?
It was written from scratch, and the player is rectangular, and so are the tiles.
Here's the basic code:
var Player = function(hue, x, y, xSize, ySize, health) {
this.hue = hue;
this.position = new PVector(x, y);
this.originalPosition = new PVector(x, y);
//this.previousPosition = new PVector(x, y);
//this.ppp = new PVector(x, y);
//this.virtualPosition = new PVector(x, y);
//this.predictedPosition = new PVector(x, y);
this.velocity = new PVector(0, 0);
//this.predictedVelocity = new PVector(0, 0);
this.acceleration = new PVector(0, 0);
}
/*Player.prototype.testCollision = function(tile) {
if (this.predictedPosition.y < tile.position.y + tile.size.y && this.predictedPosition.y + this.size.y > tile.size.y && this.predictedPosition.x < tile.position.x + tile.size.x && this.predictedPosition.x + tile.size.x > tile.position.x) {
return false;
} else {
return true;
}
};*/
Player.prototype.ifColliding = function(tile) {
if (this.position.x < tile.position.x + tile.size.x && this.position.x + tile.size.x > tile.position.x) {
/*if (this.position.x + this.size.x > tile.position.x) {
this.position.set(tile.position.x - this.size.x, this.position.y);
} else if (this.position.x < tile.position.x + tile.size.x) {
this.position.set(tile.position.x + tile.size.x, this.position.y);
}*/
this.velocity.set(0, this.velocity.y);
//this.acceleration.set(0, this.acceleration.y);
/*if (this.ppp.x < tile.position.x + tile.size.x && this.ppp.x + tile.size.x > tile.position.x) {
if (this.ppp.x + this.size.x > tile.position.x) {
this.position.set(tile.position.x - this.size.x, this.position.y);
} else if (this.ppp.x < tile.position.x + tile.size.x) {
this.position.set(tile.position.x + tile.size.x, this.position.y);
}
} else if (this.previousPosition.x < tile.position.x + tile.size.x && this.previousPosition.x + tile.size.x > tile.position.x) {
this.position.set(this.ppp.x, this.position.y);
} else {
this.position.set(this.previousPosition.x, this.position.y);
}*/
}
if (this.position.y < tile.position.y + tile.size.y && this.position.y + this.size.y > tile.size.y) {
this.velocity.set(this.velocity.x, 0);
this.acceleration.set(this.acceleration.x, 0);
this.yColliding = true;
/*if (this.position.y + this.size.y > tile.position.y) {
this.position.set(this.position.x, tile.position.y - this.size.y);
rect(0, 20, 0, 0);
} else if (this.position.y < tile.position.y + tile.size.y) {
this.position.set(this.position.x, tile.position.y + tile.size.y);
rect(20, 20, 0, 0);
}*/
}
}
Player.prototype.update = function(tiles) {
//this.ppp.set(this.previousPosition.x, this.previousPosition.y);
//this.previousPosition.set(this.position.x, this.position.y);
this.velocity.add(this.acceleration);
/*this.predictedVelocity.set(this.velocity.x, this.velocity.y);
this.predictedVelocity.add(this.acceleration);
this.virtualPosition.set(this.position.x, this.position.y);
this.virtualPosition.add(this.velocity);
this.predictedPosition.set(this.virtualPosition.x, this.virtualPosition.y);
this.predictedPosition.add(this.predictedVelocity);
var collDcted = false;
for (var i = 0; i < tiles.length; i++) {
if (this.testCollision(tiles[i], true) === false) {
collDcted = false;
}
}*/
//if (collDcted) {
this.position.add(this.velocity);
//}
}
The commented out code is failed attempts. The non-commented code is the closest I could get it to working.
This is a sample collision I made:
<!DOCTYPE html>
<html>
<body>
<p id="Health">Health</p>
<canvas id="gameCanvas" width="600" height="480" style = "border:1px solid gray"></canvas>
<script>
// Adding keyboard evt listener
document.addEventListener("keydown", keyPressed);
document.addEventListener("keyup", keyReleased);
//defining canvas
var canvas;
var canvasContext;
//defining Player variables
var PLAYER_X = 100;
var PLAYER_Y = 100;
var PLAYER_WIDTH = 20;
var PLAYER_HEIGHT = 20;
var PLAYER_HEALTH = 100;
//defining keypress codes
var KEY_LEFT = 37;
var KEY_RIGHT = 39;
var KEY_UP = 38;
var KEY_DOWN = 40;
//variables used to test movement
var keyHeld_Up = false;
var keyHeld_Down = false;
var keyHeld_Left = false;
var keyHeld_Right = false;
//Keypress?
function keyPressed(evt) {
if(evt.keyCode == KEY_UP) {
keyHeld_Up = true;
}
if(evt.keyCode == KEY_DOWN) {
keyHeld_Down = true;
}
if(evt.keyCode == KEY_LEFT) {
keyHeld_Left = true;
}
if(evt.keyCode == KEY_RIGHT) {
keyHeld_Right = true;
}
//prevents page from scrolling when arrow keys are pressed
evt.preventDefault();
}
//Key Released?
function keyReleased(evt) {
if(evt.keyCode == KEY_UP) {
keyHeld_Up = false;
}
if(evt.keyCode == KEY_DOWN) {
keyHeld_Down = false;
}
if(evt.keyCode == KEY_LEFT) {
keyHeld_Left = false;
}
if(evt.keyCode == KEY_RIGHT) {
keyHeld_Right = false;
}
}
//Initialize Canvas and Game Loop
window.onload = function() {
console.log("Is this thing on?");
canvas = document.getElementById('gameCanvas');
canvasContext = canvas.getContext('2d');
var framesPerSecond = 30;
setInterval(function() {
drawObjects();
movePlayer();
damageTest();
}, 1000/framesPerSecond);
}
// Drawing function
function colorRect(x,y, width,height, color, health) {
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.color = color;
this.health = health;
this.update = function() {
this.draw();
}
this.draw = function() {
canvasContext.beginPath();
canvasContext.rect(this.x, this.y, this.width, this.height);
canvasContext.fillStyle = this.color;
canvasContext.fill();
canvasContext.closePath();
}
};
// Creating Objects
var Screen = new colorRect( 0, 0, 600, 480, 'black', 0);
var Player = new colorRect( PLAYER_X, PLAYER_Y, PLAYER_WIDTH, PLAYER_HEIGHT, 'red', PLAYER_HEALTH);
var Box = new colorRect( 200, 200, 30, 30, 'green', 0);
var Spike = new colorRect( 300, 300, 25, 25, 'white', 0);
// Drawing Objects
function drawObjects() {
Screen.update();
Spike.update();
Player.update();
Box.update();
}
//Collision Test
function collides( a, b ) {
return a.x < b.x + b.width &&
a.x + a.width > b.x &&
a.y < b.y + b.height &&
a.y + a.height > b.y;
}
//Movement based on keypress events
function movePlayer() {
if(collides( Player, Box ) === false) {
if(keyHeld_Up) {
Player.y -= 2;
}
if(keyHeld_Down) {
Player.y += 2;
}
if(keyHeld_Left) {
Player.x -= 2;
}
if(keyHeld_Right) {
Player.x += 2;
}
}
}
//Testing Collision for damage
function damageTest() {
if(collides( Player, Spike ) === true) {
Player.health -= 1;
}
//Displaying Health in <body>
document.getElementById("Health").innerHTML = "Health: " + Player.health;
}
</script>
</body>
</html>
The code I made stops the player in its tracks completely when hitting the box, but you could create individual collision circumstances for when objects collide on each side of another object, and use those to detect collision.
I hope this helped! If you have any questions regarding this code, just ask! (To run code snippet you might want to go full screen and click inside 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.

Categories