11package ;
22
33import flixel .FlxG ;
4+ import flixel .effects .particles .FlxEmitter ;
45import flixel .graphics .frames .FlxAtlasFrames ;
6+ import flixel .tweens .FlxEase ;
7+ import flixel .tweens .FlxTween ;
58import haxe .ds .StringMap ;
69
710class Enemy extends GameObject
811{
9- // shared frames and variant list (initialized once)
12+ public var variant : String ;
1013 public static var SHARED_FRAMES : FlxAtlasFrames = null ;
1114 public static var VARIANTS : Array <String > = [];
12- // map from variant id -> array of frame names (as present in the atlas)
1315 public static var VARIANT_FRAMES : StringMap <Array <String >> = null ;
1416
1517 private static function ensureFrames (): Void
@@ -19,12 +21,9 @@ class Enemy extends GameObject
1921 SHARED_FRAMES = FlxAtlasFrames .fromSparrow (" assets/images/enemies.png" , " assets/images/enemies.xml" );
2022 VARIANTS = [];
2123 VARIANT_FRAMES = new StringMap <Array <String >>();
22-
23- // Iterate atlas frames and collect prefixes where frame names end with a single letter suffix (a,b,c...)
2424 for (f in 0 ... SHARED_FRAMES .numFrames )
2525 {
2626 var rawName : String = SHARED_FRAMES .getByIndex (f ).name ;
27- // strip extension if present
2827 var base = rawName ;
2928 var dot = base .lastIndexOf (' .' );
3029 if (dot >= 0 )
@@ -42,12 +41,163 @@ class Enemy extends GameObject
4241 VARIANT_FRAMES .set (prefix , list );
4342 VARIANTS .push (prefix );
4443 }
45- // store the atlas frame name (use rawName as that's what the atlas uses)
4644 list .push (rawName );
4745 }
4846 }
4947 }
5048
49+ private function spawnCrumbleParticles (count : Int ): Void
50+ {
51+ try
52+ {
53+ var emitter = new FlxEmitter ();
54+ // emit along the bottom of the sprite so particles "rain" down
55+ emitter .setPosition (x + 2 , y + height - 2 );
56+ emitter .setSize (Math .max (2 , width - 4 ), 2 );
57+ emitter .makeParticles (2 , 2 , 0xFF888888 , count );
58+ // slightly longer lifespan for falling dust
59+ emitter .lifespan .max = 0.5 ;
60+ emitter .lifespan .min = 0.2 ;
61+ // small horizontal spread, positive Y speeds so particles fall downwards
62+ emitter .speed .start .min = - 10 ;
63+ emitter .speed .start .max = 10 ;
64+ emitter .speed .end .min = 20 ;
65+ emitter .speed .end .max = 60 ;
66+ // gentle downward acceleration (gravity-like)
67+ emitter .acceleration .start .min .y = 40 ;
68+ emitter .acceleration .end .min .y = 120 ;
69+ emitter .alpha .start .min = 1.0 ;
70+ emitter .alpha .end .max = 0.0 ;
71+ emitter .start (true );
72+ try
73+ {
74+ FlxG .state .add (emitter );
75+ }
76+ catch (e : Dynamic ) {}
77+ }
78+ catch (e : Dynamic ) {}
79+ }
80+
81+ public function capture (byPlayer : Player ): Void
82+ {
83+ if (! exists )
84+ return ;
85+ velocity .set (0 , 0 );
86+ acceleration .set (0 , 0 );
87+ try
88+ {
89+ trace (" Enemy.capture() start - variant=" + (variant == null ? " null" : variant ));
90+ }
91+ catch (e : Dynamic ) {}
92+ try
93+ {
94+ if (animation != null )
95+ {
96+ animation .stop ();
97+ }
98+ }
99+ catch (e : Dynamic ) {}
100+
101+ try
102+ {
103+ try
104+ {
105+ trace (" Enemy.capture() creating shader" );
106+ }
107+ catch (e : Dynamic ) {}
108+ var sh = new shaders. PhotoDissolve ();
109+ try
110+ {
111+ trace (" Enemy.capture() shader created" );
112+ }
113+ catch (e : Dynamic ) {}
114+ sh .desat = 1.0 ;
115+ sh .dissolve = 0.0 ;
116+ this .shader = sh ;
117+ try
118+ {
119+ trace (" Enemy.capture() shader assigned: " + (this .shader != null ));
120+ }
121+ catch (e : Dynamic ) {}
122+
123+ FlxTween .tween (sh , {dissolve : 1.0 }, Constants .PHOTO_DISSOLVE_DURATION , {
124+ startDelay : Constants .PHOTO_DISSOLVE_DELAY ,
125+ type : FlxTweenType .ONESHOT ,
126+ ease : FlxEase .quadOut ,
127+ onStart : function (_ )
128+ {
129+ try
130+ {
131+ trace (" Enemy.capture() tween started" );
132+ }
133+ catch (e : Dynamic ) {}
134+ try
135+ {
136+ spawnCrumbleParticles (20 );
137+ }
138+ catch (e : Dynamic ) {}
139+ },
140+ onComplete : function (_ )
141+ {
142+ try
143+ {
144+ trace (" Enemy.capture() tween complete" );
145+ }
146+ catch (e : Dynamic ) {}
147+ exists = false ;
148+ alive = false ;
149+ if (byPlayer != null )
150+ byPlayer .captured .push (variant != null ? variant : " enemy" );
151+ kill ();
152+ }
153+ });
154+ }
155+ catch (e : Dynamic )
156+ {
157+ try
158+ {
159+ trace (" Enemy.capture() shader failed: " + Std .string (e ));
160+ }
161+ catch (e : Dynamic ) {}
162+ color = 0xAAAAAA ;
163+ try
164+ {
165+ if (animation != null )
166+ animation .stop ();
167+ }
168+ catch (e : Dynamic ) {}
169+ FlxTween .tween (this , {alpha : 0 }, Constants .PHOTO_DISSOLVE_DURATION , {
170+ startDelay : Constants .PHOTO_DISSOLVE_DELAY ,
171+ onStart : function (_ )
172+ {
173+ try
174+ {
175+ trace (" Enemy.capture() fallback tween started" );
176+ }
177+ catch (e : Dynamic ) {}
178+ try
179+ {
180+ spawnCrumbleParticles (24 );
181+ }
182+ catch (e : Dynamic ) {}
183+ },
184+ onComplete : function (_ )
185+ {
186+ try
187+ {
188+ trace (" Enemy.capture() fallback complete" );
189+ }
190+ catch (e : Dynamic ) {}
191+ exists = false ;
192+ alive = false ;
193+ if (byPlayer != null )
194+ byPlayer .captured .push (variant != null ? variant : " enemy" );
195+ kill ();
196+ }
197+ });
198+ }
199+ }
200+
51201 public static function pickVariant (): String
52202 {
53203 ensureFrames ();
@@ -64,6 +214,10 @@ class Enemy extends GameObject
64214 public function new (tileX : Int , tileY : Int , ? variant : String )
65215 {
66216 super (tileX , tileY );
217+ if (variant == null )
218+ this .variant = pickVariant ();
219+ else
220+ this .variant = variant ;
67221 speed = 50 ;
68222 }
69223
@@ -73,7 +227,9 @@ class Enemy extends GameObject
73227 if (SHARED_FRAMES != null )
74228 {
75229 this .frames = SHARED_FRAMES ;
76- var variant : String = pickVariant ();
230+ var variant : String = this .variant ;
231+ if (variant == null )
232+ variant = pickVariant ();
77233 if (variant != null )
78234 {
79235 var names = VARIANT_FRAMES .get (variant );
0 commit comments