Skip to content

Commit

Permalink
Implement Replay view with a side track
Browse files Browse the repository at this point in the history
Refactor PlayingField into a proper component and move the engine to a view.
Adjust to API changes
Obtain current git hash for later analysis of replay data

ref #33
  • Loading branch information
frostburn committed Oct 11, 2023
1 parent 7b515cf commit 110710d
Show file tree
Hide file tree
Showing 14 changed files with 1,070 additions and 474 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 7 additions & 40 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
<script setup lang="ts">
import PlayingField from './components/PlayingField.vue'
import { onMounted, onUnmounted } from 'vue'
import { useWebSocketStore } from '@/stores/websocket'
import { useAudioContextStore } from './stores/audio-context'
Expand All @@ -12,7 +10,6 @@ const audioContext = useAudioContextStore()
function hello() {
console.log(`Websocket opened to ${WS_URL}`)
websocket.requestGame()
}
function initializeAudio() {
Expand Down Expand Up @@ -47,27 +44,20 @@ onUnmounted(() => {
</script>

<template>
<div class="field-container">
<PlayingField />
</div>
<nav>
<RouterLink to="/">Home</RouterLink>
<RouterLink to="/about">About</RouterLink>
<RouterLink to="/play-online">Play Online</RouterLink>
<RouterLink to="/replay">Replay</RouterLink>
</nav>
<RouterView />
</template>

<style scoped>
header {
line-height: 1.5;
max-height: 100vh;
}
.field-container {
height: 800px;
width: 1200px;
}
nav {
width: 100%;
font-size: 12px;
text-align: center;
margin-top: 2rem;
}
nav a.router-link-exact-active {
Expand All @@ -87,27 +77,4 @@ nav a {
nav a:first-of-type {
border: 0;
}
@media (min-width: 1024px) {
header {
display: flex;
place-items: center;
padding-right: calc(var(--section-gap) / 2);
}
header .wrapper {
display: flex;
place-items: flex-start;
flex-wrap: wrap;
}
nav {
text-align: left;
margin-left: -1rem;
font-size: 1rem;
padding: 1rem 0;
margin-top: 1rem;
}
}
</style>
24 changes: 11 additions & 13 deletions src/assets/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@
padding: 2rem;

font-weight: normal;

display: flex;
flex-direction: column;
}

#app nav {
flex: 0 0 auto;
}

#app main {
flex: 1 1 auto;
}

a,
Expand All @@ -20,16 +31,3 @@ a,
background-color: hsla(160, 100%, 37%, 0.2);
}
}

@media (min-width: 1024px) {
body {
display: flex;
place-items: center;
}

#app {
display: grid;
grid-template-columns: 1fr 1fr;
padding: 0 2rem;
}
}
78 changes: 78 additions & 0 deletions src/chain-deck.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import {
WIDTH,
type GameState,
type MultiplayerGame,
type TickResult,
GHOST_Y
} from 'pujo-puyo-core'

export type Chain = {
number: number
age: number
x: number
y: number
}

const MAX_CHAIN_CARD_AGE = 100

export class ChainDeck {
chains: Chain[][]
ignitionCenters: number[][]

constructor() {
this.chains = [[], []]
this.ignitionCenters = [
[0, 0],
[0, 0]
]
}

clone(): ChainDeck {
const result = new ChainDeck()
result.chains = this.chains.map((cs) => cs.map((c) => ({ ...c })))
result.ignitionCenters = this.ignitionCenters.map((i) => [...i])
return result
}

processTick(game: MultiplayerGame, tickResults: TickResult[]) {
for (let i = 0; i < this.chains.length; ++i) {
for (const chain of this.chains[i]) {
chain.age++
}
while (this.chains[i][0]?.age > MAX_CHAIN_CARD_AGE) {
this.chains[i].shift()
}
}

let states: GameState[] | undefined
for (let i = 0; i < tickResults.length; ++i) {
if (tickResults[i].didJiggle) {
if (states === undefined) {
states = game.state
}
let numIgnitions = 0
let x = 0
let y = 0
states[i].screen.ignited.slice(WIDTH * (GHOST_Y + 1)).forEach((flag, index) => {
if (flag) {
x += index % WIDTH
y += Math.floor(index / WIDTH)
numIgnitions++
}
})
if (numIgnitions) {
this.ignitionCenters[i][0] = x / numIgnitions
this.ignitionCenters[i][1] = y / numIgnitions
}
}
if (tickResults[i].didClear) {
this.chains[i].push({
number: tickResults[i].chainNumber,
age: 0,
x: this.ignitionCenters[i][0],
y: this.ignitionCenters[i][1]
})
}
}
}
}
Loading

0 comments on commit 110710d

Please sign in to comment.