大侠
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

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
}