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

201 lines
7.5 KiB

import { _decorator, CCInteger, clamp, Component, Enum, EventTouch, game, Node, Rect, UITransform, v3, Vec2, Vec3 } from 'cc';
const { ccclass, property } = _decorator;
enum MoveType {
Vertical,
Horizontal,
}
@ccclass('MoveContent')
export class MoveContent extends Component {
/** 当顶部超出时触发 */
static EVENT_ON_TOP = "MoveContent.EVENT_ON_TOP";
/** 当底部超出时触发 */
static EVENT_ON_BOTTOM = "MoveContent.EVENT_ON_BOTTOM";
/** 当左侧超出时触发 */
static EVENT_ON_LEFT = "MoveContent.EVENT_ON_LEFT";
/** 当右侧超出时触发 */
static EVENT_ON_RIGHT = "MoveContent.EVENT_ON_RIGHT";
/** 每次验证边界都会触发 */
static EVENT_ON_CHECKBOUNDARY = "MoveContent.EVENT_ON_CHECKBOUNDARY";
@property({ type: Enum(MoveType) })
moveType: MoveType = MoveType.Vertical;
@property({ type: Node })
content: Node = null;
@property({ type: CCInteger })
top = 0;
@property({ type: CCInteger })
bottom = 0;
@property({ type: CCInteger })
left = 0;
@property({ type: CCInteger })
right = 0;
protected onEnable(): void {
this.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
this.node.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
this.node.on(Node.EventType.TOUCH_END, this.onTouchEnd, this);
this.node.on(Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
this.scheduleOnce(() => {
this.checkBoundary();
});
}
protected onDisable(): void {
this.node.off(Node.EventType.TOUCH_START, this.onTouchStart, this);
this.node.off(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
this.node.off(Node.EventType.TOUCH_END, this.onTouchEnd, this);
this.node.off(Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
this.startAutoMove = false;
}
protected update(dt: number): void {
if (this.startAutoMove) {
if (this.moveDir < 0) {
this.moveOffset += dt * 10;
if (this.moveOffset >= 0)
this.startAutoMove = false;
}
else {
this.moveOffset -= dt * 10;
if (this.moveOffset <= 0)
this.startAutoMove = false;
}
this.move();
}
}
protected lateUpdate(dt: number): void {
this.canEmit = true;
}
startMove = false;
moveOffset = 0;
moveDir = 1;
startPos = null;
startTime = 0;
startAutoMove = false;
touchDistance = 0;
canEmit = true;
onTouchStart(event: EventTouch) {
this.moveOffset = 0;
this.startMove = true;
this.startAutoMove = false;
this.startPos = event.getUILocation();
this.startTime = game.totalTime;
}
onTouchMove(event: EventTouch) {
if (this.startMove) {
let pos = event.getDelta();
//计算滑动方向
this.moveOffset = this.moveType == MoveType.Vertical ? pos.y : pos.x;
this.moveDir = this.moveOffset > 0 ? 1 : -1;
this.move();
}
}
onTouchEnd(event: EventTouch) {
this.startMove = false;
let pos = event.getUILocation();
let endTime = game.totalTime;
let duration = endTime - this.startTime;
this.startAutoMove = true;
this.touchDistance = Vec2.distance(pos, this.startPos);
this.moveOffset = this.moveOffset / duration * 500;
}
move() {
let x = 0, y = 0;
if (this.moveType == MoveType.Vertical) y = this.moveOffset;
if (this.moveType == MoveType.Horizontal) x = this.moveOffset;
this.content.position = this.content.position.add(new Vec3(x, y, 0));
this.checkBoundary();
}
checkBoundary() {
let boundary = this.getBoundary();
let x = 0, y = 0;
if (this.moveType == MoveType.Vertical) {
if (boundary.yMin > -this.node.h * this.node.anchor_y + this.bottom + this.node.worldPosition.y) {
y = (-this.node.h * this.node.anchor_y + this.bottom) - boundary.yMin + this.node.worldPosition.y;
this.node.emit(MoveContent.EVENT_ON_BOTTOM, boundary);
}
if (boundary.yMax < this.node.h * (1 - this.node.anchor_y) - this.top + this.node.worldPosition.y) {
y = (this.node.h * (1 - this.node.anchor_y) - this.top) - boundary.yMax + this.node.worldPosition.y;
this.node.emit(MoveContent.EVENT_ON_TOP, boundary);
}
} else {
if (boundary.xMax < this.node.w * (1 - this.node.anchor_x) - this.right + this.node.worldPosition.x) {
x = boundary.xMax - (this.node.w * (1 - this.node.anchor_x) - this.right);
this.node.emit(MoveContent.EVENT_ON_RIGHT, boundary);
}
if (boundary.xMin > -this.node.w * this.node.anchor_x + this.left + this.node.worldPosition.x) {
x = boundary.xMin - (-this.node.w * this.node.anchor_x + this.left);
this.node.emit(MoveContent.EVENT_ON_LEFT, boundary);
}
}
if (x != 0 || y != 0) {
this.content.position = this.content.position.add(new Vec3(x, y, 0));
}
this.node.emit(MoveContent.EVENT_ON_CHECKBOUNDARY, boundary);
this.canEmit = false;
if (this.canEmit) {
}
return this._boundaryRect;
}
getBoundary() {
this._boundaryRect.set(0, 0, 0, 0);
for (let i = 0; i < this.content.children.length; i++) {
let c = this.content.children[i];
if ((i == 0) || (c.worldPosition.y + c.h * (1 - c.anchor_y) > this._boundaryRect.yMax)) { this._boundaryRect.yMax = c.worldPosition.y + c.h * (1 - c.anchor_y); this._topNode = c; }
if ((i == 0) || (c.worldPosition.y - c.h * c.anchor_y < this._boundaryRect.yMin)) { this._boundaryRect.yMin = c.worldPosition.y - c.h * c.anchor_y; this._bottomNode = c; }
if ((i == 0) || (c.worldPosition.x + c.w * (1 - c.anchor_x) > this._boundaryRect.xMax)) { this._boundaryRect.xMax = c.worldPosition.x + c.w * (1 - c.anchor_x); this._rightNode = c; }
if ((i == 0) || (c.worldPosition.x - c.w * c.anchor_x < this._boundaryRect.xMin)) { this._boundaryRect.xMin = c.worldPosition.x - c.w * c.anchor_x; this._leftNode = c; }
}
return this._boundaryRect;
}
private _boundaryRect = new Rect();
private _topNode: Node = null;
private _bottomNode: Node = null;
private _leftNode: Node = null;
private _rightNode: Node = null;
moveToChild(node: Node) {
if (this.content.children.indexOf(node) < 0) return;
// 获取节点的世界坐标
let worldPos = node.getWorldPosition();
// 转换为content节点的本地坐标系统
let localPos = this.content.getComponent(UITransform).convertToNodeSpaceAR(worldPos);
// 计算目标位置:将节点移动到视图中心
let targetX = this.moveType == MoveType.Vertical ? 0 : -localPos.x;
let targetY = this.moveType == MoveType.Vertical ? -localPos.y : 0;
// 应用移动并检查边界
this.content.setPosition(targetX, targetY, 0);
this.checkBoundary();
}
moveToXY(x: number = 0, y: number = 0) {
let pso = this.content.position;
x = x == 0 || this.moveType == MoveType.Vertical ? pso.x : x;
y = y == 0 || this.moveType == MoveType.Horizontal ? pso.y : y;
this.content.position = v3(x, y, 0);
this.checkBoundary();
}
}