Compare commits
No commits in common. "main" and "develop" have entirely different histories.
@ -8,7 +8,7 @@
|
|||||||
},
|
},
|
||||||
"package": {
|
"package": {
|
||||||
"productName": "domino-client",
|
"productName": "domino-client",
|
||||||
"version": "0.2.1"
|
"version": "0.2.0"
|
||||||
},
|
},
|
||||||
"tauri": {
|
"tauri": {
|
||||||
"allowlist": {
|
"allowlist": {
|
||||||
@ -72,7 +72,7 @@
|
|||||||
"fullscreen": false,
|
"fullscreen": false,
|
||||||
"height": 720,
|
"height": 720,
|
||||||
"resizable": true,
|
"resizable": true,
|
||||||
"title": "Domino v0.2.1",
|
"title": "Domino v0.2.0",
|
||||||
"width": 1280,
|
"width": 1280,
|
||||||
"minHeight": 720,
|
"minHeight": 720,
|
||||||
"minWidth": 1280,
|
"minWidth": 1280,
|
||||||
|
@ -15,3 +15,9 @@
|
|||||||
--bulma-danger-s: 74%;
|
--bulma-danger-s: 74%;
|
||||||
--bulma-danger-l: 37%;
|
--bulma-danger-l: 37%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tabs li.is-disabled {
|
||||||
|
pointer-events: none;
|
||||||
|
cursor: default;
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
@ -1,35 +1,7 @@
|
|||||||
@import './base.css';
|
@import './base.css';
|
||||||
|
|
||||||
html,
|
html {
|
||||||
body,
|
|
||||||
#app {
|
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#app.game {
|
|
||||||
overflow-y: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs li.is-disabled {
|
|
||||||
pointer-events: none;
|
|
||||||
cursor: default;
|
|
||||||
opacity: 0.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.box.is-no-shadow {
|
|
||||||
box-shadow: none;
|
|
||||||
border: 1px solid var(--bulma-input-border-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.landing .unauthenticated-layout {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.is-ellipsis {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
}
|
||||||
|
@ -143,10 +143,3 @@ export function createStringMatrix(
|
|||||||
|
|
||||||
return matrix
|
return matrix
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isMobile() {
|
|
||||||
const userAgent = navigator.userAgent || navigator.vendor || window.opera
|
|
||||||
return /android|avantgo|blackberry|bada\/|bb|meego|ip(hone|od|ad)|opera m(ob|in)i|phone|tablet|mobi|ipad|playbook|silk|windows (phone|ce)|webos|kindle|mobile|palm|fennec|gobrowser|hiptop|iemobile|iris|w3c|wap|opera mini|iemobile/i.test(
|
|
||||||
userAgent,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
@ -19,7 +19,7 @@ let options = ref<MatchSessionOptions>({
|
|||||||
|
|
||||||
const winTargetPointsList = [20, 50, 80, 100, 150, 200]
|
const winTargetPointsList = [20, 50, 80, 100, 150, 200]
|
||||||
const winTargetRoundsList = [1, 2, 3, 4, 5, 6]
|
const winTargetRoundsList = [1, 2, 3, 4, 5, 6]
|
||||||
const turnWaitSecondsList = [5, 10, 15, 20, 30, 40, 50, 60]
|
const turnWaitSecondsList = [15, 20, 30, 40, 50, 60]
|
||||||
|
|
||||||
const backgroundOptiopnList = [
|
const backgroundOptiopnList = [
|
||||||
{
|
{
|
||||||
@ -58,93 +58,89 @@ function startSingleMatch() {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="fixed-grid has-3-cols has-1-cols-mobile">
|
<div class="grid">
|
||||||
<div class="grid">
|
<div class="cell">
|
||||||
<div class="cell">
|
<div class="field">
|
||||||
<div class="field">
|
<label class="label">{{ $t('mode') }}</label>
|
||||||
<label class="label">{{ $t('mode') }}</label>
|
<div class="control">
|
||||||
<div class="control">
|
<div class="buttons has-addons">
|
||||||
<div class="buttons has-addons">
|
<button
|
||||||
<button
|
class="button"
|
||||||
class="button"
|
:class="{ 'is-primary is-selected': isSinglePlayer }"
|
||||||
:class="{ 'is-primary is-selected': isSinglePlayer }"
|
@click="
|
||||||
@click="
|
() => {
|
||||||
() => {
|
console.log('options :>> ', options)
|
||||||
console.log('options :>> ', options)
|
options.numPlayers = 1
|
||||||
options.numPlayers = 1
|
}
|
||||||
}
|
"
|
||||||
"
|
>
|
||||||
>
|
{{ $t('singleplayer') }}
|
||||||
{{ $t('singleplayer') }}
|
</button>
|
||||||
</button>
|
<button
|
||||||
<button
|
class="button"
|
||||||
class="button"
|
:class="{ 'is-primary is-selected': isMultiPlayer }"
|
||||||
:class="{ 'is-primary is-selected': isMultiPlayer }"
|
@click="
|
||||||
@click="
|
() => {
|
||||||
() => {
|
console.log('options :>> ', options)
|
||||||
console.log('options :>> ', options)
|
options.numPlayers = 2
|
||||||
options.numPlayers = 2
|
}
|
||||||
}
|
"
|
||||||
"
|
>
|
||||||
>
|
{{ $t('multiplayer') }}
|
||||||
{{ $t('multiplayer') }}
|
</button>
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="cell">
|
|
||||||
<div class="field" v-if="isMultiPlayer">
|
|
||||||
<label class="label">{{ $t('players-number') }}</label>
|
|
||||||
<div class="control">
|
|
||||||
<div class="buttons has-addons">
|
|
||||||
<button
|
|
||||||
class="button is-primary"
|
|
||||||
@click="options.numPlayers--"
|
|
||||||
:disabled="options.numPlayers <= 2"
|
|
||||||
>
|
|
||||||
-
|
|
||||||
</button>
|
|
||||||
<button class="button is-primary" disabled>{{ options.numPlayers }}</button>
|
|
||||||
<button
|
|
||||||
class="button is-primary"
|
|
||||||
@click="options.numPlayers++"
|
|
||||||
:disabled="options.numPlayers >= 4"
|
|
||||||
>
|
|
||||||
+
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="cell">
|
|
||||||
<div class="field" v-if="isMultiPlayer">
|
|
||||||
<div class="control">
|
|
||||||
<label for="teamed" class="checkbox">
|
|
||||||
<input v-model="options.teamed" name="teamed" type="checkbox" />
|
|
||||||
{{ $t('crossed-game-teamed') }}
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="cell">
|
||||||
<div class="flex-grid has-2-cols has-1-cols-mobile" v-if="info?.development">
|
<div class="field" v-if="isMultiPlayer">
|
||||||
<div class="grid">
|
<label class="label">{{ $t('players-number') }}</label>
|
||||||
<div class="cell">
|
<div class="control">
|
||||||
<div class="field">
|
<div class="buttons has-addons">
|
||||||
<label class="label">{{ $t('session-name') }}</label>
|
<button
|
||||||
<div class="control">
|
class="button is-primary"
|
||||||
<input
|
@click="options.numPlayers--"
|
||||||
type="text"
|
:disabled="options.numPlayers <= 2"
|
||||||
class="input"
|
>
|
||||||
v-model="options.sessionName"
|
-
|
||||||
placeholder="$t('session-name-placeholder')"
|
</button>
|
||||||
/>
|
<button class="button is-primary" disabled>{{ options.numPlayers }}</button>
|
||||||
|
<button
|
||||||
|
class="button is-primary"
|
||||||
|
@click="options.numPlayers++"
|
||||||
|
:disabled="options.numPlayers >= 4"
|
||||||
|
>
|
||||||
|
+
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="cell">
|
||||||
|
<div class="field" v-if="isMultiPlayer">
|
||||||
|
<div class="control">
|
||||||
|
<label for="teamed" class="checkbox">
|
||||||
|
<input v-model="options.teamed" name="teamed" type="checkbox" />
|
||||||
|
{{ $t('crossed-game-teamed') }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="grid" v-if="info?.development">
|
||||||
|
<div class="cell">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">{{ $t('session-name') }}</label>
|
||||||
|
<div class="control">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="input"
|
||||||
|
v-model="options.sessionName"
|
||||||
|
placeholder="$t('session-name-placeholder')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
<div class="cell">
|
<div class="cell">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
|
@ -1,86 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="block">
|
|
||||||
<h2 class="title is-4">{{ sessionState?.name }}</h2>
|
|
||||||
<h6 class="title is-size-5">{{ $t('players') }}</h6>
|
|
||||||
<div v-for="player in sessionState?.players" :key="player.id">
|
|
||||||
<div class="fixed-grid" style="max-width: 300px">
|
|
||||||
<div class="grid">
|
|
||||||
<div class="cell">{{ player.name }}</div>
|
|
||||||
<div class="cell has-text-centered">
|
|
||||||
<div class="mb-2">
|
|
||||||
<span
|
|
||||||
class="tag"
|
|
||||||
:class="{ 'is-success': player.ready, 'is-danger': !player.ready }"
|
|
||||||
>{{ $t(player.ready ? 'ready' : 'unready') }}</span
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="mt-4" v-if="amIHost && gameOptions?.teamed && playersToTeamUpWith.length > 0">
|
|
||||||
<div class="field">
|
|
||||||
<label for="background" class="label">Team up with</label>
|
|
||||||
<div class="control">
|
|
||||||
<div class="select">
|
|
||||||
<select v-model="teamedWith" name="teamedWidth">
|
|
||||||
<option v-for="player in playersToTeamUpWith" :key="player.id" :value="player.id">
|
|
||||||
{{ player.name }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="buttons mt-6">
|
|
||||||
<button class="button is-dark" @click="() => emit('ready')">
|
|
||||||
<span v-if="!readyForStart">{{ $t('ready') }}</span
|
|
||||||
><span v-else>{{ $t('unready') }}</span>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="button is-success"
|
|
||||||
:disabled="!canStart"
|
|
||||||
@click="() => emit('start', teamedWith)"
|
|
||||||
v-if="amIHost"
|
|
||||||
>
|
|
||||||
<span>{{ $t('start') }}</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button class="button is-danger" @click="() => emit('cancel')">
|
|
||||||
<span>{{ $t('cancel') }}</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { useGameStore } from '@/stores/game'
|
|
||||||
import { useGameOptionsStore } from '@/stores/gameOptions'
|
|
||||||
import { storeToRefs } from 'pinia'
|
|
||||||
import { computed, ref } from 'vue'
|
|
||||||
|
|
||||||
let teamedWith = ref<string | undefined>(undefined)
|
|
||||||
const emit = defineEmits(['ready', 'start', 'cancel'])
|
|
||||||
|
|
||||||
const gameStore = useGameStore()
|
|
||||||
const gameOptionsStore = useGameOptionsStore()
|
|
||||||
|
|
||||||
const { sessionState, amIHost, readyForStart } = storeToRefs(gameStore)
|
|
||||||
const { gameOptions } = storeToRefs(gameOptionsStore)
|
|
||||||
|
|
||||||
const playersToTeamUpWith = computed(() => {
|
|
||||||
return (
|
|
||||||
sessionState?.value?.players.filter((player) => player.id !== sessionState?.value?.creator) ||
|
|
||||||
[]
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const canStart = computed(() => {
|
|
||||||
const players = sessionState?.value?.players || []
|
|
||||||
const options = gameOptions.value
|
|
||||||
const allReady = (players.length || 0) > 0 && players.every((player) => player.ready)
|
|
||||||
return (!options?.teamed && allReady) || (options?.teamed && !!teamedWith.value && allReady)
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
@ -1,69 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-content">
|
|
||||||
<p class="title is-6">{{ props.session.name }}</p>
|
|
||||||
<div class="fixed-grid">
|
|
||||||
<div class="grid">
|
|
||||||
<div class="cell has-text-weight-light">{{ $t('id-session-_id') }}</div>
|
|
||||||
<div class="cell has-text-weight-medium">{{ props.session._id }}</div>
|
|
||||||
<div class="cell has-text-weight-light">{{ $t('host-session-host') }}</div>
|
|
||||||
<div class="cell has-text-weight-medium">{{ creatorName }}</div>
|
|
||||||
<div class="cell has-text-weight-light">{{ $t('players-session-players-length') }}</div>
|
|
||||||
<div class="cell has-text-weight-medium">
|
|
||||||
{{ props.session.numPlayers }} / {{ props.session.options.numPlayers }}
|
|
||||||
</div>
|
|
||||||
<div class="cell has-text-weight-light" v-if="info.development">
|
|
||||||
{{ $t('seed-session-seed') }}
|
|
||||||
</div>
|
|
||||||
<div class="cell has-text-weight-medium is-family-monospace" v-if="info.development">
|
|
||||||
<span class="is-ellipsis is-display-inline-block" style="max-width: 100px">{{
|
|
||||||
props.session.seed
|
|
||||||
}}</span>
|
|
||||||
<a class="" @click="() => emit('copy', props.session.seed)">
|
|
||||||
{{ $t('copy') }}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="cell has-text-weight-light">{{ $t('status-session-status') }}</div>
|
|
||||||
<div class="cell has-text-weight-medium">{{ props.session.status }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="buttons is-centered mt-6">
|
|
||||||
<button
|
|
||||||
class="button is-primary"
|
|
||||||
@click.once.prevent="() => emit('join', props.session._id)"
|
|
||||||
>
|
|
||||||
<span>{{ $t('join') }}</span>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
v-if="amIHost || info.development"
|
|
||||||
class="button is-text"
|
|
||||||
@click.once.prevent="() => emit('delete', props.session._id)"
|
|
||||||
>
|
|
||||||
<span>{{ $t('delete') }}</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import type { MatchSessionDto } from '@/common/interfaces'
|
|
||||||
import type { InfoService } from '@/services/InfoService'
|
|
||||||
import { useGameStore } from '@/stores/game'
|
|
||||||
import { storeToRefs } from 'pinia'
|
|
||||||
import { computed, inject } from 'vue'
|
|
||||||
const emit = defineEmits(['join', 'delete', 'copy'])
|
|
||||||
const gameStore = useGameStore()
|
|
||||||
const { amIHost } = storeToRefs(gameStore)
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
session: MatchSessionDto
|
|
||||||
}>()
|
|
||||||
const info: InfoService = inject<InfoService>('info') as InfoService
|
|
||||||
const creatorName = computed(() => {
|
|
||||||
return props.session.players.find((player) => player.id === props.session.creator)?.name || ''
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
@ -102,7 +102,7 @@ if (info.tauri) {
|
|||||||
>Check for update</a
|
>Check for update</a
|
||||||
>
|
>
|
||||||
<hr class="navbar-divider" />
|
<hr class="navbar-divider" />
|
||||||
<div class="navbar-item">Version 0.2.1</div>
|
<div class="navbar-item">Version 0.2.0</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
export default {
|
|
||||||
install(app: any) {
|
|
||||||
app.config.globalProperties.$isMobile = () => {
|
|
||||||
const userAgent = navigator.userAgent || navigator.vendor || window.opera
|
|
||||||
return /android|avantgo|blackberry|bada\/|bb|meego|ip(hone|od|ad)|opera m(ob|in)i|phone|tablet|mobi|ipad|playbook|silk|windows (phone|ce)|webos|kindle|mobile|palm|fennec|gobrowser|hiptop|iemobile|iris|w3c|wap|opera mini|iemobile/i.test(
|
|
||||||
userAgent,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
@ -16,7 +16,6 @@ import { DIRECTION_INDEXES, DIRECTIONS, ORIENTATION_ANGLES } from '@/common/cons
|
|||||||
import type { OtherHand } from './OtherHand'
|
import type { OtherHand } from './OtherHand'
|
||||||
import { SoundManager } from '@/game/utilities/SoundManager'
|
import { SoundManager } from '@/game/utilities/SoundManager'
|
||||||
import { t } from '@/i18n'
|
import { t } from '@/i18n'
|
||||||
import { gsap } from 'gsap'
|
|
||||||
|
|
||||||
export class Board extends EventEmitter {
|
export class Board extends EventEmitter {
|
||||||
private _scale: number = 1
|
private _scale: number = 1
|
||||||
@ -226,7 +225,7 @@ export class Board extends EventEmitter {
|
|||||||
const availableMoves = this.nextTileValidMoves(tileDto, move.type)
|
const availableMoves = this.nextTileValidMoves(tileDto, move.type)
|
||||||
const availablePositions = this.nextTileValidPoints(tileDto, move.type, availableMoves)
|
const availablePositions = this.nextTileValidPoints(tileDto, move.type, availableMoves)
|
||||||
|
|
||||||
let directionIndex = DIRECTION_INDEXES[direction]
|
let directionIndex = DIRECTIONS.indexOf(direction)
|
||||||
let availablePosition: [number, number] | undefined = availablePositions[directionIndex]
|
let availablePosition: [number, number] | undefined = availablePositions[directionIndex]
|
||||||
let endlessLoop: number = 0
|
let endlessLoop: number = 0
|
||||||
while (endlessLoop < 4 && availablePosition === undefined) {
|
while (endlessLoop < 4 && availablePosition === undefined) {
|
||||||
@ -235,10 +234,7 @@ export class Board extends EventEmitter {
|
|||||||
endlessLoop++
|
endlessLoop++
|
||||||
}
|
}
|
||||||
if (endlessLoop >= 4) {
|
if (endlessLoop >= 4) {
|
||||||
console.log('availableMoves :>>', availableMoves)
|
throw new Error('No available position')
|
||||||
console.log('availablePositions :>>', availablePositions)
|
|
||||||
// throw new Error('No available position')
|
|
||||||
directionIndex = DIRECTION_INDEXES[direction]
|
|
||||||
}
|
}
|
||||||
direction = DIRECTIONS[directionIndex]
|
direction = DIRECTIONS[directionIndex]
|
||||||
isLeft ? (this.leftDirection = direction) : (this.rightDirection = direction)
|
isLeft ? (this.leftDirection = direction) : (this.rightDirection = direction)
|
||||||
@ -264,37 +260,23 @@ export class Board extends EventEmitter {
|
|||||||
async animateTile(tile: Tile, x: number, y: number, orientation: string, move: Movement) {
|
async animateTile(tile: Tile, x: number, y: number, orientation: string, move: Movement) {
|
||||||
const targetX = this.scaleX(x)
|
const targetX = this.scaleX(x)
|
||||||
const targetY = this.scaleY(y)
|
const targetY = this.scaleY(y)
|
||||||
|
const animation: AnimationOptions = {
|
||||||
|
x: targetX,
|
||||||
|
y: targetY,
|
||||||
|
rotation: ORIENTATION_ANGLES[orientation],
|
||||||
|
duration: 20,
|
||||||
|
}
|
||||||
const tempAlpha = tile.alpha
|
const tempAlpha = tile.alpha
|
||||||
tile.alpha = 0
|
tile.alpha = 0
|
||||||
const clonedTile = tile.clone()
|
const clonedTile = tile.clone()
|
||||||
clonedTile.addTo(this.tilesContainer)
|
clonedTile.addTo(this.tilesContainer)
|
||||||
const pos = this.getAnimationInitialPosition(move)
|
const pos = this.getAnimationInitialPosition(move)
|
||||||
clonedTile.setPosition(this.scaleX(pos.x), this.scaleY(pos.y))
|
clonedTile.setPosition(this.scaleX(pos.x), this.scaleY(pos.y))
|
||||||
|
await clonedTile.animateTo(animation)
|
||||||
return new Promise((resolve) => {
|
clonedTile.removeFromParent()
|
||||||
gsap.timeline({ repeat: 0 }).fromTo(
|
tile.setOrientation(orientation)
|
||||||
clonedTile.getSprite(),
|
tile.setPosition(targetX, targetY)
|
||||||
{
|
tile.alpha = tempAlpha
|
||||||
x: this.scaleX(pos.x),
|
|
||||||
y: this.scaleY(pos.y),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
x: targetX,
|
|
||||||
y: targetY,
|
|
||||||
duration: 1,
|
|
||||||
rotation: ORIENTATION_ANGLES[orientation],
|
|
||||||
// rotate: ,
|
|
||||||
onComplete: () => {
|
|
||||||
clonedTile.removeFromParent()
|
|
||||||
tile.setOrientation(orientation)
|
|
||||||
tile.setPosition(targetX, targetY)
|
|
||||||
tile.alpha = tempAlpha
|
|
||||||
resolve('done')
|
|
||||||
},
|
|
||||||
ease: 'power4.out',
|
|
||||||
},
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getAnimationInitialPosition(move: Movement): { x: number; y: number } {
|
getAnimationInitialPosition(move: Movement): { x: number; y: number } {
|
||||||
@ -363,7 +345,6 @@ export class Board extends EventEmitter {
|
|||||||
try {
|
try {
|
||||||
// const { tileDto: tileDto } = move
|
// const { tileDto: tileDto } = move
|
||||||
// const tile = this.getTileInHand(tileDto?.id ?? '')
|
// const tile = this.getTileInHand(tileDto?.id ?? '')
|
||||||
this.interactionContainer.removeChildren()
|
|
||||||
this.movements.push(move)
|
this.movements.push(move)
|
||||||
if (tile === undefined) {
|
if (tile === undefined) {
|
||||||
return
|
return
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { Dimension } from '@/common/interfaces'
|
import type { Dimension } from '@/common/interfaces'
|
||||||
import { BlurFilter, Container, Graphics, Point, Text } from 'pixi.js'
|
import { BlurFilter, Container, Graphics, Point, Text, TextStyle } from 'pixi.js'
|
||||||
import { gsap } from 'gsap'
|
import { gsap } from 'gsap'
|
||||||
import { SoundManager } from '@/game/utilities/SoundManager'
|
import { SoundManager } from '@/game/utilities/SoundManager'
|
||||||
|
|
||||||
|
@ -20,8 +20,6 @@ import Config from './Config'
|
|||||||
import { createText, grayStyle } from './utilities/fonts'
|
import { createText, grayStyle } from './utilities/fonts'
|
||||||
import { t } from '@/i18n'
|
import { t } from '@/i18n'
|
||||||
import { DIRECTION_INDEXES, DIRECTIONS } from '@/common/constants'
|
import { DIRECTION_INDEXES, DIRECTIONS } from '@/common/constants'
|
||||||
import { SoundManager } from './utilities/SoundManager'
|
|
||||||
|
|
||||||
export class Game extends EventEmitter {
|
export class Game extends EventEmitter {
|
||||||
public board!: Board
|
public board!: Board
|
||||||
public hand!: Hand
|
public hand!: Hand
|
||||||
@ -32,7 +30,6 @@ export class Game extends EventEmitter {
|
|||||||
private backgroundLayer: Container = new Container()
|
private backgroundLayer: Container = new Container()
|
||||||
private gameSummaryView!: GameSummayView
|
private gameSummaryView!: GameSummayView
|
||||||
private players: PlayerDto[] = []
|
private players: PlayerDto[] = []
|
||||||
private soundManager: SoundManager = new SoundManager()
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private options: MatchSessionOptions,
|
private options: MatchSessionOptions,
|
||||||
@ -200,6 +197,7 @@ export class Game extends EventEmitter {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
const freeEnds = this.board.freeEnds
|
const freeEnds = this.board.freeEnds
|
||||||
|
console.log('freeEnds :>> ', freeEnds, this.playerId)
|
||||||
const move: Movement = {
|
const move: Movement = {
|
||||||
id: '',
|
id: '',
|
||||||
tile,
|
tile,
|
||||||
@ -217,6 +215,8 @@ export class Game extends EventEmitter {
|
|||||||
dirIndex += 1
|
dirIndex += 1
|
||||||
safeCount -= 1
|
safeCount -= 1
|
||||||
}
|
}
|
||||||
|
console.log('validMoves :>> ', validMoves)
|
||||||
|
console.log('validPoints :>> ', validPoints)
|
||||||
const validPoint = validPoints[dirIndex % 4]
|
const validPoint = validPoints[dirIndex % 4]
|
||||||
if (validPoint !== undefined) {
|
if (validPoint !== undefined) {
|
||||||
move.x = validPoint[0]
|
move.x = validPoint[0]
|
||||||
@ -227,7 +227,6 @@ export class Game extends EventEmitter {
|
|||||||
}
|
}
|
||||||
this.currentMove = move
|
this.currentMove = move
|
||||||
this.board.updateBoard(move, this.hand.tileMoved(tile))
|
this.board.updateBoard(move, this.hand.tileMoved(tile))
|
||||||
this.hand.afterMove()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async sendPassEvent() {
|
private async sendPassEvent() {
|
||||||
@ -237,7 +236,7 @@ export class Game extends EventEmitter {
|
|||||||
playerId: this.playerId,
|
playerId: this.playerId,
|
||||||
}
|
}
|
||||||
this.socketService &&
|
this.socketService &&
|
||||||
this.socketService.send('client:player-move', {
|
this.socketService.sendMessage('client:player-move', {
|
||||||
sessionId: this.sessionId,
|
sessionId: this.sessionId,
|
||||||
move: move,
|
move: move,
|
||||||
})
|
})
|
||||||
@ -288,7 +287,6 @@ export class Game extends EventEmitter {
|
|||||||
this.hand.setActive(true)
|
this.hand.setActive(true)
|
||||||
this.hand.prepareForMove(this.board.count === 0, this.board.freeEnds)
|
this.hand.prepareForMove(this.board.count === 0, this.board.freeEnds)
|
||||||
this.board.setPlayerTurn(currentPlayer)
|
this.board.setPlayerTurn(currentPlayer)
|
||||||
this.soundManager.play('snd-ding-1')
|
|
||||||
} else {
|
} else {
|
||||||
this.board.setServerPlayerTurn(currentPlayer)
|
this.board.setServerPlayerTurn(currentPlayer)
|
||||||
this.highLightPlayer(currentPlayer)
|
this.highLightPlayer(currentPlayer)
|
||||||
@ -325,20 +323,17 @@ export class Game extends EventEmitter {
|
|||||||
this.board.on('game:tile-animation-ended', async (tile) => {
|
this.board.on('game:tile-animation-ended', async (tile) => {
|
||||||
if (tile !== null && tile !== undefined && tile.playerId === this.playerId) {
|
if (tile !== null && tile !== undefined && tile.playerId === this.playerId) {
|
||||||
this.socketService &&
|
this.socketService &&
|
||||||
this.socketService.send('client:player-move', {
|
this.socketService.sendMessage('client:player-move', {
|
||||||
sessionId: this.sessionId,
|
sessionId: this.sessionId,
|
||||||
move: this.currentMove,
|
move: this.currentMove,
|
||||||
})
|
})
|
||||||
// this.socketService.sendMessage('client:player-move', {
|
} else {
|
||||||
// sessionId: this.sessionId,
|
this.socketService &&
|
||||||
// move: this.currentMove,
|
this.socketService.sendMessage('client:animation-ended', {
|
||||||
// })
|
sessionId: this.sessionId,
|
||||||
|
userId: this.playerId,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
this.socketService &&
|
|
||||||
this.socketService.sendMessage('client:animation-ended', {
|
|
||||||
sessionId: this.sessionId,
|
|
||||||
userId: this.playerId,
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@ import { createText, playerNameText, whiteStyle } from './utilities/fonts'
|
|||||||
import Config from '@/game/Config'
|
import Config from '@/game/Config'
|
||||||
import { TimerText } from './TimerText'
|
import { TimerText } from './TimerText'
|
||||||
import { Button } from './Button'
|
import { Button } from './Button'
|
||||||
import gsap from 'gsap'
|
|
||||||
|
|
||||||
export class Hand extends EventEmitter {
|
export class Hand extends EventEmitter {
|
||||||
tiles: Tile[] = []
|
tiles: Tile[] = []
|
||||||
@ -113,16 +112,10 @@ export class Hand extends EventEmitter {
|
|||||||
this.buttonPass.disabled = false
|
this.buttonPass.disabled = false
|
||||||
}
|
}
|
||||||
this.availableTiles.forEach((tile) => {
|
this.availableTiles.forEach((tile) => {
|
||||||
gsap.to(tile.getSprite(), {
|
tile.animateTo({
|
||||||
duration: 0.3,
|
x: tile.x,
|
||||||
y: tile.y - 10,
|
y: tile.y - 10,
|
||||||
alpha: 1,
|
|
||||||
ease: 'power4.out',
|
|
||||||
})
|
})
|
||||||
// tile.animateTo({
|
|
||||||
// x: tile.x,
|
|
||||||
// y: tile.y - 10,
|
|
||||||
// })
|
|
||||||
tile.interactive = true
|
tile.interactive = true
|
||||||
})
|
})
|
||||||
if (this.timer) {
|
if (this.timer) {
|
||||||
@ -153,21 +146,15 @@ export class Hand extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
afterMove() {
|
afterMove() {
|
||||||
this.timer && this.timer.reset()
|
|
||||||
this.availableTiles.forEach((tile) => {
|
this.availableTiles.forEach((tile) => {
|
||||||
if (tile.selected) return
|
tile.animateTo({
|
||||||
gsap.to(tile.getSprite(), {
|
x: tile.x,
|
||||||
duration: 0.3,
|
|
||||||
y: tile.y + 10,
|
y: tile.y + 10,
|
||||||
alpha: 0.7,
|
|
||||||
ease: 'power4.out',
|
|
||||||
})
|
})
|
||||||
// tile.animateTo({
|
tile.setPosition(tile.x, tile.y + 10)
|
||||||
// x: tile.x,
|
tile.interactive = false
|
||||||
// y: tile.y + 10,
|
|
||||||
// })
|
|
||||||
// tile.setPosition(tile.x, tile.y + 10)
|
|
||||||
})
|
})
|
||||||
|
this.timer && this.timer.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
hasMoves(tile: TileDto, freeEnds?: [number, number]): boolean {
|
hasMoves(tile: TileDto, freeEnds?: [number, number]): boolean {
|
||||||
@ -228,12 +215,7 @@ export class Hand extends EventEmitter {
|
|||||||
if (!tile) return
|
if (!tile) return
|
||||||
|
|
||||||
this.afterMove()
|
this.afterMove()
|
||||||
this.tiles = this.tiles.filter((t) => t.id !== tile.id)
|
this.tiles = this.tiles.filter((t) => t.id !== tileDto.id)
|
||||||
this.tiles.forEach((t) => {
|
|
||||||
t.interactive = false
|
|
||||||
t.alpha = 0.7
|
|
||||||
t.clearFilters()
|
|
||||||
})
|
|
||||||
|
|
||||||
tile.interactive = false
|
tile.interactive = false
|
||||||
tile.clearFilters()
|
tile.clearFilters()
|
||||||
@ -308,9 +290,9 @@ export class Hand extends EventEmitter {
|
|||||||
newTile.setFilters([
|
newTile.setFilters([
|
||||||
new GlowFilter({
|
new GlowFilter({
|
||||||
distance: 10,
|
distance: 10,
|
||||||
outerStrength: 1,
|
outerStrength: 2,
|
||||||
innerStrength: 1,
|
innerStrength: 1,
|
||||||
color: 0xffff66,
|
color: 0xffffff,
|
||||||
quality: 0.5,
|
quality: 0.5,
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
@ -318,7 +300,7 @@ export class Hand extends EventEmitter {
|
|||||||
newTile.on('pointerout', () => {
|
newTile.on('pointerout', () => {
|
||||||
if (!newTile.selected) {
|
if (!newTile.selected) {
|
||||||
this.emit('tileHover')
|
this.emit('tileHover')
|
||||||
newTile.alpha = 1
|
newTile.alpha = 0.7
|
||||||
newTile.getSprite().filters = []
|
newTile.getSprite().filters = []
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -337,18 +319,18 @@ export class Hand extends EventEmitter {
|
|||||||
this.scoreLayer.removeChildren()
|
this.scoreLayer.removeChildren()
|
||||||
const name = createText({
|
const name = createText({
|
||||||
text: this.player?.name ?? '-',
|
text: this.player?.name ?? '-',
|
||||||
x: 65,
|
x: 100,
|
||||||
y: 25,
|
y: 50,
|
||||||
style: playerNameText,
|
style: playerNameText,
|
||||||
})
|
})
|
||||||
const text = createText({
|
const text = createText({
|
||||||
text: `${this.score}`,
|
text: `${this.score}`,
|
||||||
x: 65,
|
x: 100,
|
||||||
// x: this.width - 5,
|
// x: this.width - 5,
|
||||||
y: 75,
|
y: 80,
|
||||||
style: whiteStyle(60, 'bold'),
|
style: whiteStyle(36, 'bold'),
|
||||||
})
|
})
|
||||||
text.anchor.set(0.5, 0.5)
|
text.anchor.set(1, 0.5)
|
||||||
this.scoreLayer.addChild(name)
|
this.scoreLayer.addChild(name)
|
||||||
this.scoreLayer.addChild(text)
|
this.scoreLayer.addChild(text)
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ export abstract class SpriteBase {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected ticker?: Ticker,
|
protected ticker?: Ticker,
|
||||||
protected scale: number = 1,
|
protected scale: number = 1
|
||||||
) {
|
) {
|
||||||
this.ticker = ticker
|
this.ticker = ticker
|
||||||
this.scale = scale
|
this.scale = scale
|
||||||
@ -84,6 +84,58 @@ export abstract class SpriteBase {
|
|||||||
this.sprite.filters = []
|
this.sprite.filters = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
animateTo(options: AnimationOptions): Promise<void> {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const {
|
||||||
|
x: targetX,
|
||||||
|
y: targetY,
|
||||||
|
rotation: targetRotation,
|
||||||
|
duration = 10,
|
||||||
|
width: targetWidth,
|
||||||
|
height: targetHeight
|
||||||
|
} = options
|
||||||
|
|
||||||
|
const initialX = this.sprite.x
|
||||||
|
const initialY = this.sprite.y
|
||||||
|
const initialRotation = this.sprite.rotation
|
||||||
|
const initialWidth = this.sprite.width
|
||||||
|
const initialHeight = this.sprite.height
|
||||||
|
|
||||||
|
const deltaX = targetX ? targetX - this.sprite.x : null
|
||||||
|
const deltaY = targetY ? targetY - this.sprite.y : null
|
||||||
|
const deltaRotation = targetRotation ? targetRotation - this.sprite.rotation : null
|
||||||
|
const deltaWidth = targetWidth ? targetWidth - this.sprite.width : null
|
||||||
|
const deltaHeight = targetHeight ? targetHeight - this.sprite.height : null
|
||||||
|
|
||||||
|
let elapsed: number = 0
|
||||||
|
|
||||||
|
const tick: any = (delta: any) => {
|
||||||
|
elapsed += delta.deltaTime
|
||||||
|
const progress = Math.min(elapsed / duration, 1)
|
||||||
|
|
||||||
|
// Linear interpolation
|
||||||
|
if (deltaX !== null) this.sprite.x = initialX + deltaX * progress
|
||||||
|
if (deltaY !== null) this.sprite.y = initialY + deltaY * progress
|
||||||
|
|
||||||
|
// Rotation interpolation
|
||||||
|
if (deltaRotation !== null)
|
||||||
|
this.sprite.rotation = initialRotation + deltaRotation * progress
|
||||||
|
|
||||||
|
// Scale interpolation
|
||||||
|
// this.sprite.width = initialWidth + deltaWidth * progress
|
||||||
|
// this.sprite.height = initialHeight + deltaHeight * progress
|
||||||
|
|
||||||
|
//
|
||||||
|
if (progress === 1) {
|
||||||
|
this.ticker?.remove(tick)
|
||||||
|
resolve()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ticker?.add(tick)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
addTo(container: any) {
|
addTo(container: any) {
|
||||||
this.container = container
|
this.container = container
|
||||||
container.addChild(this.sprite)
|
container.addChild(this.sprite)
|
||||||
|
@ -2,10 +2,9 @@ import { Container, Point, Text, TextStyle } from 'pixi.js'
|
|||||||
import { createText, timerStyle } from './utilities/fonts'
|
import { createText, timerStyle } from './utilities/fonts'
|
||||||
|
|
||||||
import { gsap } from 'gsap'
|
import { gsap } from 'gsap'
|
||||||
import { Timer } from './utilities/Timer'
|
|
||||||
|
|
||||||
export class TimerText extends Container {
|
export class TimerText extends Container {
|
||||||
private timer: Timer
|
private intervalHandle?: any
|
||||||
private text?: Text
|
private text?: Text
|
||||||
animation: boolean = false
|
animation: boolean = false
|
||||||
textStyle: TextStyle = timerStyle()
|
textStyle: TextStyle = timerStyle()
|
||||||
@ -17,35 +16,41 @@ export class TimerText extends Container {
|
|||||||
private point: Point,
|
private point: Point,
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
this.timer = new Timer(seconds)
|
|
||||||
this.timer.on('timeout', this.onTImeOut.bind(this))
|
|
||||||
this.timer.on('tick', this.onTick.bind(this))
|
|
||||||
this.countdown = seconds
|
|
||||||
this.render()
|
|
||||||
}
|
|
||||||
|
|
||||||
private onTImeOut() {
|
|
||||||
this.timer.reset()
|
|
||||||
this.emit('timeout')
|
|
||||||
}
|
|
||||||
|
|
||||||
private onTick(seconds: number) {
|
|
||||||
!this.animation && this.text?.destroy()
|
|
||||||
this.countdown = seconds
|
this.countdown = seconds
|
||||||
this.render()
|
this.render()
|
||||||
}
|
}
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
this.timer.stop()
|
this.stop()
|
||||||
this.timer.reset()
|
|
||||||
this.countdown = this.seconds
|
this.countdown = this.seconds
|
||||||
this.isInitiated = false
|
this.isInitiated = false
|
||||||
this.render()
|
this.render()
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
this.timer.reset()
|
clearInterval(this.intervalHandle)
|
||||||
this.timer.start()
|
this.isInitiated = true
|
||||||
|
this.removeChildren()
|
||||||
|
this.render()
|
||||||
|
this.intervalHandle = setInterval(() => {
|
||||||
|
this.countdown--
|
||||||
|
!this.animation && this.text?.destroy()
|
||||||
|
this.render()
|
||||||
|
if (this.countdown === 0) {
|
||||||
|
clearInterval(this.intervalHandle)
|
||||||
|
this.emit('timeout')
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
this.stop()
|
||||||
|
this.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
clearInterval(this.intervalHandle)
|
||||||
|
this.emit('stop', this.countdown)
|
||||||
}
|
}
|
||||||
|
|
||||||
private render() {
|
private render() {
|
||||||
|
@ -15,7 +15,6 @@ export class Timer extends EventEmitter {
|
|||||||
this.countdown--
|
this.countdown--
|
||||||
if (this.countdown === 0) {
|
if (this.countdown === 0) {
|
||||||
clearInterval(this.intervalHandle)
|
clearInterval(this.intervalHandle)
|
||||||
console.log('tic')
|
|
||||||
this.emit('timeout')
|
this.emit('timeout')
|
||||||
} else {
|
} else {
|
||||||
this.emit('tick', this.countdown)
|
this.emit('tick', this.countdown)
|
||||||
|
@ -14,11 +14,11 @@
|
|||||||
"scoreboard": "Scoreboard",
|
"scoreboard": "Scoreboard",
|
||||||
"available-sessions": "Available Sessions",
|
"available-sessions": "Available Sessions",
|
||||||
"no-sessions-available": "No sessions available",
|
"no-sessions-available": "No sessions available",
|
||||||
"id-session-_id": "ID:",
|
"id-session-_id": "ID: {0}",
|
||||||
"players-session-players-length": "Players:",
|
"players-session-players-length": "Players: {0}",
|
||||||
"copy": "Copy",
|
"copy": "Copy",
|
||||||
"seed-session-seed": "Seed:",
|
"seed-session-seed": "Seed: {0}",
|
||||||
"status-session-status": "Status:",
|
"status-session-status": "Status: {0}",
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
"join": "Join",
|
"join": "Join",
|
||||||
"welcome-to-the-user-username-s-home-page": "Welcome to the {0}'s Home Page",
|
"welcome-to-the-user-username-s-home-page": "Welcome to the {0}'s Home Page",
|
||||||
@ -35,7 +35,7 @@
|
|||||||
"crossed-game-teamed": "Crossed game",
|
"crossed-game-teamed": "Crossed game",
|
||||||
"create-match-session": "Create Match Session",
|
"create-match-session": "Create Match Session",
|
||||||
"ready": "Ready",
|
"ready": "Ready",
|
||||||
"unready": "Not ready",
|
"unready": "Unready",
|
||||||
"start": "Start",
|
"start": "Start",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"game": {
|
"game": {
|
||||||
@ -59,18 +59,16 @@
|
|||||||
"n-rounds": "One Round|{count} Rounds",
|
"n-rounds": "One Round|{count} Rounds",
|
||||||
"n-of-m-rounds": "{0} of {1} Rounds",
|
"n-of-m-rounds": "{0} of {1} Rounds",
|
||||||
"create-session": "Create Session",
|
"create-session": "Create Session",
|
||||||
"join-a-multiplayer-session": "Multiplayer (0)|Multiplayer ({count})|Multiplayer ({count})",
|
"join-a-multiplayer-session": "Join a Multiplayer Session (No sessions)|Join a Multiplayer Session ({count})|Join a Multiplayer Session ({count})",
|
||||||
"tournaments": "Tournaments",
|
"tournaments": "Tournaments",
|
||||||
"start-game": "Start Game",
|
"start-game": "Start Game",
|
||||||
"player": "Player",
|
"player": "Player",
|
||||||
"final-score": "Final Score",
|
"final-score": "Final Score",
|
||||||
"round-index": "Round #{0}",
|
"round-index": "Round #{0}",
|
||||||
"first-actor-to-win-this-options-wintarget-this-options-wintype": "First {0} to reach {1}",
|
"first-actor-to-win-this-options-wintarget-this-options-wintype": "First {0} to win {1}",
|
||||||
"team": "team",
|
"team": "team",
|
||||||
"winner-name": "Winner: {0}",
|
"winner-name": "Winner: {0}",
|
||||||
"blocked": "Blocked",
|
"blocked": "Blocked",
|
||||||
"round-summary": "Round Summary",
|
"round-summary": "Round Summary",
|
||||||
"match-finished": "Match Finished",
|
"match-finished": "Match Finished"
|
||||||
"host-session-host": "Host:",
|
|
||||||
"players": "Players"
|
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,10 @@
|
|||||||
"scoreboard": "Marcador",
|
"scoreboard": "Marcador",
|
||||||
"winner": "Ganador",
|
"winner": "Ganador",
|
||||||
"final-scoreboard": "Puntaje Final",
|
"final-scoreboard": "Puntaje Final",
|
||||||
"id-session-_id": "ID:",
|
"id-session-_id": "ID: {0}",
|
||||||
"seed-placeholder": "¡Escriba la semilla de la sesión aquí!",
|
"seed-placeholder": "¡Escriba la semilla de la sesión aquí!",
|
||||||
"session-name-placeholder": "Nombre de la sesión",
|
"session-name-placeholder": "Nombre de la sesión",
|
||||||
"status-session-status": "Estado:",
|
"status-session-status": "Estado: {0}",
|
||||||
"unready": "No preparado",
|
"unready": "No preparado",
|
||||||
"welcome-to-the-user-username-s-home-page": "Bienvenido a la página de inicio de {0}",
|
"welcome-to-the-user-username-s-home-page": "Bienvenido a la página de inicio de {0}",
|
||||||
"available-sessions": "Sesiones disponibles",
|
"available-sessions": "Sesiones disponibles",
|
||||||
@ -38,11 +38,11 @@
|
|||||||
"join": "Unirse",
|
"join": "Unirse",
|
||||||
"name": "Nombre",
|
"name": "Nombre",
|
||||||
"no-sessions-available": "No hay sesiones disponibles",
|
"no-sessions-available": "No hay sesiones disponibles",
|
||||||
"players-session-players-length": "Jugadores:",
|
"players-session-players-length": "Jugadores: {0}",
|
||||||
"ready": "Listo",
|
"ready": "Listo",
|
||||||
"red-fabric": "Tela roja",
|
"red-fabric": "Tela roja",
|
||||||
"seed": "Semilla",
|
"seed": "Semilla",
|
||||||
"seed-session-seed": "Semilla:",
|
"seed-session-seed": "Semilla: {0}",
|
||||||
"start": "Comenzar",
|
"start": "Comenzar",
|
||||||
"yellow-fabric": "Tela amarilla",
|
"yellow-fabric": "Tela amarilla",
|
||||||
"back": "Volver",
|
"back": "Volver",
|
||||||
@ -70,7 +70,5 @@
|
|||||||
"blocked": "Cerrado",
|
"blocked": "Cerrado",
|
||||||
"round-summary": "Resumen de la ronda",
|
"round-summary": "Resumen de la ronda",
|
||||||
"match-finished": "Partida terminado",
|
"match-finished": "Partida terminado",
|
||||||
"team": "equipo",
|
"team": "equipo"
|
||||||
"host-session-host": "Creada por:",
|
|
||||||
"players": "Jugadores"
|
|
||||||
}
|
}
|
||||||
|
@ -105,16 +105,4 @@ router.beforeEach((to, from, next) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
router.beforeResolve((to, from, next) => {
|
|
||||||
const app = document.querySelector('#app')
|
|
||||||
if (app) {
|
|
||||||
if (from.name !== undefined) {
|
|
||||||
app.classList.replace(<string>from.name, <string>to.name)
|
|
||||||
} else {
|
|
||||||
app.classList.add(<string>to.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
next()
|
|
||||||
})
|
|
||||||
|
|
||||||
export default router
|
export default router
|
||||||
|
@ -50,10 +50,9 @@ export class SocketIoClientService extends ServiceBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addEvents(): void {
|
addEvents(): void {
|
||||||
this.socket.on('disconnect', (reason) => {
|
this.socket.on('disconnect', () => {
|
||||||
this.isConnected = false
|
this.isConnected = false
|
||||||
console.log('SOCKET: Disconnected from server')
|
console.log('SOCKET: Disconnected from server')
|
||||||
console.log(`Reason: ${reason}`)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
this.socket.on('reconnect', () => {
|
this.socket.on('reconnect', () => {
|
||||||
@ -88,15 +87,6 @@ export class SocketIoClientService extends ServiceBase {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
send(event: string, data: any): void {
|
|
||||||
if (this.isConnected) {
|
|
||||||
this.socket?.emit(event, data)
|
|
||||||
this.logger.trace(`SOCKET: sendEvent :>> ${event}`, data)
|
|
||||||
} else {
|
|
||||||
this.logger.trace('Not connected to server')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sendMessage(event: string, data: any): void {
|
sendMessage(event: string, data: any): void {
|
||||||
if (this.isConnected) {
|
if (this.isConnected) {
|
||||||
this.socket?.emit('client:event', { event, data })
|
this.socket?.emit('client:event', { event, data })
|
||||||
|
@ -23,6 +23,7 @@ if (!playerState?.value) {
|
|||||||
function makeMove(move: any) {
|
function makeMove(move: any) {
|
||||||
moveToMake.value = move
|
moveToMake.value = move
|
||||||
canMakeMove.value = false
|
canMakeMove.value = false
|
||||||
|
console.log('makemove :>> ', move)
|
||||||
}
|
}
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
|
@ -13,8 +13,6 @@ import MatchConfiguration from '@/components/MatchConfiguration.vue'
|
|||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { SessionExpiredError } from '@/common/errors/SessionExpiredError'
|
import { SessionExpiredError } from '@/common/errors/SessionExpiredError'
|
||||||
import type { AuthenticationService } from '@/services/AuthenticationService'
|
import type { AuthenticationService } from '@/services/AuthenticationService'
|
||||||
import SessionBoxComponent from '@/components/SessionBoxComponent.vue'
|
|
||||||
import MultiplayerSetupComponent from '@/components/MultiplayerSetupComponent.vue'
|
|
||||||
|
|
||||||
let teamedWith = ref<string | undefined>(undefined)
|
let teamedWith = ref<string | undefined>(undefined)
|
||||||
|
|
||||||
@ -33,7 +31,8 @@ const authService: AuthenticationService = inject<AuthenticationService>(
|
|||||||
'auth',
|
'auth',
|
||||||
) as AuthenticationService
|
) as AuthenticationService
|
||||||
|
|
||||||
const { sessionState, isSessionStarted, playerState, amIHost } = storeToRefs(gameStore)
|
const { sessionState, isSessionStarted, playerState, amIHost, readyForStart } =
|
||||||
|
storeToRefs(gameStore)
|
||||||
const { gameOptions } = storeToRefs(gameOptionsStore)
|
const { gameOptions } = storeToRefs(gameOptionsStore)
|
||||||
const { updateSessionState, updatePlayerState, updateGameState } = gameStore
|
const { updateSessionState, updatePlayerState, updateGameState } = gameStore
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
@ -44,13 +43,17 @@ eventBus.subscribe('window-before-unload', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
async function createMatch(options: MatchSessionOptions) {
|
async function createMatch(options: MatchSessionOptions) {
|
||||||
|
logger.debug('Creating match')
|
||||||
await socketService.connect()
|
await socketService.connect()
|
||||||
gameOptions.value = options
|
gameOptions.value = options
|
||||||
const sessionId = await gameService.createMatchSession(options)
|
const sessionId = await gameService.createMatchSession(options)
|
||||||
socketService.joinRoom(`room-${sessionId}`)
|
socketService.joinRoom(`room-${sessionId}`)
|
||||||
|
logger.debug('Match created successfully')
|
||||||
|
// router.push({ name: 'match', params: { id } })
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setPlayerReady() {
|
async function setPlayerReady() {
|
||||||
|
logger.debug('Starting game')
|
||||||
if (!sessionState.value) {
|
if (!sessionState.value) {
|
||||||
logger.error('No session found')
|
logger.error('No session found')
|
||||||
return
|
return
|
||||||
@ -65,15 +68,14 @@ async function setPlayerReady() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function startMatch(teamedWith?: string) {
|
async function startMatch() {
|
||||||
console.log('teamedWith :>> ', teamedWith)
|
|
||||||
const sessionId = sessionState?.value?.id
|
const sessionId = sessionState?.value?.id
|
||||||
const playerId = playerState?.value?.id
|
const playerId = playerState?.value?.id
|
||||||
if (sessionId) {
|
if (sessionId) {
|
||||||
await socketService.sendMessageWithAck('client:start-session', {
|
await socketService.sendMessageWithAck('client:start-session', {
|
||||||
sessionId: sessionId,
|
sessionId: sessionId,
|
||||||
playerId: playerId,
|
playerId: playerId,
|
||||||
teamedWith: teamedWith,
|
teamedWith: teamedWith.value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,6 +117,20 @@ async function deleteMatch(id: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const playersToTeamUpWith = computed(() => {
|
||||||
|
return (
|
||||||
|
sessionState?.value?.players.filter((player) => player.id !== sessionState?.value?.creator) ||
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const canStart = computed(() => {
|
||||||
|
const players = sessionState?.value?.players || []
|
||||||
|
const options = gameOptions.value
|
||||||
|
const allReady = (players.length || 0) > 0 && players.every((player) => player.ready)
|
||||||
|
return (!options?.teamed && allReady) || (options?.teamed && !!teamedWith.value && allReady)
|
||||||
|
})
|
||||||
|
|
||||||
const isMultiplayer = computed(
|
const isMultiplayer = computed(
|
||||||
() => (sessionState?.value?.options?.numPlayers || gameOptions.value?.numPlayers || 0) > 1,
|
() => (sessionState?.value?.options?.numPlayers || gameOptions.value?.numPlayers || 0) > 1,
|
||||||
)
|
)
|
||||||
@ -151,18 +167,18 @@ function copy(sessionSeed: string) {
|
|||||||
copyToclipboard(sessionSeed)
|
copyToclipboard(sessionSeed)
|
||||||
}
|
}
|
||||||
|
|
||||||
let selectedTab = ref('join-tab')
|
let selectedTab = ref('create-tab')
|
||||||
const isCreateTab = computed(() => selectedTab.value === 'create-tab')
|
const isCreateTab = computed(() => selectedTab.value === 'create-tab')
|
||||||
const isJoinTab = computed(() => selectedTab.value === 'join-tab')
|
const isJoinTab = computed(() => selectedTab.value === 'join-tab')
|
||||||
const isTournamentTab = computed(() => selectedTab.value === 'torunaments-tab')
|
const isTournamentTab = computed(() => selectedTab.value === 'torunaments-tab')
|
||||||
|
|
||||||
const tabs = computed<any[]>((): any => [
|
const tabs = computed<any[]>((): any => [
|
||||||
{
|
|
||||||
label: t('join-a-multiplayer-session', matchSessions.value?.length ?? 0),
|
|
||||||
id: 'join-tab',
|
|
||||||
disabled: false, //matchSessions.value.length <= 0,
|
|
||||||
},
|
|
||||||
{ label: t('create-session'), id: 'create-tab', disabled: false },
|
{ label: t('create-session'), id: 'create-tab', disabled: false },
|
||||||
|
{
|
||||||
|
label: t('join-a-multiplayer-session', matchSessions.value.length),
|
||||||
|
id: 'join-tab',
|
||||||
|
disabled: matchSessions.value.length <= 0,
|
||||||
|
},
|
||||||
{ label: t('tournaments'), id: 'torunaments-tab', disabled: true },
|
{ label: t('tournaments'), id: 'torunaments-tab', disabled: true },
|
||||||
])
|
])
|
||||||
|
|
||||||
@ -213,28 +229,38 @@ async function onStartSingleMatch(options: MatchSessionOptions) {
|
|||||||
<section class="section available-sessions" v-if="isJoinTab">
|
<section class="section available-sessions" v-if="isJoinTab">
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<div v-if="matchSessions.length === 0">
|
<div v-if="matchSessions.length === 0">
|
||||||
<p class="has-text-centered mt-6 pt-6">{{ $t('no-sessions-available') }}</p>
|
<p>{{ $t('no-sessions-available') }}</p>
|
||||||
<div class="buttons is-justify-content-center mt-6">
|
|
||||||
<button class="button is-primary is-small" @click="() => tabClick(tabs[1])">
|
|
||||||
{{ $t('create-session') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else class="fixed-grid has-3-cols">
|
||||||
<div class="buttons is-justify-content-center mt-6">
|
<div class="grid">
|
||||||
<button class="button is-primary is-small" @click="() => tabClick(tabs[1])">
|
<div class="cell" v-for="session in matchSessions" :key="session.id">
|
||||||
{{ $t('create-session') }}
|
<div class="card">
|
||||||
</button>
|
<div class="card-content">
|
||||||
</div>
|
<p class="title is-6">{{ session.name }}</p>
|
||||||
<div class="fixed-grid has-3-cols">
|
<p>{{ $t('id-session-_id', [session._id]) }}</p>
|
||||||
<div class="grid">
|
<p>{{ $t('players-session-players-length', [session.players.length]) }}</p>
|
||||||
<div class="cell" v-for="session in matchSessions" :key="session.id">
|
<p>
|
||||||
<SessionBoxComponent
|
{{ $t('seed-session-seed', [session.seed]) }}
|
||||||
:session="session"
|
<button class="button is-small is-ghost" @click="() => copy(session.seed)">
|
||||||
@join="joinMatch"
|
{{ $t('copy') }}
|
||||||
@delete="deleteMatch"
|
</button>
|
||||||
@copy="copy"
|
</p>
|
||||||
/>
|
<p>{{ $t('status-session-status', [session.status]) }}</p>
|
||||||
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -246,12 +272,45 @@ async function onStartSingleMatch(options: MatchSessionOptions) {
|
|||||||
<section class="section" v-if="isTournamentTab"></section>
|
<section class="section" v-if="isTournamentTab"></section>
|
||||||
<!-- Tournaments End -->
|
<!-- Tournaments End -->
|
||||||
</div>
|
</div>
|
||||||
<MultiplayerSetupComponent
|
<div class="block" v-if="isSessionStarted && isMultiplayer">
|
||||||
v-if="isSessionStarted && isMultiplayer"
|
<h2 class="title is-4">{{ sessionState?.name }}</h2>
|
||||||
@ready="setPlayerReady"
|
<h6 class="title is-size-5">Players</h6>
|
||||||
@start="startMatch"
|
<div v-for="player in sessionState?.players" :key="player.id">
|
||||||
@cancel="cancelMatch"
|
<p>{{ player.name }} ({{ player.ready ? 'Ready' : 'Not ready' }})</p>
|
||||||
/>
|
</div>
|
||||||
|
<div class="mt-4" v-if="amIHost && gameOptions?.teamed && playersToTeamUpWith.length > 0">
|
||||||
|
<div class="field">
|
||||||
|
<label for="background" class="label">Team up with</label>
|
||||||
|
<div class="control">
|
||||||
|
<div class="select">
|
||||||
|
<select v-model="teamedWith" name="teamedWidth">
|
||||||
|
<option v-for="player in playersToTeamUpWith" :key="player.id" :value="player.id">
|
||||||
|
{{ player.name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="buttons mt-6">
|
||||||
|
<button class="button is-dark" @click="setPlayerReady">
|
||||||
|
<span v-if="!readyForStart">{{ $t('ready') }}</span
|
||||||
|
><span v-else>{{ $t('unready') }}</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="button is-success"
|
||||||
|
:disabled="!canStart"
|
||||||
|
@click="startMatch"
|
||||||
|
v-if="amIHost"
|
||||||
|
>
|
||||||
|
<span>{{ $t('start') }}</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="button is-danger" @click="cancelMatch">
|
||||||
|
<span>{{ $t('cancel') }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -52,56 +52,45 @@ async function login() {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="container login">
|
<div class="login">
|
||||||
<div class="is-flex is-justify-content-center is-align-items-center">
|
<h1 class="title">{{ $t('login') }}</h1>
|
||||||
<div class="login-form-container box is-no-shadow" style="width: 400px">
|
<div class="message is-danger">
|
||||||
<div class="message is-danger">
|
<div class="message-body" v-if="errorLogin">
|
||||||
<div class="message-body" v-if="errorLogin">
|
{{ $t('invalid-username-or-password') }}
|
||||||
{{ $t('invalid-username-or-password') }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<form class="form" @submit.prevent="login">
|
|
||||||
<div class="field">
|
|
||||||
<label class="label">{{ $t('username') }}</label>
|
|
||||||
<div class="control">
|
|
||||||
<input
|
|
||||||
class="input"
|
|
||||||
type="text"
|
|
||||||
v-model="username"
|
|
||||||
:placeholder="t('username-placeholder')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<label class="label">{{ $t('password') }}</label>
|
|
||||||
<div class="control">
|
|
||||||
<input
|
|
||||||
class="input"
|
|
||||||
type="password"
|
|
||||||
v-model="password"
|
|
||||||
:placeholder="t('password-placeholder')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field is-grouped">
|
|
||||||
<div class="control">
|
|
||||||
<button class="button is-primary" type="submit">{{ $t('login-button') }}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<form class="form" @submit.prevent="login">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">{{ $t('username') }}</label>
|
||||||
|
<div class="control">
|
||||||
|
<input
|
||||||
|
class="input"
|
||||||
|
type="text"
|
||||||
|
v-model="username"
|
||||||
|
:placeholder="t('username-placeholder')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">{{ $t('password') }}</label>
|
||||||
|
<div class="control">
|
||||||
|
<input
|
||||||
|
class="input"
|
||||||
|
type="password"
|
||||||
|
v-model="password"
|
||||||
|
:placeholder="t('password-placeholder')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field is-grouped">
|
||||||
|
<div class="control">
|
||||||
|
<button class="button is-primary" type="submit">{{ $t('login-button') }}</button>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="control">
|
||||||
|
<button class="button">Cancel</button>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.login,
|
|
||||||
.login > div {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-form-container {
|
|
||||||
width: 400px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
1
types/type.d.ts
vendored
1
types/type.d.ts
vendored
@ -6,5 +6,4 @@ declare module 'socket.io' {
|
|||||||
|
|
||||||
declare interface Window {
|
declare interface Window {
|
||||||
__TAURI__: any
|
__TAURI__: any
|
||||||
opera: any
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user