Renommage assets > /public + Refonte logique et interface de jeu

This commit is contained in:
2024-10-24 19:03:44 +02:00
parent ecfae6d29d
commit bb781f590c
21 changed files with 149 additions and 21 deletions

View File

Before

Width:  |  Height:  |  Size: 169 B

After

Width:  |  Height:  |  Size: 169 B

View File

Before

Width:  |  Height:  |  Size: 179 B

After

Width:  |  Height:  |  Size: 179 B

View File

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

View File

Before

Width:  |  Height:  |  Size: 163 B

After

Width:  |  Height:  |  Size: 163 B

View File

Before

Width:  |  Height:  |  Size: 162 B

After

Width:  |  Height:  |  Size: 162 B

View File

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

View File

Before

Width:  |  Height:  |  Size: 160 B

After

Width:  |  Height:  |  Size: 160 B

View File

Before

Width:  |  Height:  |  Size: 181 B

After

Width:  |  Height:  |  Size: 181 B

View File

Before

Width:  |  Height:  |  Size: 117 B

After

Width:  |  Height:  |  Size: 117 B

BIN
public/sEmpty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

View File

Before

Width:  |  Height:  |  Size: 184 B

After

Width:  |  Height:  |  Size: 184 B

View File

Before

Width:  |  Height:  |  Size: 221 B

After

Width:  |  Height:  |  Size: 221 B

View File

Before

Width:  |  Height:  |  Size: 232 B

After

Width:  |  Height:  |  Size: 232 B

View File

Before

Width:  |  Height:  |  Size: 195 B

After

Width:  |  Height:  |  Size: 195 B

View File

Before

Width:  |  Height:  |  Size: 131 B

After

Width:  |  Height:  |  Size: 131 B

View File

Before

Width:  |  Height:  |  Size: 702 B

After

Width:  |  Height:  |  Size: 702 B

View File

Before

Width:  |  Height:  |  Size: 141 B

After

Width:  |  Height:  |  Size: 141 B

View File

