From 975eba9b919f80128e44e15773d0f5e7dc6c84c4 Mon Sep 17 00:00:00 2001 From: Senhung Wong Date: Tue, 5 Jan 2021 19:02:44 +0800 Subject: [PATCH] Use FSM on Cheese --- source/enemies/Cheese.hx | 232 +++++++++++++++++++-------------------- 1 file changed, 110 insertions(+), 122 deletions(-) diff --git a/source/enemies/Cheese.hx b/source/enemies/Cheese.hx index 93c2891..42fc0b4 100644 --- a/source/enemies/Cheese.hx +++ b/source/enemies/Cheese.hx @@ -3,29 +3,23 @@ package enemies; import flixel.FlxG; import flixel.FlxObject; import flixel.FlxSprite; +import flixel.addons.util.FlxFSM; import flixel.math.FlxMath; import flixel.math.FlxPoint; import flixel.math.FlxVector; import flixel.system.FlxSound; -import flixel.util.FlxTimer; import modules.Entity; -import modules.brains.statemachine.State; -import modules.brains.statemachine.StateMachine; class Cheese extends Enemy { - var target:Entity; - var brain = new StateMachine(); - var margin = 240.0; - var flyTo:FlxPoint = new FlxPoint(); - var getBullet:() -> FlxSprite; - var attackPattern = Math.random(); - var aimCooldown = 0.3; - var _aimCooldown = 0.0; - var fireCooldown = 0.8; - var _fireCooldown = 0.0; - var charged = false; - var shootSound:FlxSound; + public var tick = 0.5; + public var target:Entity; + public var getBullet:() -> FlxSprite; + public var flyTo:FlxPoint = new FlxPoint(); + public var shootSound:FlxSound; + public var attackPattern = Math.random(); + + var fsm:FlxFSM; public function new(target:Entity, getBullet:() -> FlxSprite) { @@ -35,13 +29,17 @@ class Cheese extends Enemy this.getBullet = getBullet; grav.grav = 0.0; - brain.states.push(MakeChangeLocationState()); - brain.states.push(MakeChargeState()); - brain.states.push(MakeFireState()); - brain.states.push(MakeAimState()); - shootSound = FlxG.sound.load(#if html5 AssetPaths.cheese_shoot__mp3 #else AssetPaths.cheese_shoot__wav #end); shootSound.volume = Reg.sfxVolume; + + fsm = new FlxFSM(this); + fsm.transitions.add(Idle, Charge, c -> c.tick <= 0) + .add(Charge, FireAround, c -> c.tick <= 0 && attackPattern > 0.5) + .add(Charge, FireAim, c -> c.tick <= 0 && attackPattern <= 0.5) + .add(FireAround, ChangeLocation, c -> c.tick <= 0) + .add(FireAim, ChangeLocation, c -> c.tick <= 0) + .add(ChangeLocation, Idle, c -> new FlxVector(c.x, c.y).distanceTo(c.flyTo) < 30) + .start(Idle); } override function render() @@ -53,29 +51,72 @@ class Cheese extends Enemy animation.add("idle", [0, 1, 2], 6, true); animation.add("charge", [3, 4, 5], 3, false); animation.add("attack", [6, 7], 6, true); - animation.finishCallback = (name:String) -> - { - if (name == "charge") - charged = true; - } } override function update(elapsed:Float) { - brain.update(elapsed); + tick -= elapsed; + fsm.update(elapsed); super.update(elapsed); } - function fireCircular(amount:Int) + override function destroy() + { + fsm.destroy(); + fsm = null; + super.destroy(); + } +} + +class Idle extends FlxFSMState +{ + override function enter(owner:Cheese, fsm:FlxFSM) + { + owner.tick = 0.5; + owner.animation.play("idle"); + } +} + +class Charge extends FlxFSMState +{ + override function enter(owner:Cheese, fsm:FlxFSM) + { + owner.tick = 0.5; + owner.attackPattern = Math.random(); + owner.animation.play("charge"); + } +} + +class FireAround extends FlxFSMState +{ + var cd = 0.8; + var _cd = 0.0; + + override function enter(owner:Cheese, fsm:FlxFSM) { - var center = getMidpoint(); - var targetCenter = target.getMidpoint(); + owner.tick = 3; + owner.animation.play("attack"); + } + + override function update(elapsed:Float, owner:Cheese, fsm:FlxFSM) + { + _cd -= elapsed; + if (_cd > 0) + return; + fire(owner, 10); + _cd = cd; + } + + function fire(owner:Cheese, amount:Int) + { + var center = owner.getMidpoint(); + var targetCenter = owner.target.getMidpoint(); var v = new FlxVector(targetCenter.x - center.x, targetCenter.y - center.y).normalize(); var speed = 100.0; var deg = 360.0 / amount; for (_ in 0...amount) { - var bullet = getBullet(); + var bullet = owner.getBullet(); if (bullet == null) return; bullet.reset(center.x - bullet.width / 2, center.y - bullet.height / 2); @@ -85,116 +126,63 @@ class Cheese extends Enemy bullet.angle = v.angleBetween(new FlxVector()) + 90; v.rotateByDegrees(deg); } - shootSound.play(true); + owner.shootSound.play(true); } +} - function fireDirectly() +class FireAim extends FlxFSMState +{ + var cd = 0.3; + var _cd = 0.0; + + override function enter(owner:Cheese, fsm:FlxFSM) { - var bullet = getBullet(); - if (bullet == null) + owner.tick = 3; + owner.animation.play("attack"); + } + + override function update(elapsed:Float, owner:Cheese, fsm:FlxFSM) + { + _cd -= elapsed; + if (_cd > 0) return; + fire(owner); + _cd = cd; + } - var center = getMidpoint(); - var targetCenter = target.getMidpoint(); + function fire(owner:Cheese) + { + var bullet = owner.getBullet(); + if (bullet == null) + return; + var center = owner.getMidpoint(); + var targetCenter = owner.target.getMidpoint(); var v = new FlxVector(targetCenter.x - center.x, targetCenter.y + 75 - center.y).normalize(); var speed = 400.0; - bullet.reset(center.x - bullet.width / 2, center.y - bullet.height / 2); bullet.velocity.x = speed * v.x; bullet.velocity.y = speed * v.y; bullet.animation.play("fire", true); bullet.angle = v.angleBetween(new FlxVector()) + 90; - shootSound.play(true); - } - - function MakeChangeLocationState() - { - var state = new State(); - var timer = new FlxTimer(); - timer.start(3.0); - state.shouldEnable = () -> timer.finished; - state.enable = () -> - { - animation.play("idle"); - flyTo.x = x > FlxG.width / 2 ? margin : FlxG.width - margin - width; - flyTo.y = Math.random() * 480.0 + 64.0; - }; - state.handle = elapsed -> - { - x = FlxMath.lerp(x, flyTo.x, elapsed * 0.7); - y = FlxMath.lerp(y, flyTo.y, elapsed * 0.7); - facing = x < FlxG.width / 2 ? FlxObject.RIGHT : FlxObject.LEFT; - }; - state.shouldDisable = () -> new FlxVector(x, y).distanceTo(flyTo) < 30; - state.disable = () -> - { - attackPattern = Math.random(); - timer.start(3.0); - } - return state; + owner.shootSound.play(true); } +} - function MakeChargeState() - { - var state = new State(); - var timer = new FlxTimer(); - timer.start(0); - state.shouldEnable = () -> timer.finished && !charged; - state.enable = () -> - { - animation.play("charge"); - timer.start(1); - } - return state; - } +class ChangeLocation extends FlxFSMState +{ + var margin = 240.0; - function MakeFireState() + override function enter(owner:Cheese, fsm:FlxFSM) { - var state = new State(); - var timer = new FlxTimer(); - timer.start(0); - state.shouldEnable = () -> charged && attackPattern >= 0.5; - state.enable = () -> - { - animation.play("attack"); - timer.start(3); - } - state.handle = elapsed -> - { - _fireCooldown -= elapsed; - if (_fireCooldown > 0) - return; - fireCircular(10); - _fireCooldown = fireCooldown; - } - state.shouldDisable = () -> timer.finished; - state.disable = () -> charged = false; - - return state; + owner.animation.play("idle"); + owner.flyTo.x = owner.x > FlxG.width / 2 ? margin : FlxG.width - margin - owner.width; + owner.flyTo.y = Math.random() * 480.0 + 64.0; } - function MakeAimState() + override function update(elapsed:Float, owner:Cheese, fsm:FlxFSM) { - var state = new State(); - var timer = new FlxTimer(); - timer.start(0); - state.shouldEnable = () -> charged && attackPattern < 0.5; - state.enable = () -> - { - animation.play("attack"); - timer.start(3); - } - state.handle = elapsed -> - { - _aimCooldown -= elapsed; - if (_aimCooldown > 0) - return; - fireDirectly(); - _aimCooldown = aimCooldown; - } - state.shouldDisable = () -> timer.finished; - state.disable = () -> charged = false; - - return state; + owner.x = FlxMath.lerp(owner.x, owner.flyTo.x, elapsed * 0.7); + owner.y = FlxMath.lerp(owner.y, owner.flyTo.y, elapsed * 0.7); + owner.facing = owner.x < FlxG.width / 2 ? FlxObject.RIGHT : FlxObject.LEFT; } }