You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
5.2 KiB
152 lines
5.2 KiB
import { _decorator, clamp, Component, director, find, instantiate, lerp, Node, Prefab, tween, UITransform, v2, v3, Vec3 } from 'cc';
|
|
import { SuDacePlayer } from './SuDacePlayer';
|
|
import { SuDace } from './SuDace';
|
|
import { SuDaceBullet } from './SuDaceBullet';
|
|
import { SuDacePoint } from './SuDacePoint';
|
|
const { ccclass, property } = _decorator;
|
|
|
|
@ccclass('SuDaceMap')
|
|
export class SuDaceMap extends Component {
|
|
|
|
@property(Prefab)
|
|
enemyTemplate: Prefab = null;
|
|
/**子弹模版 */
|
|
@property(Prefab)
|
|
bulletTemplate: Prefab = null;
|
|
/**落石模版 */
|
|
@property(Prefab)
|
|
stoneTemplate: Prefab = null;
|
|
|
|
player: SuDacePlayer = null;
|
|
gridNode: Node = null;
|
|
enemyNode: Node = null;
|
|
bulletNode: Node = null;
|
|
spawnPointNode: Node = null;
|
|
private readonly _tmpV2 = v2();
|
|
|
|
protected onLoad(): void {
|
|
this.player = find("player", this.node).getComponent(SuDacePlayer);
|
|
this.gridNode = find("grids", this.node);
|
|
this.enemyNode = find("enemys", this.node);
|
|
this.bulletNode = find("bullets", this.node);
|
|
this.spawnPointNode = find("spawnPoints", this.node);
|
|
}
|
|
|
|
/**
|
|
* 根据世界坐标查找所在格子节点(grids 子节点)。
|
|
* 多个格子重叠时以子节点顺序先命中者为准。
|
|
*/
|
|
getGridCellAtWorld(worldPos: Readonly<Vec3>): Node | null {
|
|
if (!this.gridNode?.isValid) return null;
|
|
this._tmpV2.set(worldPos.x, worldPos.y);
|
|
for (let i = 0; i < this.gridNode.children.length; i++) {
|
|
const cell = this.gridNode.children[i];
|
|
if (!cell.activeInHierarchy) continue;
|
|
const ui = cell.getComponent(UITransform);
|
|
if (!ui) continue;
|
|
if (ui.getBoundingBoxToWorld().contains(this._tmpV2)) {
|
|
return cell;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/** 格子上的 SuDacePoint(无组件则返回 null) */
|
|
getSuDacePointAtWorld(worldPos: Readonly<Vec3>): SuDacePoint | null {
|
|
const cell = this.getGridCellAtWorld(worldPos);
|
|
return cell?.getComponent(SuDacePoint) ?? null;
|
|
}
|
|
|
|
protected start(): void {
|
|
tween(this.node).to(0.5, { scale: v3(0.6, 0.6, 0.6) }, {
|
|
onUpdate: () => {
|
|
this.checkMapBoundary();
|
|
}
|
|
}).start();
|
|
}
|
|
|
|
|
|
/**生成怪物 */
|
|
generateMonster(): Node {
|
|
const spawnPos = this.spawnPointNode?.worldPosition ?? this.player?.node?.worldPosition ?? Vec3.ZERO;
|
|
let monster: Node = null;
|
|
if (SuDace.instance.enemyPool.length > 0) {
|
|
monster = SuDace.instance.enemyPool.shift();
|
|
} else {
|
|
monster = instantiate(this.enemyTemplate);
|
|
}
|
|
monster.setParent(this.enemyNode ?? this.node);
|
|
monster.setWorldPosition(spawnPos.clone().add(v3(Math.random() * 200 - 100, 0, 0)));
|
|
monster.active = true;
|
|
return monster;
|
|
}
|
|
|
|
/**生成子弹 */
|
|
generateBullet(): Node {
|
|
let bullet = null;
|
|
if (SuDace.instance.bulletPool.length > 0) {
|
|
bullet = SuDace.instance.bulletPool.shift()!;
|
|
} else {
|
|
bullet = instantiate(this.bulletTemplate);
|
|
}
|
|
bullet.setParent(this.bulletNode);
|
|
const comp = bullet.getComponent(SuDaceBullet);
|
|
if (comp) {
|
|
comp.isStone = false;
|
|
}
|
|
bullet.active = true;
|
|
return bullet;
|
|
}
|
|
|
|
/**生成落石 */
|
|
generateStone(): Node {
|
|
let stone: Node = null;
|
|
if (SuDace.instance.stonePool.length > 0) {
|
|
stone = SuDace.instance.stonePool.shift();
|
|
} else {
|
|
stone = instantiate(this.stoneTemplate);
|
|
}
|
|
stone.setParent(this.bulletNode);
|
|
const comp = stone.getComponent(SuDaceBullet);
|
|
if (comp) {
|
|
comp.isStone = true;
|
|
}
|
|
// 竖直向下
|
|
stone.angle = 180;
|
|
stone.active = true;
|
|
if (stone.children.length > 0) {
|
|
const index = Math.floor(Math.random() * stone.children.length);
|
|
stone.children.forEach((x, idx) => x.active = index === idx);
|
|
}
|
|
return stone;
|
|
}
|
|
|
|
protected update(dt: number): void {
|
|
//差值移动地图,将地图的本地坐标设置为角色本地坐标乘-1
|
|
if (this.player?.node) {
|
|
let x = this.player.node.position.x * -1 * this.node.scale.x;
|
|
let y = this.player.node.position.y * -1 * this.node.scale.y;
|
|
this.node.setPosition(lerp(this.node.position.x, x, 0.1), lerp(this.node.position.y, y, 0.1), 0);
|
|
this.checkMapBoundary();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 验证地图边界
|
|
*/
|
|
private checkMapBoundary() {
|
|
let minY = -45;
|
|
let maxY = 30;
|
|
let minX = -720;
|
|
let maxX = 720;
|
|
let tf = this.node.getComponent(UITransform);
|
|
minX = -tf.width * this.node.scale.x / 2 + 375;
|
|
maxX = tf.width * this.node.scale.x / 2 - 375;
|
|
minY = tf.height * this.node.scale.y / 2 + 800;
|
|
maxY = tf.height * this.node.scale.y / 2 - 800;
|
|
if (this.node.y < minY) this.node.y = minY;
|
|
if (this.node.y > maxY) this.node.y = maxY;
|
|
if (this.node.x > maxX) this.node.x = maxX;
|
|
if (this.node.x < minX) this.node.x = minX;
|
|
}
|
|
}
|
|
|