mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-01-31 23:29:27 +08:00
feat: 智慧塔弹幕战最后一个阶段
This commit is contained in:
parent
b353eba55c
commit
3202cffd5d
@ -414,6 +414,8 @@ export namespace Hitbox {
|
||||
const { x: cx, y: cy, radius: r } = circle;
|
||||
const { x, y, w, h } = rect;
|
||||
|
||||
if (cx > x && cx < x + w && cy > y && cy < y + h) return false;
|
||||
|
||||
// 找到圆心到矩形的最近点
|
||||
const closestX = Math.max(x, Math.min(cx, x + w));
|
||||
const closestY = Math.max(y, Math.min(cy, y + h));
|
||||
|
@ -17,6 +17,8 @@ import {
|
||||
import { Container } from '@/core/render/container';
|
||||
import {
|
||||
ArrowProjectile,
|
||||
BoomProjectile,
|
||||
ChainProjectile,
|
||||
IceProjectile,
|
||||
PortalProjectile,
|
||||
ProjectileDirection,
|
||||
@ -513,6 +515,10 @@ export class TowerBoss extends BarrageBoss {
|
||||
core.setBlock(527, n, ny);
|
||||
core.setBlock(527, 15 - n, ny);
|
||||
}
|
||||
core.setHeroLoc('x', 7);
|
||||
core.setHeroLoc('y', 7);
|
||||
core.setHeroLoc('direction', 'up');
|
||||
core.setBlock(557, 7, n + 1);
|
||||
}
|
||||
|
||||
private aiDialogue2(time: number, frame: number) {
|
||||
@ -523,21 +529,123 @@ export class TowerBoss extends BarrageBoss {
|
||||
this.skill7Time = 2;
|
||||
}
|
||||
|
||||
releaseSkill6() {}
|
||||
releaseSkill6(n: number, last: number) {
|
||||
const s = 13 - n * 2;
|
||||
const x = Math.floor(Math.random() * s + n);
|
||||
const y = Math.floor(Math.random() * s + n);
|
||||
const proj = this.createProjectile(BoomProjectile, 0, 0);
|
||||
proj.setData(x, y, last);
|
||||
}
|
||||
|
||||
releaseSkill7() {}
|
||||
async releaseSkill7(n: number) {
|
||||
const count = Math.floor(Math.random() * 6 + 3);
|
||||
const nodes: LocArr[] = [];
|
||||
const s = 13 - n * 2;
|
||||
const used = new Set<number>();
|
||||
let i = 0;
|
||||
while (i < count) {
|
||||
const x = Math.floor(Math.random() * s + n);
|
||||
const y = Math.floor(Math.random() * s + n);
|
||||
const index = x + y * s;
|
||||
if (used.has(index)) continue;
|
||||
i++;
|
||||
used.add(index);
|
||||
nodes.push([x, y]);
|
||||
if (nodes.length > 1) {
|
||||
const [lx, ly] = nodes[i - 1];
|
||||
const proj = this.createProjectile(ChainProjectile, 0, 0);
|
||||
proj.hitbox.setPoint1(lx, ly);
|
||||
proj.hitbox.setPoint2(x, y);
|
||||
}
|
||||
await sleep(200);
|
||||
}
|
||||
}
|
||||
|
||||
private aiStage3(time: number, frame: number) {}
|
||||
private aiStage3(time: number, frame: number) {
|
||||
const skill6Release = this.skill6Time * this.skill6Interval;
|
||||
const skill7Release = this.skill7Time * this.skill7Interval;
|
||||
const attack = this.attackTime * this.attackInterval;
|
||||
|
||||
private aiStage4(time: number, frame: number) {}
|
||||
if (time > skill6Release) {
|
||||
this.releaseSkill6(2, 500);
|
||||
this.skill6Time++;
|
||||
}
|
||||
if (time > skill7Release) {
|
||||
this.releaseSkill7(2);
|
||||
this.skill7Time++;
|
||||
}
|
||||
if (time > attack) {
|
||||
this.addAttackCircle(3000, 500);
|
||||
this.attackTime++;
|
||||
}
|
||||
|
||||
private aiStage5(time: number, frame: number) {}
|
||||
if (this.hp <= 2000) {
|
||||
this.changeStage(TowerBossStage.Stage4, time);
|
||||
this.terrainClose(2);
|
||||
this.attackTime = 1;
|
||||
this.skill6Time = 12;
|
||||
this.skill6Interval = 400;
|
||||
this.skill7Time = 1;
|
||||
}
|
||||
}
|
||||
|
||||
private aiStage4(time: number, frame: number) {
|
||||
const skill6Release = this.skill6Time * this.skill6Interval;
|
||||
const skill7Release = this.skill7Time * this.skill7Interval;
|
||||
const attack = this.attackTime * this.attackInterval;
|
||||
|
||||
if (time > skill6Release) {
|
||||
this.releaseSkill6(3, 500);
|
||||
this.skill6Time++;
|
||||
}
|
||||
if (time > skill7Release) {
|
||||
this.releaseSkill7(3);
|
||||
this.skill7Time++;
|
||||
}
|
||||
if (time > attack) {
|
||||
this.addAttackCircle(3000, 500);
|
||||
this.attackTime++;
|
||||
}
|
||||
|
||||
if (this.hp <= 1000) {
|
||||
this.changeStage(TowerBossStage.Stage5, time);
|
||||
this.terrainClose(3);
|
||||
this.attackTime = 1;
|
||||
this.skill6Time = 17;
|
||||
this.skill6Interval = 300;
|
||||
this.skill7Time = 1;
|
||||
}
|
||||
}
|
||||
|
||||
private aiStage5(time: number, frame: number) {
|
||||
const skill6Release = this.skill6Time * this.skill6Interval;
|
||||
const skill7Release = this.skill7Time * this.skill7Interval;
|
||||
const attack = this.attackTime * this.attackInterval;
|
||||
|
||||
if (time > skill6Release) {
|
||||
this.releaseSkill6(4, 500);
|
||||
this.skill6Time++;
|
||||
}
|
||||
if (time > skill7Release) {
|
||||
this.releaseSkill7(4);
|
||||
this.skill7Time++;
|
||||
}
|
||||
if (time > attack) {
|
||||
this.addAttackCircle(3000, 500);
|
||||
this.attackTime++;
|
||||
}
|
||||
|
||||
if (this.hp <= 1000) {
|
||||
this.changeStage(TowerBossStage.End, time);
|
||||
}
|
||||
}
|
||||
|
||||
private aiEnd(time: number, frame: number) {}
|
||||
}
|
||||
|
||||
class BossEffect extends BossSprite<TowerBoss> {
|
||||
private attackCircle: AttackCircleRenderable[] = [];
|
||||
private chainPath: LocArr[] = [];
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
|
@ -124,6 +124,7 @@ export class ArrowProjectile extends Projectile<TowerBoss> {
|
||||
|
||||
render(canvas: MotaOffscreenCanvas2D, transform: Transform): void {
|
||||
const ctx = canvas.ctx;
|
||||
ctx.globalAlpha = 1;
|
||||
|
||||
if (this.time < 3000) {
|
||||
let begin = 1;
|
||||
@ -295,13 +296,9 @@ export class IceProjectile extends Projectile<TowerBoss> {
|
||||
render(canvas: MotaOffscreenCanvas2D, transform: Transform): void {
|
||||
const ctx = canvas.ctx;
|
||||
if (this.time < 2000) {
|
||||
const fill = ctx.fillStyle;
|
||||
const alpha = ctx.globalAlpha;
|
||||
ctx.fillStyle = 'rgb(150,150,255)';
|
||||
ctx.globalAlpha = 0.6;
|
||||
ctx.fillRect(this.x + 2, this.y + 2, 28, 28);
|
||||
ctx.fillStyle = fill;
|
||||
ctx.globalAlpha = alpha;
|
||||
} else {
|
||||
if (!this.animated) {
|
||||
this.animated = true;
|
||||
@ -683,24 +680,79 @@ export class BoomProjectile extends Projectile<TowerBoss> {
|
||||
damage: number = 3000;
|
||||
hitbox: Hitbox.Rect = new Hitbox.Rect(0, 0, 32, 32);
|
||||
|
||||
private bx: number = 0;
|
||||
private by: number = 0;
|
||||
private last: number = 500;
|
||||
|
||||
private damaged: boolean = false;
|
||||
private animated: boolean = false;
|
||||
|
||||
setData(x: number, y: number, last: number) {
|
||||
this.bx = x;
|
||||
this.by = y;
|
||||
this.last = last;
|
||||
this.setPosition(x * 32, y * 32);
|
||||
}
|
||||
|
||||
isIntersect(hitbox: Hitbox.HitboxType): boolean {
|
||||
throw new Error('Method not implemented.');
|
||||
if (this.time < this.last + 1000) return false;
|
||||
if (this.damaged) return false;
|
||||
if (hitbox instanceof Hitbox.Rect) {
|
||||
return Hitbox.checkRectRect(this.hitbox, hitbox);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
updateHitbox(x: number, y: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
this.hitbox.setPosition(x, y);
|
||||
}
|
||||
|
||||
doDamage(target: IStateDamageable): boolean {
|
||||
throw new Error('Method not implemented.');
|
||||
if (this.damaged) return false;
|
||||
target.hp -= this.damage;
|
||||
this.damaged = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
ai(boss: TowerBoss, time: number, frame: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
if (!this.animated && time > this.last + 1000) {
|
||||
core.drawAnimate('explosion1', this.bx, this.by);
|
||||
}
|
||||
if (time > this.last + 1100) {
|
||||
this.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
render(canvas: MotaOffscreenCanvas2D, transform: Transform): void {
|
||||
throw new Error('Method not implemented.');
|
||||
const ctx = canvas.ctx;
|
||||
const end = this.last + 1000;
|
||||
const r = 12;
|
||||
const mr = 27;
|
||||
if (this.time < end) {
|
||||
const angle = this.time / 30;
|
||||
const sin = Math.sin(angle);
|
||||
const cos = Math.cos(angle);
|
||||
ctx.fillStyle = 'rgb(255,50,50)';
|
||||
ctx.strokeStyle = 'rgb(255,50,50)';
|
||||
ctx.lineWidth = 1;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(this.x + r * cos, this.y + r * sin);
|
||||
ctx.lineTo(this.x + mr * cos, this.y + mr * sin);
|
||||
ctx.moveTo(this.x - r * cos, this.y - r * sin);
|
||||
ctx.lineTo(this.x - mr * cos, this.y - mr * sin);
|
||||
ctx.arc(this.x, this.y, r, 0, Math.PI * 2);
|
||||
ctx.stroke();
|
||||
ctx.beginPath();
|
||||
ctx.arc(this.x, this.y, 2, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
}
|
||||
if (this.time > end - 500) {
|
||||
const dt = this.time - end + 500;
|
||||
const pos = this.y - (1 - dt / 500) * 480;
|
||||
const img = core.material.images.images['boom.png'];
|
||||
ctx.drawImage(img, this.x - 16, pos - 80, 36, 80);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -708,23 +760,53 @@ export class ChainProjectile extends Projectile<TowerBoss> {
|
||||
damage: number = 4000;
|
||||
hitbox: Hitbox.Line = new Hitbox.Line(0, 0, 0, 0);
|
||||
|
||||
private damaged: boolean = false;
|
||||
|
||||
isIntersect(hitbox: Hitbox.HitboxType): boolean {
|
||||
throw new Error('Method not implemented.');
|
||||
if (this.time < 1000) return false;
|
||||
if (this.damaged) return false;
|
||||
if (hitbox instanceof Hitbox.Rect) {
|
||||
return Hitbox.checkLineRect(this.hitbox, hitbox);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
updateHitbox(x: number, y: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
this.hitbox.setPoint1(x, y);
|
||||
}
|
||||
|
||||
doDamage(target: IStateDamageable): boolean {
|
||||
throw new Error('Method not implemented.');
|
||||
if (this.damaged) return false;
|
||||
target.hp -= this.damage;
|
||||
this.damaged = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
ai(boss: TowerBoss, time: number, frame: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
if (time > 2000) {
|
||||
this.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
render(canvas: MotaOffscreenCanvas2D, transform: Transform): void {
|
||||
throw new Error('Method not implemented.');
|
||||
const ctx = canvas.ctx;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(this.hitbox.x1, this.hitbox.y1);
|
||||
ctx.lineTo(this.hitbox.x2, this.hitbox.y2);
|
||||
|
||||
if (this.time < 1000) {
|
||||
ctx.globalAlpha = 0.6;
|
||||
ctx.strokeStyle = 'rgb(220,100,255)';
|
||||
ctx.stroke();
|
||||
} else {
|
||||
ctx.strokeStyle = '#fff';
|
||||
ctx.shadowBlur = 3;
|
||||
ctx.shadowColor = '#62c8f4';
|
||||
ctx.globalAlpha = 0.6;
|
||||
ctx.stroke();
|
||||
ctx.shadowBlur = 0;
|
||||
ctx.shadowColor = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user