Skip to content

Commit 5c13327

Browse files
committed
- better ennemy attack handling
1 parent 0ebd85f commit 5c13327

File tree

15 files changed

+119
-56
lines changed

15 files changed

+119
-56
lines changed

desktop.ini

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[.ShellClassInfo]
2+
IconResource=S:\Dev\Games\phaser-platform\public\favicon.ico,0
3+
[ViewState]
4+
Mode=
5+
Vid=
6+
FolderType=Generic
45.8 KB
Binary file not shown.
2.39 KB
Loading
4.37 KB
Loading
-6.03 KB
Binary file not shown.
-13.3 KB
Binary file not shown.

public/assets/tilemaps/forest-map.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -466,8 +466,8 @@
466466
"type":"ennemy_patrol",
467467
"visible":true,
468468
"width":0,
469-
"x":690,
470-
"y":403.333333333333
469+
"x":691,
470+
"y":391.833333333333
471471
},
472472
{
473473
"height":0,
@@ -486,8 +486,8 @@
486486
"type":"ennemy_patrol",
487487
"visible":true,
488488
"width":0,
489-
"x":981.333333333333,
490-
"y":204.666666666667
489+
"x":982.833333333333,
490+
"y":194.666666666667
491491
},
492492
{
493493
"height":0,
@@ -506,8 +506,8 @@
506506
"type":"ennemy_patrol",
507507
"visible":true,
508508
"width":0,
509-
"x":1255.5,
510-
"y":401.5
509+
"x":1253,
510+
"y":387.5
511511
}],
512512
"opacity":1,
513513
"type":"objectgroup",

src/configs/assets.config.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,10 @@ export class AssetsConfig {
120120
},
121121
{
122122
tag: EnnemyTag.PIXIE,
123-
url: "spritesheets/ennemies/pixie-spritesheet.webp",
123+
url: "spritesheets/ennemies/pixie-spritesheet-32x46.webp",
124124
config: {
125125
frameWidth: 32,
126-
frameHeight: 32,
126+
frameHeight: 46,
127127
},
128128
},
129129
{
@@ -142,6 +142,14 @@ export class AssetsConfig {
142142
frameHeight: 36,
143143
},
144144
},
145+
{
146+
tag: EnnemyTag.PIXIE_ATTACK,
147+
url: "spritesheets/ennemies/pixie-attack-96x46.webp",
148+
config: {
149+
frameWidth: 96,
150+
frameHeight: 46,
151+
},
152+
},
145153
];
146154
}
147155

src/game-objects/ennemy.game-object.ts

Lines changed: 80 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { Scene } from "phaser";
22
import { depthsConfig } from "../configs";
33
import { GameHelper } from "../helpers";
4-
import { ArcadeBody, Sprite } from "../phaser-aliases";
5-
import { AnimationTag, EnnemyTag, SfxTag, SpritesheetTag } from "../tags";
4+
import { ANIMATION, ArcadeBody, ArcadeSprite } from "../phaser-aliases";
5+
import { AnimationTag, EnnemyTag, SfxTag } from "../tags";
66
import { Hero } from "./hero.game-object";
77

