Cocos creator主程入門教程——瓦片地圖
這一篇介紹瓦片地圖,在開發(fā)模擬經(jīng)營類游戲、SLG類游戲、RPG游戲,都會使用到瓦片地圖。瓦片地圖地面是通過一個個地磚拼起來的,又分為45度角和90度角兩種。45度角俗稱2.5D,每個格子都是菱形,而90度角每個格子都是正方形。
瓦片地圖一般包括以下圖層(不一定同時存在,例如一般RPG游戲沒有背景和自由裝飾層):
1.背景層(大圖拼接的背景)
2.地形層(瓦片格子拼接的地形)
3.建筑層(按瓦片格子擺放的建筑、地面物品、角色)
4.自由裝飾層(云朵、煙霧)
除此以外,還需要提供隱藏的層用于編輯數(shù)據(jù),控制游戲邏輯,例如阻擋、擺放區(qū)域等,稱為數(shù)據(jù)層。其中需要瓦片布局的有3種圖層:地形層、建筑層、數(shù)據(jù)層。
先來說說背景層BgLayer,背景層在美術設計里是張完整的大圖,為了避免連續(xù)內(nèi)存太大導致加載失敗,把大圖打碎成等大小的小圖拼接。一般出于性能考慮,小圖長寬選擇為1024、512、256、128。
設置背景需要提供背景的小圖數(shù)組,列數(shù),每張小圖的寬高
1public setPieces(fileArr: Array, colCount: number, pieceW: number, pieceH: number, loadAtOnce: boolean = true): void {}
如果是在H5平臺,要考慮資源的逐步加載。所以在H5平臺該方法最好只是做占位,提供方法進行資源加載
1public loadPiece(file: string) {}
除了加載外,由于玩家在移動地圖時只看到背景的一部分,不在視窗內(nèi)的應該裁剪掉,所以還要提供方法對背景進行裁剪
1public setViewPort(x: number, y: number, w: number, h: number): void {}
完全不在視窗的小圖,通過removeFromParent從渲染列表移除。
接下來說說基于瓦片布局的圖層?;谕咂膱D片我們會擺放一些物品,例如地形層的地形塊、建筑層的建筑、地面物品、角色。所以在介紹瓦片布局的圖層前,先介紹下地圖里的物品。一般包括:
1.地形塊
2.建筑、地面物品
3.角色
4.編輯數(shù)據(jù)
先設計一個基類MapItem,定義物品的基本屬性:格子位置、寬高占格子數(shù)、是否可穿越、可否編輯
export class MapItem extends cc.Component {
protected mGridX: number = 0;
protected mGridY: number = 0;
protected mRow: number = 1;
protected mCol: number = 1;
protected mCanPass: boolean = true;
private mEditable: boolean = true;
private mIsLock: boolean = false;
}
地形塊主要是顯示一張一格大小的圖片,一般會先把這些地形圖片合成一張大圖,按照格子大小等分。設計一個TileSet類定義這張合圖的結(jié)構(gòu)
export class TileSet {
private mId: number = -1;
private resPath: string = null;
private tex: cc.Texture2D = null;
private gridW: number = 0;
private gridH: number = 0;
private row: number = 0;
private col: number = 0;
}
每個地形塊Tile引用TileSet里的資源
export class Tile extends MapItem {
private mSpr: cc.Sprite = null;
private mId: number = 0;
private mTileSetId: number = 0;
private mIdx: number = 0;
}
當然,如果希望地面有幀動畫,也可以讓Tile保存一個幀系列,按順序切換mSpr的spriteFrame屬性。
建筑要考慮建筑、地面物品的方向和操作
export class MapBuilding extends MapItem {
protected mId: number = 0;
protected mType: number = 0;
protected mResType: number = 0; // 0 image, 1 spine
protected mResPath: string = null;
protected mDir: number = 0;
protected mReverse: boolean = false;
}
為了區(qū)分擺放和旋轉(zhuǎn)點,我會給MapBuilding添加兩個子節(jié)點,因為在45角地圖擺放建筑時,一般以右下角格子做擺放參考點,但是旋轉(zhuǎn)是以左上角格子為參考。
需要注意,在H5平臺,建筑的圖片資源應該是動態(tài)加載的,在地圖移動時逐漸加載顯示。所以要提供接口對資源進行加載。
1public loadRes(): void {}
還有點擊范圍,圖片是矩形的,點擊的時候可能是點到了圖片的空白區(qū)域,這時后玩家看到的是點擊了后面的建筑,如果沒有處理透明區(qū)域剔除,實際判斷卻是點擊了前面的建筑。對于圖片資源的建筑在H5平臺,可以通過使用該圖片相同位置,截取點擊區(qū)的一個像素,模擬畫在屏幕該地方,如果getImageData獲取的data[3]不是0,說明點擊到了該建筑,否則是點擊了空白區(qū)。
角色都是spine動畫,是可以運動的物體,需要路徑、速度相關的屬性
export class MapActor extends cc.Component {
protected mActorId: number = 0;
protected mResPath: string = null;
protected mRoadGrids: Array = []; // 路徑
protected mCurRoadIdx: number = 0;
protected mSpeed: number = 0; // 設置的行走速度, 跟x方向速度絕對值一樣
protected mSpeedX: number = 0; // 實時行走X速度
protected mSpeedY: number = 0; // 實時行走Y速度
protected mTestActor: boolean = false;
protected mIsKeepRoad: boolean = false;
protected mIsPauseWalk: boolean = false;
}
編輯數(shù)據(jù)是不可見的,只有基本的位置信息和相應數(shù)據(jù)
export class MapDataItem extends MapItem {
private data: any = null;
}
瓦片布局的圖層有一個基類,負責物品MapItem的添加、刪除、查詢等操作
/**
* 基于地磚的圖層基類
* 定義基于地磚圖層基本數(shù)據(jù)和接口
*/
export abstract class TileBaseLayer extends cc.Component implements GestureListener {
protected mRow: number = 0;
protected mCol: number = 0;
protected mGridW: number = 0;
protected mGridH: number = 0;
protected mMapItems: Array<MapItem> = [];
protected mOriX: number = 0;
protected mOriY: number = 0;
}
對于90度角的地圖,沒有太多復雜的地方需要處理。點擊點到格子的映射是簡單除以寬、高。遮擋是從左往右,從上到下設定zorder。
對于45度角的地圖,點擊點到格子的映射需要用到解析幾何


