Skip to content

Commit

Permalink
Switch to stroke count
Browse files Browse the repository at this point in the history
  • Loading branch information
s5bug committed Nov 15, 2024
1 parent c897ee3 commit 18edfa2
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 102 deletions.
144 changes: 56 additions & 88 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
RawGolfRoom,
hostMpRoom, joinMpRoom,
NameAndPass, numColors, numShapes,
PassLetter, BallStatePayload, HoleFinishedPayload, HoleLostPayload, GameOverPayload
PassLetter, BallStatePayload, HoleFinishedPayload, GameOverPayload
} from "./multiplayer.ts";

(window as any).sss = sss;
Expand Down Expand Up @@ -43,11 +43,10 @@ type InGameState = {
isHost: boolean,
ballColor: Color,
ourBall: Ball,
ourLives: number,
ourStrokes: number,
otherBalls: Record<string, BallStatePayload>,
spectating: boolean,
finishedBalls: Record<string, HoleFinishedPayload>,
lostBalls: Record<string, HoleLostPayload>
mapSeed: number,
platforms: Platform[],
ticksLeft: number,
Expand All @@ -60,8 +59,7 @@ type LeaderboardState = {
state: "leaderboard",
room: RawGolfRoom,
isHost: boolean,
winners: Record<string, number>,
losers: Record<string, number>,
strokeCount: Record<string, number>,
colors: Record<string, Color>,
hostId: string,
}
Expand Down Expand Up @@ -436,11 +434,10 @@ function nextHole(seed: number) {
isHost: state.isHost,
ballColor: state.colors[state.room.ownId],
ourBall: ball,
ourLives: 5,
ourStrokes: 0,
spectating: false,
otherBalls: {},
finishedBalls: {},
lostBalls: {},
mapSeed: seed,
platforms: createHole(seed, ball),
ticksLeft: 60 * 50,
Expand All @@ -454,12 +451,15 @@ function nextHole(seed: number) {
newState.room.recvBallState((bs, pid) => {
newState.otherBalls[pid] = bs
})
newState.room.recvHoleLost((hl, pid) => {
newState.lostBalls[pid] = hl
})
newState.room.recvHoleFinished((hl, pid) => {
if(Object.keys(newState.finishedBalls).length == 0) {
newState.room.sendFinishedFirst(null, pid)
}
newState.finishedBalls[pid] = hl
})
newState.room.recvFinishedFirst(() => {
newState.ourStrokes -= 3
})
newState.room.recvGameOver(go => {
initLeaderboard(state as InGameState, go)
})
Expand All @@ -474,20 +474,17 @@ function nextHole(seed: number) {
}
return;
case "inGame": {
const didFail = state.room.ownId in state.lostBalls

const newBall = initBall()
const newState: InGameState = {
state: "inGame",
room: state.room,
isHost: state.isHost,
ballColor: state.ballColor,
ourBall: newBall,
ourLives: didFail ? 0 : 5 + state.ourLives,
spectating: didFail,
ourStrokes: state.ourStrokes,
spectating: false,
otherBalls: {},
finishedBalls: {},
lostBalls: {},
mapSeed: seed,
platforms: createHole(seed, newBall),
ticksLeft: 60 * 50,
Expand All @@ -501,23 +498,22 @@ function nextHole(seed: number) {
newState.room.recvBallState((bs, pid) => {
newState.otherBalls[pid] = bs
})
newState.room.recvHoleLost((hl, pid) => {
newState.lostBalls[pid] = hl
})
newState.room.recvHoleFinished((hl, pid) => {
if(Object.keys(newState.finishedBalls).length == 0) {
newState.room.sendFinishedFirst(null, pid)
}
newState.finishedBalls[pid] = hl
})
newState.room.recvFinishedFirst(() => {
newState.ourStrokes -= 3
})
newState.room.recvCollision(coll => {
if(newState.ourBall.pos.y > 0) {
newState.ourBall.state = "fly"
newState.ourBall.vel.add((coll.initiatorVx + Math.random()) * 0.8, (coll.initiatorVy + Math.random()) * 0.8)
}
})

if(didFail) {
initGiveUp(newState)
}

state = newState;
}
return;
Expand Down Expand Up @@ -655,6 +651,13 @@ function transitionToLobbyAsNonHost(connectingState: ConnectingState) {
})

newState.room.recvStartHole(hole => {
switch (state.state) {
case "inGame":
if(!(state.room.ownId in state.finishedBalls))
state.ourStrokes += 7;
break;
default: break;
}
nextHole(hole)
})

Expand Down Expand Up @@ -694,18 +697,9 @@ function updateInGame(inGameState: InGameState) {
// - otherwise, go to leaderboard
if(inGameState.isHost) {
const shouldAdvance = Object.values(inGameState.otherBalls).every(p => p.spectating)
const shouldLeaderboard = (
Object.keys(inGameState.finishedBalls).length == 0 &&
(Object.keys(inGameState.finishedBalls).length + Object.keys(inGameState.lostBalls).length >=
inGameState.room.getPeerIds().length + 1)
)

if (shouldAdvance) {
if (shouldLeaderboard) {
hostToLeaderboard(inGameState)
} else {
hostAdvanceHole(inGameState)
}
hostAdvanceHole(inGameState)
}
}

Expand All @@ -728,7 +722,7 @@ function updateInGame(inGameState: InGameState) {
y: ball.pos.y,
vx: ball.vel.x,
vy: ball.vel.y,
lives: inGameState.ourLives,
strokes: inGameState.ourStrokes,
color: inGameState.ballColor,
spectating: inGameState.spectating,
})
Expand All @@ -737,15 +731,19 @@ function updateInGame(inGameState: InGameState) {

if(inGameState.ticksLeft > 0) {
inGameState.ticksLeft--;
} else if(inGameState.isHost) {
inGameState.ourStrokes += 7;
hostAdvanceHole(inGameState)
}

drawBallAndTime(inGameState);
}

function drawBallAndTime(igs: InGameState) {
color("black");
color(igs.ballColor);
char("a", 3, 4);
text(`x${igs.ourLives}`, 9, 3);
color("black")
text(`score: ${igs.ourStrokes}`, 9, 3);
drawTime(igs.ticksLeft, 110, 3);
}

Expand Down Expand Up @@ -803,7 +801,7 @@ function updatePowerState(igs: InGameState) {
play("laser");
ball.vel.set().addWithAngle(ball.angle, ball.power * 0.5 * ball.basePower);
ball.state = "fly";
igs.ourLives--;
igs.ourStrokes++;
}
}

Expand Down Expand Up @@ -848,15 +846,13 @@ function updateFlyState(igs: InGameState) {
if (cv.white) {
initGoToNextHole(igs);
return;
} else if (igs.ourLives <= 0) {
initGiveUp(igs);
return;
}
initBallShotState(igs);
ball.basePower = cv.yellow ? 0.5 : 1;
if (cv.blue) {
color("blue");
particle(ball.pos.x, ball.pos.y + 2, 9, 0.5, -PI / 2, PI / 2);
igs.ourStrokes++;
backToPrevBallPos(igs);
}
ball.prevPos.set(ball.pos);
Expand All @@ -882,10 +878,7 @@ function updateFlyState(igs: InGameState) {
ball.vel.mul(0.98);
ball.vel.y += 0.1;
if (ball.pos.y > 110) {
if (igs.ourLives <= 0) {
initGiveUp(igs);
return;
}
igs.ourStrokes++;
backToPrevBallPos(igs);
initBallShotState(igs);
}
Expand Down Expand Up @@ -962,11 +955,6 @@ function drawFlag(x: number, y: number) {
}

function initGoToNextHole(igs: InGameState) {
// TODO if host
// if (hostHoleSeedIdx === holeSeeds.length) {
// initHoleOut();
// return;
// }
sss.playMml(
sss.generateMml({
seed: 1,
Expand All @@ -983,26 +971,19 @@ function initGoToNextHole(igs: InGameState) {
totalTicksLived: igs.totalTicksLived,
}
igs.room.sendHoleFinished(payload)
if(igs.isHost && Object.keys(igs.finishedBalls).length == 0) {
igs.ourStrokes -= 3
}
igs.finishedBalls[igs.room.ownId] = payload
igs.ticksLivedThisHole = 0;
}

function initGiveUp(igs: InGameState) {
igs.spectating = true;
igs.totalTicksLived += igs.ticksLivedThisHole;
const payload = { totalTicksLived: igs.totalTicksLived }
igs.room.sendHoleLost(payload)
igs.lostBalls[igs.room.ownId] = payload
igs.ticksLivedThisHole = 0;
}

function initLeaderboard(igs: InGameState, go: GameOverPayload) {
const newState: LeaderboardState = {
state: "leaderboard",
room: igs.room,
isHost: igs.isHost,
winners: go.winners,
losers: go.losers,
strokeCount: go.strokeCount,
colors: igs.cachedColors,
hostId: igs.hostId
}
Expand Down Expand Up @@ -1043,18 +1024,21 @@ function returnToLobbyFromLeaderboard() {
}

function hostToLeaderboard(igs: InGameState) {
let winners: Record<string, number> = {}
for(let pid in igs.finishedBalls) {
winners[pid] = igs.finishedBalls[pid].totalTicksLived
}
let losers: Record<string, number> = {}
for(let pid in igs.lostBalls) {
losers[pid] = igs.lostBalls[pid].totalTicksLived
// add 7 to balls that didn't make it because they can't themselves
let strokeCounts: Record<string, number> = {}
for(let pid in igs.otherBalls) {
if(pid in igs.finishedBalls) {
strokeCounts[pid] = igs.otherBalls[pid].strokes
} else {
strokeCounts[pid] = igs.otherBalls[pid].strokes + 7
}
}
// and ourselves
if(igs.room.ownId in igs.finishedBalls) strokeCounts[igs.room.ownId] = igs.ourStrokes
else strokeCounts[igs.room.ownId] = igs.ourStrokes + 7

const go: GameOverPayload = {
winners: winners,
losers: losers
strokeCount: strokeCounts
}

igs.room.sendGameOver(go)
Expand All @@ -1064,29 +1048,13 @@ function hostToLeaderboard(igs: InGameState) {
function updateLeaderboard(ls: LeaderboardState) {
let placement: number = 1

let pidListLtg = Object.entries(ls.winners)
.sort(([_, at], [__, bt]) => at - bt)
let pidList = Object.entries(ls.strokeCount)
.sort(([_, at], [__, bt]) => bt - at)
.map(([pid, _]) => pid)
for(let pid of pidListLtg) {
for(let pid of pidList) {
text(`${placement}.`, 50, placement * 8)
char("a", 62, placement * 8, { color: ls.colors[pid] })

color("green")
drawTime(ls.winners[pid], 70, placement * 8)
color("black")

placement++
}
let pidLstGtl = Object.entries(ls.losers)
.sort(([_, at], [__, bt]) => at - bt)
.map(([pid, _]) => pid)
for(let pid of pidLstGtl) {
text(`${placement}.`, 50, placement * 8)
char("a", 62, placement * 8, { color: ls.colors[pid] })

color("red")
drawTime(ls.losers[pid], 70, placement * 8)
color("black")
text(`${ls.strokeCount[pid]} strokes`, 70, placement * 8)

placement++
}
Expand Down
22 changes: 8 additions & 14 deletions src/multiplayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,23 +104,17 @@ export type BallStatePayload = {
vx: number,
vy: number,
color: Color,
lives: number,
strokes: number,
spectating: boolean
}

export type HoleLostPayload = {
totalTicksLived: number
}

export type HoleFinishedPayload = {
holeTicksLived: number,
totalTicksLived: number
}

export type GameOverPayload = {
// map of Id to totalTicksLived
winners: Record<string, number>,
losers: Record<string, number>,
strokeCount: Record<string, number>
}

export type CollisionPayload = {
Expand Down Expand Up @@ -167,12 +161,12 @@ export interface RawGolfRoom {
// every player can send their own ball state
sendBallState: ActionSender<BallStatePayload>,
recvBallState: ActionReceiver<BallStatePayload>,
// if they run out of lives, they announce that they are entering spectator mode
sendHoleLost: ActionSender<HoleLostPayload>,
recvHoleLost: ActionReceiver<HoleLostPayload>,
// or if they complete the hole, they announce how many lives they completed it with and how many ticks it took
sendHoleFinished: ActionSender<HoleFinishedPayload>,
recvHoleFinished: ActionReceiver<HoleFinishedPayload>,
// the host tells the ball that finished first to win -3 strokes
sendFinishedFirst: ActionSender<null>,
recvFinishedFirst: ActionReceiver<null>,

// when at least one person has finished the hole, host runs a `sendStartHole`
// when all holes are done, or everyone has died, host broadcasts that it's game over
Expand Down Expand Up @@ -208,8 +202,8 @@ const createActions = (nameAndPass: NameAndPass, rawRoom: Room): RawGolfRoom =>
const [sendLobbyInfo, recvLobbyInfo] = rawRoom.makeAction<LobbyInfoPayload>("lobInfo")
const [sendStartHole, recvStartHole] = rawRoom.makeAction<number>("startHole")
const [sendBallState, recvBallState] = rawRoom.makeAction<BallStatePayload>("ballState")
const [sendHoleLost, recvHoleLost] = rawRoom.makeAction<HoleLostPayload>("holeLose")
const [sendHoleFinished, recvHoleFinished] = rawRoom.makeAction<HoleFinishedPayload>("holeFin")
const [sendFinishedFirst, recvFinishedFirst] = rawRoom.makeAction<null>("firstFin")
const [sendGameOver, recvGameOver] = rawRoom.makeAction<GameOverPayload>("gameOver")
const [sendCollision, recvCollision] = rawRoom.makeAction<CollisionPayload>("collision")

Expand All @@ -233,10 +227,10 @@ const createActions = (nameAndPass: NameAndPass, rawRoom: Room): RawGolfRoom =>
recvStartHole,
sendBallState,
recvBallState,
sendHoleLost,
recvHoleLost,
sendHoleFinished,
recvHoleFinished,
sendFinishedFirst,
recvFinishedFirst,
sendGameOver,
recvGameOver,
sendCollision,
Expand Down

0 comments on commit 18edfa2

Please sign in to comment.