feat(game): 添加麻将牌图片映射配置并优化成都麻将页面
- 新增 tileMap.ts 配置文件,定义麻将牌图片映射逻辑 - 实现根据花色和点数获取对应图片路径的功能 - 添加麻将牌验证和基础牌生成工具函数 - 在 ChengduGamePage.vue 中导入并使用 getTileImage 函数 - 添加服务器响应日志用于调试 - 优化玩家手牌显示区域的布局结构
This commit is contained in:
111
src/config/tileMap.ts
Normal file
111
src/config/tileMap.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
// src/config/tileMap.ts
|
||||
|
||||
export type Suit = 'W' | 'T' | 'B'
|
||||
|
||||
export interface Tile {
|
||||
id: number
|
||||
suit: Suit
|
||||
value: number
|
||||
}
|
||||
|
||||
export type TilePosition = 'bottom'
|
||||
|
||||
const SUIT_INDEX_MAP: Record<Suit, 1 | 2 | 3> = {
|
||||
W: 1, // 万
|
||||
T: 2, // 筒
|
||||
B: 3, // 条
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前目录结构:
|
||||
* /src/assets/images/tiles/bottom/p4b1_1.png
|
||||
* /src/assets/images/tiles/bottom/p4b2_1.png
|
||||
* /src/assets/images/tiles/bottom/p4b3_1.png
|
||||
*/
|
||||
function buildTileImageKey(
|
||||
suit: Suit,
|
||||
value: number,
|
||||
position: TilePosition = 'bottom',
|
||||
): string {
|
||||
const suitIndex = SUIT_INDEX_MAP[suit]
|
||||
return `/src/assets/images/tiles/${position}/p4b${suitIndex}_${value}.png`
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过 Vite 收集所有麻将牌资源
|
||||
*/
|
||||
const tileImageModules = import.meta.glob(
|
||||
'/src/assets/images/tiles/bottom/*.png',
|
||||
{
|
||||
eager: true,
|
||||
import: 'default',
|
||||
},
|
||||
) as Record<string, string>
|
||||
|
||||
/**
|
||||
* 判断是否为合法花色
|
||||
*/
|
||||
export function isValidSuit(suit: string): suit is Suit {
|
||||
return suit === 'W' || suit === 'T' || suit === 'B'
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为合法点数
|
||||
*/
|
||||
export function isValidTileValue(value: number): boolean {
|
||||
return Number.isInteger(value) && value >= 1 && value <= 9
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为合法牌
|
||||
*/
|
||||
export function isValidTile(tile: { suit: string; value: number }): tile is Pick<Tile, 'suit' | 'value'> {
|
||||
return isValidSuit(tile.suit) && isValidTileValue(tile.value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据花色 + 点数获取图片路径
|
||||
*/
|
||||
export function getTileImageBySuitAndValue(
|
||||
suit: Suit,
|
||||
value: number,
|
||||
position: TilePosition = 'bottom',
|
||||
): string {
|
||||
if (!isValidTileValue(value)) {
|
||||
return ''
|
||||
}
|
||||
|
||||
const key = buildTileImageKey(suit, value, position)
|
||||
return tileImageModules[key] || ''
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 Tile 获取图片路径
|
||||
*/
|
||||
export function getTileImage(
|
||||
tile: Pick<Tile, 'suit' | 'value'>,
|
||||
position: TilePosition = 'bottom',
|
||||
): string {
|
||||
if (!isValidTile(tile)) {
|
||||
return ''
|
||||
}
|
||||
|
||||
const key = buildTileImageKey(tile.suit, tile.value, position)
|
||||
return tileImageModules[key] || ''
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全部基础牌
|
||||
*/
|
||||
export function getAllTiles(): Array<Pick<Tile, 'suit' | 'value'>> {
|
||||
const suits: Suit[] = ['W', 'T', 'B']
|
||||
const result: Array<Pick<Tile, 'suit' | 'value'>> = []
|
||||
|
||||
for (const suit of suits) {
|
||||
for (let value = 1; value <= 9; value++) {
|
||||
result.push({suit, value})
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import {useGameStore} from '../store/gameStore'
|
||||
import {setActiveRoom, useActiveRoomState} from '../store'
|
||||
import type {PlayerState} from '../types/state'
|
||||
import type {Tile} from '../types/tile'
|
||||
import {getTileImage} from "../config/tileMap.ts";
|
||||
|
||||
const gameStore = useGameStore()
|
||||
const activeRoom = useActiveRoomState()
|
||||
@@ -451,6 +452,7 @@ function handleRoomInfoResponse(message: unknown): void {
|
||||
const summary = asRecord(payload.summary) ?? asRecord(payload.room_summary) ?? null
|
||||
const publicState = asRecord(payload.public) ?? asRecord(payload.public_state) ?? null
|
||||
const privateState = asRecord(payload.private) ?? asRecord(payload.private_state) ?? null
|
||||
console.log("server response payload: " + payload)
|
||||
const roomId =
|
||||
readString(summary ?? {}, 'room_id', 'roomId') ||
|
||||
readString(publicState ?? {}, 'room_id', 'roomId') ||
|
||||
@@ -1455,8 +1457,8 @@ onBeforeUnmount(() => {
|
||||
<span class="ready-toggle-label">开始游戏</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="player-hand" v-if="myHandTiles.length > 0">
|
||||
|
||||
<button
|
||||
v-for="tile in myHandTiles"
|
||||
:key="tile.id"
|
||||
|
||||
Reference in New Issue
Block a user