Laya中使用tiledMap瓦片地图以及遇到的坑

/**
* 瓦片地图
*/
import Stage = Laya.Stage;
import TiledMap = Laya.TiledMap;
import Browser = Laya.Browser;
import Sprite = Laya.Sprite;
import MapLayer = Laya.MapLayer;
import Point = Laya.Point;

import Brick from './Brick';

export default class CTiledMap {//extends Laya.Script

    private _tMap: Laya.TiledMap;
    
    private mLastMouseX: number = 0;
    private mLastMouseY: number = 0;

    private mX: number = 0; //地图初始位置
    private mY: number = 0;
    private _moveSpeedY:number = 1;//移动速度

    private _loadFinished:boolean = false;//是否加载完成
    private _startMove: boolean = true;
    private _testSprite:Sprite = null;//用于测试瓦片位置的精灵对象
    private _bgLayer:MapLayer = null; //背景层
    private _objLayer:MapLayer = null;//对象层
    private _showCollider:boolean = false;//是否显示碰撞体
    private _testTouch:boolean = false;//是否测试触摸反馈

    // constructor() {
    //     super();
    // }

    // onEnable(){

    /**
     * 加载瓦片地图
     * path:地图文件路径
     */
    loadTiledMap(path:string){
        if(this._tMap){
            return;
        }
        //注意!!!
        //在加载成功之前如果调用地图刷新,会使用到错误的数据,导致显示错误或者显示不出来,必须要等进入回调后再调用TileMap对象的接口。
        this._tMap = new Laya.TiledMap();
        this._tMap.createMap(path, new Laya.Rectangle(0, 0, Browser.width, Browser.height), Laya.Handler.create(this, this.onLoaded)
        ,new Laya.Rectangle(500, 500, 0, 0));//该扩展区域牵扯到瓦片地图的裁剪优化
    }

    /**
     * 是否有效的地图,地图销毁后返回false
     */
    isValid():boolean{
        return this._tMap != null;
    }

    createTestSprite(){
        let radiusX:number = 32;
        let radiusY:number = 32;//Math.tan(180 / Math.PI * 30) * radiusX;
        let color:string = "#FF7F50";
        
        this._testSprite = new Sprite();
        this._testSprite.graphics.drawLine(0, 0, 0, radiusY*2, color);
        this._testSprite.graphics.drawLine(radiusX*2, 0, radiusX*2, radiusY*2, color);
        this._testSprite.graphics.drawLine(0, 0, radiusX*2, 0, color);
        this._testSprite.graphics.drawLine(0, 0, radiusX*2, 0, color);
        Laya.stage.addChild(this._testSprite);
    }

    onLoaded(){
        console.log('LoadMap success.');
        this._tMap.setViewPortPivotByScale(0,0);
        //Laya引擎默认把瓦片地图直接add到stage上,导致加载的地图必然在整个Scene上方,所以这里手动调整层级
        //stage共有两个node,0:Scene,1:tiledMap,将tiledMap移动到Scene中。
        let mapNode:Laya.Node = Laya.stage.removeChildAt(1);
        Laya.stage.getChildAt(0).getChildAt(0).addChild(mapNode);
        // let sp = this._tMap.mapSprite() as Laya.Sprite;
        
        this.mY = this._tMap.height;//地图初始位置在屏幕外

        // this._bgLayer = this._tMap.getLayerByIndex(0);
        // if(this._bgLayer){
        //     //this._bgLayer.getTileData();
        // }

        this._objLayer = this._tMap.getLayerByName("Objects");
        //this._tMap.getTileProperties();
        if(this._objLayer){
            for(let i = 0; i < this._objLayer.numChildren; ++i){
                let obj = this._objLayer.getChildAt(i);
                if(obj instanceof Laya.GridSprite){
                    let objData = this._objLayer.getObjectDataByName(obj.name);
                    let type = objData['type'];
                    let gid = objData['gid'];
                    let h = objData['height'];
                    console.log('objName: ', obj.name, obj.x, obj.y);
                    if(type == "Brick"){
                        let boxCollider:Laya.BoxCollider = obj.addComponent(Laya.BoxCollider);
                        boxCollider.width = h;
                        boxCollider.height = h;

                        let rigid:Laya.RigidBody = obj.addComponent(Laya.RigidBody);
                        rigid.type = "static";
                        obj.addComponent(Brick);
                    }else if(type == "PolygonCollider"){
                        let points = objData['polygon'];
                        let pStr:string = '';
                       
                        for (let index = 0; index < points.length; index++) {
                            let p = points[index];
                            if(index == points.length - 1){
                                pStr = pStr + p.x + ',' + p.y;
                            }else{
                                pStr = pStr + p.x + ',' + p.y +',';
                            }
                        }
                        //console.log('XY: ', pStr);

                        //绘制碰撞体
                        if (this._showCollider) {
                            let sp = new Laya.Sprite();
                            this._objLayer.addChild(sp);
                            let ps:number[] = [];
                            for (let index = 0; index < points.length; index++) {
                                let p = points[index];
                                ps.push(p.x);
                                ps.push(p.y);
                            }
                            sp.graphics.drawPoly(obj.x, obj.y, ps, "#ffff00");//
                        }
                        
                        //解析并且创建多边形碰撞体
                        let collider:Laya.PolygonCollider = obj.addComponent(Laya.PolygonCollider);
                        collider.points = pStr;
                        collider.label = type;
                        
                        let rigid:Laya.RigidBody = obj.addComponent(Laya.RigidBody);
                        rigid.type = "static";

                        obj.addComponent(Brick);
                        obj.y -= this.mY;//这里初始化每个子对象的位置
                        obj.getComponent(Brick).setCheckDestroyRangeWH(this._tMap.width ,this._tMap.height);
                    }
                }
            }

            // let obj:Laya.GridSprite = this._objLayer.getObjectByName("monster");
            // if(obj != null){
            //     let objData = this._objLayer.getObjectDataByName("monster");
            //     let type = objData['type'];
            //     let gid = objData['gid'];
            //     let test;
            // }
        }
        Laya.stage.on(Laya.Event.RESIZE,this,this.resize);

        if (this._testTouch) {
            Laya.stage.on(Laya.Event.MOUSE_DOWN, this, this.mouseDown);
            Laya.stage.on(Laya.Event.MOUSE_UP, this, this.mouseUp);            
        }
        this._loadFinished = true;

        this.resize();

        //this.createTestSprite();
    }

