game flow
This commit is contained in:
@ -14,10 +14,13 @@ import { Tile } from '@/game/Tile'
|
||||
import { DIRECTIONS, createContainer, isTilePair } from '@/common/helpers'
|
||||
import { createText } from '@/game/utilities/fonts'
|
||||
import { Dot } from '@/game/Dot'
|
||||
import { LoggingService } from '@/services/LoggingService'
|
||||
import { inject } from 'vue'
|
||||
|
||||
export class Board extends EventEmitter {
|
||||
private _scale: number = 1
|
||||
private _canMove: boolean = false
|
||||
private logger = inject<LoggingService>('logger')!
|
||||
|
||||
ticker: Ticker
|
||||
height: number
|
||||
@ -25,7 +28,7 @@ export class Board extends EventEmitter {
|
||||
grain: number = 25
|
||||
scaleY: ScaleFunction
|
||||
scaleX: ScaleFunction
|
||||
state: GameState | undefined
|
||||
state?: GameState
|
||||
container!: Container
|
||||
initialContainer!: Container
|
||||
tilesContainer!: Container
|
||||
@ -45,7 +48,7 @@ export class Board extends EventEmitter {
|
||||
leftDirection: string = 'west'
|
||||
rightDirection: string = 'east'
|
||||
playerHand: Tile[] = []
|
||||
firstTile: Tile | undefined
|
||||
firstTile?: Tile
|
||||
|
||||
constructor(app: Application) {
|
||||
super()
|
||||
@ -63,8 +66,8 @@ export class Board extends EventEmitter {
|
||||
})
|
||||
|
||||
const background = new Sprite(Assets.get('bg-1'))
|
||||
background.width = this.width
|
||||
background.height = this.height
|
||||
// background.width = this.width
|
||||
// background.height = this.height
|
||||
this.container.addChild(background)
|
||||
|
||||
this.initialContainer = createContainer({
|
||||
@ -102,7 +105,13 @@ export class Board extends EventEmitter {
|
||||
this.tilesContainer.addChild(verticalLine)
|
||||
this.tilesContainer.addChild(horizontalLine)
|
||||
|
||||
this.createTexts()
|
||||
this.textContainer = createContainer({
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
parent: this.container
|
||||
})
|
||||
|
||||
this.showText('Starting game...')
|
||||
}
|
||||
|
||||
private calculateScale() {
|
||||
@ -138,20 +147,17 @@ export class Board extends EventEmitter {
|
||||
this.playerHand = tiles
|
||||
}
|
||||
|
||||
createTexts() {
|
||||
this.textContainer = new Container()
|
||||
this.textWaitForPlayers = createText('Waiting for players', this.scaleX(0), 100)
|
||||
this.textYourTurn = createText('Your turn!', this.scaleX(0), 100)
|
||||
|
||||
this.container.addChild(this.textContainer)
|
||||
this.textContainer.addChild(this.textWaitForPlayers)
|
||||
this.textContainer.addChild(this.textYourTurn)
|
||||
this.textYourTurn.visible = false
|
||||
showText(text: string) {
|
||||
this.textContainer.removeChildren()
|
||||
this.textContainer.addChild(createText(text, this.scaleX(0), 100))
|
||||
}
|
||||
|
||||
private updateCanMoveText() {
|
||||
this.textWaitForPlayers.visible = !this.canMove
|
||||
this.textYourTurn.visible = this.canMove
|
||||
if (this.canMove) {
|
||||
this.showText('Your turn!')
|
||||
} else {
|
||||
this.showText('Waiting for players')
|
||||
}
|
||||
}
|
||||
|
||||
setState(state: GameState, playerId: string) {
|
||||
@ -161,7 +167,6 @@ export class Board extends EventEmitter {
|
||||
if (lastMove === null) {
|
||||
return
|
||||
}
|
||||
console.log('lastMove :>> ', lastMove)
|
||||
if (
|
||||
lastMove !== null &&
|
||||
lastMove.tile !== undefined &&
|
||||
@ -319,7 +324,6 @@ export class Board extends EventEmitter {
|
||||
y += isEndVertical && !isNextVertical ? 0 : 1
|
||||
}
|
||||
}
|
||||
console.log('position::>>', tile.pips, x, y)
|
||||
tile.setPosition(this.scaleX(x), this.scaleY(y))
|
||||
tile.setOrientation(orientation)
|
||||
tile.reScale(this.scale)
|
||||
@ -386,7 +390,7 @@ export class Board extends EventEmitter {
|
||||
this.addTile(tile, move)
|
||||
this.setFreeEnd(move)
|
||||
} catch (error) {
|
||||
console.log('error :>> ', error)
|
||||
this.logger.error(error, 'Error updating board')
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,7 +399,6 @@ export class Board extends EventEmitter {
|
||||
}
|
||||
|
||||
setValidEnds(values: boolean[], tile: TileDto) {
|
||||
console.log('validEnds')
|
||||
if (this.count === 0) {
|
||||
this.createInteractionsII('right', [[0, 0], undefined, undefined, undefined])
|
||||
return
|
||||
@ -405,15 +408,12 @@ export class Board extends EventEmitter {
|
||||
const side = 'left'
|
||||
const validInteractions = this.nextTileValidMoves(tile, side)
|
||||
const validPoints = this.nextTileValidPoints(tile, side, validInteractions)
|
||||
console.log('validInteractions :>> ', validInteractions)
|
||||
// this.createInteractions(side, tile)
|
||||
this.createInteractionsII(side, validPoints)
|
||||
}
|
||||
if (values[1]) {
|
||||
const side = 'right'
|
||||
const validInteractions = this.nextTileValidMoves(tile, side)
|
||||
const validPoints = this.nextTileValidPoints(tile, side, validInteractions)
|
||||
console.log('validInteractions :>> ', validInteractions)
|
||||
this.createInteractionsII(side, validPoints)
|
||||
}
|
||||
}
|
||||
@ -501,7 +501,6 @@ export class Board extends EventEmitter {
|
||||
dot.alpha = 0.5
|
||||
dot.interactive = true
|
||||
dot.on('pointerdown', () => {
|
||||
console.log('direction :>> ', direction)
|
||||
this.emit(`${side}Click`, direction && { direction, x, y })
|
||||
this.cleanInteractions()
|
||||
})
|
||||
@ -567,4 +566,21 @@ export class Board extends EventEmitter {
|
||||
}
|
||||
return [canPlayNorth, canPlayEast, canPlaySouth, canPlayWest]
|
||||
}
|
||||
|
||||
gameFinished() {
|
||||
this.tiles = []
|
||||
this.boneyard = []
|
||||
this.movements = []
|
||||
this.playerHand = []
|
||||
this.freeEnds = undefined
|
||||
this.leftTile = undefined
|
||||
this.rightTile = undefined
|
||||
this.nextTile = undefined
|
||||
this.leftDirection = 'west'
|
||||
this.rightDirection = 'east'
|
||||
this.firstTile = undefined
|
||||
this.tilesContainer.removeChildren()
|
||||
this.interactionContainer.removeChildren()
|
||||
this.showText('Game finished')
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import { assets } from '@/game/utilities/assets'
|
||||
import { Tile } from '@/game/Tile'
|
||||
import { Hand } from '@/game/Hand'
|
||||
import type { Movement, TileDto } from '@/common/interfaces'
|
||||
import type { SocketIoClientService } from '@/services/SocketIoClientService'
|
||||
|
||||
export class Game {
|
||||
public board!: Board
|
||||
@ -19,7 +20,9 @@ export class Game {
|
||||
height: 650
|
||||
},
|
||||
private emit: any,
|
||||
private props: any
|
||||
private socketService: SocketIoClientService,
|
||||
private playerId: string,
|
||||
private sessionId: string
|
||||
) {}
|
||||
|
||||
async setup(): Promise<HTMLCanvasElement> {
|
||||
@ -66,11 +69,18 @@ export class Game {
|
||||
const move: Movement = {
|
||||
id: '',
|
||||
type: 'pass',
|
||||
playerId: this.props.playerId ?? ''
|
||||
playerId: this.playerId
|
||||
}
|
||||
this.emit('move', move)
|
||||
this.board.updateBoard(move)
|
||||
})
|
||||
|
||||
this.hand.on('nextClick', async () => {
|
||||
await this.socketService.sendMessageWithAck('playerReady', {
|
||||
user: this.playerId,
|
||||
sessionId: this.sessionId
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
getMoves(tile: any): [boolean, boolean] {
|
||||
@ -101,7 +111,7 @@ export class Game {
|
||||
const move: Movement = {
|
||||
tile: this.selectedTile,
|
||||
type: 'left',
|
||||
playerId: this.props.playerId ?? '',
|
||||
playerId: this.playerId,
|
||||
...data
|
||||
}
|
||||
this.emit('move', move)
|
||||
@ -115,7 +125,7 @@ export class Game {
|
||||
const move: Movement = {
|
||||
tile: this.selectedTile,
|
||||
type: 'right',
|
||||
playerId: this.props.playerId ?? '',
|
||||
playerId: this.playerId,
|
||||
...data
|
||||
}
|
||||
this.emit('move', move)
|
||||
@ -124,6 +134,11 @@ export class Game {
|
||||
})
|
||||
}
|
||||
|
||||
gameFinished() {
|
||||
this.hand.gameFinished()
|
||||
this.board.gameFinished()
|
||||
}
|
||||
|
||||
private removeBoardEvents() {
|
||||
this.board.off('leftClick')
|
||||
this.board.off('rightClick')
|
||||
|
@ -9,13 +9,16 @@ import {
|
||||
Ticker
|
||||
} from 'pixi.js'
|
||||
import { Tile } from '@/game/Tile'
|
||||
import type { PlayerState, TileDto } from '@/common/interfaces'
|
||||
import type { Dimension, PlayerDto, TileDto } from '@/common/interfaces'
|
||||
import { GlowFilter } from 'pixi-filters'
|
||||
import { Scale, type ScaleFunction } from './utilities/scale'
|
||||
import { LoggingService } from '@/services/LoggingService'
|
||||
|
||||
export class Hand extends EventEmitter {
|
||||
tiles: Tile[] = []
|
||||
container: Container = new Container()
|
||||
buttonPassContainer: Container = new Container()
|
||||
buttonPass: Container = new Container()
|
||||
buttonNext: Container = new Container()
|
||||
height: number
|
||||
width: number
|
||||
ticker: Ticker
|
||||
@ -24,6 +27,10 @@ export class Hand extends EventEmitter {
|
||||
initialized: boolean = false
|
||||
_canMove: boolean = false
|
||||
scale: number = 1
|
||||
scaleY!: ScaleFunction
|
||||
scaleX!: ScaleFunction
|
||||
grain: number = 25
|
||||
logger: LoggingService = new LoggingService()
|
||||
|
||||
constructor(app: Application) {
|
||||
super()
|
||||
@ -34,24 +41,47 @@ export class Hand extends EventEmitter {
|
||||
this.container.y = app.canvas.height - this.height
|
||||
this.container.width = this.width
|
||||
this.container.height = this.height
|
||||
this.calculateScale()
|
||||
this.addBg()
|
||||
this.createPassButton()
|
||||
}
|
||||
|
||||
gameFinished() {
|
||||
this.logger.debug('gameFinished')
|
||||
this.tiles = []
|
||||
this.container.removeChildren()
|
||||
this.initialized = false
|
||||
this.buttonNext = this.createButton(
|
||||
'NEXT',
|
||||
{ x: this.width / 2 - 25, y: this.height / 2, width: 50, height: 20 },
|
||||
'nextClick'
|
||||
)
|
||||
}
|
||||
|
||||
get canMove() {
|
||||
return this._canMove
|
||||
}
|
||||
|
||||
private calculateScale() {
|
||||
const scaleXSteps = Math.floor(this.width / (this.grain * this.scale)) / 2
|
||||
const scaleYSteps = Math.floor(this.height / (this.grain * this.scale)) / 2
|
||||
this.scaleX = Scale([-scaleXSteps, scaleXSteps], [0, this.width])
|
||||
this.scaleY = Scale([-scaleYSteps, scaleYSteps], [0, this.height])
|
||||
}
|
||||
|
||||
set canMove(value: boolean) {
|
||||
this._canMove = value
|
||||
this.buttonPassContainer.eventMode = value ? 'static' : 'none'
|
||||
this.buttonPassContainer.cursor = value ? 'pointer' : 'default'
|
||||
if (value) {
|
||||
this.createPassButton()
|
||||
} else {
|
||||
this.container.removeChild(this.buttonPass)
|
||||
}
|
||||
|
||||
this.tiles.forEach((tile) => {
|
||||
tile.interactive = value
|
||||
})
|
||||
}
|
||||
|
||||
initialize(playerState: PlayerState) {
|
||||
initialize(playerState: PlayerDto) {
|
||||
this.tiles = this.createTiles(playerState)
|
||||
this.emit('handUpdated', this.tiles)
|
||||
this.initialized = this.tiles.length > 0
|
||||
@ -106,11 +136,15 @@ export class Hand extends EventEmitter {
|
||||
tile.off('pointerout')
|
||||
}
|
||||
|
||||
private createPassButton() {
|
||||
const rectangle = new Graphics().roundRect(0, 0, 80, 30, 10).fill(0xffff00)
|
||||
|
||||
private createButton(
|
||||
textStr: string,
|
||||
dimension: Dimension,
|
||||
action: string | Function
|
||||
): Container {
|
||||
const { x, y, width, height } = dimension
|
||||
const rectangle = new Graphics().roundRect(x, y, width + 4, height + 4, 5).fill(0xffff00)
|
||||
const text = new Text({
|
||||
text: 'PASS',
|
||||
text: textStr,
|
||||
style: {
|
||||
fontFamily: 'Arial',
|
||||
fontSize: 12,
|
||||
@ -120,38 +154,45 @@ export class Hand extends EventEmitter {
|
||||
}
|
||||
})
|
||||
text.anchor = 0.5
|
||||
const container = new Container()
|
||||
container.addChild(rectangle)
|
||||
container.addChild(text)
|
||||
|
||||
this.buttonPassContainer = new Container()
|
||||
text.y = y + height / 2
|
||||
text.x = x + width / 2
|
||||
|
||||
this.buttonPassContainer.addChild(rectangle)
|
||||
this.buttonPassContainer.addChild(text)
|
||||
|
||||
text.y = this.buttonPassContainer.height / 2 - 4
|
||||
text.x = this.buttonPassContainer.width / 2 - 8
|
||||
|
||||
this.buttonPassContainer.eventMode = 'none'
|
||||
this.buttonPassContainer.cursor = 'default'
|
||||
this.buttonPassContainer.x = 20
|
||||
this.buttonPassContainer.y = this.height / 2 - 10
|
||||
container.eventMode = 'static'
|
||||
container.cursor = 'pointer'
|
||||
rectangle.alpha = 0.7
|
||||
text.alpha = 0.7
|
||||
this.buttonPassContainer.on('pointerdown', () => {
|
||||
this.emit('passClick')
|
||||
container.on('pointerdown', () => {
|
||||
action instanceof Function ? action() : this.emit(action)
|
||||
})
|
||||
this.buttonPassContainer.on('pointerover', () => {
|
||||
container.on('pointerover', () => {
|
||||
rectangle.alpha = 1
|
||||
text.alpha = 1
|
||||
})
|
||||
|
||||
this.buttonPassContainer.on('pointerout', () => {
|
||||
container.on('pointerout', () => {
|
||||
rectangle.alpha = 0.7
|
||||
text.alpha = 0.7
|
||||
})
|
||||
|
||||
this.container.addChild(this.buttonPassContainer)
|
||||
this.container.addChild(container)
|
||||
return container
|
||||
}
|
||||
|
||||
update(playerState: PlayerState) {
|
||||
private createPassButton() {
|
||||
const lastTile = this.tiles[this.tiles.length - 1]
|
||||
const x = lastTile ? lastTile.x + lastTile.width : this.scaleX(0)
|
||||
this.buttonPass = this.createButton(
|
||||
'PASS',
|
||||
{ x, y: this.height / 2, width: 50, height: 20 },
|
||||
'passClick'
|
||||
)
|
||||
}
|
||||
|
||||
update(playerState: PlayerDto) {
|
||||
if (!this.initialized) {
|
||||
this.initialize(playerState)
|
||||
return
|
||||
@ -167,7 +208,7 @@ export class Hand extends EventEmitter {
|
||||
this.renderTiles()
|
||||
}
|
||||
|
||||
private createTiles(playerState: PlayerState) {
|
||||
private createTiles(playerState: PlayerDto) {
|
||||
return playerState.hand.map((tile) => {
|
||||
const newTile: Tile = new Tile(tile.id, this.ticker, tile.pips, this.scale)
|
||||
newTile.alpha = 0.7
|
||||
|
Reference in New Issue
Block a user