/**
* 瓦片地图
*/
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的标记