I am currently creating a fighting game from scratch using native JavaScript, HTML, and CSS. When I run my button clicks and have them hit each other, the health boxes do not shrink or move.
Question: How can I get my health bars to work in native JS?
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext("2d");
canvas.width = 1024;
canvas.height = 576;
function logMessage(msg) {
document.querySelector('#myMessage').textContent += msg + '. ';
}
//This creates a background
ctx.fillRect(0, 0, canvas.width, canvas.height);
//Changing this value changes how fast the sprites fall
const gravity = 0.7;
class Sprite {
//The curly braces makes it easier to pass values back and forth
constructor({position, velocity, color, offset}) {
this.position = position;
this.velocity = velocity;
this.height = 150;
this.width = 50;
this.lastKey;
this.attackBox = {
position: {
x: this.position.x,
y: this.position.y
},
offset,
width: 100,
height: 50,
color: 'green'
}
this.color = color;
this.isAttacking;
this.health = 100;
}
draw() {
ctx.fillStyle = this.color;
ctx.fillRect(this.position.x, this.position.y, this.width, this.height);
//Attack box: only appears when attacking
if (this.isAttacking) {
ctx.fillStyle = this.attackBox.color;
ctx.fillRect(
this.attackBox.position.x,
this.attackBox.position.y,
this.attackBox.width,
this.attackBox.height
)
}
}
update() {
this.draw();
this.attackBox.position.x = this.position.x - this.attackBox.offset.x;
this.attackBox.position.y = this.position.y;
//This keeps the Sprites from going off the edge of the canvas
this.position.x = Math.max(0, Math.min(canvas.width - this.width, this.position.x + this.velocity.x));
//This stops the sprite from going above the canvas
this.position.y = Math.max(0, Math.min(canvas.height, this.position.y + this.velocity.y));
//Stops the velocity in the y direction if the sprite hits the bottom
if (this.position.y + this.height + this.velocity.y >= canvas.height) {
this.velocity.y = 0;
} else {
this.velocity.y += gravity;
}
}
attack() {
this.isAttacking = true;
setTimeout(() => {
this.isAttacking = false;
}, 100)
}
}
const Player = new Sprite({
position: {
x: 0,
y: 0
},
velocity: {
x: 0,
y: 0
},
offset: {
x: 0,
y: 0
},
color: 'blue'
})
const Enemy = new Sprite({
position: {
x: 400,
y: 100
},
velocity: {
x: 0,
y: 0
},
offset: {
x: 50,
y: 0
},
color: 'red'
})
const keys = {
w: {
pressed: false
},
a: {
pressed: false
},
d: {
pressed: false
},
ArrowUp: {
pressed: false
},
ArrowLeft: {
pressed: false
},
ArrowRight: {
pressed: false
}
}
function rectangularCollision({rectangle1, rectangle2}) {
return (
rectangle1.attackBox.position.x + rectangle1.attackBox.width >= rectangle2.position.x &&
rectangle1.attackBox.position.x <= rectangle2.position.x + rectangle2.width &&
rectangle1.attackBox.position.y + rectangle1.attackBox.height >= rectangle2.position.y &&
rectangle1.attackBox.position.y <= rectangle2.position.y + rectangle2.height &&
rectangle1.isAttacking
)
}
function animate() {
window.requestAnimationFrame(animate);
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, canvas.width, canvas.height);
Player.update();
Enemy.update();
//Player movement
Player.velocity.x = 0;
if (keys.a.pressed == true && Player.lastKey == "a") {
Player.velocity.x = -5;
} else if (keys.d.pressed == true && Player.lastKey == "d") {
Player.velocity.x = 5;
}
//Enemy movement
Enemy.velocity.x = 0;
if (keys.ArrowLeft.pressed == true && Enemy.lastKey == "ArrowLeft") {
Enemy.velocity.x = -5;
} else if (keys.ArrowRight.pressed == true && Enemy.lastKey == "ArrowRight") {
Enemy.velocity.x = 5;
}
//Detect for the player hitting the enemy
if (rectangularCollision({rectangle1: Player, rectangle2: Enemy})) {
Player.isAttacking = false;
Enemy.health -= 20;
document.querySelector('#enemy-health').style.width = Enemy.health;
}
//Detect for thr enemy hitting the player
if (rectangularCollision({rectangle1: Enemy, rectangle2: Player})) {
Enemy.isAttacking = false;
Player.health -= 20;
document.querySelector('#player-health').style.width = Player.health;
}
}
animate();
//Event listeners that move the player when certain keys are pressed
window.addEventListener('keydown', (event) => {
switch (event.key) {
//Player movement
case 'w':
Player.velocity.y = -20;
break;
case 'a':
keys.a.pressed = true;
Player.lastKey = "a";
break
case 'd':
keys.d.pressed = true;
Player.lastKey = "d";
break;
case ' ':
Player.attack();
break;
}
//Enemy movement
switch (event.key) {
case 'ArrowUp':
Enemy.velocity.y = -20;
break;
case 'ArrowRight':
keys.ArrowRight.pressed = true;
Enemy.lastKey = 'ArrowRight'
break
case 'ArrowLeft':
keys.ArrowLeft.pressed = true;
Enemy.lastKey = 'ArrowLeft'
break;
case 'Enter':
Enemy.attack();
break;
}
})
window.addEventListener('keyup', (event) => {
//Player keys
switch (event.key) {
case 'w':
keys.w.pressed = false;
break;
case 'a':
keys.a.pressed = false;
break
case 'd':
keys.d.pressed = false;
break;
}
//Enemy keys
switch (event.key) {
case 'ArrowUp':
keys.ArrowUp.pressed = false;
break;
case 'ArrowLeft':
keys.ArrowLeft.pressed = false;
break
case 'ArrowRight':
keys.ArrowRight.pressed = false;
break;
}
})
* {
box-sizing: border-box;
}
#mother-div {
position: relative;
display: inline-block;
}
#small-container {
position: absolute;
display: flex;
width: 100%;
align-items: center;
padding: 20px;
}
.healthDiv {
position: relative;
height: 30px;
width: 100%;
}
#player-health, #enemy-health {
position: absolute;
background-color: blue;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
#timer {
background-color: red;
width: 100px;
height: 100px;
flex-shrink: 0;
}
#myConsole {
background-color: black;
color: white;
min-height: 100px;
}
<!DOCTYPE html>
<html lang="en">
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE-edge">
<meta name="viewport", content="width=device-width, initial-scale=1.0">
<meta name="author" content="Christian Davis">
<link rel="stylesheet" href="styles.css">
<title>Fighting Game</title>
</head>
<body>
<!--Red container div-->
<div id="mother-div">
<!--Smaller red container div-->
<div id="small-container">
<!--Player Health-->
<div class="healthDiv">
<div id="player-health">
</div>
</div>
<!--Timer-->
<div id="timer">
</div>
<!--Enemy Health-->
<div class="healthDiv">
<div id="enemy-health">
</div>
</div>
</div>
<canvas id="canvas"></canvas>
</div>
<p id="myConsole">> <span id="myMessage"></span></p>
<script src="app.js"></script>
</body>
</html>
What I need to happen is the bars on either side of the box in the center need to shrink their width inward (they need to get thinner and closer to the center box).
2
Answers
After editing my code a little bit, it works perfectly. All I did was change some divs and I also had to separate the enemy health and player health inside of the CSS. The solution proposed by @Harry Hsu gave me a start but did not help entirely.
Finished code:
When setting width/height value, you need unit suffix like "px" if value is not 0