mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-01-31 15:09:26 +08:00
Compare commits
No commits in common. "41028939163dd59a324495eea0c0e5039807f9f3" and "e99320c52dba3675ac3fc925c51b0159264e2f7e" have entirely different histories.
4102893916
...
e99320c52d
@ -1 +0,0 @@
|
|||||||
export * from './ui';
|
|
@ -1,55 +0,0 @@
|
|||||||
import { Component, VNodeProps } from 'vue';
|
|
||||||
|
|
||||||
export interface IUIControllerConfig<Element, UI> {
|
|
||||||
/**
|
|
||||||
* 将一个ui挂载至目标元素时的操作
|
|
||||||
* @param element 要挂载至的目标元素
|
|
||||||
* @param ui 要挂载的ui对象
|
|
||||||
*/
|
|
||||||
insert(element: Element, ui: UI): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将一个ui从目标元素上移除时的操作
|
|
||||||
* @param element 被移除ui的父元素
|
|
||||||
* @param ui 要被移除的ui元素
|
|
||||||
*/
|
|
||||||
remove(element: Element, ui: UI): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建一个新UI
|
|
||||||
* @param component UI组件
|
|
||||||
* @param props UI传递的props
|
|
||||||
*/
|
|
||||||
createUI(
|
|
||||||
component: Component,
|
|
||||||
props?: (VNodeProps & { [key: string]: any }) | null
|
|
||||||
): UI;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const enum OpenOption {
|
|
||||||
Push,
|
|
||||||
Unshift
|
|
||||||
}
|
|
||||||
|
|
||||||
export const enum CloseOption {
|
|
||||||
Splice,
|
|
||||||
Pop,
|
|
||||||
Shift
|
|
||||||
}
|
|
||||||
|
|
||||||
export class UIController<Element, UI> {
|
|
||||||
constructor(config: IUIControllerConfig<Element, UI>) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置当ui改变时控制器的行为
|
|
||||||
* @param open 打开时的行为
|
|
||||||
* @param close 关闭时的行为
|
|
||||||
*/
|
|
||||||
setChangeMode(open: OpenOption, close: CloseOption) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将这个UI控制器挂载至容器上
|
|
||||||
* @param container 要挂载至的容器
|
|
||||||
*/
|
|
||||||
mount(container: Element) {}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export * from './controller';
|
|
@ -17,11 +17,8 @@ export abstract class BarrageBoss extends EventEmitter<BarrageBossEvent> {
|
|||||||
|
|
||||||
/** 开始时刻 */
|
/** 开始时刻 */
|
||||||
private startTime: number = 0;
|
private startTime: number = 0;
|
||||||
|
|
||||||
/** 当前帧数 */
|
/** 当前帧数 */
|
||||||
frame: number = 0;
|
frame: number = 0;
|
||||||
/** 上一帧的时刻 */
|
|
||||||
lastTime: number = 0;
|
|
||||||
|
|
||||||
/** 这个boss战的主渲染元素,所有弹幕都会在此之上渲染 */
|
/** 这个boss战的主渲染元素,所有弹幕都会在此之上渲染 */
|
||||||
abstract readonly main: BossSprite;
|
abstract readonly main: BossSprite;
|
||||||
@ -34,19 +31,17 @@ export abstract class BarrageBoss extends EventEmitter<BarrageBossEvent> {
|
|||||||
* boss的ai,战斗开始后,每帧执行一次
|
* boss的ai,战斗开始后,每帧执行一次
|
||||||
* @param time 从战斗开始算起至现在经过了多长时间
|
* @param time 从战斗开始算起至现在经过了多长时间
|
||||||
* @param frame 从战斗开始算起至现在经过了多少帧,即当前是第几帧
|
* @param frame 从战斗开始算起至现在经过了多少帧,即当前是第几帧
|
||||||
* @param dt 本帧距上一帧多长时间,即上一帧持续了多长时间
|
|
||||||
*/
|
*/
|
||||||
abstract ai(time: number, frame: number, dt: number): void;
|
abstract ai(time: number, frame: number): void;
|
||||||
|
|
||||||
private tick = () => {
|
private tick = () => {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const dt = now - this.lastTime;
|
this.ai(now - this.startTime, this.frame);
|
||||||
this.ai(now - this.startTime, this.frame, dt);
|
|
||||||
this.frame++;
|
this.frame++;
|
||||||
this.projectiles.forEach(v => {
|
this.projectiles.forEach(v => {
|
||||||
const time = now - v.startTime;
|
const time = now - v.startTime;
|
||||||
v.time = time;
|
v.time = time;
|
||||||
v.ai(this, time, v.frame, dt);
|
v.ai(this, time, v.frame);
|
||||||
v.frame++;
|
v.frame++;
|
||||||
if (time > 60_000) {
|
if (time > 60_000) {
|
||||||
this.destroyProjectile(v);
|
this.destroyProjectile(v);
|
||||||
@ -55,7 +50,6 @@ export abstract class BarrageBoss extends EventEmitter<BarrageBossEvent> {
|
|||||||
v.doDamage(this.state);
|
v.doDamage(this.state);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.lastTime = now;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -236,9 +230,8 @@ export abstract class Projectile<T extends BarrageBoss = BarrageBoss> {
|
|||||||
* @param boss 从属的boss
|
* @param boss 从属的boss
|
||||||
* @param time 从弹幕生成开始算起至现在经过了多长时间
|
* @param time 从弹幕生成开始算起至现在经过了多长时间
|
||||||
* @param frame 从弹幕生成开始算起至现在经过了多少帧,即当前是第几帧
|
* @param frame 从弹幕生成开始算起至现在经过了多少帧,即当前是第几帧
|
||||||
* @param dt 本帧距上一帧多长时间,即上一帧持续了多长时间
|
|
||||||
*/
|
*/
|
||||||
abstract ai(boss: T, time: number, frame: number, dt: number): void;
|
abstract ai(boss: T, time: number, frame: number): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 这个弹幕的渲染函数,原则上一个boss的弹幕应该全部画在同一层,而且渲染前画布不进行矩阵变换
|
* 这个弹幕的渲染函数,原则上一个boss的弹幕应该全部画在同一层,而且渲染前画布不进行矩阵变换
|
||||||
|
@ -1,131 +0,0 @@
|
|||||||
import { IStateDamageable } from '@/game/state/interface';
|
|
||||||
import { BarrageBoss, BossSprite, Hitbox } from './barrage';
|
|
||||||
import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d';
|
|
||||||
import {
|
|
||||||
Container,
|
|
||||||
HeroRenderer,
|
|
||||||
LayerGroup,
|
|
||||||
MotaRenderer,
|
|
||||||
RenderItem,
|
|
||||||
Shader,
|
|
||||||
Transform
|
|
||||||
} from '@/core/render';
|
|
||||||
import { Pop } from '../fx/pop';
|
|
||||||
import { SplittableBall } from './palaceBossProjectile';
|
|
||||||
import { PointEffect } from '../fx/pointShader';
|
|
||||||
|
|
||||||
Mota.require('var', 'loading').once('coreInit', () => {
|
|
||||||
const shader = new Shader();
|
|
||||||
shader.size(480, 480);
|
|
||||||
shader.setHD(true);
|
|
||||||
shader.setZIndex(120);
|
|
||||||
PalaceBoss.shader = shader;
|
|
||||||
PalaceBoss.effect.create(shader, 40);
|
|
||||||
});
|
|
||||||
|
|
||||||
const enum BossStage {
|
|
||||||
Prologue,
|
|
||||||
|
|
||||||
Stage1,
|
|
||||||
Stage2,
|
|
||||||
Stage3,
|
|
||||||
Stage4,
|
|
||||||
|
|
||||||
End
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PalaceBoss extends BarrageBoss {
|
|
||||||
static effect: PointEffect = new PointEffect();
|
|
||||||
static shader: Shader;
|
|
||||||
|
|
||||||
main: BossSprite<BarrageBoss>;
|
|
||||||
hitbox: Hitbox.Circle;
|
|
||||||
state: IStateDamageable;
|
|
||||||
|
|
||||||
private stage: BossStage = BossStage.Prologue;
|
|
||||||
|
|
||||||
/** 用于展示傅里叶频谱的背景元素 */
|
|
||||||
private back: SonicBack;
|
|
||||||
/** 楼层渲染元素 */
|
|
||||||
private group: LayerGroup;
|
|
||||||
/** 楼层渲染容器 */
|
|
||||||
private mapDraw: Container;
|
|
||||||
/** 伤害弹出 */
|
|
||||||
pop: Pop;
|
|
||||||
|
|
||||||
private heroHp: number = 0;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
|
|
||||||
const render = MotaRenderer.get('render-main')!;
|
|
||||||
this.group = render.getElementById('layer-main') as LayerGroup;
|
|
||||||
this.mapDraw = render.getElementById('map-draw') as Container;
|
|
||||||
this.pop = render.getElementById('pop-main') as Pop;
|
|
||||||
|
|
||||||
this.state = core.status.hero;
|
|
||||||
this.main = new BossEffect('static', this);
|
|
||||||
this.back = new SonicBack('static');
|
|
||||||
const { x, y } = core.status.hero.loc;
|
|
||||||
const cell = 32;
|
|
||||||
this.hitbox = new Hitbox.Circle(x + cell / 2, y + cell / 2, cell / 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
override start(): void {
|
|
||||||
super.start();
|
|
||||||
|
|
||||||
PalaceBoss.shader.append(this.mapDraw);
|
|
||||||
this.main.append(this.group);
|
|
||||||
|
|
||||||
// const event = this.group.getLayer('event');
|
|
||||||
// const hero = event?.getExtends('floor-hero') as HeroRenderer;
|
|
||||||
// hero?.on('moveTick', this.moveTick);
|
|
||||||
|
|
||||||
SplittableBall.init({});
|
|
||||||
this.heroHp = core.status.hero.hp;
|
|
||||||
}
|
|
||||||
|
|
||||||
override end(): void {
|
|
||||||
super.end();
|
|
||||||
|
|
||||||
PalaceBoss.shader.remove();
|
|
||||||
this.main.remove();
|
|
||||||
this.back.remove();
|
|
||||||
this.main.destroy();
|
|
||||||
this.back.destroy();
|
|
||||||
|
|
||||||
// const event = this.group.getLayer('event');
|
|
||||||
// const hero = event?.getExtends('floor-hero') as HeroRenderer;
|
|
||||||
// hero?.off('moveTick', this.moveTick);
|
|
||||||
|
|
||||||
SplittableBall.end();
|
|
||||||
|
|
||||||
PalaceBoss.effect.end();
|
|
||||||
core.status.hero.hp = this.heroHp;
|
|
||||||
|
|
||||||
Mota.Plugin.require('replay_g').clip('choices:0');
|
|
||||||
}
|
|
||||||
|
|
||||||
ai(time: number, frame: number): void {}
|
|
||||||
}
|
|
||||||
|
|
||||||
class BossEffect extends BossSprite<PalaceBoss> {
|
|
||||||
protected preDraw(
|
|
||||||
canvas: MotaOffscreenCanvas2D,
|
|
||||||
transform: Transform
|
|
||||||
): boolean {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected postDraw(
|
|
||||||
canvas: MotaOffscreenCanvas2D,
|
|
||||||
transform: Transform
|
|
||||||
): void {}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SonicBack extends RenderItem {
|
|
||||||
protected render(
|
|
||||||
canvas: MotaOffscreenCanvas2D,
|
|
||||||
transform: Transform
|
|
||||||
): void {}
|
|
||||||
}
|
|
@ -1,261 +0,0 @@
|
|||||||
import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d';
|
|
||||||
import { Transform } from '@/core/render';
|
|
||||||
import { IStateDamageable } from '@/game/state/interface';
|
|
||||||
import { Hitbox, Projectile } from './barrage';
|
|
||||||
import type { PalaceBoss } from './palaceBoss';
|
|
||||||
import { clamp } from '../utils';
|
|
||||||
|
|
||||||
function popDamage(damage: number, boss: PalaceBoss, color: string) {
|
|
||||||
const { x, y } = core.status.hero.loc;
|
|
||||||
boss.pop.addPop(
|
|
||||||
(-damage).toString(),
|
|
||||||
1000,
|
|
||||||
x * 32 + 16,
|
|
||||||
y * 32 + 16,
|
|
||||||
color
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ISplitData {
|
|
||||||
split: boolean;
|
|
||||||
/** 分裂时刻,以弹幕被创建时刻为基准 */
|
|
||||||
time: number;
|
|
||||||
/** 分裂起始角度,以该弹幕朝向方向为 0 */
|
|
||||||
startAngle: number;
|
|
||||||
/** 分裂终止角度,以该弹幕朝向方向为 0 */
|
|
||||||
endAngle: number;
|
|
||||||
/** 每秒加速度 */
|
|
||||||
acc: number;
|
|
||||||
/** 初始速度 */
|
|
||||||
startVel: number;
|
|
||||||
/** 终止速度 */
|
|
||||||
endVel: number;
|
|
||||||
/** 持续时长 */
|
|
||||||
lastTime: number;
|
|
||||||
/** 分裂数量 */
|
|
||||||
count: number;
|
|
||||||
/** 这个弹幕分裂产生的弹幕的分裂信息,不填则表示产生的弹幕不会分裂 */
|
|
||||||
data?: ISplitData;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SplittableBall extends Projectile<PalaceBoss> {
|
|
||||||
damage: number = 10000;
|
|
||||||
hitbox: Hitbox.Circle = new Hitbox.Circle(0, 0, 8);
|
|
||||||
|
|
||||||
static ball: Map<string, MotaOffscreenCanvas2D> = new Map();
|
|
||||||
|
|
||||||
private damaged: boolean = false;
|
|
||||||
private splitData?: ISplitData;
|
|
||||||
private last: number = 60_000;
|
|
||||||
|
|
||||||
/** 角度,水平向右为 0,顺时针旋转一圈为 Math.PI * 2 */
|
|
||||||
private angle: number = 0;
|
|
||||||
/** 每秒加速度 */
|
|
||||||
private acc: number = 0;
|
|
||||||
/** 初始速度,每秒多少像素 */
|
|
||||||
private startVel: number = 0;
|
|
||||||
/** 终止速度 */
|
|
||||||
private endVel: number = 0;
|
|
||||||
/** 弹幕颜色 */
|
|
||||||
private color?: string;
|
|
||||||
|
|
||||||
private startVelX: number = 0;
|
|
||||||
private startVelY: number = 0;
|
|
||||||
private endVelX: number = 0;
|
|
||||||
private endVelY: number = 0;
|
|
||||||
private vx: number = 0;
|
|
||||||
private vy: number = 0;
|
|
||||||
// 加速度
|
|
||||||
private ax: number = 0;
|
|
||||||
private ay: number = 0;
|
|
||||||
|
|
||||||
static init(colors: Record<string, string[]>) {
|
|
||||||
this.ball.clear();
|
|
||||||
for (const [key, color] of Object.entries(colors)) {
|
|
||||||
const canvas = new MotaOffscreenCanvas2D();
|
|
||||||
canvas.size(32, 32);
|
|
||||||
canvas.withGameScale(true);
|
|
||||||
canvas.setHD(true);
|
|
||||||
const ctx = canvas.ctx;
|
|
||||||
const gradient = ctx.createRadialGradient(16, 16, 8, 16, 16, 16);
|
|
||||||
const step = 1 / (color.length - 1);
|
|
||||||
for (let i = 0; i < color.length; i++) {
|
|
||||||
gradient.addColorStop(i * step, color[i]);
|
|
||||||
}
|
|
||||||
ctx.fillStyle = gradient;
|
|
||||||
ctx.arc(16, 16, 16, 0, Math.PI * 2);
|
|
||||||
ctx.fill();
|
|
||||||
canvas.freeze();
|
|
||||||
this.ball.set(key, canvas);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static end() {
|
|
||||||
this.ball.forEach(v => {
|
|
||||||
v.clear();
|
|
||||||
v.delete();
|
|
||||||
});
|
|
||||||
this.ball.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置持续时长
|
|
||||||
* @param time 持续时长
|
|
||||||
*/
|
|
||||||
setLastTime(time: number) {
|
|
||||||
this.last = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置这个弹幕的分裂数据
|
|
||||||
* @param data 分裂数据,不填表示该弹幕不会分裂
|
|
||||||
*/
|
|
||||||
setSplitData(data?: ISplitData) {
|
|
||||||
this.splitData = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 计算速度分量信息
|
|
||||||
*/
|
|
||||||
private calVel() {
|
|
||||||
const sin = Math.sin(this.angle);
|
|
||||||
const cos = Math.cos(this.angle);
|
|
||||||
const vel = Math.hypot(this.vx, this.vy);
|
|
||||||
|
|
||||||
this.startVelX = this.startVel * cos;
|
|
||||||
this.startVelY = this.startVel * sin;
|
|
||||||
this.endVelX = this.endVel * cos;
|
|
||||||
this.endVelY = this.endVel * sin;
|
|
||||||
this.ax = this.acc * cos;
|
|
||||||
this.ay = this.acc * sin;
|
|
||||||
this.vx = vel * cos;
|
|
||||||
this.vy = vel * sin;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置弹幕速度朝向
|
|
||||||
* @param angle 朝向
|
|
||||||
*/
|
|
||||||
setAngle(angle: number) {
|
|
||||||
this.angle = angle;
|
|
||||||
this.calVel();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置速度
|
|
||||||
* @param start 起始速度
|
|
||||||
* @param end 终止速度
|
|
||||||
*/
|
|
||||||
setVel(start: number, end: number) {
|
|
||||||
this.startVel = start;
|
|
||||||
this.endVel = end;
|
|
||||||
this.calVel();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置加速度
|
|
||||||
* @param acc 加速度,每秒加速多少像素
|
|
||||||
*/
|
|
||||||
setAcc(acc: number) {
|
|
||||||
this.acc = acc;
|
|
||||||
this.calVel();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置弹幕的颜色
|
|
||||||
* @param color 颜色
|
|
||||||
*/
|
|
||||||
setColor(color: string) {
|
|
||||||
this.color = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
isIntersect(hitbox: Hitbox.HitboxType): boolean {
|
|
||||||
if (hitbox instanceof Hitbox.Circle) {
|
|
||||||
return Hitbox.checkCircleCircle(hitbox, this.hitbox);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateHitbox(x: number, y: number): void {
|
|
||||||
this.hitbox.setCenter(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
doDamage(target: IStateDamageable): boolean {
|
|
||||||
if (this.damaged) return false;
|
|
||||||
target.hp -= this.damage;
|
|
||||||
this.damaged = true;
|
|
||||||
core.drawHeroAnimate('hand');
|
|
||||||
popDamage(this.damage, this.boss, '#ff8180');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private split(boss: PalaceBoss) {
|
|
||||||
if (!this.splitData?.split) return;
|
|
||||||
const {
|
|
||||||
startAngle,
|
|
||||||
endAngle,
|
|
||||||
startVel,
|
|
||||||
endVel,
|
|
||||||
acc,
|
|
||||||
lastTime,
|
|
||||||
count,
|
|
||||||
data
|
|
||||||
} = this.splitData;
|
|
||||||
|
|
||||||
const sa = this.angle + startAngle;
|
|
||||||
const ea = this.angle + endAngle;
|
|
||||||
const step = (ea - sa - 1) / count;
|
|
||||||
const { x, y } = this.hitbox;
|
|
||||||
|
|
||||||
for (let i = 0; i < count; i++) {
|
|
||||||
const proj = boss.createProjectile(SplittableBall, x, y);
|
|
||||||
proj.setAngle(sa + step * i);
|
|
||||||
proj.setAcc(acc);
|
|
||||||
proj.setVel(startVel, endVel);
|
|
||||||
proj.setLastTime(lastTime);
|
|
||||||
proj.setSplitData(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ai(boss: PalaceBoss, time: number, frame: number, dt: number): void {
|
|
||||||
if (this.splitData?.split) {
|
|
||||||
if (time > this.splitData.time) {
|
|
||||||
this.split(boss);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (time > this.last) {
|
|
||||||
this.destroy();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const p = dt / 1000;
|
|
||||||
this.vx += this.ax * p;
|
|
||||||
this.vy += this.ay * p;
|
|
||||||
|
|
||||||
const sx = Math.sign(this.vx);
|
|
||||||
const sy = Math.sign(this.vy);
|
|
||||||
const cx = clamp(
|
|
||||||
Math.abs(this.vx),
|
|
||||||
Math.abs(this.startVelX),
|
|
||||||
Math.abs(this.endVelX)
|
|
||||||
);
|
|
||||||
const cy = clamp(
|
|
||||||
Math.abs(this.vy),
|
|
||||||
Math.abs(this.startVelY),
|
|
||||||
Math.abs(this.endVelY)
|
|
||||||
);
|
|
||||||
this.vx = cx * sx;
|
|
||||||
this.vy = cy * sy;
|
|
||||||
|
|
||||||
const { x, y } = this.hitbox;
|
|
||||||
this.setPosition(x + this.vx * p, y + this.vy * p);
|
|
||||||
}
|
|
||||||
|
|
||||||
render(canvas: MotaOffscreenCanvas2D, transform: Transform): void {
|
|
||||||
if (!this.color) return;
|
|
||||||
const texture = SplittableBall.ball.get(this.color);
|
|
||||||
if (!texture) return;
|
|
||||||
const ctx = canvas.ctx;
|
|
||||||
ctx.drawImage(texture.canvas, this.x - 16, this.y - 16, 32, 32);
|
|
||||||
}
|
|
||||||
}
|
|
@ -179,8 +179,6 @@ export class TowerBoss extends BarrageBoss {
|
|||||||
this.healthBar.remove();
|
this.healthBar.remove();
|
||||||
this.word.remove();
|
this.word.remove();
|
||||||
this.main.remove();
|
this.main.remove();
|
||||||
this.main.destroy();
|
|
||||||
this.healthBar.destroy();
|
|
||||||
|
|
||||||
const event = this.group.getLayer('event');
|
const event = this.group.getLayer('event');
|
||||||
const hero = event?.getExtends('floor-hero') as HeroRenderer;
|
const hero = event?.getExtends('floor-hero') as HeroRenderer;
|
||||||
|
@ -517,11 +517,3 @@ export function calStringSize(str: string) {
|
|||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function clamp(num: number, start: number, end: number) {
|
|
||||||
const s = Math.min(start, end);
|
|
||||||
const e = Math.max(start, end);
|
|
||||||
if (num < s) return s;
|
|
||||||
else if (num > e) return e;
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user