added basic scoreboard for now
This commit is contained in:
268
'
Normal file
268
'
Normal file
@@ -0,0 +1,268 @@
|
||||
<script setup lang="ts">
|
||||
import { Ref, computed, onMounted, ref } from 'vue';
|
||||
|
||||
const grid = ref(genGrid(30, 30))
|
||||
const currentCoin = ref(spawnCoin())
|
||||
const direction: Ref<'left' | 'right' | 'top' | 'bottom' | undefined> = ref(undefined)
|
||||
const snake = ref(spawnSnake())
|
||||
const score = ref(0)
|
||||
const lastScore: Ref<undefined | number> = ref(undefined)
|
||||
const scores: Ref<Score[]> = ref([])
|
||||
const backendUrl = import.meta.env.BACKENDURL ? import.meta.env.BACKENDURL : 'http://localhost:5000'
|
||||
|
||||
interface Cell {
|
||||
x: number
|
||||
y: number
|
||||
color: 'white' | 'yellow' | 'green'
|
||||
}
|
||||
|
||||
interface Snake {
|
||||
cell: Cell
|
||||
history: Cell[]
|
||||
length: number
|
||||
}
|
||||
|
||||
interface Score {
|
||||
username: String
|
||||
score: number
|
||||
}
|
||||
|
||||
function genGrid(length: number, height: number) {
|
||||
const grid: Cell[][] = []
|
||||
for (let i = 0; i < length; i++) {
|
||||
const currentRow: Cell[] = []
|
||||
for (let j = 0; j < height; j++) {
|
||||
currentRow[j] = {
|
||||
x: i,
|
||||
y: j,
|
||||
color: 'white'
|
||||
}
|
||||
}
|
||||
grid[i] = currentRow
|
||||
}
|
||||
|
||||
return grid
|
||||
}
|
||||
|
||||
|
||||
function spawnCoin() {
|
||||
const cell = randomCell()
|
||||
cell.color = 'yellow'
|
||||
return cell
|
||||
}
|
||||
|
||||
function spawnSnake(): Snake {
|
||||
const row = random(grid.value)
|
||||
const cell = random(row)
|
||||
|
||||
cell.color = 'green'
|
||||
return {
|
||||
cell: cell,
|
||||
history: [cell],
|
||||
length: 3
|
||||
}
|
||||
}
|
||||
|
||||
function random<T>(array: Array<T>) {
|
||||
return array[Math.floor(Math.random() * array.length)]
|
||||
|
||||
}
|
||||
|
||||
function randomCell() {
|
||||
const randomRow = random(grid.value)
|
||||
const randomCell = random(randomRow)
|
||||
|
||||
return randomCell
|
||||
}
|
||||
|
||||
function moveSnake(x: number, y: number) {
|
||||
const current = snake.value.cell
|
||||
const newCell = getCell(current.x + x, current.y + y);
|
||||
|
||||
if (newCell === undefined || newCell.color === 'green') {
|
||||
death()
|
||||
return;
|
||||
}
|
||||
|
||||
newCell.color = 'green'
|
||||
snake.value.cell = newCell
|
||||
snake.value.history.push(newCell)
|
||||
|
||||
if (snake.value.history.length > length) {
|
||||
const currentLength = snake.value.history.length
|
||||
const allowedLength = snake.value.length
|
||||
|
||||
if (currentLength > allowedLength) {
|
||||
const toDelete = snake.value.history.shift()
|
||||
|
||||
if (toDelete !== undefined) {
|
||||
toDelete.color = 'white'
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getCell(x: number, y: number) {
|
||||
try {
|
||||
return grid.value[x][y]
|
||||
} catch {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
function death() {
|
||||
killSnake()
|
||||
killCoin()
|
||||
currentCoin.value = spawnCoin()
|
||||
snake.value = spawnSnake()
|
||||
direction.value = undefined;
|
||||
lastScore.value = score.value
|
||||
score.value = 0
|
||||
clearInterval(currentInterval)
|
||||
currentInterval = createInterval()
|
||||
}
|
||||
|
||||
function killSnake() {
|
||||
snake.value.history
|
||||
for (const cell of snake.value.history) {
|
||||
cell.color = 'white'
|
||||
}
|
||||
}
|
||||
|
||||
function killCoin() {
|
||||
const coinCell = grid.value[currentCoin.value.x][currentCoin.value.y]
|
||||
coinCell.color = 'white'
|
||||
}
|
||||
|
||||
const speed = computed(() => {
|
||||
return 500 / (score.value + 1)
|
||||
})
|
||||
|
||||
let currentInterval = createInterval()
|
||||
|
||||
function createInterval() {
|
||||
return setInterval(() => {
|
||||
|
||||
if (direction.value === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
switch (direction.value) {
|
||||
case 'left':
|
||||
moveSnake(-1, 0)
|
||||
break
|
||||
case 'right':
|
||||
moveSnake(1, 0)
|
||||
break
|
||||
case 'top':
|
||||
moveSnake(0, -1)
|
||||
break
|
||||
case 'bottom':
|
||||
moveSnake(0, 1)
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
if (currentCoin.value.x === snake.value.cell.x && currentCoin.value.y === snake.value.cell.y) {
|
||||
snake.value.length + 10
|
||||
currentCoin.value = spawnCoin()
|
||||
score.value++
|
||||
|
||||
if (currentInterval) {
|
||||
clearInterval(currentInterval)
|
||||
currentInterval = createInterval()
|
||||
}
|
||||
}
|
||||
}, speed.value);
|
||||
|
||||
}
|
||||
|
||||
function keydown(event: KeyboardEvent) {
|
||||
switch (event.key) {
|
||||
case 'ArrowRight': direction.value = direction.value !== 'left' ? 'right' : 'left'
|
||||
break
|
||||
case 'ArrowLeft': direction.value = direction.value !== 'right' ? 'left' : 'right'
|
||||
break
|
||||
case 'ArrowUp': direction.value = direction.value !== 'bottom' ? 'top' : 'bottom'
|
||||
break
|
||||
case 'ArrowDown': direction.value = direction.value !== 'top' ? 'bottom' : 'top'
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
async function loadDashboard() {
|
||||
const response = await fetch(`${backendUrl}/score`)
|
||||
const data = await response.json()
|
||||
scores.value = data
|
||||
console.log('scors', data)
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await loadDashboard()
|
||||
})
|
||||
|
||||
window.addEventListener('keydown', keydown)
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>Score {{ score }}</h1>
|
||||
<h2 v-if="lastScore">Last Score {{ lastScore }}</h2>
|
||||
|
||||
<main>
|
||||
<div class="grid" @keyup="keydown($event)">
|
||||
<div class="row" v-for="row in grid">
|
||||
<div class="cell" :class="`cell-${cell.y}-${cell.x}`" v-for="cell in row"
|
||||
:style="{ backgroundColor: cell.color }">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="scoreboard">
|
||||
<li v-for="score in scores">
|
||||
{{ score.username }} : {{ score.score }}
|
||||
</li>
|
||||
</ul>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.grid {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
-webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.75);
|
||||
-moz-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.75);
|
||||
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.75);
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.cell {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
main {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.scoreboard {
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
-webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.75);
|
||||
-moz-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.75);
|
||||
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.75);
|
||||
|
||||
}
|
||||
</style>
|
||||
76
src/App.vue
76
src/App.vue
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { Ref, computed, ref } from 'vue';
|
||||
import { Ref, computed, onMounted, ref } from 'vue';
|
||||
|
||||
const grid = ref(genGrid(30, 30))
|
||||
const currentCoin = ref(spawnCoin())
|
||||
@@ -7,6 +7,8 @@ const direction: Ref<'left' | 'right' | 'top' | 'bottom' | undefined> = ref(unde
|
||||
const snake = ref(spawnSnake())
|
||||
const score = ref(0)
|
||||
const lastScore: Ref<undefined | number> = ref(undefined)
|
||||
const scores: Ref<Score[]> = ref([])
|
||||
const backendUrl = import.meta.env.BACKENDURL ? import.meta.env.BACKENDURL : 'http://localhost:5000'
|
||||
|
||||
interface Cell {
|
||||
x: number
|
||||
@@ -20,6 +22,11 @@ interface Snake {
|
||||
length: number
|
||||
}
|
||||
|
||||
interface Score {
|
||||
username: String
|
||||
score: number
|
||||
}
|
||||
|
||||
function genGrid(length: number, height: number) {
|
||||
const grid: Cell[][] = []
|
||||
for (let i = 0; i < length; i++) {
|
||||
@@ -34,9 +41,6 @@ function genGrid(length: number, height: number) {
|
||||
grid[i] = currentRow
|
||||
}
|
||||
|
||||
|
||||
console.log(grid)
|
||||
|
||||
return grid
|
||||
}
|
||||
|
||||
@@ -188,20 +192,39 @@ function keydown(event: KeyboardEvent) {
|
||||
}
|
||||
}
|
||||
|
||||
async function loadDashboard() {
|
||||
const response = await fetch(`${backendUrl}/score`)
|
||||
const data = await response.json()
|
||||
scores.value = data
|
||||
console.log('scors', data)
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await loadDashboard()
|
||||
})
|
||||
|
||||
window.addEventListener('keydown', keydown)
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>Score {{ score }}</h1>
|
||||
<h2 v-if="lastScore">Last Score {{ lastScore}}</h2>
|
||||
<div class="grid" @keyup="keydown($event)">
|
||||
<div class="row" v-for="row in grid">
|
||||
<div class="cell" :class="`cell-${cell.y}-${cell.x}`" v-for="cell in row"
|
||||
:style="{ backgroundColor: cell.color }">
|
||||
<h2 v-if="lastScore">Last Score {{ lastScore }}</h2>
|
||||
|
||||
<main>
|
||||
<div class="grid" @keyup="keydown($event)">
|
||||
<div class="row" v-for="row in grid">
|
||||
<div class="cell" :class="`cell-${cell.y}-${cell.x}`" v-for="cell in row"
|
||||
:style="{ backgroundColor: cell.color }">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="scoreboard">
|
||||
<li v-for="score in scores">
|
||||
{{ score.username }} : {{ score.score }}
|
||||
</li>
|
||||
</ul>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@@ -209,8 +232,12 @@ window.addEventListener('keydown', keydown)
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 1px solid white;
|
||||
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
-webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.75);
|
||||
-moz-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.75);
|
||||
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.75);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.row {
|
||||
@@ -225,4 +252,29 @@ window.addEventListener('keydown', keydown)
|
||||
width: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
</style>
|
||||
=======
|
||||
|
||||
main {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.scoreboard {
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
-webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.75);
|
||||
-moz-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.75);
|
||||
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.75);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.scoreboard li {
|
||||
all: unset;
|
||||
|
||||
}
|
||||
</style>
|
||||
>>>>>>> bf4a773 (added basic scoreboard for now)
|
||||
|
||||
Reference in New Issue
Block a user