Skip to content

Commit be1cd1b

Browse files
committed
Switch activation mask to fast interval on bridge destruction
After a bridge is hit, set ActivationMask to ActivationIntervalFast (15) so newly spawned objects activate within 16 frames instead of 32. The mask is reset to normal by ResetPerLife when the life ends.
1 parent e3466d5 commit be1cd1b

4 files changed

Lines changed: 48 additions & 1 deletion

File tree

pkg/domain/constants.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ const (
1616

1717
// Timing constants.
1818
const (
19-
ActivationIntervalNormal = 31
19+
ActivationIntervalNormal = 31 // 32-frame activation interval during normal gameplay
20+
ActivationIntervalFast = 15 // 16-frame activation interval after bridge destruction
2021
)
2122

2223
// Player constants.

pkg/logic/death_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,21 @@ func TestTriggerGameOver_TwoPlayer_UsesHigherScore(t *testing.T) {
313313
}
314314
}
315315

316+
// TestResetPerLife_ActivationMaskReset checks that the fast activation mask set after
317+
// bridge destruction is reset to normal on respawn (fast interval is per-life only).
318+
func TestResetPerLife_ActivationMaskReset(t *testing.T) {
319+
t.Parallel()
320+
321+
s := newDeathTestState()
322+
s.Viewport.ActivationMask = domain.ActivationIntervalFast
323+
ResetPerLife(s, noopTerrain)
324+
325+
if s.Viewport.ActivationMask != domain.ActivationIntervalNormal {
326+
t.Errorf("ActivationMask = %d after ResetPerLife, want %d (ActivationIntervalNormal)",
327+
s.Viewport.ActivationMask, domain.ActivationIntervalNormal)
328+
}
329+
}
330+
316331
func TestResetPerLife_ScorePreserved(t *testing.T) {
317332
t.Parallel()
318333

pkg/logic/gameplay.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ func step(s *state.GameState, in input.Interface, terrain TerrainRenderer) {
9797
}
9898
if collision.BridgeHit {
9999
s.BridgeDestroyed = true
100+
s.Viewport.ActivationMask = domain.ActivationIntervalFast
100101
s.Players[s.CurrentPlayer].BridgeCounter++
101102
// Re-render the bridge fragment into the terrain buffer with the destruction
102103
// gap so the visual change is immediate. The fragment was last rendered without

pkg/logic/gameplay_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,36 @@ func newScrollInTestState() *state.GameState {
1818
return s
1919
}
2020

21+
// TestStep_BridgeHit_SetsActivationFast verifies that hitting a bridge raises the
22+
// activation mask to ActivationIntervalFast for the remainder of the life.
23+
func TestStep_BridgeHit_SetsActivationFast(t *testing.T) {
24+
t.Parallel()
25+
26+
s := state.NewGameState()
27+
s.GameplayMode = domain.GameplayNormal
28+
s.InputInterface = input.InterfaceFor(0)
29+
s.PlaneX = domain.PlaneStartX
30+
s.Missile = &state.PlayerMissile{}
31+
s.TankShell = &state.TankShell{}
32+
s.HeliMissile = &state.HeliMissile{}
33+
s.Viewport = state.NewViewport()
34+
35+
// Position the missile to hit the bridge (bridgeY=60, extent=22: missile at Y=45 overlaps).
36+
const bridgeY = 60
37+
s.BridgeSection = true
38+
s.BridgeYPosition = bridgeY
39+
s.Missile.Active = true
40+
s.Missile.X = domain.PlaneStartX
41+
s.Missile.Y = 45
42+
43+
step(s, s.InputInterface, newMockTerrainBuffer())
44+
45+
if s.Viewport.ActivationMask != domain.ActivationIntervalFast {
46+
t.Errorf("ActivationMask = %d after bridge hit, want %d (ActivationIntervalFast)",
47+
s.Viewport.ActivationMask, domain.ActivationIntervalFast)
48+
}
49+
}
50+
2151
// TestScrollIn_DecrementsLivesOnCompletion checks that lives are decremented
2252
// when the scroll-in sequence finishes.
2353
func TestScrollIn_DecrementsLivesOnCompletion(t *testing.T) {

0 commit comments

Comments
 (0)