消消方块阵换皮表情
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

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;
}
}