mirror of
https://github.com/imjasonh/nescript
synced 2026-07-11 10:10:49 +00:00
101 lines
3.3 KiB
Text
101 lines
3.3 KiB
Text
|
|
// pong/play_state.ne — the Playing state and its inner phase machine.
|
||
|
|
//
|
||
|
|
// The phase machine cycles through P_SERVE → P_PLAY → P_POINT:
|
||
|
|
//
|
||
|
|
// P_SERVE — brief countdown, then serve_ball() and switch to P_PLAY
|
||
|
|
// P_PLAY — normal gameplay: update paddles, balls, powerups, draw
|
||
|
|
// P_POINT — a side just scored; short pause then re-serve (or Victory)
|
||
|
|
|
||
|
|
// Inline helper to set the phase and zero the timer atomically.
|
||
|
|
inline fun set_phase(p: u8) {
|
||
|
|
phase = p
|
||
|
|
phase_timer = 0
|
||
|
|
}
|
||
|
|
|
||
|
|
state Playing {
|
||
|
|
on enter {
|
||
|
|
// Reset scores and paddle state on a fresh game.
|
||
|
|
score[0] = 0
|
||
|
|
score[1] = 0
|
||
|
|
paddle_y[0] = 96
|
||
|
|
paddle_y[1] = 96
|
||
|
|
paddle_long[0] = 0
|
||
|
|
paddle_long[1] = 0
|
||
|
|
paddle_fast[0] = 0
|
||
|
|
paddle_fast[1] = 0
|
||
|
|
paddle_multi[0] = 0
|
||
|
|
paddle_multi[1] = 0
|
||
|
|
serving_side = SIDE_RIGHT // first serve goes toward the right paddle
|
||
|
|
set_phase(P_SERVE)
|
||
|
|
}
|
||
|
|
|
||
|
|
on frame {
|
||
|
|
global_tick += 1
|
||
|
|
phase_timer += 1
|
||
|
|
|
||
|
|
// ── Phase dispatch ───────────────────────────────
|
||
|
|
// Using `match` so at most one arm executes per frame
|
||
|
|
// (prevents one phase from advancing into the next in
|
||
|
|
// the same frame — the same rationale as war's phase
|
||
|
|
// machine).
|
||
|
|
match phase {
|
||
|
|
P_SERVE => {
|
||
|
|
// Draw the static table while the serve countdown
|
||
|
|
// ticks. After FRAMES_SERVE frames, launch the ball
|
||
|
|
// and start play.
|
||
|
|
draw_center_line()
|
||
|
|
draw_scores()
|
||
|
|
draw_paddles()
|
||
|
|
|
||
|
|
if phase_timer >= FRAMES_SERVE {
|
||
|
|
serve_ball(serving_side)
|
||
|
|
set_phase(P_PLAY)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
P_PLAY => {
|
||
|
|
// Core gameplay loop.
|
||
|
|
step_paddles()
|
||
|
|
step_balls()
|
||
|
|
step_powerup()
|
||
|
|
|
||
|
|
draw_center_line()
|
||
|
|
draw_scores()
|
||
|
|
draw_paddles()
|
||
|
|
draw_balls()
|
||
|
|
draw_powerup()
|
||
|
|
}
|
||
|
|
P_POINT => {
|
||
|
|
// Short pause after a score before re-serving.
|
||
|
|
// Keep drawing the table and scores so the new
|
||
|
|
// score reads on-screen.
|
||
|
|
draw_center_line()
|
||
|
|
draw_scores()
|
||
|
|
draw_paddles()
|
||
|
|
|
||
|
|
if phase_timer >= FRAMES_POINT {
|
||
|
|
// Check for match win.
|
||
|
|
if score[SIDE_LEFT] >= WIN_SCORE {
|
||
|
|
winner = 0
|
||
|
|
transition Victory
|
||
|
|
}
|
||
|
|
if score[SIDE_RIGHT] >= WIN_SCORE {
|
||
|
|
winner = 1
|
||
|
|
transition Victory
|
||
|
|
}
|
||
|
|
// Not over yet — serve again. The serving_side
|
||
|
|
// was set in on_score() to the scoring side, so
|
||
|
|
// the ball is served TOWARD the side that lost
|
||
|
|
// the point.
|
||
|
|
if serving_side == SIDE_LEFT {
|
||
|
|
serving_side = SIDE_RIGHT
|
||
|
|
} else {
|
||
|
|
serving_side = SIDE_LEFT
|
||
|
|
}
|
||
|
|
set_phase(P_SERVE)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
_ => {}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|