0.1.4
This commit is contained in:
parent
4e75c3af77
commit
54bd7f3840
24
.hmrc
24
.hmrc
@ -1,9 +1,11 @@
|
||||
{
|
||||
"path": "G:\\Other\\Development\\Projects\\[ideas]\\domino-client",
|
||||
"name": "domino-client",
|
||||
"initialVersion": "0.1.0",
|
||||
"version": "0.1.0",
|
||||
"initialVersion": "0.1.4",
|
||||
"version": "0.1.4",
|
||||
"docker": {
|
||||
"useRegistry": true,
|
||||
"registry": "192.168.1.115:5000",
|
||||
"repository": "arhuako/domino-client"
|
||||
},
|
||||
"repository": {
|
||||
@ -12,16 +14,15 @@
|
||||
"manage": true
|
||||
},
|
||||
"changelog": {
|
||||
"create": true,
|
||||
"managed": true,
|
||||
"createHTML": true,
|
||||
"htmlPath": "public"
|
||||
},
|
||||
"_backupInitial": {
|
||||
"name": "domino-client",
|
||||
"version": "0.0.0",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"type": "commonjs",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "run-p type-check \"build-only {@}\" --",
|
||||
@ -30,7 +31,12 @@
|
||||
"build-only": "vite build",
|
||||
"type-check": "vue-tsc --build --force",
|
||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
||||
"format": "prettier --write src/"
|
||||
"format": "prettier --write src/",
|
||||
"docker-build": "docker build -t arhuako/domino-client:latest .",
|
||||
"docker-tag": "docker tag arhuako/domino-client:latest 192.168.1.115:5000/arhuako/domino-client:0.1.0",
|
||||
"docker-push": "docker push 192.168.1.115:5000/arhuako/domino-client:latest && docker push 192.168.1.115:5000/arhuako/domino-client:0.1.0",
|
||||
"publish": "npm run docker-build && npm run docker-tag && npm run docker-push",
|
||||
"serve": "npm run build-only && http-server ./dist -c-1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@pixi/sound": "^6.0.0",
|
||||
@ -60,6 +66,7 @@
|
||||
"@vue/tsconfig": "^0.5.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-vue": "^9.23.0",
|
||||
"http-server": "^14.1.1",
|
||||
"jsdom": "^24.1.0",
|
||||
"npm-run-all2": "^6.2.0",
|
||||
"prettier": "^3.2.5",
|
||||
@ -68,6 +75,11 @@
|
||||
"vite": "^5.3.1",
|
||||
"vitest": "^1.6.0",
|
||||
"vue-tsc": "^2.0.21"
|
||||
},
|
||||
"author": "arhuako",
|
||||
"reposityory": {
|
||||
"type": "git",
|
||||
"url": "https://gitea.xintanalabs.net/arhuako/domino-client"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
13
CHANGELOG.md
13
CHANGELOG.md
@ -1,5 +1,16 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## Unreleased
|
||||
Initial commit
|
||||
|
||||
### Added
|
||||
|
||||
- Initial commit
|
||||
- Match page back button
|
||||
- Team play
|
||||
- Movement synchronized netween clients and AI players
|
||||
|
||||
### Fixed
|
||||
|
||||
- Button statuses
|
||||
|
40
Dockerfile
40
Dockerfile
@ -1,7 +1,37 @@
|
||||
# Create the container from the alpine linux image
|
||||
#FROM alpine:3.7
|
||||
FROM node:22-alpine
|
||||
WORKDIR /usr/src/app
|
||||
COPY package*.json ./
|
||||
RUN npm i
|
||||
|
||||
# Add nginx and nodejs
|
||||
#RUN apk add --update nginx nodejs
|
||||
RUN apk add --update nginx
|
||||
|
||||
# Create the directories we will need
|
||||
RUN mkdir -p /tmp/nginx/vue-single-page-app
|
||||
RUN mkdir -p /var/log/nginx
|
||||
RUN mkdir -p /var/www/html
|
||||
|
||||
# Copy the respective nginx configuration files
|
||||
COPY nginx/nginx.conf /etc/nginx/nginx.conf
|
||||
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
# Set the directory we want to run the next commands for
|
||||
WORKDIR /tmp/nginx/vue-single-page-app
|
||||
|
||||
COPY . .
|
||||
EXPOSE 8080
|
||||
CMD ["npm", "run", "serve"]
|
||||
# Copy our source code into the container
|
||||
# Install the dependencies, can be commented out if you're running the same node version
|
||||
RUN npm install
|
||||
|
||||
# run webpack and the vue-loader
|
||||
RUN npm run build-only
|
||||
|
||||
|
||||
# copy the built app to our served directory
|
||||
RUN cp -r dist/* /var/www/html
|
||||
|
||||
# make all files belong to the nginx user
|
||||
RUN chown nginx:nginx /var/www/html
|
||||
|
||||
# start nginx and keep the process from backgrounding and the container from quitting
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
6
nginx/default.conf
Normal file
6
nginx/default.conf
Normal file
@ -0,0 +1,6 @@
|
||||
server {
|
||||
location / {
|
||||
root /var/www/html;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
23
nginx/nginx.conf
Normal file
23
nginx/nginx.conf
Normal file
@ -0,0 +1,23 @@
|
||||
user nginx;
|
||||
worker_processes 1;
|
||||
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
sendfile off;
|
||||
|
||||
keepalive_timeout 60;
|
||||
|
||||
#gzip on;
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
}
|
10
package.json
10
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "domino-client",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.3",
|
||||
"private": true,
|
||||
"type": "commonjs",
|
||||
"scripts": {
|
||||
@ -12,11 +12,11 @@
|
||||
"type-check": "vue-tsc --build --force",
|
||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
||||
"format": "prettier --write src/",
|
||||
"docker-build": "docker build -t arhuako/domino-client:latest .",
|
||||
"docker-tag": "docker tag arhuako/domino-client:latest 192.168.1.115:5000/arhuako/domino-client:0.1.0",
|
||||
"docker-push": "docker push 192.168.1.115:5000/arhuako/domino-client:latest && docker push 192.168.1.115:5000/arhuako/domino-client:0.1.0",
|
||||
"docker-build": "docker build -t 192.168.1.115:5000/arhuako/domino-client:latest .",
|
||||
"docker-tag": "docker tag 192.168.1.115:5000/arhuako/domino-client:latest 192.168.1.115:5000/arhuako/domino-client:0.1.4",
|
||||
"docker-push": "docker push 192.168.1.115:5000/arhuako/domino-client:latest && docker push 192.168.1.115:5000/arhuako/domino-client:0.1.4",
|
||||
"publish": "npm run docker-build && npm run docker-tag && npm run docker-push",
|
||||
"serve": "npm run build-only && http-server ./dist -c-1"
|
||||
"serve": "npm run build-only && http-server ./dist -c-1 -s "
|
||||
},
|
||||
"dependencies": {
|
||||
"@pixi/sound": "^6.0.0",
|
||||
|
31
src/App.vue
31
src/App.vue
@ -3,6 +3,7 @@ import { inject, onMounted, onUnmounted } from 'vue'
|
||||
import { RouterView } from 'vue-router'
|
||||
import type { AuthenticationService } from './services/AuthenticationService'
|
||||
import { useEventBusStore } from './stores/eventBus'
|
||||
import { sound } from '@pixi/sound'
|
||||
|
||||
const auth: AuthenticationService = inject<AuthenticationService>('auth') as AuthenticationService
|
||||
auth.fromStorage()
|
||||
@ -17,8 +18,38 @@ const handleBeforeUnload = (evt: any) => {
|
||||
// console.log('location.href :>> ', location.pathname)
|
||||
}
|
||||
|
||||
// document.addEventListener('visibilitychange', () => {
|
||||
// console.log('visibilitychange')
|
||||
// let playingOnHide = false
|
||||
// if (document.hidden) {
|
||||
// playingOnHide = true
|
||||
// sound.pauseAll()
|
||||
// } else {
|
||||
// // Page became visible! Resume playing if audio was "playing on hide"
|
||||
// if (playingOnHide) {
|
||||
// sound.resumeAll()
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
|
||||
// const soundContextResume = () => {
|
||||
// const context = sound.context.audioContext
|
||||
// if (context.state === 'suspended' || context.state === 'interrupted') {
|
||||
// context.resume()
|
||||
// }
|
||||
// }
|
||||
|
||||
// document.addEventListener('click', function (event) {
|
||||
// console.log('click document :>> ', event)
|
||||
// console.log('screen :>> ', screen)
|
||||
// // if (event.target instanceof HTMLButtonElement) {
|
||||
// // sound.play('click')
|
||||
// // }
|
||||
// })
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('beforeunload', handleBeforeUnload)
|
||||
// window.addEventListener('focus', soundContextResume)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
|
@ -1,9 +1,17 @@
|
||||
:root {
|
||||
/* bulma color variables */
|
||||
--bulma-primary-h: 40deg;
|
||||
--bulma-primary-s: 48%;
|
||||
--bulma-primary-l: 48%;
|
||||
--bulma-info-h: 168deg;
|
||||
--bulma-info-s: 58%;
|
||||
--bulma-info-l: 28%;
|
||||
--bulma-primary-l: 38%;
|
||||
--bulma-link-h: 36deg;
|
||||
--bulma-link-s: 19%;
|
||||
--bulma-link-l: 16%;
|
||||
--bulma-info-h: 192deg;
|
||||
--bulma-info-l: 34%;
|
||||
--bulma-success-s: 52%;
|
||||
--bulma-success-l: 38%;
|
||||
--bulma-warning-h: 58deg;
|
||||
--bulma-warning-s: 61%;
|
||||
--bulma-warning-l: 41%;
|
||||
--bulma-danger-s: 74%;
|
||||
--bulma-danger-l: 37%;
|
||||
}
|
||||
|
@ -3,11 +3,20 @@ export const DEFAULT_CONTAINER_OPTIONS = {
|
||||
height: 100,
|
||||
x: 0,
|
||||
y: 0,
|
||||
visible: true
|
||||
visible: true,
|
||||
}
|
||||
export const ORIENTATION_ANGLES: { [key: string]: number } = {
|
||||
north: 0,
|
||||
east: Math.PI / 2,
|
||||
south: Math.PI,
|
||||
west: (3 * Math.PI) / 2
|
||||
west: (3 * Math.PI) / 2,
|
||||
}
|
||||
|
||||
export const DIRECTION_INDEXES: { [key: string]: number } = {
|
||||
north: 0,
|
||||
east: 1,
|
||||
south: 2,
|
||||
west: 3,
|
||||
}
|
||||
|
||||
export const DIRECTIONS = ['north', 'east', 'south', 'west']
|
||||
|
@ -99,8 +99,6 @@ export async function wait(ms: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms))
|
||||
}
|
||||
|
||||
export const DIRECTIONS = ['north', 'east', 'south', 'west']
|
||||
|
||||
export function isTilePair(tile: TileDto): boolean {
|
||||
return !!(tile.pips && tile.pips[0] === tile.pips[1])
|
||||
}
|
||||
|
@ -2,11 +2,11 @@ import { Application, Container, EventEmitter, Text, Ticker } from 'pixi.js'
|
||||
import { Scale, type ScaleFunction } from '@/game/utilities/scale'
|
||||
import type { AnimationOptions, Movement, PlayerDto, TileDto } from '@/common/interfaces'
|
||||
import { Tile } from '@/game/Tile'
|
||||
import { DIRECTIONS, createContainer, isTilePair } from '@/common/helpers'
|
||||
import { createContainer, isTilePair } from '@/common/helpers'
|
||||
import { createText } from '@/game/utilities/fonts'
|
||||
import { LoggingService } from '@/services/LoggingService'
|
||||
import { GlowFilter } from 'pixi-filters'
|
||||
import { ORIENTATION_ANGLES } from '@/common/constants'
|
||||
import { DIRECTION_INDEXES, DIRECTIONS, ORIENTATION_ANGLES } from '@/common/constants'
|
||||
import type { OtherHand } from './OtherHand'
|
||||
import { sound } from '@pixi/sound'
|
||||
import { t } from '@/i18n'
|
||||
@ -181,6 +181,8 @@ export class Board extends EventEmitter {
|
||||
const tileDto = tile.toPlain()
|
||||
let direction = move.type === 'left' ? this.leftDirection : this.rightDirection
|
||||
|
||||
move.direction = this.hasSpaceToMove(move)
|
||||
|
||||
if (this.tiles.length === 0) {
|
||||
x = 0
|
||||
y = 0
|
||||
@ -592,6 +594,22 @@ export class Board extends EventEmitter {
|
||||
return [canPlayNorth, canPlayEast, canPlaySouth, canPlayWest]
|
||||
}
|
||||
|
||||
hasSpaceToMove(move: Movement): string | undefined {
|
||||
if (move.tile === undefined || move.direction === undefined) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const nextValidMoves = this.nextTileValidMoves(move.tile, move.type)
|
||||
let index = DIRECTION_INDEXES[move.direction]
|
||||
let valid = nextValidMoves[index]
|
||||
while (!valid && index < nextValidMoves.length) {
|
||||
index++
|
||||
valid = nextValidMoves[index % nextValidMoves.length]
|
||||
}
|
||||
|
||||
return DIRECTIONS[index]
|
||||
}
|
||||
|
||||
clean() {
|
||||
this.tiles = []
|
||||
this.boneyard = []
|
||||
|
@ -81,8 +81,7 @@ export class Game extends EventEmitter {
|
||||
iniialStuff(app: Application) {
|
||||
app.stage.addChild(this.backgroundLayer)
|
||||
const background = new Sprite(Assets.get(`bg-${this.options.background}`))
|
||||
background.width = this.app.canvas.width
|
||||
background.height = this.app.canvas.height
|
||||
|
||||
this.backgroundLayer.addChild(background)
|
||||
}
|
||||
|
||||
|
@ -44,5 +44,7 @@
|
||||
"starting_game": "Starting game...",
|
||||
"your-turn": "Your turn!",
|
||||
"player-turn": "{0}'s turn!"
|
||||
}
|
||||
},
|
||||
"back": "Back",
|
||||
"session-name": "Session Name"
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
"welcome-to-the-user-username-s-home-page": "Bienvenido a la página de inicio de {0}",
|
||||
"available-sessions": "Sesiones disponibles",
|
||||
"background-color": "Color de fondo",
|
||||
"blue-fabric": "Fabrica azul",
|
||||
"blue-fabric": "Tela azul",
|
||||
"cancel": "Cancelar",
|
||||
"copy": "Copiar",
|
||||
"game": {
|
||||
@ -44,5 +44,7 @@
|
||||
"seed": "Semilla",
|
||||
"seed-session-seed": "Semilla: {0}",
|
||||
"start": "Comenzar",
|
||||
"yellow-fabric": "Tela amarilla"
|
||||
"yellow-fabric": "Tela amarilla",
|
||||
"back": "Volver",
|
||||
"session-name": "Nombre de la sesión"
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
import './assets/main.css'
|
||||
|
||||
import { createApp } from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
|
||||
import '../node_modules/bulma/css/bulma.css'
|
||||
import './assets/main.css'
|
||||
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
@ -51,7 +51,7 @@ const router = createRouter({
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/game:id',
|
||||
path: '/game/:id',
|
||||
component: AuthenticatedLayout,
|
||||
children: [
|
||||
{
|
||||
|
@ -15,7 +15,7 @@ let background = ref<string>('green')
|
||||
let teamed = ref<boolean>(false)
|
||||
let pointsToWin = ref<number>(100)
|
||||
let seed = ref<string>('')
|
||||
let sessionName = ref('Test Value')
|
||||
let sessionName = ref(`Test #${Date.now()}`)
|
||||
let matchSessions = ref<MatchSessionDto[]>([])
|
||||
let dataInterval: any
|
||||
|
||||
@ -130,7 +130,6 @@ async function deleteMatch(id: string) {
|
||||
async function loadData() {
|
||||
const listResponse = await gameService.listMatchSessions()
|
||||
matchSessions.value = listResponse.data
|
||||
sessionName.value = `Test #${Date.now()}`
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
@ -156,7 +155,7 @@ function copy(sessionSeed: string) {
|
||||
</h1>
|
||||
<div class="block" v-if="!isSessionStarted">
|
||||
<div class="field">
|
||||
<label class="label">{{ $t('name') }}</label>
|
||||
<label class="label">{{ $t('session-name') }}</label>
|
||||
<div class="control">
|
||||
<input
|
||||
type="text"
|
||||
@ -174,7 +173,7 @@ function copy(sessionSeed: string) {
|
||||
class="input"
|
||||
style="margin-bottom: 0"
|
||||
v-model="seed"
|
||||
placeholder="$t('seed-placeholder')"
|
||||
:placeholder="$t('seed-placeholder')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -226,7 +225,14 @@ function copy(sessionSeed: string) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons" v-if="isSessionStarted">
|
||||
<div class="block" v-if="isSessionStarted">
|
||||
<h2 class="title is-4">{{ sessionState?.name }}</h2>
|
||||
<h6 class="title is-size-5">Players</h6>
|
||||
<div v-for="player in sessionState?.players" :key="player.id">
|
||||
<p>{{ player.name }}</p>
|
||||
<p>{{ player.ready ? 'Ready' : 'Not ready' }}</p>
|
||||
</div>
|
||||
<div class="buttons mt-6">
|
||||
<button class="button" @click="setPlayerReady">
|
||||
<span v-if="!readyForStart">{{ $t('ready') }}</span
|
||||
><span v-else>{{ $t('unready') }}</span>
|
||||
@ -239,14 +245,16 @@ function copy(sessionSeed: string) {
|
||||
<span>{{ $t('cancel') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="section available-sessions">
|
||||
<section class="section available-sessions" v-if="!isSessionStarted">
|
||||
<h2 class="title is-4">{{ $t('available-sessions') }}</h2>
|
||||
<div class="block">
|
||||
<div v-if="matchSessions.length === 0">
|
||||
<p>{{ $t('no-sessions-available') }}</p>
|
||||
</div>
|
||||
<div v-else class="grid is-col-min-12">
|
||||
<div v-else class="fixed-grid has-3-cols">
|
||||
<div class="grid">
|
||||
<div class="cell" v-for="session in matchSessions" :key="session.id">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
@ -255,24 +263,26 @@ function copy(sessionSeed: string) {
|
||||
<p>{{ $t('players-session-players-length', [session.players.length]) }}</p>
|
||||
<p>
|
||||
{{ $t('seed-session-seed', [session.seed]) }}
|
||||
<button class="button is-small" @click="() => copy(session.seed)">
|
||||
<button class="button is-small is-ghost" @click="() => copy(session.seed)">
|
||||
{{ $t('copy') }}
|
||||
</button>
|
||||
</p>
|
||||
<p>{{ $t('status-session-status', [session.status]) }}</p>
|
||||
<div class="buttons is-centered mt-4"></div>
|
||||
<div class="buttons is-centered mt-6">
|
||||
<button
|
||||
class="button is-primary"
|
||||
@click.once.prevent="() => joinMatch(session._id)"
|
||||
>
|
||||
<span>{{ $t('join') }}</span>
|
||||
</button>
|
||||
<button
|
||||
class="button is-text"
|
||||
@click.once.prevent="() => deleteMatch(session._id)"
|
||||
>
|
||||
<span>{{ $t('delete') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<p class="card-footer-item">
|
||||
<a href="#" @click.once.prevent="() => joinMatch(session._id)">
|
||||
{{ $t('join') }}
|
||||
</a>
|
||||
</p>
|
||||
<p class="card-footer-item">
|
||||
<a href="#" @click.once.prevent="() => deleteMatch(session._id)">
|
||||
{{ $t('delete') }}
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -73,6 +73,11 @@ onBeforeMount(() => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button class="button is-primary" @click="router.push({ name: 'home' })">
|
||||
{{ $t('back') }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="section">
|
||||
<!-- <div>{{ matchSession }}</div> -->
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user