需求
滑动屏幕调整镜头位置。
可以限制只能竖向或横向滑动。
效果
思路
提供一个SingleTouchCtr,用于发出单指滑屏的相关事件,传出参数为手指触点位置。
CamMoveCtr控制镜头移动:在手指移动时根据手指位置换算出镜头应移动至的目标位置,在update中根据配置的速度使镜头缓动至目标位置。
配置
代码
SingleTouchCtr.ts
import { _decorator, Component, Node, input, Input, EventTouch, EventTarget } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('SingleTouchCtr')
export class SingleTouchCtr extends Component
{
private _touchId: number;
private static readonly defaultTouchId = -1;
private _eventTarget: EventTarget;
public get eventTarget(): EventTarget { return this._eventTarget };
public static readonly SingleTouchDownEvent: string = 'SingleTouchDownEvent';
public static readonly SingleTouchMoveEvent: string = 'SingleTouchMoveEvent';
public static readonly SingleTouchUpEvent: string = 'SingleTouchUpEvent';
start()
{
this.init();
}
onDestroy()
{
this.myDestroy();
}
private init(): void
{
input.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
input.on(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);
input.on(Input.EventType.TOUCH_END, this.onTouchEnd, this);
this.resetTouchId();
this._eventTarget = new EventTarget();
}
private myDestroy(): void
{
input.off(Input.EventType.TOUCH_START, this.onTouchStart, this);
input.off(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);
input.off(Input.EventType.TOUCH_END, this.onTouchEnd, this);
this._eventTarget = null;
}
private resetTouchId(): void
{
this._touchId = SingleTouchCtr.defaultTouchId;
}
private hasTouchId(): boolean
{
return this._touchId != SingleTouchCtr.defaultTouchId;
}
private onTouchStart(event: EventTouch):void
{
if (!this.hasTouchId())
{
this._touchId = event.touch.getID();
this.eventTarget.emit(SingleTouchCtr.SingleTouchDownEvent, event.touch.getLocation());
}
}
private onTouchMove(event: EventTouch):void
{
if (this._touchId == event.touch.getID())
{
this.eventTarget.emit(SingleTouchCtr.SingleTouchMoveEvent, event.touch.getLocation());
}
}
private onTouchEnd(event: EventTouch):void
{
if (this._touchId == event.touch.getID())
{
this.eventTarget.emit(SingleTouchCtr.SingleTouchUpEvent, event.touch.getLocation());
this.resetTouchId();
}
}
}
CamMoveCtr.ts
import { _decorator, Component, Node, Vec2, CCFloat, Vec3, Enum, } from 'cc';
import { SingleTouchCtr } from './SingleTouchCtr';
const { ccclass, property } = _decorator;
enum MoveDir
{
Horizontal,
Vertical,
Both,
}
@ccclass('CamMoveCtr')
export class CamMoveCtr extends Component
{
@property({ type: Node, visible: true, displayName: '相机Node' })
private _camNode: Node;
@property({ type: SingleTouchCtr, visible: true, displayName: '单指触屏控制' })
private _singleTouchCtr: SingleTouchCtr;
private _lastTouchPos: Vec2;
private _targetPos: Vec3;
@property({ type: CCFloat, visible: true, displayName: '移动速度' })
private _moveSpeed: number = 10;
@property({ type: CCFloat, visible: true, displayName: '距离系数' })
private _lengthFactor: number = 0.01;
@property({ type: Enum(MoveDir), visible: true, displayName: '可移动的朝向' })
private _moveDir: MoveDir = MoveDir.Both;
start()
{
this.init();
}
onDestroy()
{
this.myDestroy();
}
update(deltaTime: number)
{
if (!this._camNode.position.equals(this._targetPos))
{
this._camNode.position = this._camNode.position.lerp(this._targetPos, this._moveSpeed * deltaTime);
}
}
private init(): void
{
this._singleTouchCtr.eventTarget.on(SingleTouchCtr.SingleTouchDownEvent, this.onTouchDown, this);
this._singleTouchCtr.eventTarget.on(SingleTouchCtr.SingleTouchMoveEvent, this.onTouchMove, this);
this._singleTouchCtr.eventTarget.on(SingleTouchCtr.SingleTouchUpEvent, this.onTouchUp, this);
this.stopMove();
}
private myDestroy(): void
{
this._singleTouchCtr.eventTarget.off(SingleTouchCtr.SingleTouchDownEvent, this.onTouchDown, this);
this._singleTouchCtr.eventTarget.off(SingleTouchCtr.SingleTouchMoveEvent, this.onTouchMove, this);
this._singleTouchCtr.eventTarget.off(SingleTouchCtr.SingleTouchUpEvent, this.onTouchUp, this);
}
private onTouchDown(pos: Vec2): void
{
this._lastTouchPos = pos;
this.stopMove();
}
private onTouchMove(pos: Vec2): void
{
let dir: Vec2 = pos.subtract(this._lastTouchPos);
const length: number = dir.length();
dir = dir.normalize();
const posOffset = dir.multiplyScalar(length * this._lengthFactor);
let tempPos: Vec3 = new Vec3(0, 0, 0);
Vec3.add(tempPos, this._camNode.position, new Vec3(posOffset.x, posOffset.y, 0));
if (this._moveDir == MoveDir.Horizontal)
{
tempPos.y = this._camNode.position.y;
}
else if (this._moveDir == MoveDir.Vertical)
{
tempPos.x = this._camNode.position.x;
}
this._targetPos = tempPos;
}
private onTouchUp(pos: Vec2): void
{
// this.stopMove();
}
private stopMove(): void
{
this._targetPos = this._camNode.position;
}
}