Related
I'm using Javascript to make a game and my character is supposed to move a box only when it's touching the box, but it always moves and when my character is on the same y-axis as the right side of of the box the game freezes, even if my character is not touching the right side of the box. I only coded the box to be able to be pushed left so far. I want to make sure that it can move left properly before I move on to making it be able to move elsewhere. My character does not move, instead everything but the character moves to make it seem like its moving without having to have different areas and stuff. There is code for other things, but its not used so I can isolate the code for the box. My code is mostly Javascript but does have a little bit of html.
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>
canvas {
border:1px solid #d3d3d3;
background-color: #f1f1f1;
}
</style>
</head>
<body onload="startGame()">
<script src="script2.js"></script>
</body>
</html>
var wall
var myGamePiece;
var myObstacle;
var object1;
var objects;
var box;
function startGame() {
//creation of objects
wall = new component(30, 100, "black", 300, 200);
myGamePiece = new component(30, 30, "red", 240, 135);
myObstacle = new component(100, 100, "green", 200, 100);
myMap = new component(0, 0, "map.jpeg", -100, -100, "image")
object1 = new component(30, 30, "gray", 340, 125);
box = new component(30, 30, "blue", 290, 145);
myGameArea.start();
}
var myGameArea = {
canvas : document.createElement("canvas"),
start : function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.interval = setInterval(updateGameArea, 20);
window.addEventListener('keydown', function (e) {
myGameArea.key = e.keyCode;
})
window.addEventListener('keyup', function (e) {
myGameArea.key = false;
})
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
},
collide : function() {
object1.x += 1;
object1.y += 1;
},
boxup : function() {
box.x -= 1;
}
}
function component(width, height, color, x, y, type) {
this.type = type;
if (type == "image") {
this.image = new Image();
this.image.src = color;
}
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
if (type == "image") {
ctx.drawImage(this.image,
this.x,
this.y,
this.width,
this.height);
} else {
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
}
this.crashWith = function(object1) {
var myleft = this.x;
var myright = this.x + (this.width);
var mytop = this.y;
var mybottom = this.y + (this.height);
var otherleft = object1.x;
var otherright = object1.x + (object1.width);
var othertop = object1.y;
var otherbottom = object1.y + (object1.height);
var crash = true;
if ((mybottom < othertop) ||
(mytop > otherbottom) ||
(myright < otherleft) ||
(myleft > otherright)) {
crash = false;
}
return crash;
}
this.pushboxleftWith = function(box) {
var myleft = this.x;
var myright = this.x + (this.width);
var mytop = this.y;
var mybottom = this.y + (this.height);
var boxleft = box.x;
var boxright = box.x + (box.width);
var boxtop = box.y;
var boxbottom = box.y + (box.height);
var pushboxdown = true;
var pushboxup = true;
var pushboxleft = true;
var pushboxright = true;
if (mybottom < boxtop) {
pushboxdown = true;
}
if (mytop > boxbottom) {
pushboxup = true;
}
if (myright < boxleft) {
pushboxright = true;
}
if ((myleft > boxright) && (((myBottom <= boxtop) && (myBottom >= boxbottom)) || ((myTop <= boxtop) && (myTop >= boxbottom)))) {
pushboxleft = false;
}
return pushboxleft;
return pushboxright;
return pushboxdown;
return pushboxup;
}
}
function updateGameArea() {
if (myGamePiece.crashWith(object1)) {
myGameArea.collide();
} else {
if (myGamePiece.pushboxleftWith(box)) {
myGameArea.boxup();
}
myGameArea.clear();
myGamePiece.speedX = 0;
myGamePiece.speedY = 0;
//keyboard controls. work but look ugly. moves everything but the player
if (myGameArea.key && myGameArea.key == 37) {myObstacle.x += 2; myMap.x += 2;object1.x+=2; box.x += 2; wall.x += 2;}
if (myGameArea.key && myGameArea.key == 39) {myObstacle.x += -2; myMap.x += -2; object1.x+=-2; box.x += -2; wall.x += -2;}
if (myGameArea.key && myGameArea.key == 38) {myObstacle.y += 2; myMap.y += 2; object1.y+=2; box.y += 2; wall.y += 2}
if (myGameArea.key && myGameArea.key == 40) {myObstacle.y+=-2; object1.y += -2; myMap.y += -2; box.y += -2; wall.y += -2}
//other square movement. disabled to isolate code.
/*
if (object1.x < myGamePiece.x) {
object1.x += 1;
}
if (object1.x > myGamePiece.x) {
object1.x += -1;
}
if (object1.y < myGamePiece.y) {
object1.y += 1;
}
if (object1.y > myGamePiece.y) {
object1.y += -1;
}
*/
/* object order: the object that is higher on the list
will be on top of objects lower on the list
*/
myMap.update();
myObstacle.update();
myGamePiece.newPos();
myGamePiece.update();
wall.update();
object1.update();
box.update();
//end of list
}
}```
My game piece won't move properly and freezes the game
As Baro pointed out, JavaScript variables are case-sensitive, meaning mybottom and myBottom are completely different variables. So when you tried to access myBottom, having only set mybottom, you got an error. Your game froze because you were running that code in your set interval, every 20 milliseconds.
Here is a working version of your code that you can play around with. I have refactored it a little:
let objects;
let wall = new component(30, 100, "black", 300, 200);
let myGamePiece = new component(30, 30, "red", 240, 135);
let myObstacle = new component(100, 100, "green", 200, 100);
let myMap = new component(0, 0, "orange", -100, -100)
let object1 = new component(30, 30, "gray", 340, 125);
let box = new component(30, 30, "blue", 290, 145);
const myGameArea = {
canvas: document.querySelector("#game-area"),
start: function() {
this.context = this.canvas.getContext("2d");
this.interval = setInterval(updateGameArea, 20);
window.addEventListener('keydown', function(e) {
myGameArea.key = e.keyCode;
})
window.addEventListener('keyup', function(e) {
myGameArea.key = false;
})
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
},
collide: function() {
object1.x += 1;
object1.y += 1;
},
boxup: function() {
box.x -= 1;
}
}
myGameArea.start();
function component(width, height, color, x, y) {
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
}
this.crashWith = function(object1) {
let myleft = this.x;
let myright = this.x + (this.width);
let mytop = this.y;
let mybottom = this.y + (this.height);
let otherleft = object1.x;
let otherright = object1.x + (object1.width);
let othertop = object1.y;
let otherbottom = object1.y + (object1.height);
let crash = true;
if ((mybottom < othertop) ||
(mytop > otherbottom) ||
(myright < otherleft) ||
(myleft > otherright)) {
crash = false;
}
return crash;
}
this.pushboxleftWith = function(box) {
let myleft = this.x;
let myright = this.x + (this.width);
let mytop = this.y;
let mybottom = this.y + (this.height);
let boxleft = box.x;
let boxright = box.x + (box.width);
let boxtop = box.y;
let boxbottom = box.y + (box.height);
let pushboxdown = true;
let pushboxup = true;
let pushboxleft = true;
let pushboxright = true;
if (mybottom < boxtop) pushboxdown = true;
if (mytop > boxbottom) pushboxup = true;
if (myright < boxleft) pushboxright = true;
if ((myleft > boxright) && (((mybottom <= boxtop) && (mybottom >= boxbottom)) || ((mytop <= boxtop) && (mytop >= boxbottom)))) {
pushboxleft = false;
}
return pushboxleft;
return pushboxright;
return pushboxdown;
return pushboxup;
}
}
function updateGameArea() {
if (myGamePiece.crashWith(object1)) {
myGameArea.collide();
} else {
if (myGamePiece.pushboxleftWith(box)) {
myGameArea.boxup();
}
myGameArea.clear();
myGamePiece.speedX = 0;
myGamePiece.speedY = 0;
//keyboard controls. moves everything but the player
if (myGameArea.key && myGameArea.key == 37) {
myObstacle.x += 2;
myMap.x += 2;
object1.x += 2;
box.x += 2;
wall.x += 2;
}
if (myGameArea.key && myGameArea.key == 39) {
myObstacle.x += -2;
myMap.x += -2;
object1.x += -2;
box.x += -2;
wall.x += -2;
}
if (myGameArea.key && myGameArea.key == 38) {
myObstacle.y += 2;
myMap.y += 2;
object1.y += 2;
box.y += 2;
wall.y += 2
}
if (myGameArea.key && myGameArea.key == 40) {
myObstacle.y += -2;
object1.y += -2;
myMap.y += -2;
box.y += -2;
wall.y += -2
}
myMap.update();
myObstacle.update();
myGamePiece.newPos();
myGamePiece.update();
wall.update();
object1.update();
box.update();
}
}
canvas {
border: 1px solid #d3d3d3;
background-color: #f1f1f1;
}
<body>
<script src="script2.js" type="module"></script>
<canvas id="game-area" width="480" height="270"></canvas>
</body>
When the component or square touches the bottom of the canvas and I press the up arrow afterwards it collides with the bottom, every jump the component jumps when I press the up arrow it jumps upwards less and less until the component eventually does not jump at all. But the component at the same time moves left and right perfectly still when this problem occurs.
I am controlling the square with the arrow keys and it is the player for this platform game that i am creating and i have no clue how i can change it.
var myGamePiece;
var platformWidth = 500;
var platformX = 0;
var platformY = 250;
function startGame() {
myGameArea.start();
myGamePiece = new component(30, 30, "red", 10, 120);
}
var myGameArea = {
canvas: document.createElement("canvas"),
start: function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.interval = setInterval(updateGameArea, 20);
window.addEventListener("keydown", function(e) {
myGameArea.key = e.keyCode;
});
window.addEventListener("keyup", function(e) {
myGameArea.key = false;
});
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
};
function component(width, height, color, x, y, type) {
this.type = type;
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.speedX = 0;
this.speedY = 0;
this.gravity = 0.05;
this.gravitySpeed = 0;
this.update = function() {
ctx = myGameArea.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
};
this.newPos = function() {
this.gravitySpeed += this.gravity;
this.x += this.speedX;
this.y += this.speedY + this.gravitySpeed;
this.hitBottom();
};
this.hitBottom = function() {
var rockbottom = myGameArea.canvas.height - this.height;
if (this.y > rockbottom) {
this.y = rockbottom;
if (myGameArea.canvas.height - this.height && myGamePiece.key == 38) {
this.y = this.speedY;
}
}
};
}
function updateGameArea() {
myGameArea.clear();
myGamePiece.speedX = 0;
myGamePiece.speedY = 0;
if (myGameArea.key && myGameArea.key == 37) {
myGamePiece.speedX = -5;
}
if (myGameArea.key && myGameArea.key == 39) {
myGamePiece.speedX = 5;
}
if (myGameArea.key && myGameArea.key == 38) {
myGamePiece.speedY = -5;
} else {
myGamePiece.speedY = 5;
}
if (myGameArea.key && myGameArea.key == 40) {
myGamePiece.speedY = 5;
}
myGamePiece.newPos();
myGamePiece.update();
}
startGame();
Did you forget to reset the gravity speed?
this.hitBottom = function() {
// ...
if (this.y > rockbottom) {
// ...
this.gravitySpeed = 0; // reset?
}
};
var myGamePiece;
var platformWidth = 360;
var platformX = 0;
var platformY = 120;
function startGame() {
myGameArea.start();
myGamePiece = new Component(12, 12, "red", 10, 10);
}
var myGameArea = {
canvas: document.createElement("canvas"),
start: function() {
this.canvas.width = platformWidth;
this.canvas.height = platformY;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.interval = setInterval(updateGameArea, 20);
window.addEventListener("keydown", function(e) {
myGameArea.key = e.keyCode;
});
window.addEventListener("keyup", function(e) {
myGameArea.key = false;
});
},
fill: function(color) {
this.context.save();
this.context.fillStyle = color;
this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
this.context.restore();
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
};
function Component(width, height, color, x, y, type) {
this.type = type;
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.speedX = 0;
this.speedY = 0;
this.gravity = 0.05;
this.gravitySpeed = 0;
this.update = function() {
ctx = myGameArea.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
};
this.newPos = function() {
this.gravitySpeed += this.gravity;
this.x += this.speedX;
this.y += this.speedY + this.gravitySpeed;
this.hitBottom();
};
this.hitBottom = function() {
var rockbottom = myGameArea.canvas.height - this.height;
if (this.y > rockbottom) {
this.y = rockbottom;
if (myGameArea.canvas.height - this.height && myGamePiece.key == 38) {
this.y = this.speedY;
}
this.gravitySpeed = 0; // reset?
}
};
}
function updateGameArea() {
myGameArea.fill('#DE7');
myGamePiece.speedX = 0;
myGamePiece.speedY = 0;
if (myGameArea.key) {
switch (myGameArea.key) {
case 37: // left arrow
myGamePiece.speedX = -5;
break;
case 38: // up arrow
myGamePiece.speedY = -5;
break;
case 39: // right arrow
myGamePiece.speedX = +5;
break;
case 40: // down arrow
default:
myGamePiece.speedY = +5;
}
}
myGamePiece.newPos();
myGamePiece.update();
}
startGame();
body {
background: #000;
}
Here is another approach using classes, you can clean up the vector math, by using actual vector classes e.g. Victor.js.
const main = () => {
new GravityGame({
width : 360,
height : 180,
refreshRate : 20
}).start();
}
class AbstractGameClient {
constructor(options) {
this.refreshRate = options.refreshRate
this.view = new GameArea({
width : options.width,
height : options.height
})
}
update() {
this.view.update()
}
start() {
let self = this
self.intervalId = setInterval(function() { self.update() }, self.refreshRate)
return self
}
stop() {
if (self.intervalId) {
clearInterval(self.intervalId)
}
}
}
class GravityGame extends AbstractGameClient {
constructor(options) {
super(options)
let myGamePiece = new Component({
width : 12,
height : 12,
color : 'red'
})
this.view.addComponent(myGamePiece)
}
}
class GameArea {
constructor(options) {
let self = this
self.canvas = document.createElement('canvas')
self.width = options.width
self.height = options.height
self.key = null
self.components = []
self.addListeners()
self.render()
}
render() {
let self = this
self.canvas.width = self.width
self.canvas.height = self.height
self.context = self.canvas.getContext('2d')
document.body.insertBefore(self.canvas, document.body.childNodes[0])
}
addComponent(component) {
this.centerComponent(component)
this.components.push(component)
}
addListeners() {
let self = this;
window.addEventListener('keydown', function(e) {
self.key = e.keyCode;
});
window.addEventListener('keyup', function(e) {
self.key = false;
});
}
fill(color) {
this.context.save();
this.context.fillStyle = color;
this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
this.context.restore();
}
clear() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
update() {
let self = this
let speed = { x : 0, y : 0 }
if (self.key) {
switch (self.key) {
case 37: // left arrow
speed.x = -5;
break;
case 38: // up arrow
speed.y = -5;
break;
case 39: // right arrow
speed.x = +5;
break;
case 40: // down arrow
default:
speed.y = +5;
}
}
self.fill('#DE7')
self.components.forEach(component => {
component.speed.x = speed.x
component.speed.y = speed.y
component.reposition(self.context)
component.redraw(self.context)
})
}
centerComponent(component) {
let xOffset = Math.floor((this.canvas.width / 2) - component.width / 2)
let yOffset = Math.floor((this.canvas.height / 2) - component.height / 2)
component.position = { x : xOffset, y : yOffset }
}
};
class Component {
constructor(options) {
let self = this
self.width = options.width
self.height = options.height
self.position = options.position
self.color = options.color
self.type = options.type
self.speed = { x : 0, y : 0 }
self.gravity = { x : 0, y : 0.05 };
self.acceleration = { x : 0, y : 0 };
}
redraw(context) {
context.fillStyle = this.color;
context.fillRect(this.position.x, this.position.y, this.width, this.height);
}
reposition(context) {
let self = this
// Increase acceleration
self.acceleration.x += self.gravity.x;
self.acceleration.y += self.gravity.y;
// pos + speed + acceleration
self.position.x += self.speed.x + self.acceleration.x;
self.position.y += self.speed.y + self.acceleration.y;
self.checkBounds(context);
}
checkBounds(context) {
let self = this
let rockbottom = context.canvas.height - this.height
if (self.position.y > rockbottom) {
self.position.y = rockbottom
if (context.canvas.height - self.height && self.key == 38) {
self.position.y = self.speed.y
}
self.acceleration = { x : 0, y : 0 } // reset
}
}
}
main();
body {
background: #000;
}
Im trying to make a function that when hitting a enemy makes that bullet in the array disappear.
Ive tried useing pop, slice, shift but i cant get those to work.
the closest thing Ive found is to just make the array empty but it really should be the array -1 or minus that bullet.
js fiddle: https://jsfiddle.net/tmanrocks999/64thbvm3/309/
code:
var myGamePiece;
var endGoalPiece;
var myEnemy1;
var bullets = [];
var myEnemy1Hp = 10;
var myEnemy1Armor = 0;
var damage = 1;
var playerExp = 0;
var playerMaxExp = 10;
function startGame() {
myGameArea.start();
myGamePiece = new component(30, 30, 'red', 0, 240);
endGoalPiece = new component(30, 30, 'black', 450, 240);
myEnemy1 = new component(30, 30, 'green', 200, 240);
}
var myGameArea = {
canvas: document.createElement('canvas'),
start: function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext('2d');
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.interval = setInterval(updateGameArea, 20);
window.addEventListener('keydown', function(e) {
myGameArea.key = e.keyCode;
})
window.addEventListener('keyup', function(e) {
myGameArea.key = false;
})
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
};
function component(width, height, color, x, y) {
this.gamearea = myGameArea;
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
//this.gravity = 0.05;
//this.gravitySpeed = 0;
this.x = x;
this.y = y;
this.color = color;
this.update = function() {
ctx = myGameArea.context;
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.newPos = function() {
this.gravitySpeed += this.gravity;
this.x += this.speedX;
this.y += this.speedY; //+ this.gravitySpeed;
this.hitBottom();
this.hitTop();
this.hitRight();
this.hitLeft();
this.hitObject();
}
this.hitBottom = function() {
var rockbottom = myGameArea.canvas.height - this.height;
if (this.y > rockbottom) {
this.y = rockbottom;
}
}
this.hitTop = function() {
var rockTop = 0;
if (this.y < rockTop) {
this.y = rockTop;
}
}
this.hitRight = function() {
var rockRight = myGameArea.canvas.width - this.width;
if (this.x > rockRight) {
this.x = rockRight;
}
}
this.hitLeft = function() {
var rockLeft = 0;
if (this.x < rockLeft) {
this.x = rockLeft;
}
}
function enemyRespawn() {
myEnemy1 = new component(30, 30, "green", 200, 240);
myEnemy1Hp = 10;
document.getElementById('myEnemy1Hp').innerHTML = myEnemy1Hp;
}
this.hitObject = function() {
myGamePiece.update();
var enemy = myEnemy1.x - 11;
if (this.x == enemy) {
myEnemy1Hp = myEnemy1Hp - (damage - myEnemy1Armor);
bullets = [];
document.getElementById('myEnemy1Hp').innerHTML = myEnemy1Hp;
if (myEnemy1Hp <=0) {
myEnemy1Hp = 0;
document.getElementById('myEnemy1Hp').innerHTML = myEnemy1Hp;
playerExp = playerExp+1;
document.getElementById('playerExp').innerHTML = playerExp;
if (playerExp >= playerMaxExp) {
playerExp = 0;
playerMaxExp = playerMaxExp * 1.5;
damage = damage + 1;
document.getElementById('playerExp').innerHTML = playerExp;
document.getElementById('playerMaxExp').innerHTML = playerMaxExp;
}
myEnemy1 = new component(0, 0, 'green', 0, 0);
myEnemy1.update();
setTimeout(enemyRespawn, 5000);
}
}
}
}
function shootGun() {
let bullet = new component(11, 5, 'blue', myGamePiece.x + 27, myGamePiece.y + 13);
bullet.newPos();
bullet.speedX = 1;
bullets.push(bullet);
}
function updateGameArea() {
myGameArea.clear();
myGamePiece.speedX = 0;
myGamePiece.speedY = 0;
if (myGameArea.key && myGameArea.key == 37) {
myGamePiece.speedX = -1;
} //left
if (myGameArea.key && myGameArea.key == 39) {
myGamePiece.speedX = 1;
} //right
if (myGameArea.key && myGameArea.key == 38) {
myGamePiece.gravitySpeed = -1;
} //jump
if (myGameArea.key && myGameArea.key == 32) {
shootGun()
} //shoot gun
//if (myGameArea.key && myGameArea.key == 40) {myGamePiece.speedY = 1; }// down
myEnemy1.update();
endGoalPiece.update();
myGamePiece.newPos();
myGamePiece.update();
bullets.forEach((bullet) => {
bullet.newPos()
bullet.update();
});
// bullet.newPos();
// bullet.update();
}
startGame();
canvas {
border: 4px solid #d3d3d3;
background-color: #f1f1f1;
}
<p>use the arrow keys on you keyboard to move the red square.</p>
<span id="myEnemy1Hp">10</span> <br>
<span id="playerExp">0</span> / <span id="playerMaxExp">10</span> 🐺
I expect when the bullet hit the enemy for it to disappear then enemy takes 1 damage. but at the moment this works but if u have more then 1 bullet on the screen all the bullets disappear when 1 hits the enemy. How do i make it current bullet or array = array -1
I believe you are looking for array.splice()
In the context of your hitObject method, the code would look like this:
bullets.splice(bullets.indexOf(this), 1);
Also, there are a ton of notes in my answer to a similar question which you may find useful.
...and here's your updated game:
var myGamePiece;
var endGoalPiece;
var myEnemy1;
var bullets = [];
var myEnemy1Hp = 10;
var myEnemy1Armor = 0;
var damage = 1;
var playerExp = 0;
var playerMaxExp = 10;
function startGame() {
myGameArea.start();
myGamePiece = new component(30, 30, 'red', 0, 240);
endGoalPiece = new component(30, 30, 'black', 450, 240);
myEnemy1 = new component(30, 30, 'green', 200, 240);
}
var myGameArea = {
canvas: document.createElement('canvas'),
start: function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext('2d');
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.interval = setInterval(updateGameArea, 20);
window.addEventListener('keydown', function(e) {
myGameArea.key = e.keyCode;
})
window.addEventListener('keyup', function(e) {
myGameArea.key = false;
})
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
};
function component(width, height, color, x, y) {
this.gamearea = myGameArea;
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
//this.gravity = 0.05;
//this.gravitySpeed = 0;
this.x = x;
this.y = y;
this.color = color;
this.update = function() {
ctx = myGameArea.context;
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.newPos = function() {
this.gravitySpeed += this.gravity;
this.x += this.speedX;
this.y += this.speedY; //+ this.gravitySpeed;
this.hitBottom();
this.hitTop();
this.hitRight();
this.hitLeft();
this.hitObject();
}
this.hitBottom = function() {
var rockbottom = myGameArea.canvas.height - this.height;
if (this.y > rockbottom) {
this.y = rockbottom;
}
}
this.hitTop = function() {
var rockTop = 0;
if (this.y < rockTop) {
this.y = rockTop;
}
}
this.hitRight = function() {
var rockRight = myGameArea.canvas.width - this.width;
if (this.x > rockRight) {
this.x = rockRight;
}
}
this.hitLeft = function() {
var rockLeft = 0;
if (this.x < rockLeft) {
this.x = rockLeft;
}
}
function enemyRespawn() {
myEnemy1 = new component(30, 30, 'green', 200, 240);
myEnemy1Hp = 10;
document.getElementById('myEnemy1Hp').innerHTML = myEnemy1Hp;
}
this.hitObject = function() {
myGamePiece.update();
var enemy = myEnemy1.x - 11;
if (this.x == enemy) {
myEnemy1Hp = myEnemy1Hp - (damage - myEnemy1Armor);
// bullets = []; // replaces all bullets
const index = bullets.indexOf(this)
bullets.splice(index, 1)
document.getElementById('myEnemy1Hp').innerHTML = myEnemy1Hp;
if (myEnemy1Hp <= 0) {
myEnemy1Hp = 0;
document.getElementById('myEnemy1Hp').innerHTML = myEnemy1Hp;
playerExp = playerExp + 1;
document.getElementById('playerExp').innerHTML = playerExp;
if (playerExp >= playerMaxExp) {
playerExp = 0;
playerMaxExp = playerMaxExp * 1.5;
damage = damage + 1;
document.getElementById('playerExp').innerHTML = playerExp;
document.getElementById('playerMaxExp').innerHTML = playerMaxExp;
}
myEnemy1 = new component(0, 0, 'green', 0, 0);
myEnemy1.update();
setTimeout(enemyRespawn, 5000);
}
}
}
}
function shootGun() {
let bullet = new component(11, 5, 'blue', myGamePiece.x + 27, myGamePiece.y + 13);
bullet.newPos();
bullet.speedX = 1;
bullets.push(bullet);
}
function updateGameArea() {
myGameArea.clear();
myGamePiece.speedX = 0;
myGamePiece.speedY = 0;
if (myGameArea.key && myGameArea.key == 37) {
myGamePiece.speedX = -1;
} //left
if (myGameArea.key && myGameArea.key == 39) {
myGamePiece.speedX = 1;
} //right
if (myGameArea.key && myGameArea.key == 38) {
myGamePiece.gravitySpeed = -1;
} //jump
if (myGameArea.key && myGameArea.key == 32) {
shootGun()
} //shoot gun
//if (myGameArea.key && myGameArea.key == 40) {myGamePiece.speedY = 1; }// down
myEnemy1.update();
endGoalPiece.update();
myGamePiece.newPos();
myGamePiece.update();
bullets.forEach((bullet) => {
bullet.newPos(); // update and check for collisions
bullet.update();
});
// bullet.newPos();
// bullet.update();
}
startGame();
canvas {
border: 4px solid #d3d3d3;
background-color: #f1f1f1;
}
<p>use the arrow keys on you keyboard to move the red square.</p>
<span id="myEnemy1Hp">10</span> <br>
<span id="playerExp">0</span> / <span id="playerMaxExp">10</span> 🐺
I've been following W3schools tutorial on creating a JavaScript game in a canvas https://www.w3schools.com/graphics/game_obstacles.asp
I've got to the stage where they add an obstacle in. Currently, it has collision detection which stops the game when it hits the wall. I am trying to figure out a way to treat it like a wall where the box could hit it and no longer move that direction and continue the game, making the wall work.
I've previously tried detecting what direction hit the wall and stopping movement that direction, but when I hold down an arrow key it moves through it.
Heres what I've got so far: https://jsfiddle.net/j9cy1mne/1/
<body onload="startGame()">
<script>
var myGamePiece;
var myObstacle;
var speed = 3;
function startGame() {
myGamePiece = new component(30, 30, "red", 10, 120);
myObstacle = new component(10, 200, "green", 300, 120);
myGameArea.start();
}
var myGameArea = {
canvas: document.createElement("canvas"),
start: function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.interval = setInterval(updateGameArea, 20);
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
},
stop: function() {
clearInterval(this.interval);
}
}
function component(width, height, color, x, y) {
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.crashWith = function(otherobj) {
var myleft = this.x;
var myright = this.x + (this.width);
var mytop = this.y;
var mybottom = this.y + (this.height);
var otherleft = otherobj.x;
var otherright = otherobj.x + (otherobj.width);
var othertop = otherobj.y;
var otherbottom = otherobj.y + (otherobj.height);
var crash = true;
if ((mybottom < othertop) || (mytop > otherbottom) || (myright < otherleft) || (myleft > otherright)) {
crash = false;
}
return crash;
}
}
function updateGameArea() {
if (myGamePiece.crashWith(myObstacle)) {
console.log("crash");
} else {
myGameArea.clear();
myObstacle.update();
myGamePiece.x += myGamePiece.speedX;
myGamePiece.y += myGamePiece.speedY;
myGamePiece.update();
}
}
document.onkeydown = checkKeyD;
function checkKeyD(e) {
e = e || window.event;
if (e.keyCode == '38') {
// up arrow
myGamePiece.speedY = -speed;
} else if (e.keyCode == '40') {
// down arrow
myGamePiece.speedY = speed;
} else if (e.keyCode == '37') {
// left arrow
myGamePiece.speedX = -speed;
} else if (e.keyCode == '39') {
// right arrow
myGamePiece.speedX = speed;
}
}
document.onkeyup = clearmove;
function clearmove() {
myGamePiece.speedX = 0;
myGamePiece.speedY = 0;
}
</script>
</body>
The problem is here:
if (myGamePiece.crashWith(myObstacle)) {
console.log("crash");
} else {
In a real physics engine you detect collisions then you resolve collisions. The simplest "resolve collision" would be to move the piece back to the place it was before the crash. Something like:
if (myGamePiece.crashWith(myObstacle)) {
resolveCollision(myGamePiece, myObstacle);
} else {
But to do this you'll need to modify your physics engine, and your movement function to use a velocity vector. That means that instead of function checkKeyD(e) moving the piece, that function sets a velocity vector. Then crashWith() will determine if the position plus the velocity vector is going to crash and resolve collision will un-crash it.
I'm new to programming and I tried to make a game. You move a red block and when you hit a green block the you go back to (0,0) and the green block goes to a random location.
Now my question is how do I put a score counter in the game when I hit the green block that it counts +1.
var myGamePiece;
var myObstacle;
function startGame() {
myGamePiece = new component(40, 40, "red", 0, 0);
myObstacle = new component(40, 40, "green", Math.floor((Math.random() *
560) +
0), Math.floor((Math.random() * 360) + 0));
myGameArea.start();
}
var myGameArea = {
canvas: document.createElement("canvas"),
start: function() {
this.canvas.width = 600;
this.canvas.height = 400;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.interval = setInterval(updateGameArea, 20);
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
},
stop: function() {
clearInterval(this.interval);
}
}
function component(width, height, color, x, y) {
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.crashWith = function(otherobj) {
var myleft = this.x;
var myright = this.x + (this.width);
var mytop = this.y;
var mybottom = this.y + (this.height);
var otherleft = otherobj.x;
var otherright = otherobj.x + (otherobj.width);
var othertop = otherobj.y;
var otherbottom = otherobj.y + (otherobj.height);
var crash = true;
if ((mybottom < othertop) || (mytop > otherbottom) || (myright <
otherleft) || (myleft > otherright)) {
crash = false;
}
return crash;
}
}
function updateGameArea() {
if (myGamePiece.crashWith(myObstacle)) {
return startGame();
} else {
myGameArea.clear();
myObstacle.update();
myGamePiece.x += myGamePiece.speedX;
myGamePiece.y += myGamePiece.speedY;
myGamePiece.update();
if (myGamePiece.x >= 580) {
myGamePiece.x -= 20;
}
if (myGamePiece.x <= -20) {
myGamePiece.x += 20;
}
if (myGamePiece.y <= -20) {
myGamePiece.y += 20;
}
if (myGamePiece.y >= 380) {
myGamePiece.y -= 20;
}
}
}
function anim(e) {
if (e.keyCode == 39) {
myGamePiece.speedX = 1;
myGamePiece.speedY = 0;
}
if (e.keyCode == 37) {
myGamePiece.speedX = -1;
myGamePiece.speedY = 0;
}
if (e.keyCode == 40) {
myGamePiece.speedY = 1;
myGamePiece.speedX = 0;
}
if (e.keyCode == 38) {
myGamePiece.speedY = -1;
myGamePiece.speedX = 0;
}
if (e.keyCode == 32) {
myGamePiece.speedY = 0;
myGamePiece.speedX = 0;
}
}
document.onkeydown = anim;
window.onload=startGame();
canvas {
border: 1px solid #d3d3d3;
background-color: #f1f1f1;
}
<button onmousedown="anim(e)" onmouseup="clearmove()" ontouchstart="moveup()">Start</button>
<br><br>
<p>press start to start
<br> use the buttons ↑ ↓ → ← on your keyboard to move stop with the space</p>
Changes
Added an <output> tag to display score.
Redefined event handlers/listeners
Details on changes are commented in demo
Demo
// Reference output#score
var score = document.getElementById('score');
// Declare points
var points = 0;
var myGamePiece;
var myObstacle;
function startGame() {
myGamePiece = new component(40, 40, "red", 0, 0);
myObstacle = new component(40, 40, "green", Math.floor((Math.random() *
560) +
0), Math.floor((Math.random() * 360) + 0));
myGameArea.start();
}
var myGameArea = {
canvas: document.createElement("canvas"),
start: function() {
this.canvas.width = 600;
this.canvas.height = 400;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.interval = setInterval(updateGameArea, 20);
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
},
stop: function() {
clearInterval(this.interval);
}
}
function component(width, height, color, x, y) {
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.crashWith = function(otherobj) {
var myleft = this.x;
var myright = this.x + (this.width);
var mytop = this.y;
var mybottom = this.y + (this.height);
var otherleft = otherobj.x;
var otherright = otherobj.x + (otherobj.width);
var othertop = otherobj.y;
var otherbottom = otherobj.y + (otherobj.height);
var crash = true;
if ((mybottom < othertop) || (mytop > otherbottom) || (myright <
otherleft) || (myleft > otherright)) {
crash = false;
}
return crash;
}
}
function updateGameArea() {
if (myGamePiece.crashWith(myObstacle)) {
// Convert points to a real number
points = parseInt(points, 10);
// Increment points
points++;
// Set output#score value to points
score.value = points;
return startGame();
} else {
myGameArea.clear();
myObstacle.update();
myGamePiece.x += myGamePiece.speedX;
myGamePiece.y += myGamePiece.speedY;
myGamePiece.update();
if (myGamePiece.x >= 580) {
myGamePiece.x -= 20;
}
if (myGamePiece.x <= -20) {
myGamePiece.x += 20;
}
if (myGamePiece.y <= -20) {
myGamePiece.y += 20;
}
if (myGamePiece.y >= 380) {
myGamePiece.y -= 20;
}
}
}
function anim(e) {
if (e.keyCode == 39) {
myGamePiece.speedX = 1;
myGamePiece.speedY = 0;
}
if (e.keyCode == 37) {
myGamePiece.speedX = -1;
myGamePiece.speedY = 0;
}
if (e.keyCode == 40) {
myGamePiece.speedY = 1;
myGamePiece.speedX = 0;
}
if (e.keyCode == 38) {
myGamePiece.speedY = -1;
myGamePiece.speedX = 0;
}
if (e.keyCode == 32) {
myGamePiece.speedY = 0;
myGamePiece.speedX = 0;
}
}
/* Set on click handler
|| When event occurs call startGame() / exclude
|| parenthesis
*/
document.onclick = startGame;
/* Register keydown event
|| When event occurs call anim() / exclude parenthesis
*/
document.addEventListener('keydown', anim, false);
/* When a callback is a named function / exclude the
|| parenthesis
*/
window.onload = startGame;
canvas {
border: 1px solid #d3d3d3;
background-color: #f1f1f1;
}
button {
font: inherit;
}
<br><br>
<button id='start'>Start</button>
<br><br>
<label for='score'>Score: </label>
<output id='score'>0</output>
<br><br>
<p>Click <kbd>Start</kbd> button</p>
<p>Use the buttons ↑ ↓ → ← on your keyboard to move stop with the spacebar.</p>
add
var chrashed = 0;
and use
if (myGamePiece.crashWith(myObstacle)) {
crashed++;
showCrashed;
return startGame();
}
https://jsfiddle.net/mplungjan/m4w3ahj1/