rts-demo
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
import { _decorator, Component, Node, Camera, Vec3, input, Input, EventMouse, EventTouch, KeyCode, Quat } from 'cc';
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
/**
|
||||
* RTS相机控制器
|
||||
* 提供RTS游戏常用的相机控制功能
|
||||
*/
|
||||
@ccclass('RTSCameraController')
|
||||
export class RTSCameraController extends Component {
|
||||
|
||||
@property
|
||||
moveSpeed: number = 10;
|
||||
|
||||
@property
|
||||
rotateSpeed: number = 60;
|
||||
|
||||
@property
|
||||
zoomSpeed: number = 5;
|
||||
|
||||
@property
|
||||
minZoom: number = 5;
|
||||
|
||||
@property
|
||||
maxZoom: number = 30;
|
||||
|
||||
@property
|
||||
boundarySize: number = 50;
|
||||
|
||||
private camera: Camera = null!;
|
||||
private isMouseDown: boolean = false;
|
||||
private lastMousePosition: Vec3 = Vec3.ZERO.clone();
|
||||
private currentZoom: number = 15;
|
||||
|
||||
// 键盘输入状态
|
||||
private keyStates: { [key: string]: boolean } = {};
|
||||
|
||||
onLoad() {
|
||||
this.camera = this.getComponent(Camera)!;
|
||||
this.currentZoom = this.node.position.y;
|
||||
|
||||
// 注册输入事件
|
||||
input.on(Input.EventType.MOUSE_DOWN, this.onMouseDown, this);
|
||||
input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
|
||||
input.on(Input.EventType.MOUSE_MOVE, this.onMouseMove, this);
|
||||
input.on(Input.EventType.MOUSE_WHEEL, this.onMouseWheel, this);
|
||||
input.on(Input.EventType.KEY_DOWN, this.onKeyDown, this);
|
||||
input.on(Input.EventType.KEY_UP, this.onKeyUp, this);
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
// 取消注册输入事件
|
||||
input.off(Input.EventType.MOUSE_DOWN, this.onMouseDown, this);
|
||||
input.off(Input.EventType.MOUSE_UP, this.onMouseUp, this);
|
||||
input.off(Input.EventType.MOUSE_MOVE, this.onMouseMove, this);
|
||||
input.off(Input.EventType.MOUSE_WHEEL, this.onMouseWheel, this);
|
||||
input.off(Input.EventType.KEY_DOWN, this.onKeyDown, this);
|
||||
input.off(Input.EventType.KEY_UP, this.onKeyUp, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 鼠标按下事件
|
||||
*/
|
||||
private onMouseDown(event: EventMouse) {
|
||||
if (event.getButton() === EventMouse.BUTTON_MIDDLE) {
|
||||
this.isMouseDown = true;
|
||||
this.lastMousePosition.set(event.getLocationX(), event.getLocationY(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 鼠标抬起事件
|
||||
*/
|
||||
private onMouseUp(event: EventMouse) {
|
||||
if (event.getButton() === EventMouse.BUTTON_MIDDLE) {
|
||||
this.isMouseDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 鼠标移动事件
|
||||
*/
|
||||
private onMouseMove(event: EventMouse) {
|
||||
if (this.isMouseDown) {
|
||||
const deltaX = event.getLocationX() - this.lastMousePosition.x;
|
||||
const deltaY = event.getLocationY() - this.lastMousePosition.y;
|
||||
|
||||
// 相机平移
|
||||
const moveVector = new Vec3(-deltaX * 0.01, 0, deltaY * 0.01);
|
||||
this.node.translate(moveVector);
|
||||
|
||||
this.lastMousePosition.set(event.getLocationX(), event.getLocationY(), 0);
|
||||
|
||||
// 限制相机边界
|
||||
this.clampCameraBounds();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 鼠标滚轮事件
|
||||
*/
|
||||
private onMouseWheel(event: EventMouse) {
|
||||
const scrollY = event.getScrollY();
|
||||
this.currentZoom -= scrollY * this.zoomSpeed * 0.1;
|
||||
this.currentZoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.currentZoom));
|
||||
|
||||
const pos = this.node.position;
|
||||
this.node.setPosition(pos.x, this.currentZoom, pos.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* 键盘按下事件
|
||||
*/
|
||||
private onKeyDown(event: any) {
|
||||
this.keyStates[event.keyCode] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 键盘抬起事件
|
||||
*/
|
||||
private onKeyUp(event: any) {
|
||||
this.keyStates[event.keyCode] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新相机移动
|
||||
*/
|
||||
update(deltaTime: number) {
|
||||
this.handleKeyboardMovement(deltaTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理键盘移动
|
||||
*/
|
||||
private handleKeyboardMovement(deltaTime: number) {
|
||||
const moveDistance = this.moveSpeed * deltaTime;
|
||||
let moveVector = Vec3.ZERO.clone();
|
||||
|
||||
// WASD 移动
|
||||
if (this.keyStates[KeyCode.KEY_W] || this.keyStates[KeyCode.ARROW_UP]) {
|
||||
moveVector.z -= moveDistance;
|
||||
}
|
||||
if (this.keyStates[KeyCode.KEY_S] || this.keyStates[KeyCode.ARROW_DOWN]) {
|
||||
moveVector.z += moveDistance;
|
||||
}
|
||||
if (this.keyStates[KeyCode.KEY_A] || this.keyStates[KeyCode.ARROW_LEFT]) {
|
||||
moveVector.x -= moveDistance;
|
||||
}
|
||||
if (this.keyStates[KeyCode.KEY_D] || this.keyStates[KeyCode.ARROW_RIGHT]) {
|
||||
moveVector.x += moveDistance;
|
||||
}
|
||||
|
||||
// 应用移动
|
||||
if (!moveVector.equals(Vec3.ZERO)) {
|
||||
this.node.translate(moveVector);
|
||||
this.clampCameraBounds();
|
||||
}
|
||||
|
||||
// QE 旋转
|
||||
if (this.keyStates[KeyCode.KEY_Q]) {
|
||||
const rotateAngle = this.rotateSpeed * deltaTime * Math.PI / 180;
|
||||
const currentRotation = this.node.rotation.clone();
|
||||
const yRotation = Quat.fromAxisAngle(new Quat(), Vec3.UP, rotateAngle);
|
||||
Quat.multiply(currentRotation, currentRotation, yRotation);
|
||||
this.node.rotation = currentRotation;
|
||||
}
|
||||
if (this.keyStates[KeyCode.KEY_E]) {
|
||||
const rotateAngle = -this.rotateSpeed * deltaTime * Math.PI / 180;
|
||||
const currentRotation = this.node.rotation.clone();
|
||||
const yRotation = Quat.fromAxisAngle(new Quat(), Vec3.UP, rotateAngle);
|
||||
Quat.multiply(currentRotation, currentRotation, yRotation);
|
||||
this.node.rotation = currentRotation;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 限制相机边界
|
||||
*/
|
||||
private clampCameraBounds() {
|
||||
const pos = this.node.position;
|
||||
const clampedX = Math.max(-this.boundarySize, Math.min(this.boundarySize, pos.x));
|
||||
const clampedZ = Math.max(-this.boundarySize, Math.min(this.boundarySize, pos.z));
|
||||
|
||||
this.node.setPosition(clampedX, pos.y, clampedZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置相机位置
|
||||
*/
|
||||
setCameraPosition(position: Vec3) {
|
||||
this.node.setPosition(position);
|
||||
this.clampCameraBounds();
|
||||
}
|
||||
|
||||
/**
|
||||
* 聚焦到目标位置
|
||||
*/
|
||||
focusOnTarget(target: Vec3, duration: number = 1.0) {
|
||||
const targetPos = new Vec3(target.x, this.currentZoom, target.z);
|
||||
// 这里可以添加缓动动画
|
||||
this.setCameraPosition(targetPos);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user