@@ -295,22 +295,19 @@ I used this state machine library extensively in my [Pac-Man game implementation
295
295
This is the state machine controlling the behavior of the ghosts:
296
296
297
297
``` java
298
- beginStateMachine()
299
-
300
- .description(this :: toString)
298
+ ai. beginStateMachine()
299
+ .description(name + " AI" )
301
300
.initialState(LOCKED )
302
301
303
302
.states()
304
303
305
304
.state(LOCKED )
306
305
.onEntry(() - > {
307
- fnSubsequentState = () - > LOCKED ;
308
- setVisible(true );
309
- flashing = false ;
306
+ visible = true ;
307
+ recovering = false ;
310
308
bounty = 0 ;
311
- placeAt(Tile . at(bed. col(), bed. row()), Tile . SIZE / 2 , 0 );
312
- setMoveDir(bed. exitDir);
313
- setWishDir(bed. exitDir);
309
+ nextState = LOCKED ;
310
+ placeIntoBed();
314
311
})
315
312
.onTick(this :: move)
316
313
@@ -319,30 +316,34 @@ beginStateMachine()
319
316
.onExit(() - > forceMoving(Direction . LEFT ))
320
317
321
318
.state(ENTERING_HOUSE )
322
- .onEntry(() - > steering(). init()) // TODO should not be necessary
323
319
.onTick(this :: move)
324
320
325
321
.state(SCATTERING )
326
322
.onTick(() - > {
327
- maybeMeetPacMan(pacMan);
323
+ updateMentalHealth();
324
+ checkPacManCollision(pacMan);
328
325
move();
329
326
})
330
327
331
328
.state(CHASING )
332
329
.onTick(() - > {
333
- maybeMeetPacMan(pacMan);
330
+ updateMentalHealth();
331
+ checkPacManCollision(pacMan);
334
332
move();
335
333
})
336
334
337
335
.state(FRIGHTENED )
336
+ .timeoutAfter(this :: getFrightenedTicks)
338
337
.onTick((state, consumed, remaining) - > {
339
- maybeMeetPacMan(pacMan);
338
+ updateMentalHealth();
339
+ checkPacManCollision(pacMan);
340
340
move();
341
- // one flashing animation takes 0.5 sec
342
- flashing = remaining < fnNumFlashes. getAsInt() * 0.5f ;
341
+ recovering = remaining < getFlashTimeTicks();
343
342
})
344
343
345
344
.state(DEAD )
345
+ .timeoutAfter(sec(1 ))
346
+ .onEntry(this :: computeBounty)
346
347
.onTick((s, consumed, remaining) - > {
347
348
if (remaining == 0 ) {
348
349
bounty = 0 ;
@@ -352,57 +353,67 @@ beginStateMachine()
352
353
353
354
.transitions()
354
355
355
- .when(LOCKED ). then(LEAVING_HOUSE )
356
- .on(GhostUnlockedEvent . class)
356
+ .when(LOCKED ). then(LEAVING_HOUSE ). on(GhostUnlockedEvent . class)
357
357
358
358
.when(LEAVING_HOUSE ). then(SCATTERING )
359
- .condition(() - > hasLeftGhostHouse() && fnSubsequentState. get() == SCATTERING )
359
+ .condition(() - > justLeftHouse() && nextState == SCATTERING )
360
+ .annotation(" Outside house" )
360
361
361
362
.when(LEAVING_HOUSE ). then(CHASING )
362
- .condition(() - > hasLeftGhostHouse() && fnSubsequentState. get() == CHASING )
363
+ .condition(() - > justLeftHouse() && nextState == CHASING )
364
+ .annotation(" Outside house" )
365
+
366
+ .when(LEAVING_HOUSE ). then(FRIGHTENED )
367
+ .condition(() - > justLeftHouse() && nextState == FRIGHTENED )
368
+ .annotation(" Outside house" )
363
369
364
370
.when(ENTERING_HOUSE ). then(LEAVING_HOUSE )
365
- .condition(() - > steering(). isComplete())
371
+ .condition(() - > getSteering(). isComplete())
372
+ .annotation(" Reached bed" )
366
373
367
374
.when(CHASING ). then(FRIGHTENED )
368
375
.on(PacManGainsPowerEvent . class)
369
- .act(() - > reverseDirection() )
376
+ .act(this :: reverseDirection)
370
377
371
378
.when(CHASING ). then(DEAD )
372
379
.on(GhostKilledEvent . class)
373
380
374
381
.when(CHASING ). then(SCATTERING )
375
- .condition(() - > fnSubsequentState. get() == SCATTERING )
376
- .act(() - > reverseDirection())
382
+ .condition(() - > nextState == SCATTERING )
383
+ .act(this :: reverseDirection)
384
+ .annotation(" Got scattering command" )
377
385
378
386
.when(SCATTERING ). then(FRIGHTENED )
379
387
.on(PacManGainsPowerEvent . class)
380
- .act(() - > reverseDirection() )
388
+ .act(this :: reverseDirection)
381
389
382
390
.when(SCATTERING ). then(DEAD )
383
391
.on(GhostKilledEvent . class)
384
392
385
393
.when(SCATTERING ). then(CHASING )
386
- .condition(() - > fnSubsequentState. get() == CHASING )
387
- .act(() - > reverseDirection())
394
+ .condition(() - > nextState == CHASING )
395
+ .act(this :: reverseDirection)
396
+ .annotation(" Got chasing command" )
388
397
389
- .stay(FRIGHTENED )
390
- .on(PacManGainsPowerEvent . class)
391
- .act(() - > restartTimer(FRIGHTENED ))
398
+ .stay(FRIGHTENED ). on(PacManGainsPowerEvent . class)
399
+ .act(() - > ai. resetTimer(FRIGHTENED ))
392
400
393
401
.when(FRIGHTENED ). then(DEAD )
394
402
.on(GhostKilledEvent . class)
395
403
396
404
.when(FRIGHTENED ). then(SCATTERING )
397
405
.onTimeout()
398
- .condition(() - > fnSubsequentState . get() == SCATTERING )
406
+ .condition(() - > nextState == SCATTERING )
399
407
400
408
.when(FRIGHTENED ). then(CHASING )
401
409
.onTimeout()
402
- .condition(() - > fnSubsequentState . get() == CHASING )
410
+ .condition(() - > nextState == CHASING )
403
411
404
412
.when(DEAD ). then(ENTERING_HOUSE )
405
- .condition(() - > world. isHouseEntry(tileLocation()))
413
+ .condition(this :: isAtHouseEntry)
414
+ .annotation(" Reached house entry" )
406
415
407
- .endStateMachine();
416
+ .endStateMachine();
417
+ /* @formatter:on*/
418
+ ai. setMissingTransitionBehavior(MissingTransitionBehavior . LOG );
408
419
```
0 commit comments