    //鼠标按下拖动地图
    private mouseDown(): void {
        this.mLastMouseX = Laya.stage.mouseX;
        this.mLastMouseY = Laya.stage.mouseY;
        Laya.stage.on(Laya.Event.MOUSE_MOVE, this, this.mouseMove);
        this._startMove = true;
    }

    private mouseMove(): void {
        //移动地图视口
        let moveX:number = this.mX - (Laya.stage.mouseX - this.mLastMouseX);
        let moveY:number = this.mY - (Laya.stage.mouseY - this.mLastMouseY);
        //console.log("mouseMove moveY : ", moveY);
        if (this._loadFinished) {
            this._tMap.moveViewPort(moveX, moveY);
        }
    }

    private mouseUp(): void {
        this.mX = this.mX - (Laya.stage.mouseX - this.mLastMouseX);
        this.mY = this.mY - (Laya.stage.mouseY - this.mLastMouseY);
        //console.log("mouseUp this.mY : ", this.mY);
        Laya.stage.off(Laya.Event.MOUSE_MOVE, this, this.mouseMove);

        if(this._bgLayer){
            let p:Point = new Point();
            this._bgLayer.getTilePositionByScreenPos(Laya.stage.mouseX , Laya.stage.mouseY, p);
            this._bgLayer.getScreenPositionByTilePos(Math.floor(p.x), Math.floor(p.y), p);
            if(this._testSprite){
                this._testSprite.pos(p.x, p.y);
            }
        }
    }

    // 窗口大小改变,把地图的视口区域重设下
    private resize(): void {
        //console.log("resize this.mY : ", this.mY);
        if(this._loadFinished && this._tMap){
            this._tMap.changeViewPort(this.mX, this.mY, Browser.width, Browser.height);
        }
        
    }       
    destroy(){
        if(this._tMap){
            //console.log("Destroy Map.");
            this._tMap.destroy();
            this._tMap = null;
        }
    }

    onUpdate(){        
        if(this._loadFinished && this._startMove && this._tMap){
            this._tMap.moveViewPort(this.mX, this.mY);
            this.mY -= this._moveSpeedY; 

            if (this._objLayer) {
                //this._objLayer.y = -this.mY;
                //很奇怪,只是移动 _objLayer这个父节点,子对象并不会跟着一起移动,这里必须手动处理每个子对象的移动
                //碰撞体只有地图上方的四个,其他的可能被裁剪掉了
                //碰撞体无法移动
                for(let i = 0; i < this._objLayer.numChildren; ++i){
                    let obj = this._objLayer.getChildAt(i);
                    (obj as Laya.GridSprite).y += this._moveSpeedY;
                }
            }   
            //console.log("this.mY ", this.mY);
        }
        if(this.mY < -(Laya.stage.height + 10)){
            this.destroy();
        }
    }
}

注意!!!在加载成功之前如果调用地图刷新,会使用到错误的数据,导致显示错误或者显示不出来,必须要等进入加载回调后再调用TileMap对象的接口!!!所以增加了一个LoadFinished的标记

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
LayaAir游戏引擎laya.pool是一个对象池管理器,用于创建和管理可重复使用的对象。对象池可以提高游戏的性能和内存管理效率,减少对象的频繁创建和销毁。 以下是laya.pool的基本使用方法: 1. 创建对象池:使用Laya.Pool.createPool方法创建一个新的对象池,并指定对象的类名和初始数量。 ```javascript // 创建一个名为"enemy"的对象池,并指定对象类名和初始数量 Laya.Pool.createPool("enemy", Enemy, 10); ``` 2. 从对象池获取对象:使用Laya.Pool.getItemByClass方法从指定的对象池获取一个可用的对象。 ```javascript // 从名为"enemy"的对象池获取一个Enemy对象 var enemy = Laya.Pool.getItemByClass("enemy", Enemy); ``` 3. 对象重置和使用:在获取到对象后,可以对其进行自定义的初始化或重置操作,然后将其用于你的业务逻辑。 ```javascript // 对获取到的Enemy对象进行初始化操作 enemy.init(); // 使用对象进行相关业务逻辑 enemy.move(); ``` 4. 对象回收和释放:当不再需要使用该对象时,可以使用Laya.Pool.recover方法将其回收到对象池。 ```javascript // 将不再使用的Enemy对象回收到名为"enemy"的对象池 Laya.Pool.recover("enemy", enemy); ``` 通过以上步骤,你可以在游戏使用对象池来重复利用对象,避免频繁创建和销毁对象,提高游戏性能。需要注意的是,对象池的对象应该实现相应的初始化和重置方法,以确保对象在被重新使用时具备正确的状态。 另外,Laya.Pool还提供了其他一些方法,如清空对象池、获取对象池对象数量等,可以根据需要进一步了解和使用

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逍遥游侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值