피격모션도 모션에 속하므로 이전 단계들과 유사하다.
const enemy = new Fighter({
...
sprites: {
...
takeHit: {
imageSrc: "./img/kenji/Take hit.png",
framesMax: 3,
},
},
player쪽에도 Take hit을 추가해주고
takeHit: {
imageSrc: "./img/samuraiMack/Take Hit - white silhouette.png",
framesMax: 4,
},
},
switchSprite(sprite) {
...
case "takeHit":
if (this.image !== this.sprites.takeHit.image) {
this.image = this.sprites.takeHit.image;
this.framesMax = this.sprites.takeHit.framesMax;
this.framesCurrent = 0;
}
break;
피격은 takeHit이란 메소드를 새로 만들어 관리하자 충돌부분에서 체력감소부분을 지우고 메소드를 호출하자
//detect collision & enemy get hit
if (
rectangularCollision({ rectangle1: player, rectangle2: enemy }) &&
player.isAttacking &&
player.framesCurrent === 4
) {
enemy.takeHit()
player.isAttacking = false;
enemy.health -= 20;
document.querySelector("#enemyHealth").style.width = enemy.health + "%";
console.log("player attack");
}
//detect collision & player get hit
if (
rectangularCollision({ rectangle1: enemy, rectangle2: player }) &&
enemy.isAttacking &&
enemy.framesCurrent === 2
) {
player.takeHit();
enemy.isAttacking = false;
player.health -= 20;
document.querySelector("#playerHealth").style.width = player.health + "%";
console.log("enemy attack");
}
takeHit() {
this.switchSprite("takeHit");
this.health -= 20;
}
takeHit 모션이 나오지 않는데 이전과 동일하게 idle모션이 덮어씌워지기 때문이다.
attack의 경우와 동일하게 기본 모션에 덮어씌워지도록 해야한다.
switchSprite(sprite) {
//override other animation with in attack animation
if (
this.image === this.sprites.attack1.image &&
this.framesCurrent < this.sprites.attack1.framesMax - 1
)
return;
//override other animation with in takehit animation
if (
this.image === this.sprites.takeHit.image &&
this.framesCurrent < this.sprites.takeHit.framesMax - 1
)
return;
다음으로는 체력이 0이 되면 쓰러지는 모션을 추가하자
똑같이 death도 추가해주고
death: {
imageSrc: "./img/samuraiMack/Death.png",
framesMax: 6,
},
},
death: {
imageSrc: "./img/kenji/Death.png",
framesMax: 7,
},
case "death":
if (this.image !== this.sprites.death.image) {
this.image = this.sprites.death.image;
this.framesMax = this.sprites.death.framesMax;
this.framesCurrent = 0;
}
break;
동작은 takeHit메소드에 추가로 작성해주자
takeHit() {
this.health -= 20;
if (this.health <= 0) {
this.switchSprite("death");
} else this.switchSprite("takeHit");
}
death모션 또한 덮어씌워지는 모션이므로 attackt, takehit과 같이 override해준다.
switchSprite(sprite) {
//overrride other animation with in death animation
if (this.image === this.sprites.death.image) return;
그런데 death모션이 계속해서 반복된다.
Fighter 클래스에 dead를 false로 추가하고
class Fighter extends Sprite {
constructor({
...
this.dead = false
update() {
this.draw();
if (!this.dead) this.animateFrames();
dead가 false일 때만 이후 동작을 실행하도록 한 뒤
switchSprite(sprite) {
//overrride other animation with in death animation
if (this.image === this.sprites.death.image) {
if (this.framesCurrent === this.sprites.death.framesMax - 1)
this.dead = true;
return;
}
death모션이 나올 때 dead를 true로 바꿔 다른 동작을 실행하지 않도록 한다.
그런데 계속해서 움직일 수 있다.
방금 적용한 것과 동일하게 이벤트리스너에서
window.addEventListener("keydown", (event) => {
//player key
if (!player.dead) {
switch (event.key) {
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 = -15;
break;
// if ((player.position.y = canvas.height - player.height)) {
// }
case " ":
player.attack();
break;
}
}
//enemy key
if (!enemy.dead) {
switch (event.key) {
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 = -15;
break;
case "ArrowDown":
enemy.attack();
break;
}
}
});
각 동작을 if문으로 감싸주면 된다.
동작부분은 마무리가 다 되었다.
다음 포스팅에선 UI와 세부 애니메이션을 다뤄보자.