每個點擊點,按照格子寬高比的斜率經(jīng)過該點作直線,到經(jīng)過點(oriX,oriY)平行于x軸的直線都有交點,而且交點的距離等于格子的寬度。所以,交點相對于點(oriX,oriY)的距離(x - oriX)可以判斷該點屬于哪行或哪列。對于行,交點可以通過(oriY - touchY)* (gridW / gridH) - (touchX - oriX)。對于列,交點可以通過(touchX - oriX) + (oriY - touchY)* (gridW / gridH)。(平行、三角形中同樣大小的角的對邊比鄰邊比例一樣)
角色起始在格子中心點,行走的時候,按照格子的寬高比,把速度分解為x、y兩個方向,這樣角色就能沿著格子走下去。每次走到格子中心時才做站立、繼續(xù)行走的處理。
遮擋方面,45度角依然是從上到下遮擋

要注意的是,建筑占多格,而設置遮擋時只能設置zorder,所以采用的是中心位置方式,把建筑中心格子作為zorder的參照。角色在地圖中行走的時候,按上圖的規(guī)則修改角色的zorder,建筑的zorder一直不變。
自由裝飾層沒有擺放限制,可以放置云朵、霧等動畫,增加層次感。
更多資源請訪問:https://bycwedu.vipwan.cn/promotion_channels/630597732