@@ -17,7 +17,6 @@ import {
1717 puddleSlowAt ,
1818 woundScaleOf ,
1919} from './boss'
20- import { leanCamera , screenCameraOf } from './camera'
2120import { advanceChuckers , maybeChuckerHeading , maybeShieldFor } from './chucker'
2221import {
2322 hitEvent ,
@@ -33,12 +32,10 @@ import {
3332 DRY_FIRE_DELAY_MS ,
3433 FIXED_STEP_MS ,
3534 KNOCKBACK_REST_SPEED ,
36- MAX_FRAME_DELTA_MS ,
3735 MS_PER_SECOND ,
3836 PLAYER_KNOCKBACK_DECAY_PER_SECOND ,
3937 PLAYER_RADIUS ,
4038 SEPARATION_SPEED ,
41- STEP_EPSILON_MS ,
4239 ZOMBIE_BUMP_SPEED ,
4340 ZOMBIE_KNOCKBACK_DECAY_PER_SECOND ,
4441} from './constants'
@@ -56,8 +53,7 @@ import {
5653 scaleVector ,
5754 vectorLength ,
5855} from './geometry'
59- import { deriveIntent } from './input'
60- import { advanceJuice , stopForHits , thawTick } from './juice'
56+ import { stopForHits , thawTick } from './juice'
6157import { advanceKitchen , soupSkid } from './kitchen'
6258import {
6359 Arsenal ,
@@ -80,7 +76,6 @@ import {
8076 idleIntent ,
8177} from './model'
8278import { advanceIntensity } from './pacing'
83- import { advanceParticles } from './particles'
8479import {
8580 type Clearance ,
8681 maybeNearestBait ,
@@ -90,7 +85,6 @@ import {
9085 steerToward ,
9186} from './pathing'
9287import {
93- advanceCallouts ,
9488 advancePowerUps ,
9589 bulletGlaze ,
9690 bulletPierce ,
@@ -111,7 +105,7 @@ import {
111105 tollsOf ,
112106 trapBlockers ,
113107} from './traps'
114- import { advanceRound , endWhenDefeated , isRoundActive } from './waves'
108+ import { advanceRound , endWhenDefeated } from './waves'
115109import {
116110 SIDEARM ,
117111 type WeaponStats ,
@@ -137,13 +131,12 @@ import {
137131
138132// INTENT
139133
140- export const refreshIntent = ( model : Model ) : Model =>
141- modifyFields ( model , {
142- intent : ( ) =>
143- ShopState . isAnyOf ( [ 'Browsing' , 'AtExit' ] ) ( model . shop )
144- ? idleIntent
145- : deriveIntent ( model . input , model . player , screenCameraOf ( model ) ) ,
146- } )
134+ // NOTE: the player's intent is the step's input. A player at the stall's
135+ // counter or the exit's sign does nothing else, whatever they hold.
136+ const gateIntent = ( model : Model ) : Model =>
137+ ShopState . isAnyOf ( [ 'Browsing' , 'AtExit' ] ) ( model . shop )
138+ ? modifyFields ( model , { intent : ( ) => idleIntent } )
139+ : model
147140
148141// TIMERS
149142
@@ -1261,16 +1254,13 @@ const feelIntensity = (before: Model, after: Model, deltaMs: number): Model =>
12611254
12621255// FRAME
12631256
1264- export const clampFrameDelta = ( deltaTime : number ) : number =>
1265- clamp ( deltaTime , 0 , MAX_FRAME_DELTA_MS )
1266-
12671257const advanceWorld = ( model : Model , deltaMs : number ) : Model => {
12681258 const seconds = deltaMs / MS_PER_SECOND
12691259
12701260 const level = levelOf ( model )
12711261 const blockers = trapBlockers ( level , model . traps )
12721262 const tolls = tollsOf ( level , model . traps )
1273- const moved = refreshIntent (
1263+ const moved = gateIntent (
12741264 modifyFields ( model , {
12751265 player : player =>
12761266 movePlayer (
@@ -1288,7 +1278,7 @@ const advanceWorld = (model: Model, deltaMs: number): Model => {
12881278 frameEvents : ( ) => [ ] ,
12891279 } ) ,
12901280 )
1291- const routed = refreshIntent (
1281+ const routed = gateIntent (
12921282 refreshShopPresence (
12931283 modifyFields ( moved , {
12941284 flowField : flowField =>
@@ -1326,94 +1316,17 @@ const advanceWorld = (model: Model, deltaMs: number): Model => {
13261316 )
13271317}
13281318
1329- // NOTE: one 60 Hz tick: hit-stop decides whether the world steps, then
1330- // the camera lean follows and the tick's events decide the next hit-stop.
1331- type Tick = Readonly < { model : Model ; worldMs : number } >
1319+ // NOTE: one 60 Hz tick of the world from the player's intent: hit-stop
1320+ // decides whether the world steps, then the tick's events decide the next
1321+ // hit-stop.
1322+ export type Tick = Readonly < { model : Model ; worldMs : number } >
13321323
1333- const advanceTick = ( model : Model ) : Tick => {
1324+ export const advanceTick = ( model : Model ) : Tick => {
13341325 const thaw = thawTick ( model . hitStop , FIXED_STEP_MS )
13351326 const thawed = modifyFields ( model , {
13361327 hitStop : ( ) => thaw . hitStop ,
13371328 frameEvents : ( ) => [ ] ,
13381329 } )
13391330 const stepped = thaw . worldMs > 0 ? advanceWorld ( thawed , thaw . worldMs ) : thawed
1340- const leaned = modifyFields ( stepped , {
1341- cameraLean : lean =>
1342- leanCamera ( lean , stepped . intent . maybeAim , FIXED_STEP_MS ) ,
1343- } )
1344- return { model : stopForHits ( leaned , thaw . worldMs ) , worldMs : thaw . worldMs }
1345- }
1346-
1347- type Ticks = Readonly < { count : number ; carryMs : number } >
1348-
1349- // NOTE: a 60 Hz frame on an empty carry is exactly one tick and leaves
1350- // exactly zero, so a 60 Hz display steps as it did before the fixed step.
1351- export const ticksIn = ( carryMs : number , count = 0 ) : Ticks =>
1352- carryMs >= FIXED_STEP_MS - STEP_EPSILON_MS
1353- ? ticksIn ( carryMs - FIXED_STEP_MS , count + 1 )
1354- : { count, carryMs : Math . max ( 0 , carryMs ) }
1355-
1356- type Stepped = Readonly < {
1357- model : Model
1358- events : ReadonlyArray < GameEvent >
1359- worldMs : number
1360- } >
1361-
1362- // NOTE: a tick that ends the round ends the frame's ticks.
1363- const runTicks = ( stepped : Stepped , count : number ) : Stepped => {
1364- if ( count <= 0 || ! isRoundActive ( stepped . model . phase ) ) {
1365- return stepped
1366- }
1367- const ticked = advanceTick ( stepped . model )
1368- return runTicks (
1369- {
1370- model : ticked . model ,
1371- events : [ ...stepped . events , ...ticked . model . frameEvents ] ,
1372- worldMs : stepped . worldMs + ticked . worldMs ,
1373- } ,
1374- count - 1 ,
1375- )
1376- }
1377-
1378- // NOTE: what the frame looks like once its ticks ran: particles, the
1379- // walking dust, callouts, and the juice, all from the frame's events and
1380- // the cosmetic stream, so they never touch the World.
1381- const advanceCosmetics = (
1382- model : Model ,
1383- frameMs : number ,
1384- worldMs : number ,
1385- ) : Model =>
1386- advanceJuice (
1387- advanceCallouts (
1388- worldMs > 0
1389- ? advanceParticles ( model , worldMs / MS_PER_SECOND , worldMs )
1390- : model ,
1391- worldMs ,
1392- ) ,
1393- frameMs ,
1394- worldMs ,
1395- )
1396-
1397- // NOTE: a frame runs the whole ticks its time owes and carries the rest,
1398- // then makes its cosmetics. Its `frameEvents` are every tick's events in
1399- // order, so the cosmetics, sounds, stats, and lessons see each one.
1400- export const advanceGame = ( model : Model , deltaTime : number ) : Model => {
1401- const frameMs = clampFrameDelta ( deltaTime )
1402- const ticks = ticksIn ( model . stepCarryMs + frameMs )
1403- const stepped = runTicks (
1404- {
1405- model : modifyFields ( model , {
1406- stepCarryMs : ( ) => ticks . carryMs ,
1407- frameEvents : ( ) => [ ] ,
1408- } ) ,
1409- events : [ ] ,
1410- worldMs : 0 ,
1411- } ,
1412- ticks . count ,
1413- )
1414- return advanceCosmetics (
1415- modifyFields ( stepped . model , { frameEvents : ( ) => stepped . events } ) ,
1416- frameMs ,
1417- stepped . worldMs ,
1418- )
1331+ return { model : stopForHits ( stepped , thaw . worldMs ) , worldMs : thaw . worldMs }
14191332}
0 commit comments