Add Minotaurus boss with front armor, dash stun and jumpable axe swing

This commit is contained in:
2026-08-19 14:41:02 +02:00
parent 7d41f6db6c
commit 1f67aaa982
5 changed files with 943 additions and 9 deletions
+30 -6
View File
@@ -10,6 +10,7 @@ import { Slime } from './Slime';
import { Brute } from './Brute';
import { Golem } from './Golem';
import { Krake } from './Krake';
import { Minotaurus } from './Minotaurus';
import { Crab } from './Crab';
import { Turret } from './Turret';
import { EnemyProjectile } from './EnemyProjectile';
@@ -81,8 +82,11 @@ export class Game {
private bossWaves = new Map<number, { name: string; spawn: () => Enemy }>([
[10, { name: 'Golem', spawn: () => new Golem() }],
[20, { name: 'Krake', spawn: () => new Krake() }],
[30, { name: 'Minotaurus', spawn: () => new Minotaurus() }],
]);
private bossFightActive = false;
private shakeTime = 0;
private shakeAmp = 0;
// Debug hitzone visualization
private showHitzones = false;
@@ -298,7 +302,8 @@ export class Game {
e.preventDefault();
return;
}
if (e.code === 'Space' && this.state === 'playing' && this.player.pullTime <= 0) {
if (e.code === 'Space' && this.state === 'playing'
&& this.player.pullTime <= 0 && this.player.stunTime <= 0) {
this.player.jump();
e.preventDefault();
}
@@ -728,6 +733,7 @@ export class Game {
this.spawns = 0;
this.killed = 0;
this.bossFightActive = false;
this.shakeTime = 0;
this.pendingPicks = 0;
this.hideLevelUp();
this.skillSystem = new SkillSystem(this.seed ?? 0);
@@ -754,15 +760,24 @@ export class Game {
}
// Treffer-Feedback: Schadenszahl bei Bossen einblenden
if (target?.isBoss && !target.dead) {
this.spawnDamageNumber(Math.round(damage), target.body.position);
this.spawnDamageText(`${Math.round(damage)}`, target.body.position);
}
}
spawnDamageNumber(damage: number, pos: THREE.Vector3, color?: string) {
const num = new DamageNumber(this.scene, `${damage}`, pos, color);
spawnDamageText(text: string, pos: THREE.Vector3, color?: string) {
const num = new DamageNumber(this.scene, text, pos, color);
this.damageNumbers.push(num);
}
spawnDamageNumber(damage: number, pos: THREE.Vector3, color?: string) {
this.spawnDamageText(`${damage}`, pos, color);
}
triggerCameraShake(duration: number, amp: number) {
this.shakeTime = duration;
this.shakeAmp = amp;
}
private openLevelUp() {
this.offers = this.skillSystem.rollOffers();
if (this.offers.length === 0) {
@@ -1012,7 +1027,10 @@ export class Game {
if (p.slowTimer > 0) speed *= p.slowFactor;
let isMoving = false;
if (p.pullTime > 0) {
if (p.stunTime > 0) {
// Gestunnt (Stampf-Schockwelle): keine Eingaben
p.velocity.set(0, 0, 0);
} else if (p.pullTime > 0) {
// Tentakel-Griff: Spieler wird komplett zum Boss gezogen
p.pullTime -= dt;
p.velocity.copy(p.pullDir).multiplyScalar(20);
@@ -1042,7 +1060,7 @@ export class Game {
}
// Jump / gravity
if (!p.onGround && p.pullTime <= 0) {
if (!p.onGround && p.pullTime <= 0 && p.stunTime <= 0) {
p.jumpVelocity -= 20 * dt;
p.body.position.y += p.jumpVelocity * dt;
if (p.body.position.y <= 0.5) {
@@ -1430,6 +1448,12 @@ export class Game {
25,
this.player.body.position.z - 15
);
if (this.shakeTime > 0) {
this.shakeTime -= dt;
const k = this.shakeTime * this.shakeAmp;
this.camera.position.x += (Math.random() - 0.5) * k;
this.camera.position.z += (Math.random() - 0.5) * k;
}
this.camera.lookAt(
this.player.body.position.x,
0,