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.
343 lines
12 KiB
343 lines
12 KiB
import { _decorator, Component, Node, Vec2, v2, Camera, Rect, CCFloat, EventTouch, EventMouse, UITransform, Vec3, Touch, Size, view, CCInteger, Sprite, tween } from "cc";
|
|
import { EDITOR, PREVIEW } from "cc/env";
|
|
import { IVec2Like } from "cc";
|
|
import { EBundleName } from "../const/GameEnum";
|
|
import MesMgr from "../MesEvent/MesMgr";
|
|
const { ccclass, property,executeInEditMode } = _decorator;
|
|
|
|
@ccclass("CameraScale")
|
|
export class CameraScale{
|
|
@property({ type: CCFloat, displayName: '最小值' })
|
|
min: number = 1;
|
|
@property({ type: CCFloat, displayName: '最大值' })
|
|
max: number = 1;
|
|
}
|
|
|
|
@ccclass("CameraCon")
|
|
@executeInEditMode()
|
|
export class CameraCon extends Component {
|
|
|
|
|
|
m_TounchDown: boolean = false;
|
|
m_IsClickDown: boolean = false;
|
|
m_MoveSpeed: number = 2;
|
|
m_Lastdistance: number = 0;
|
|
t_TempVec2: Vec2 = v2();
|
|
private _Camera:Camera;
|
|
public get m_Camera(): Camera{
|
|
if(!this._Camera){
|
|
this._Camera = this.node.getComponent(Camera);
|
|
}
|
|
return this._Camera;
|
|
};
|
|
|
|
@property(Sprite)
|
|
mBg:Sprite;
|
|
@property({type:Node,displayName:"摄像机矩形节点"})
|
|
mCameraRect: Node;
|
|
@property({ type: CameraScale, displayName: '摄像机缩放约束' })
|
|
mCameraScale: CameraScale = new CameraScale();
|
|
Cmaer_Scale_Speed: number = 0.01;
|
|
@property({ displayName: '摄像机移动返回约束' })
|
|
m_Rect: Rect = new Rect();
|
|
@property({ type: CCInteger, displayName: '基础' })
|
|
BaseoOrthoHeight:number = 667;
|
|
_ZoomRatio: number = 1.0;
|
|
@property({ type: CCFloat, displayName: '摄像机的Ratio' })
|
|
get mZoomRatio(){
|
|
return this._ZoomRatio;
|
|
}
|
|
|
|
set mZoomRatio(value:number){
|
|
if(this.isFreeze){return}
|
|
this._ZoomRatio = value;
|
|
this.setTounchRect();
|
|
}
|
|
|
|
private isMove:boolean =false;
|
|
private moveDir:Vec2 = new Vec2();
|
|
private time:number = 0.2;
|
|
private readonly maxTime:number = 0.5;
|
|
private tempPos: Vec3 = new Vec3();
|
|
/**默认的 宽高大小 */
|
|
initWidthAndHight: Vec2 = new Vec2();
|
|
private toRatio: number = 0;
|
|
private baseRation: number = 0;
|
|
private toTime: number = 0;
|
|
private toMaxTime: number = 0;
|
|
private isFreeze:boolean = false;
|
|
public static Ins: CameraCon;
|
|
protected onLoad(): void {
|
|
this.initWidthAndHight.x = view.getVisibleSize().width;
|
|
this.initWidthAndHight.y = view.getVisibleSize().height;
|
|
CameraCon.Ins = this;
|
|
this.addEvents();
|
|
this.setTounchRect();
|
|
if (EDITOR) {
|
|
this.node.active = false;
|
|
setTimeout(() => {
|
|
this.node.active = true;
|
|
})
|
|
}
|
|
}
|
|
|
|
setBgSpRite(url:string,Bundle:EBundleName){
|
|
CNodeUtils.SwitchTexture(url,this.mBg,Bundle);
|
|
}
|
|
|
|
private addEvents(): void {
|
|
this.mCameraRect.on(Node.EventType.TOUCH_START, this.onMouseEnter, this);
|
|
this.mCameraRect.on(Node.EventType.TOUCH_MOVE, this.onMouseMove, this);
|
|
this.mCameraRect.on(Node.EventType.TOUCH_END, this.onMouseUp, this);
|
|
this.mCameraRect.on(Node.EventType.TOUCH_CANCEL, this.onMouseLeave, this);
|
|
if(PREVIEW){
|
|
this.mCameraRect.on(Node.EventType.MOUSE_WHEEL, this.onMouseWheel, this);
|
|
}
|
|
}
|
|
|
|
get CamreaWordPos(){
|
|
return this.m_Camera.node.worldPosition;
|
|
}
|
|
|
|
TweenZoomRatio(ratio:number,time:number = 0.5){
|
|
this.toTime = 0;
|
|
this.toMaxTime = time;
|
|
this.baseRation = this._ZoomRatio;
|
|
this.toRatio = ratio - this._ZoomRatio;
|
|
let dt = this.toMaxTime / 60;
|
|
this.schedule(this.updateZoomRatio, dt);
|
|
}
|
|
|
|
private updateZoomRatio(dt:number){
|
|
//let dt = this.toMaxTime / 60;
|
|
this.toTime += dt;
|
|
let bar = this.toTime / this.toMaxTime;
|
|
if (bar >= 1) {
|
|
bar = 1;
|
|
}
|
|
this.mZoomRatio = this.baseRation + this.toRatio * bar;
|
|
if (bar >= 1) {
|
|
this.unschedule(this.updateZoomRatio);
|
|
}
|
|
}
|
|
|
|
getWordRect(){
|
|
return this.mCameraRect.getComponent(UITransform).getBoundingBoxToWorld();
|
|
}
|
|
|
|
/**获取视野的最大范围半径 */
|
|
getWordRange(){
|
|
let rect = this.getWordRect();
|
|
return Math.max(rect.width,rect.height) / 2;
|
|
}
|
|
|
|
/**获取视野的最大范围半径 */
|
|
getWordRange2() {
|
|
let rect = this.getWordRect();
|
|
//return Math.max(rect.width, rect.height) / 2;
|
|
return { width: rect.width / 2, height: rect.height / 1.7 };
|
|
}
|
|
|
|
SetCameraPos(pos:IVec2Like,isSet:boolean = true){
|
|
if (this.isFreeze) { return }
|
|
pos.x = Math.max(this.m_Rect.xMin / this._ZoomRatio, pos.x);
|
|
pos.x = Math.min(this.m_Rect.width / this._ZoomRatio, pos.x);
|
|
pos.y = Math.max(this.m_Rect.yMin / this._ZoomRatio, pos.y);
|
|
pos.y = Math.min(this.m_Rect.height / this._ZoomRatio, pos.y);
|
|
this.m_Camera.node.setPosition(pos.x, pos.y, 1000)
|
|
}
|
|
|
|
SetCameraFixdPos(pos:IVec2Like,isSet:boolean = true){
|
|
this.m_Camera.node.setPosition(pos.x, pos.y, 1000)
|
|
}
|
|
|
|
|
|
/**获取UI坐标通过摄像机转世界坐标 */
|
|
getScreenToWorldPoint(event: EventTouch, out?: Vec3) {
|
|
return this.m_Camera.screenToWorld(new Vec3(event.getLocation().x, event.getLocation().y), out);
|
|
}
|
|
|
|
getWordPosToUIPos(wordPos: Vec3,prent:Node, out?: Vec3) {
|
|
return this.m_Camera.convertToUINode(wordPos,prent, out);
|
|
}
|
|
|
|
updateBg(){
|
|
//背景跟随
|
|
let sprite = this.mBg.getComponent(Sprite);
|
|
if(sprite.spriteFrame){
|
|
let material = sprite.sharedMaterial;
|
|
let uvOffset = new Vec2(this.node.position.x / 512, -this.node.position.y / 512);
|
|
material.setProperty("tilingOffset", uvOffset);
|
|
}
|
|
//bg.position = position;
|
|
}
|
|
|
|
protected update(dt: number): void {
|
|
this.isMove && this.moveByDir(dt);
|
|
}
|
|
|
|
private moveByDir(dt:number){
|
|
if (dt >= 0) {
|
|
this.time = Math.max(0, this.time - dt);
|
|
if (this.time <= 0) { this.isMove = false; }
|
|
}
|
|
const moveScale = dt < 0 ? 1 : this.time / this.maxTime;
|
|
this.tempPos.x = this.node.position.x;
|
|
this.tempPos.y = this.node.position.y;
|
|
this.tempPos.x -= this.moveDir.x * this.m_MoveSpeed / this.mZoomRatio * moveScale;
|
|
this.tempPos.y -= this.moveDir.y * this.m_MoveSpeed / this.mZoomRatio * moveScale;
|
|
|
|
this.SetCameraPos(this.tempPos);
|
|
}
|
|
|
|
setFreeze(Ration:number,pos:IVec2Like){
|
|
this.isFreeze = true;
|
|
this._ZoomRatio = Ration;
|
|
this.setTounchRect(false);
|
|
this.m_Camera.node.setPosition(pos.x, pos.y, 1000)
|
|
}
|
|
|
|
RestoreFreeze(){
|
|
this.isFreeze = false;
|
|
}
|
|
|
|
|
|
|
|
private setTounchRect(isCheck:boolean = true) {
|
|
if(isCheck){
|
|
this._ZoomRatio = Math.min(this._ZoomRatio, this.mCameraScale.max);
|
|
this._ZoomRatio = Math.max(this._ZoomRatio, this.mCameraScale.min);
|
|
}
|
|
this.m_Camera.orthoHeight = this.BaseoOrthoHeight * this._ZoomRatio;
|
|
ConsoleEx.Log("当前缩放",this._ZoomRatio);
|
|
this.mCameraRect.getComponent(UITransform).setContentSize(new Size(this.initWidthAndHight.x * this._ZoomRatio,
|
|
this.initWidthAndHight.y * this._ZoomRatio
|
|
));
|
|
// this.mBg.node.setScale(this._ZoomRatio,this._ZoomRatio,this._ZoomRatio)
|
|
let tX = this.initWidthAndHight.x * this._ZoomRatio;
|
|
let tY = this.initWidthAndHight.y * this._ZoomRatio;
|
|
tX = Math.ceil((tX / 512) + 1) * 512;
|
|
tY = Math.ceil((tY / 512) + 1) * 512;
|
|
this.mBg.node.getComponent(UITransform).setContentSize(new Size(tX,tY))
|
|
//ConsoleEx.Log("当前",this._ZoomRatio)
|
|
}
|
|
|
|
//#region 摄像机触摸事件
|
|
|
|
/**手指按下 */
|
|
public onMouseEnter(event: EventTouch) {
|
|
this.m_TounchDown = true;
|
|
this.m_Lastdistance = -1;
|
|
this.m_IsClickDown = true;
|
|
this.isMove = false;
|
|
}
|
|
|
|
movebottom(time:number = 0){
|
|
if(time<=0){
|
|
this.tempPos.x = this.node.position.x;
|
|
this.tempPos.y = -Number.MAX_VALUE;
|
|
this.SetCameraPos(this.tempPos);
|
|
}else{
|
|
this.tempPos.x = this.node.position.x;
|
|
this.tempPos.y = -Number.MAX_VALUE;
|
|
this.tempPos.x = Math.max(this.m_Rect.xMin / this._ZoomRatio, this.tempPos.x);
|
|
this.tempPos.x = Math.min(this.m_Rect.width / this._ZoomRatio, this.tempPos.x);
|
|
this.tempPos.y = Math.max(this.m_Rect.yMin / this._ZoomRatio, this.tempPos.y);
|
|
this.tempPos.y = Math.min(this.m_Rect.height / this._ZoomRatio, this.tempPos.y);
|
|
let target = this.tempPos.clone();
|
|
target.z = 1000;
|
|
tween(this.m_Camera.node).to(time, { position: target }).start();
|
|
}
|
|
|
|
}
|
|
|
|
moveTop(time:number = 0){
|
|
if(time<=0){
|
|
this.tempPos.x = this.node.position.x;
|
|
this.tempPos.y = Number.MAX_VALUE;
|
|
this.SetCameraPos(this.tempPos);
|
|
}else{
|
|
this.tempPos.x = this.node.position.x;
|
|
this.tempPos.y = Number.MAX_VALUE;
|
|
this.tempPos.x = Math.max(this.m_Rect.xMin / this._ZoomRatio, this.tempPos.x);
|
|
this.tempPos.x = Math.min(this.m_Rect.width / this._ZoomRatio, this.tempPos.x);
|
|
this.tempPos.y = Math.max(this.m_Rect.yMin / this._ZoomRatio, this.tempPos.y);
|
|
this.tempPos.y = Math.min(this.m_Rect.height / this._ZoomRatio, this.tempPos.y);
|
|
let target = this.tempPos.clone();
|
|
target.z = 1000;
|
|
tween(this.m_Camera.node).to(time, { position: target }).start();
|
|
}
|
|
}
|
|
|
|
/**手指移动 */
|
|
public onMouseMove(event: EventTouch) {
|
|
this.m_IsClickDown = false;
|
|
if (!this.m_TounchDown) return;
|
|
let Touches: Touch[] = event.getTouches();
|
|
if (Touches.length == 1) {
|
|
this.time = this.maxTime;
|
|
this.moveDir.x = event.getDeltaX();
|
|
this.moveDir.y = event.getDeltaY();
|
|
this.moveByDir(-1);
|
|
} else if (Touches.length == 2) {
|
|
Vec2.subtract(this.t_TempVec2, Touches[0].getLocation(), Touches[1].getLocation());
|
|
// 双指当前间距
|
|
let distance = this.t_TempVec2.length();
|
|
if (this.m_Lastdistance <= 0) {
|
|
this.m_Lastdistance = distance;
|
|
}
|
|
let offdis = distance - this.m_Lastdistance
|
|
if (offdis < 0) {
|
|
this.mZoomRatio -= (distance - this.m_Lastdistance) * this.Cmaer_Scale_Speed;
|
|
} else if (offdis > 0) {
|
|
this.mZoomRatio -= (distance - this.m_Lastdistance) * this.Cmaer_Scale_Speed;
|
|
}else{
|
|
this.setTounchRect();
|
|
}
|
|
|
|
this.m_Lastdistance = distance;
|
|
}
|
|
}
|
|
|
|
/**手指抬起 */
|
|
public onMouseUp(event: EventTouch) {
|
|
this.m_TounchDown = false;
|
|
this.m_Lastdistance = -1;
|
|
if (!this.m_IsClickDown) { this.isMove = true;return;}
|
|
this.m_IsClickDown = false;
|
|
MesMgr.event("MoveToPoint", this.getScreenToWorldPoint(event))
|
|
}
|
|
|
|
/**手指在目标区域内抬起 作用同onMouseUp 一样 */
|
|
public onMouseLeave(event: EventTouch) {
|
|
this.onMouseUp(event);
|
|
}
|
|
|
|
/**滑轮滚动 */
|
|
public onMouseWheel(event: EventMouse) {
|
|
let scrollY = event.getScrollY();
|
|
this.mZoomRatio += scrollY / 100 * this.Cmaer_Scale_Speed;
|
|
//this.setTounchRect();
|
|
}
|
|
|
|
private onMouseWheel_document(e) {
|
|
let dir = 0;
|
|
if (e.wheelDelta) {
|
|
dir = e.wheelDelta;
|
|
}
|
|
else if (e.detail) {
|
|
dir = e.detail;
|
|
}
|
|
if (dir < 0) {
|
|
this.mZoomRatio += dir / 100 * this.Cmaer_Scale_Speed;
|
|
} else if (dir > 0) {
|
|
this.mZoomRatio += dir / 100 * this.Cmaer_Scale_Speed;
|
|
}else{
|
|
this.setTounchRect();
|
|
}
|
|
|
|
}
|
|
|
|
//#endregion
|
|
|
|
}
|