pinball/assets/_Game/Scripts/GamePlay/Enemy.ts

156 lines
5.3 KiB
TypeScript
Raw Normal View History

2024-03-10 03:12:55 -07:00
import {
_decorator,
CCFloat,
CCInteger,
Component,
geometry,
math,
Node,
Vec3,
tween,
Collider2D,
Sprite,
Contact2DType,
2024-04-03 02:43:18 -07:00
AudioClip,
Tween,
2024-03-10 03:12:55 -07:00
} from 'cc';
import { EventManger } from '../Manager/EventManger';
import GameEvent from '../Events/GameEvent';
import ScoreType from '../Enum/ScoreType';
2024-03-11 04:12:22 -07:00
import GameState from '../Enum/GameState';
2024-04-03 02:43:18 -07:00
import { SoundManager } from '../Manager/SoundManager';
2024-03-10 03:12:55 -07:00
const { ccclass, property } = _decorator;
@ccclass('Enemy')
export class Enemy extends Component {
@property({ type: Collider2D, visible: true })
private _collider: Collider2D;
@property({ type: Sprite, visible: true })
private _sprite: Sprite;
@property({ type: Node, visible: true })
private _patrolPoint1: Node;
@property({ type: Node, visible: true })
private _patrolPoint2: Node;
@property({ type: CCFloat, visible: true })
private _speed = 100;
@property({ type: CCInteger, visible: true })
private _requireGoal = 1;
@property({ visible: true })
private _curveY = false;
@property({ type: geometry.AnimationCurve, visible: true })
private _patrolCurve: geometry.AnimationCurve = new geometry.AnimationCurve();
@property({ type: CCFloat, visible: true })
private _multiplierCurve = 100;
2024-04-03 02:43:18 -07:00
@property({ type: AudioClip, visible: true })
private _hitSound: AudioClip;
2024-03-10 03:12:55 -07:00
private x: number;
private y: number;
private _distance: number;
private _processDistance = 0;
private _direction = 1;
private _isActive = false;
private _currentGoal = 0;
protected onLoad(): void {
EventManger.instance.on(GameEvent.Score, this.onScore, this);
2024-03-11 04:12:22 -07:00
EventManger.instance.on(GameEvent.GameStateChange, this.onGameStateChange, this);
2024-03-10 03:12:55 -07:00
this._collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
}
2024-03-11 04:12:22 -07:00
protected start(): void {
this.init();
}
protected async init() {
2024-03-10 03:12:55 -07:00
this._collider.node.setWorldPosition(this._patrolPoint1.worldPosition);
const pos = this._patrolPoint1.getWorldPosition();
this.x = pos.x;
this.y = pos.y;
this._distance = Math.abs(this._patrolPoint2.worldPosition.x - this.x);
this._direction = this._patrolPoint1.worldPosition.x < this._patrolPoint2.worldPosition.x ? 1 : -1;
2024-03-11 04:12:22 -07:00
this._processDistance = 0;
this._currentGoal = 0;
this._isActive = false;
2024-03-10 03:12:55 -07:00
this._collider.node.active = false;
}
protected update(dt: number): void {
if (!this._isActive) return;
if (this._curveY) {
this._processDistance += this._speed * dt;
this._processDistance = math.clamp(this._processDistance, 0, this._distance);
const process = math.clamp01(this._processDistance / this._distance);
this.x += this._speed * dt * this._direction;
this.y = this._patrolPoint1.worldPosition.y + this._patrolCurve.evaluate(process) * this._multiplierCurve;
} else {
const dir = new Vec3();
Vec3.subtract(dir, this._patrolPoint2.worldPosition, this._patrolPoint1.worldPosition);
dir.multiplyScalar(this._direction).normalize();
this._processDistance += dir.x * this._speed * dt * this._direction;
this._processDistance = math.clamp(this._processDistance, 0, this._distance);
this.x += dir.x * this._speed * dt;
this.y += dir.y * this._speed * dt;
this.y = math.clamp(this.y, this._patrolPoint1.worldPosition.y, this._patrolPoint2.worldPosition.y);
}
this.x = math.clamp(this.x, this._patrolPoint1.worldPosition.x, this._patrolPoint2.worldPosition.x);
this._collider.node.setWorldPosition(new Vec3(this.x, this.y));
if (this._processDistance == this._distance) {
this._direction *= -1;
this._processDistance = 0;
}
}
private onBeginContact(self: Collider2D, other: Collider2D) {
2024-04-03 02:43:18 -07:00
SoundManager.instance.playSfx(this._hitSound);
Tween.stopAllByTarget(this._sprite.node.scale);
2024-03-10 03:12:55 -07:00
tween(this._sprite.node.scale)
2024-04-03 02:43:18 -07:00
.set(Vec3.ONE)
2024-03-10 03:12:55 -07:00
.to(0.1, new Vec3(1.2, 1.2), { easing: 'backInOut' })
.to(0.5, Vec3.ONE, { easing: 'backOut' })
.start();
}
2024-03-28 20:35:44 -07:00
private onScore(score: number, points: number, type: ScoreType) {
2024-03-10 03:12:55 -07:00
if (type == ScoreType.Goal) {
this._currentGoal++;
if (this._currentGoal == this._requireGoal) {
this._sprite.node.setScale(Vec3.ZERO);
this._collider.node.active = true;
tween(this._sprite.node.scale)
.delay(1)
.to(0.5, Vec3.ONE, {
easing: 'backOut',
onComplete: () => {
this._isActive = true;
},
})
.start();
}
}
}
2024-03-11 04:12:22 -07:00
private onGameStateChange(state: GameState) {
switch (state) {
case GameState.Init:
break;
2024-04-03 02:43:18 -07:00
case GameState.Ready:
break;
2024-03-11 04:12:22 -07:00
case GameState.Playing:
2024-03-29 04:24:58 -07:00
this.init();
2024-03-11 04:12:22 -07:00
break;
case GameState.GameOver:
break;
2024-04-03 02:43:18 -07:00
case GameState.Relive:
break;
case GameState.End:
break;
2024-03-11 04:12:22 -07:00
}
}
2024-03-10 03:12:55 -07:00
}