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();
|
|
|
|
}
|
|
|
|
|
2024-04-21 19:04:58 -07:00
|
|
|
private 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:
|
2024-04-15 19:24:47 -07:00
|
|
|
this.init();
|
2024-04-03 02:43:18 -07:00
|
|
|
break;
|
2024-03-11 04:12:22 -07:00
|
|
|
case GameState.Playing:
|
|
|
|
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
|
|
|
}
|