昨天我們造了一個簡易版本Redux,當然有很多其他Redux方便的東西,但小弟水平有限、並沒有特別使用其他部分,畢竟學的穩才能走得久,沒有特別學一手工具,未來慢慢增加囉!考量到其實用到的不多,其實籌碼、金額差不多就這樣,但因為我不想讓狀態非常凌亂。
我們新增了一個Store資料夾,有actions、reducer、store等等,我們需要的一切。
└─src
│ App.ts
│ Game.ts
├─components
│ ├─elements
│ │ ...省略
│ ├─groups
│ │ ...省略
│ └─objects
│ ...省略
├─config
│ ...省略
│
├─loaders
│ ...省略
├─store ***
│ actions.ts
│ index.ts
│ reducer.ts
│ redux.ts
│ store.ts
└─utils
這是我們action部分,包含action type,有給他一些基礎類型,讓我們派發的時候順順利利,有預設類型,方便我選擇。
import chipType from '@/config/chipType'
export interface Action {
type: string,
payload: any
}
export interface chipPayload {
chip: keyof typeof chipType
}
export interface balancePayload {
balance: Number
}
/*
* action type
*/
export const UPDATE_BALANCE = 'UPDATE_BALANCE'
export const UPDATE_CHIP = 'UPDATE_CHIP'
export const INIT = 'INIT'
/*
* action creator
*/
export function updateBalance(payload: balancePayload) {
return { type: UPDATE_BALANCE, payload }
}
export function updateChip(payload: chipPayload) {
return { type: UPDATE_CHIP, payload }
}
export function init() {
return { type: INIT }
}
這是我們的reducer,有一些我們派發動作之後會做的行為。有更新餘額以及更新選擇的籌碼。
import { UPDATE_BALANCE, UPDATE_CHIP, Action } from './actions'
function reducer(state = {}, action: Action) {
switch (action.type) {
case UPDATE_BALANCE:
return Object.assign({}, state, { balance: action.payload.balance })
case UPDATE_CHIP:
return Object.assign({}, state, { chip: action.payload.chip })
default:
return state
}
}
export default reducer
Store就是我們建出我們Store的地方,就可以直接引入,直接dispatch,舒舒服服的使用。
import { reducer, createStore } from "@/store/index";
let store = createStore(reducer, { chip: '1000', balance: 99999 })
export default store
我們增加hookChip,針對每一個chip綁上subscribe,只要store有更新就會通知訂閱者,訂閱者就會去與store要取新資料,並把現在選取的籌碼設定為選取狀態。至於為何要先執行一次update,其原因就是因為首次進入時,就算store有初始化,但那時訂閱者還沒訂閱store,導致畫面第一次並沒有更新,因此我們需要先取一次狀態。
ChipBox.ts
// ...引入省略
export default class ChipBox extends WrapperContainerCenter {
private _chipList: Array<Chip> = []
constructor() {
super()
for (let v in chipType) {
let chip = new Chip(v as keyof typeof chipType)
this.addChild(chip)
this._chipList.push(chip)
}
for (let i in this._chipList) {
this._chipList[i].setPosition({ animation: false }, Number(i) * this._chipList[i].width * 1.05, 0)
this._chipList[i].setInteractive(true)
this.hookChip(this._chipList[i])
}
}
public hookChip(chip: Chip) {
chip.setInteractive(true)
chip.onClick(() => {
store.dispatch(actions.updateChip({ chip: chip.value }))
})
let _update = () => {
let state = store.getState()
if (state.chip === chip.value) {
chip.setPosition({ animation: true }, chip.x, -30)
} else {
chip.setPosition({ animation: true }, chip.x, 0)
}
}
store.subscribe(_update)
_update()
}
public setPosition(animationOpt: WrapperType.animationOpt, x: number, y: number): void {
this.updateCenter()
this._centerContainer.setPosition(animationOpt, x, y)
}
}
一樣初始化時先取得目前store資料,並更新目前餘額。
// Info.ts
// ... 省略引入
export default class Info extends WrapperContainer {
private _infoMoneyNumber: InfoMoneyNumber
private _infoBg: Sprite
private _moneyIcon: Sprite
private _balance: number
constructor() {
super()
this._infoBg = new Sprite(imagePath.interfacePath, 'infobg')
this._moneyIcon = new Sprite(imagePath.interfacePath, 'money')
this._balance = 0
this._infoMoneyNumber = new InfoMoneyNumber(this._balance)
this.addChild(this._infoBg)
this.addChild(this._moneyIcon)
this.addChild(this._infoMoneyNumber)
this._infoMoneyNumber.setPosition({ animation: false }, 70, 67)
this._moneyIcon.setPosition({ animation: false }, 10, 100)
this._moneyIcon.setRotation(false, -Math.PI * 0.5)
let _update = () => {
let { balance } = store.getState()
this._infoMoneyNumber.updateNumber(balance)
}
store.subscribe(_update)
_update()
}
}
今天的內容算是昨天的延伸,接下來應該就是難搞的籌碼亂飛,下注狀態等等,目前後端遊戲伺服器已經大概有雛形,等到穩定之後即可串上前端介面了!