整個路邊賭場最主要的還是遊戲,因此平台部分我們日後再來做,其實我已經大概寫過一些部分,大概已經有一個規劃的雛型。
以下為初始化遊戲部分的專案架構
內容是基本Typescript設定以及相關套件
2019-IT30-Game
│ .gitignore
│ index.html
│ package.json
│ README.md
│ tsconfig.json
│ webpack.config.js
├─assets
└─src
App.ts
再來我們思考一下我們src內的架構會是如何呢?我們依照自己的專案要進行Pixijs封裝,要如何封裝會比較優呢?
我們新增幾層資料夾以及相關class,這是src下的資料夾結構
└─src
│ App.ts
└─components
└─elements
Wrapper.ts
WrapperType.ts
概念是,我們只要在畫面顯示的物件,基本都是Wrapper,擁有可以縮放、移動、放大等等自訂的方法,WrapperType為一些Wrapper會用到的引數型態。
import * as PIXI from "pixi.js"
import * as WrapperType from '@/components/elements/WrapperType'
export default interface Wrapper {
/**
* 座標
*/
readonly x: number;
readonly y: number
/**
* 大小
*/
readonly width: number
readonly height: number
/**
*
* @param animationOpt 動畫?
* @param x 位置
* @param y 位置
*/
setPosition(animationOpt: WrapperType.animationOpt, x: number, y: number): void
/**
* 設定長寬
* @param animation 動畫?
* @param width 寬度
* @param height 高度
*/
setSize(animation: boolean, width: number, height: number): void
/**
* 添加Container到此Wrapper內
* @param child 要添加的
*/
addChild(child: Wrapper): void
/**
* 添加Container到此Wrapper內
* @param child 要添加的
*/
addContainer(child: any): void
/**
* 取得pixi container
*/
getContainer(): PIXI.Container
/**
* 縮放
* @param animation boolean是否要使用動畫
* @param scale_x x縮放
* @param scale_y y縮放
*/
setScale(animation: boolean, scale_x: number, scale_y: number): void
/**
* interactive
* @param interactive 是否要可以互動
*/
setInteractive(interactive: boolean): void
/**
* Rotation
* @param animation boolean是否要使用動畫
* @param rotation 旋轉角度
*/
setRotation(animation: boolean, rotation: number): void
/**
* Alpha
* @param animation boolean是否要使用動畫
* @param alpha 透明度
*/
setAlpha(animation: boolean, alpha: number): void
/**
* interactive
*/
removeChildren(): void
/**
* 監聽此Container
* @param event 監聽
* @param listener 事件
*/
on(event: string, listener: any): void
/**
* 統一各種手機PC方法
* @param listener 監聽方法
*/
onClick(listener: any): void
/**
* 統一各種手機PC方法
* @param listener 監聽方法
*/
onHover(listener: any): void
}
其中有getContainer或是addChild、addContainer,是因為物件跟物件之間如果要放置在對方內部,必須要直接放進對方的Pixijs container,因次需要一個口讓物件們互相取用,因此有時候還是會使用到Pixijs的操作。
這時我們基礎還需要甚麼呢?早些年我寫過Flash,可以有Group群組的概念,我想了想我應該日後也有群組的需求,但這種多物件互動下,一定會有z-index問題,但似乎是沒有z-index可以使用,決定層級是由addChild的順序,因此我們必須要有規劃的addChild。
於是新增兩個檔案
└─src
│ App.ts
└─components
└─elements
Wrapper.ts
WrapperContainer.ts
WrapperContainerCenter.ts
WrapperType.ts
這兩個WrapperContainer、WrapperContainerCenter作用為何呢?
都是一種容器的概念,可以做為包裝Group的容器或是圖層概念的容器,用來裝更多的Wrapper物件。
WrapperContainerCenter是置中的容器,裝的物件在裡面setScale或是setRotation都會從中間轉動,那這怎麼做到的呢?就靠以下
this._centerContainer = new WrapperContainer()
this._centerContainer.getContainer().pivot.set(this._centerContainer.width / 2, this._centerContainer.height / 2)
this._centerContainer.setPosition({ animation: false }, this._centerContainer.width / 2, this._centerContainer.height / 2)
其實內部分有多包一個Wrapper把他的pivot移動到中心,再把他的position推到中心。
並且透過我們把各種方法,像是setScale要針對中心,就把setScale指定操作內部中心容器,如果像是setPosition,要是原始左上角的,就操作外部普通容器,這樣達到中間旋轉縮放等等。
再來進入我們基本的pixijs物件囉!
└─src
│ App.ts
└─components
└─elements
Animation.ts
Sprite.ts
Texture.ts
Wrapper.ts
WrapperContainer.ts
WrapperContainerCenter.ts
WrapperType.ts
新增Animation、Sprite、Texture
Animation:多張連續圖,藉此達成動畫效果。
Sprite:一堆圖壓在同一張圖上,會以對應大小位置找到圖,CSS Sprite就是這種概念。
Texture:單張大圖
Texture.ts
export default class Texture implements Wrapper {
private _container: PIXI.Container
/**
* @param targetPath 要產生甚麼圖
*/
constructor(targetPath: string) {
let sprite = new PIXI.Sprite(PIXI.utils.TextureCache[targetPath])
this._container = new PIXI.Container()
this._container.addChild(sprite)
}
...以下省略
public setSize(animation: boolean, width: number, height: number) {
if (animation) {
TweenMax.to(this._container, 0.6, { width: width, height: height });
} else {
this._container.width = width
this._container.height = height
}
}
...以下省略
}
以上為Texture使用constructor指定path來決定圖片,且搭配GSAP TweenMax達到漸變效果。
其他兩種差異不大,頂多為傳入參數不同。如果要看整個架構請至Repositories看囉!
其實這遊戲專案我已經重寫寫過兩三次,大意都差不多,但都在規劃上出了些問題,因沒考慮到某些狀況,而最後的資料websocket串接會是最麻煩的!
實際預覽發現頁面有夠難閱讀,建議直接看Github Repositories,直接看比較容易理解