The collision box for Player 1 is recording hits and dropping Player 2 health correctly. Player 2 is not able to detect attack collisions. The code for player 2 is copy and paste from Player 1. All instances of “player.” changed to “enemy.” etc. FYI the determineWinner() function is still in progress, I am aware it’s not in the code currently.
<head>
<style>
* {
box-sizing: border-box;
}
</style>
</head>
<body>
<!--- Red Container Div-->
<div style="position: relative;
display: inline-block;">
<!--- Smaller Container Div-->
<div style="position: absolute;
display: flex;
width: 100%;
align-items: center;
padding: 20px;">
<!--- Player Health --->
<div style="position: relative;
height: 30px;
width: 100%;">
<div style="background-color: rgba(0,0,0,.1);
height: 30px;
width: 100%;
border: 3px solid black;
border-radius: 5px;">
</div>
<div
id="playerHealth"
style="position: absolute;
background: blue;
border-radius: 5px;
top: 0;
right: 0;
bottom: 0;
left: 0;">
</div>
</div>
<!--- Timer --->
<div
id="timer"
style="background-color: red;
border-radius: 20px;
padding: 2px;
height: 100px;
width: 100px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;">
60
</div>
<!--- Enemy Health --->
<div style="position: relative;
height: 30px;
width: 100%;">
<div style="background-color: rgba(0,0,0,.1);
height: 30px;
width: 100%;
border: 3px solid black;
border-radius: 5px;">
</div>
<div
id="enemyHealth"
style="position: absolute;
background: blue;
border-radius: 5px;
top: 0;
right: 0;
bottom: 0;
left: 0;">
</div>
</div>
</div>
<!--- Text Display --->
<div
id="textDisplay"
style="position: absolute;
color: white;
align-items: center;
justify-content: center;
top: 0;
right: 0;
left: 0;
bottom: 0;
display: none;">
Tie
</div>
<canvas></canvas>
</div>
<script src="./js/utils.js"></script>
<script src="./js/classes.js"></script>
<script src="Index.js"></script>
</body>
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
)
};
//determine winner function
function determineWinner({player, enem, timerId}) {
clearTimeout(timerId)
document.querySelector("#textDisplay").style.display = "flex"
if (player.health === enemy.health) {
document.querySelector("#textDisplay").innerHTML = "No Victor"
} else if (player.health > enemy.health) {
document.querySelector("#textDisplay").innerHTML = "Player 1 Wins"
} else if (player.health < enemy.health) {
document.querySelector("#textDisplay").innerHTML = "Player 2 Wins"
}
};
//Timer Function
let timer = 60;
let timerId
function decreaseTimer() {
if (timer > 0) {
timerId = setTimeout(decreaseTimer, 1000)
timer--
document.querySelector("#timer").innerHTML = timer
}
if (timer === 0) {
determineWinner({player, enemy})
}
};
/* Sprite Class */
class Sprite {
constructor({
position,
imageSrc,
scale = 1,
framesMax = 1,
offset = {x: 0, y: 0},
}) {
this.position = position
this.width = 50
this.height = 150
this.image = new Image()
this.image.src = imageSrc
this.scale = scale
this.framesMax = framesMax
this.framesCurrent = 0
this.framesElapsed = 0
this.framesHold = 15
this.offset = offset
}
draw() {
c.drawImage(
this.image,
this.framesCurrent * (this.image.width / this.framesMax),
0,
this.image.width / this.framesMax,
this.image.height,
this.position.x - this.offset.x,
this.position.y - this.offset.y,
(this.image.width / this.framesMax) * this.scale,
this.image.height * this.scale
)
}
animateFrames() {
this.framesElapsed++
if (this.framesElapsed % this.framesHold === 0) {
if (this.framesCurrent < this.framesMax - 1) {
this.framesCurrent++
} else {
this.framesCurrent = 0
}
}
}
update() {
this.draw()
this.animateFrames()
}
};
//Fighter Class
class Fighter extends Sprite {
constructor({
position,
velocity,
color = 'red',
imageSrc,
scale = 1,
framesMax = 1,
offset = {x: 0, y: 0},
sprites,
attackBox = { offset: {}, width: undefined, height: undefined},
effectBox = { offset: {}, width: undefined, height: undefined}
}) {
super({
position,
imageSrc,
scale,
framesMax,
offset
})
this.velocity = velocity
this.width = 50
this.height = 150
this.lastKey
this.attackBox = {
position: {
x: this.position.x,
y: this.position.y
},
offset: attackBox.offset,
width: attackBox.width,
height: attackBox.height,
}
this.effectBox = {
position: {
x: this.position.x,
y: this.position.y
},
offset: effectBox.offset,
width: effectBox.width,
height: effectBox.height,
}
this.color = color
this.isAttacking
this.health = 100
this.framesCurrent = 0
this.framesElapsed = 0
this.framesHold = 20
this.sprites = sprites
for (const sprite in this.sprites) {
sprites[sprite].image = new Image()
sprites[sprite].image.src = sprites[sprite].imageSrc
}
}
update() {
this.animateFrames()
this.draw()
this.attackBox.position.x = this.position.x + this.attackBox.offset.x;
this.attackBox.position.y = this.position.y + this.attackBox.offset.y;
/* c.fillRect(this.attackBox.position.x,
this.attackBox.position.y,
this.attackBox.width,
this.attackBox.height)
*/
this.position.x += this.velocity.x
this.position.y += this.velocity.y
if (this.position.y + this.height + this.velocity.y >= canvas.height - 25) {
this.velocity.y = 0
this.position.y = 401.1
} else this.velocity.y += gravity
}
attack() {
this.switchSprite('attack1')
this.isAttacking = true;
}
hurt() {
this.switchSprite('hurt')
this.health -= 20
}
switchSprite(sprite) {
if (this.image === this.sprites.attack1.image
&& this.framesCurrent < this.sprites.attack1.framesMax - 1) return
switch (sprite) {
case 'idle':
if (this.image !== this.sprites.idle.image) {
this.image = this.sprites.idle.image
this.framesMax = this.sprites.idle.framesMax
this.framesCurrent = 0
}
break
case 'run':
if (this.image !== this.sprites.run.image) {
this.image = this.sprites.run.image
this.framesMax = this.sprites.run.framesMax
this.framesCurrent = 0
}
break
case 'jump':
if (this.image !== this.sprites.jump.image) {
this.image = this.sprites.jump.image
this.framesMax = this.sprites.jump.framesMax
this.framesCurrent = 0
}
break
case 'attack1':
if (this.image !== this.sprites.attack1.image) {
this.image = this.sprites.attack1.image
this.framesMax = this.sprites.attack1.framesMax
this.framesCurrent = 0
}
break
case 'hurt':
if (this.image !== this.sprites.hurt.image) {
this.image = this.sprites.hurt.image
this.framesMax = this.sprites.hurt.framesMax
this.framesCurrent = 0
}
break
}
}
};
const canvas = document.querySelector('canvas')
const c = canvas.getContext('2d')
canvas.width = 1024;
canvas.height = 576;
c.fillRect(0, 0, canvas.width, canvas.height);
const gravity = 0.3;
const background0 = new Sprite ({
position: {
x: 0,
y: 0
},
imageSrc: "./img/backgrounds/0.png",
});
const background1 = new Sprite ({
position: {
x: 0,
y: 540
},
imageSrc: "./img/backgrounds/1.5.png",
});
const pineTree = new Sprite ({
position: {
x: 700,
y: 360
},
imageSrc: "./img/backAnimation/Pine Tree - Medium Snow - Spritesheet.png",
scale: 2,
framesMax: 41,
});
const slimSpruce = new Sprite ({
position: {
x: 350,
y: 412
},
imageSrc: "./img/backAnimation/Slim Spruce Tree - High Snow - Spritesheet.png",
scale: 1.5,
framesMax: 41,
});
/* Player */
const player = new Fighter({
position: {
x: 0,
y: 0
},
velocity: {
x: 0,
y: 0
},
offset: {
x: 0,
y: 0
},
imageSrc: "./img/fighters/Homeless_1/Idle_2.png",
framesMax: 11,
scale: 1.7,
offset: {
x: -100,
y: 60
},
sprites: {
idle: {
imageSrc: "./img/fighters/Homeless_1/Idle_2.png",
framesMax: 11,
},
run: {
imageSrc: "./img/fighters/Homeless_1/walk.png",
framesMax: 8,
},
jump: {
imageSrc: "./img/fighters/Homeless_1/Jump.png",
framesMax: 16,
},
attack1: {
imageSrc: "./img/fighters/Homeless_1/Attack_1.png",
framesMax: 5,
},
},
attackBox: {
offset: {
x: 215,
y: 65
},
width: 48,
height: 50,
},
});
/* Enemy */
const enemy = new Fighter({
position: {
x: 824,
y: 250
},
velocity: {
x: 0,
y: 0
},
offset: {
x: -50,
y: 0
},
color: 'blue',
imageSrc: "./img/fighters/Homeless_2/Idle_2.png",
framesMax: 9,
scale: 1.7,
offset: {
x: 100,
y: 60
},
sprites: {
idle: {
imageSrc: "./img/fighters/Homeless_2/Idle.png",
framesMax: 7,
},
run: {
imageSrc: "./img/fighters/Homeless_2/walk.png",
framesMax: 8,
},
jump: {
imageSrc: "./img/fighters/Homeless_2/Jump.png",
framesMax: 12,
},
attack1: {
imageSrc: "./img/fighters/Homeless_2/Attack_2.png",
framesMax: 4,
},
hurt: {
imageSrc: "./img/fighters/Homeless_2/Hurt.png",
framesMax: 3
},
},
attackBox: {
offset: {
x: -59,
y: 65
},
width: 48,
height: 50,
},
});
/* Keys Object */
const keys = {
a: {
pressed: false
},
d: {
pressed: false
},
w: {
pressed: false
},
ArrowLeft: {
pressed: false
},
ArrowRight: {
pressed: false
},
ArrowUp: {
pressed: false
}
}
decreaseTimer();
/* Animation Loop */
function animate() {
window.requestAnimationFrame(animate);
c.fillStyle = 'black'
c.fillRect(0, 0, canvas.width, canvas.height)
background0.update()
pineTree.update()
slimSpruce.update()
player.update()
enemy.update()
background1.update()
player.velocity.x = 0
enemy.velocity.x = 0
// Player Movement
if (keys.a.pressed && player.lastKey === 'a') {
player.velocity.x = -2
player.switchSprite('run')
} else if (keys.d.pressed && player.lastKey === 'd') {
player.velocity.x = 2
player.switchSprite('run')
} else {
player.switchSprite('idle')
}
if (player.velocity.y < 0) {
player.switchSprite('jump')
}
// Enemy Movement
if (keys.ArrowLeft.pressed && enemy.lastKey === 'ArrowLeft') {
enemy.velocity.x = -2
enemy.switchSprite("run")
} else if (keys.ArrowRight.pressed && enemy.lastKey === 'ArrowRight') {
enemy.velocity.x = 2
enemy.switchSprite("run")
} else {
enemy.switchSprite("idle")
}
if (enemy.velocity.y < 0) {
enemy.switchSprite('jump')
}
// detect for collision player to enemy
if (
rectangularCollision({
rectangle1: player,
rectangle2: enemy
}) &&
player.isAttacking &&
player.framesCurrent === 1
) {
console.log("hit")
enemy.hurt()
player.isAttacking = false
document.querySelector('#enemyHealth').style.width = enemy.health + "%";
}
//if player misses hit
if (player.isAttacking && player.framesCurrent === 1) {
player.isAttacking = false
}
// detect for collision enemy to player
if (
rectangularCollision({
rectangle1: enemy,
rectangle2: player
}) &&
enemy.isAttacking &&
enemy.framesCurrent === 1
) {
console.log("hit")
player.hurt()
enemy.isAttacking = false
document.querySelector('#playerHealth').style.width = enemy.health + "%";
}
//if player misses hit
if (enemy.isAttacking && enemy.framesCurrent === 1) {
enemy.isAttacking = false
}
if (enemy.health <= 0 || player.health <= 0) {
determineWinner({ player, enemy, timerId })
}
}
animate();
/* Event Listeners for Controls */
window.addEventListener('keydown', (event) => {
switch (event.key) {
/* Player Controls */
case 'd':
keys.d.pressed = true;
player.lastKey = 'd';
break
case 'a':
keys.a.pressed = true;
player.lastKey = 'a';
break
case 'w':
player.velocity.y = -13;
break
case 'f':
player.attack()
break
/* Enemy Controls */
case 'ArrowRight':
keys.ArrowRight.pressed = true;
enemy.lastKey = 'ArrowRight';
break
case 'ArrowLeft':
keys.ArrowLeft.pressed = true;
enemy.lastKey = 'ArrowLeft';
break
case 'ArrowUp':
enemy.velocity.y = -13;
break
case 'Control':
enemy.attack()
break
}
});
/* Event Listeners for Controls on "Release" */
window.addEventListener('keyup', (event) => {
switch (event.key) {
/* Player Controls */
case 'd':
keys.d.pressed = false;
break
case 'a':
keys.a.pressed = false;
break
case 'w':
keys.w.pressed = false;
break
/* Enemy Controls */
case 'ArrowRight':
keys.ArrowRight.pressed = false;
break
case 'ArrowLeft':
keys.ArrowLeft.pressed = false;
break
case 'ArrowUp':
keys.ArrowUp.pressed = false;
break
}
});
I can’t seem to find what is different in the attack code and collision detection for player 2 vs player 1.