88
export interface EnnemyConfig {
@@ -14,57 +14,74 @@ export interface EnnemyConfig {
1414
speed: number;
1515
patrolSpeed: number;
1616
sprite: EnnemyTag;
17+
attackSprite?: EnnemyTag;
1718
hp: number;
1819
range: number;
1920
atkCooldown: number;
2021
damage: number;
2122
}
2223

23-
export class Ennemy extends Sprite {
24+
export class Ennemy extends ArcadeSprite {
2425
public declare body: ArcadeBody;
2526

2627
private _player: Hero;
27-
private _atkHitbox: Phaser.Types.Physics.Arcade.SpriteWithDynamicBody;
2828
private _startingX: number;
2929
private _patrolDirection = 1;
3030
private _patrolTween: Phaser.Tweens.Tween | null = null;
3131
private _config: EnnemyConfig;
3232
private _attacking = false;
3333
private _canAttack = true;
34+
private _defaultWidth: number;
35+
private _attackHitbox: Phaser.GameObjects.Rectangle & {
36+
body: ArcadeBody;
37+
};
3438

3539
private get _isPatrolling(): boolean {
3640
return this._patrolTween !== null;
3741
}
42+
private get _physics(): Phaser.Physics.Arcade.ArcadePhysics {
43+
return this.scene.physics;
44+
}
3845

3946
constructor(config: EnnemyConfig, player: Hero) {
4047
super(config.scene, config.x, config.y, config.sprite);
4148
this._startingX = config.x;
4249
this._config = config;
4350

4451
this._player = player;
52+
this._defaultWidth = this.width;
4553

4654
this.scene.add.existing(this);
47-
this.scene.physics.add.existing(this);
55+
this._physics.add.existing(this);
4856

49-
const hitbox = this.scene.add
50-
.sprite(this.x, this.y, SpritesheetTag.PIXIE_HITBOX)
51-
.setVisible(false)
52-
.setDepth(depthsConfig.atkHitbox);
57+
this.flipX = true;
5358

54-
this._atkHitbox = this.scene.physics.add.existing(hitbox) as Phaser.Types.Physics.Arcade.SpriteWithDynamicBody;
55-
this.scene.add.existing(this._atkHitbox);
59+
this.setDepth(depthsConfig.ennemies);
60+
this.setbodySize({
61+
isAttacking: false,
62+
});
5663

57-
this._atkHitbox.body.setAllowGravity(false);
58-
this._atkHitbox.body.setEnable(false);
59-
this.scene.physics.world.remove(this._atkHitbox.body);
64+
const attackHitbox = this.scene.add.rectangle(0, 0, 32, 32, 0xffffff, 0);
6065

61-
this.flipX = true;
66+
this._attackHitbox = this._physics.add.existing(attackHitbox) as Phaser.GameObjects.Rectangle & {
67+
body: ArcadeBody;
68+
};
6269

63-
this.setDepth(depthsConfig.ennemies);
70+
this._attackHitbox.body.setAllowGravity(false);
71+
this._attackHitbox.body.setEnable(false);
72+
this._physics.world.remove(this._attackHitbox.body);
6473

65-
this.scene.physics.add.collider(this._atkHitbox, this._player, () => {
66-
this._player.hurt(this._config.damage);
67-
});
74+
this._physics.add.collider(this._attackHitbox, this._player);
75+
76+
this._physics.add.overlap(
77+
this._attackHitbox,
78+
this._player,
79+
() => {
80+
this._player.hurt(this._config.damage);
81+
},
82+
undefined,
83+
this
84+
);
6885

6986
this.createAnimations();
7087
this.startPatrol();
@@ -102,7 +119,7 @@ export class Ennemy extends Sprite {
102119
this.anims.play(AnimationTag.ENNEMY_DEATH);
103120
this.body.setVelocityX(0);
104121
this.body.setEnable(false);
105-
this.on(GameHelper.animCompleteEvent(AnimationTag.ENNEMY_DEATH), () => this.destroy());
122+
this.on(ANIMATION.COMPLETE_KEY + AnimationTag.ENNEMY_DEATH, () => this.destroy());
106123
this.scene.sound.play(SfxTag.PIXIE_DEAD);
107124
} //
108125
else {
@@ -137,24 +154,33 @@ export class Ennemy extends Sprite {
137154

138155
this.scene.sound.play(SfxTag.PIXIE_ATTACK);
139156
const direction = this.flipX ? -1 : 1;
140-
this._atkHitbox.setPosition(this.x + direction * this._atkHitbox.width, this.y).setVisible(true);
141-
this._atkHitbox.setFlipX(this.flipX);
142-
this._atkHitbox.body.setEnable(true);
143-
this.scene.physics.world.add(this._atkHitbox.body);
144-
this._atkHitbox.anims.play(AnimationTag.ENNEMY_ATTACK_HITBOX);
145-
this._atkHitbox.once(GameHelper.animCompleteEvent(AnimationTag.ENNEMY_ATTACK_HITBOX), () => {
146-
this._atkHitbox.setVisible(false);
147-
this._atkHitbox.body.setEnable(false);
148-
this.scene.physics.world.remove(this._atkHitbox.body);
149-
});
157+
const hitboxPosition = {
158+
x: this.x + direction * this._attackHitbox.width,
159+
y: this.y,
160+
};
161+
162+
this._attackHitbox.setPosition(hitboxPosition.x, hitboxPosition.y).setVisible(true);
163+
this._attackHitbox.body.setEnable(true);
164+
this._physics.world.add(this._attackHitbox.body);
150165

151166
this._attacking = true;
152167
this._canAttack = false;
153168
this.body.setVelocityX(0);
154169
GameHelper.animate(this, AnimationTag.ENNEMY_ATTACK);
155170

156-
this.once(GameHelper.animCompleteEvent(AnimationTag.ENNEMY_ATTACK), () => {
171+
this.setbodySize({
172+
isAttacking: true,
173+
});
174+
175+
this.once(ANIMATION.COMPLETE_KEY + AnimationTag.ENNEMY_ATTACK, () => {
176+
this._attackHitbox.body.setEnable(false);
177+
this._physics.world.remove(this._attackHitbox.body);
178+
179+
this.anims.play(AnimationTag.ENNEMY_IDLE);
157180
this._attacking = false;
181+
this.setbodySize({
182+
isAttacking: false,
183+
});
158184
this.scene.time.delayedCall(this._config.atkCooldown, () => (this._canAttack = true));
159185
});
160186
}
@@ -199,6 +225,16 @@ export class Ennemy extends Sprite {
199225
}
200226
}
201227

228+
private setbodySize(params: { isAttacking: boolean }): void {
229+
if (params.isAttacking) {
230+
this.body.setSize(this._defaultWidth, this.body.height, true);
231+
// this.setOrigin(0.5);
232+
} else {
233+
const hitboxHeight = this.height * 0.8;
234+
this.body.setSize(this._defaultWidth, hitboxHeight);
235+
}
236+
}
237+
202238
private createAnimations(): void {
203239
this.anims.create({
204240
key: AnimationTag.ENNEMY_IDLE,
@@ -213,8 +249,8 @@ export class Ennemy extends Sprite {
213249
this.anims.create({
214250
key: AnimationTag.ENNEMY_MOVING,
215251
frames: this.anims.generateFrameNumbers(this._config.sprite, {
216-
start: 5,
217-
end: 8,
252+
start: 4,
253+
end: 7,
218254
}),
219255
frameRate: 10,
220256
repeat: -1,
@@ -223,8 +259,8 @@ export class Ennemy extends Sprite {
223259
this.anims.create({
224260
key: AnimationTag.ENNEMY_HURT,
225261
frames: this.anims.generateFrameNumbers(this._config.sprite, {
226-
start: 10,
227-
end: 11,
262+
start: 8,
263+
end: 9,
228264
}),
229265
frameRate: 20,
230266
repeat: 3,
@@ -233,25 +269,27 @@ export class Ennemy extends Sprite {
233269
this.anims.create({
234270
key: AnimationTag.ENNEMY_DEATH,
235271
frames: this.anims.generateFrameNumbers(this._config.sprite, {
236-
start: 12,
237-
end: 13,
272+
start: 10,
273+
end: 11,
238274
}),
239275
frameRate: 20,
240276
repeat: 3,
241277
});
242278

279+
const attackSprite = this._config.attackSprite || this._config.sprite;
280+
243281
this.anims.create({
244282
key: AnimationTag.ENNEMY_ATTACK,
245-
frames: this.anims.generateFrameNumbers(this._config.sprite, {
246-
start: 15,
247-
end: 19,
283+
frames: this.anims.generateFrameNumbers(attackSprite, {
284+
start: 0,
285+
end: 4,
248286
}),
249287
frameRate: 10,
250288
});
251289

252-
this._atkHitbox.anims.create({
290+
this.anims.create({
253291
key: AnimationTag.ENNEMY_ATTACK_HITBOX,
254-
frames: this.anims.generateFrameNumbers(SpritesheetTag.PIXIE_HITBOX, {
292+
frames: this.anims.generateFrameNumbers(attackSprite, {
255293
start: 0,
256294
end: 4,
257295
}),

src/game-objects/hero.game-object.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Scene } from "phaser";
22
import { depthsConfig } from "../configs";
33
import { HeroState } from "../helpers";
44
import { GameHelper } from "../helpers/game.helper";
5-
import { ArcadeBody, ArcadeSprite } from "../phaser-aliases";
5+
import { ANIMATION, ArcadeBody, ArcadeSprite } from "../phaser-aliases";
66
import { AnimationTag, HeroEventTag, ImageTag, SfxTag, SpritesheetTag } from "../tags";
77

88
export class Hero extends ArcadeSprite {
@@ -61,6 +61,8 @@ export class Hero extends ArcadeSprite {
6161

6262
this.setScale(0.5).setDepth(depthsConfig.hero);
6363

64+
// this.setCollideWorldBounds(true);
65+
6466
if (!this.scene.input.keyboard) {
6567
throw Error("Keyboard plugin is not available");
6668
}
@@ -86,6 +88,7 @@ export class Hero extends ArcadeSprite {
8688

8789
const hitboxWidth = this.width * 0.7;
8890
const hitboxHeight = this.height * 0.8;
91+
8992
this.body.setSize(hitboxWidth, hitboxHeight);
9093
this.body.setOffset(this._offset.x, this._offset.y);
9194

@@ -143,7 +146,7 @@ export class Hero extends ArcadeSprite {
143146
if (this._hp <= 0) {
144147
this.scene.sound.play(SfxTag.HERO_DIE);
145148
GameHelper.animate(this, AnimationTag.HERO_DIE);
146-
this.on(GameHelper.animCompleteEvent(AnimationTag.HERO_DIE), () => {
149+
this.on(ANIMATION.COMPLETE_KEY + AnimationTag.HERO_DIE, () => {
147150
this.destroy();
148151
});
149152
} else {
@@ -253,6 +256,7 @@ export class Hero extends ArcadeSprite {
253256
end: 10,
254257
}),
255258
frameRate: 10,
259+
repeat: GameHelper.getAnimationRepetition(this._invincibilityWindow, 2, 10),
256260
});
257261

258262
this.anims.create({

0 commit comments

Comments
 (0)