@@ -6,27 +6,27 @@ const router = createRouter({
{
path: '/',
name: 'home',
component: () => import('../views/HomeView.vue')
component: () => import('@/views/HomeView.vue')
},
{
path: '/about',
name: 'about',
component: () => import('../views/AboutView.vue')
component: () => import('@/views/AboutView.vue')
},
{
path: '/game',
name: 'game',
component: () => import('../views/GameView.vue'),
component: () => import('@/views/GameView.vue'),
children: [
{
path: 'solo',
name: 'solo',
component: () => import('../views/Game/SoloView.vue')
component: () => import('@/views/Game/SoloView.vue')
},
{
path: 'party',
name: 'party',
component: () => import('../views/Game/PartyView.vue')
component: () => import('@/views/Game/PartyView.vue')
}
]
}

View File

@@ -1,3 +1,46 @@
type CellGrid = string[][] // type CellGrid (grille de jeu)
type MineGrid = number[][] // type MineGrid (grille de bombes)
function genCellGrid(width: number, length: number): CellGrid { // fonction genCellGrid (génération de la grille de jeu)
return Array.from({ length: width }, () => Array.from({ length: length }, () => "/sUnknown.png"))
}
function genMineGrid(width: number, length: number, nbMines: number): MineGrid { // fonction genMineGrid (génération des bombes)
const mineGrid: MineGrid = [] // initialisation de la grille de bombes
while (mineGrid.length < nbMines) { // boucle pour placer les bombes
const x = Math.floor(Math.random() * length) // position x de la bombe
const y = Math.floor(Math.random() * width) // position y de la bombe
const indice = [y, x] // id de la bombe
if (!mineGrid.includes(indice)) mineGrid.push(indice) // si la bombe n'est pas déjà placée, on la place
}
return mineGrid; // retour de la grille de bombes
}
function cliqueGauche(cellGrid: CellGrid, mineGrid: MineGrid, x: number, y: number) { // fonction main (début du jeu)
//const indice = [y, x] // id de la case cliquée
//if (mineGrid.includes(indice)) bombe() // si la case cliquée est une bombe, on va dans la fonction bombe
//else if (champDeMines[indice] === 0) {caseVide(indice);} // si la case cliquée est vide, on va dans la fonction caseVide
//else if (champDeMines[indice] !== 0) {decouvreCase(indice);} // si la case cliquée est un numéro, on va dans la fonction decouvreCase
//decouvreCase(indice);
if (cellGrid[y][x] === '/sClick.png') return cellGrid[y][x] = '/sEmpty.png' // modification de l'image de la case
}
function cliqueDroit(cellGrid: string[][], x: number, y: number): void { // fonction cliqueDroit (flag d'une case) // modification de l'image de la case
switch (cellGrid[y][x]) {
case '/sUnknown.png':
cellGrid[y][x] = "/sFlag.png"
break
case '/sFlag.png':
cellGrid[y][x] = "/sQuestion.png"
break
case '/sQuestion.png':
cellGrid[y][x] = "/sUnknown.png"
break
}
}
/*
const directions: number[] = [-11, -10, -9, -1, 1, 9, 10, 11]; // directions possibles pour découvrir les cases
const champDeMines: number[] = []; // champ de mines (0 = case vide, 10 = bombe, 1 à 8 = nombre de bombes adjacentes)
for (let i = 0; i < 100; i++) {champDeMines.push(0);} // initialisation des cases à 0
@@ -19,18 +62,7 @@ function caseVide(indice: number): void {
function decouvreCase(indice: number): void { // fonction decouvreCase (découverte d'une case)
casesDecouvertes[indice] = 1; // modification dans le tableau des cases découvertes
}
*/
function flagCase(indice: number): void { // fonction flagCase (flag d'une case)
casesDecouvertes[indice] = 2; // modification dans le tableau des cases découvertes
}
function cliqueGauche(indice: number): void { // fonction main (début du jeu)
if (champDeMines[indice] === 10) {bombe();} // si la case cliquée est une bombe, on va dans la fonction bombe
else if (champDeMines[indice] === 0) {caseVide(indice);} // si la case cliquée est vide, on va dans la fonction caseVide
else if (champDeMines[indice] !== 0) {decouvreCase(indice);} // si la case cliquée est un numéro, on va dans la fonction decouvreCase
decouvreCase(indice);
}
function cliqueDroite(indice: number): void { // fonction cliqueDroite (flag d'une case)
flagCase(indice);
}
export { genCellGrid, genMineGrid, cliqueGauche, cliqueDroit } // export des variables et fonctions
export type { CellGrid, MineGrid } // export des types

View File

@@ -1,5 +1,101 @@
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { genCellGrid, genMineGrid, cliqueGauche, cliqueDroit } from '@/utils/game'
import type { CellGrid, MineGrid } from '@/utils/game'
const width = 10
const length = 15
const nbMines = 25
// Création grille des cases
const cellGrid = ref<CellGrid>([])
cellGrid.value = genCellGrid(width, length)
// Création grille des mines
let mineGrid: MineGrid = []
mineGrid = genMineGrid(width, length, nbMines)
// État pour gérer le clic et la position de la cellule
const isMouseDown = ref(false)
const currentCell = ref<{ rowIndex: number, cellIndex: number } | null>(null)
const handleMouseDown = (rowIndex: number, cellIndex: number) => {
isMouseDown.value = true
currentCell.value = { rowIndex, cellIndex }
if (cellGrid.value[rowIndex][cellIndex] === '/sUnknown.png') cellGrid.value[rowIndex][cellIndex] = '/sClick.png'
}
const handleMouseUp = (rowIndex: number, cellIndex: number) => {
isMouseDown.value = false
cliqueGauche(cellGrid.value, mineGrid, cellIndex, rowIndex)
currentCell.value = null
}
const handleMouseMove = (rowIndex: number, cellIndex: number) => {
if (isMouseDown.value && currentCell.value) {
const { rowIndex: prevRowIndex, cellIndex: prevCellIndex } = currentCell.value
if (prevRowIndex !== rowIndex || prevCellIndex !== cellIndex) {
if (cellGrid.value[prevRowIndex][prevCellIndex] === '/sClick.png') cellGrid.value[prevRowIndex][prevCellIndex] = '/sUnknown.png' // Réinitialiser l'image précédente
if (cellGrid.value[rowIndex][cellIndex] === '/sUnknown.png') cellGrid.value[rowIndex][cellIndex] = '/sClick.png' // Changer l'image actuelle
currentCell.value = { rowIndex, cellIndex }
}
}
}
const handleGlobalMouseMove = (event: MouseEvent) => {
if (isMouseDown.value && currentCell.value) {
const target = event.target as HTMLElement
if (!target.classList.contains('cell')) {
const { rowIndex, cellIndex } = currentCell.value
if (cellGrid.value[rowIndex][cellIndex] === '/sClick.png') {
cellGrid.value[rowIndex][cellIndex] = '/sUnknown.png'
}
currentCell.value = null
}
}
}
onMounted(() => document.addEventListener('mousemove', handleGlobalMouseMove))
onUnmounted(() => document.removeEventListener('mousemove', handleGlobalMouseMove))
</script>
<template>
<div class="main">
<h1>Solo</h1>
<div class="grid">
<div v-for="(row, rowIndex) in cellGrid" :key="rowIndex" class="row">
<div v-for="(cell, cellIndex) in row" :key="cellIndex">
<img class="cell" :src="cell"
@mousedown.right="cliqueDroit(cellGrid, cellIndex, rowIndex)"
@mousedown.left="handleMouseDown(rowIndex, cellIndex)"
@mouseup.left="handleMouseUp(rowIndex, cellIndex)"
@mousemove="handleMouseMove(rowIndex, cellIndex)"
@contextmenu.prevent
@select.prevent
draggable="false"
/>
</div>
</div>
</div>
</div>
</template>
</template>
<style scoped>
.grid {
display: grid;
border: 10px solid black;
}
.row {
display: flex;
height: 32px;
}
.cell {
flex: 1;
background-color: #f1f1f1;
text-align: center;
color: black;
width: 32px;
height: 32px;
user-select: none;
}
</style>

View File

@@ -2,7 +2,7 @@
<div class="main">
<h1>MultiMinesweeper</h1>
<p>
Bienvenue sur notre jeu !
Bienvenue sur notre jeu de démineur en ligne !
<br>
Pour jouer, il vous suffit de sélectionner le mode de jeu que vous souhaitez dans le menu ci-dessous.
</p>