1 module d2dactors
is aliced
;
14 // ////////////////////////////////////////////////////////////////////////// //
21 int xv
, yv
; // current velocity
22 int vx
, vy
; // desired velocity (usually)
24 int height
; // radius, height
27 ubyte t
, d
, st
, ftime
;
29 int s
; // for item too
31 int aim
, life
, pain
, ac
, tx
, ty
, ammo
;
35 ActionScript acs
; // just a cache; NEVER change this!
38 int framesLeft
; // # of frames left before next state
39 ImgSprite frame
; // can be null
44 void acsSetState (string astate
) {
46 pc
= acs
.getLabelId(astate
);
50 dead
= true; // mark as dead, so game gc will collect it
55 if (framesLeft
> 0) { --framesLeft
; return; }
56 if (acs
is null) { acsRemove(); return; }
57 while (framesLeft
<= 0) {
58 if (pc
< 0 || pc
>= acs
.actions
.length
) { acsRemove(); return; }
59 auto act
= acs
.actions
.ptr
[pc
++];
60 if (auto a
= cast(AnimActionRemove
)act
) {
66 if (auto a
= cast(AnimActionSpr
)act
) {
67 frame
= findSprite(tpl
.base
, a
.spr
);
71 if (auto a
= cast(AnimActionJump
)act
) {
76 if (auto a
= cast(AnimActionJumpState
)act
) {
86 // ////////////////////////////////////////////////////////////////////////// //
87 public class ImgSprite
{
91 string name
; // full disk name
95 // ////////////////////////////////////////////////////////////////////////// //
96 public __gshared ImgSprite
[string
] sprites
;
97 public __gshared Actor
[] actors
;
100 // ////////////////////////////////////////////////////////////////////////// //
101 char[] buildCacheName (char[] buf
, const(char)[] path
, const(char)[] name
=null) nothrow @safe @nogc {
103 if (path
.length
&& name
.length
) {
104 buf
[0..path
.length
] = path
[];
106 if (path
[$-1] != '/') buf
[pos
++] = '/';
107 buf
[pos
..pos
+name
.length
] = name
[];
109 } else if (path
.length
) {
110 buf
[0..path
.length
] = path
[];
112 } else if (name
.length
) {
113 buf
[0..name
.length
] = name
[];
120 void cacheSprite (string path
, string name
=null) {
121 if (path
.length
+name
.length
+5 > 256) throw new Exception("sprite name too long");
122 char[256] namebuf
= void;
123 auto nm
= buildCacheName(namebuf
, path
, name
);
124 if (nm
in sprites
) return;
125 conwriteln("precaching '", nm
, ".vga'...");
129 img
= new D2DImage(snm
~"0.vga");
130 } catch (Exception
) {
132 img
= new D2DImage(snm
~"1.vga");
133 } catch (Exception
) {
134 img
= new D2DImage(snm
~"1"~snm
[$-1]~"2.vga");
137 //conwriteln(" sx=", img.sx, "; sy=", img.sy);
138 auto spr
= new ImgSprite();
140 spr
.tex
= new Texture(spr
.vga
.asTCImage
, Texture
.Option
.Nearest
);
146 void cacheSpritesForActor (Actor actor
) {
147 if (actor
is null || actor
.acs
is null) return;
148 foreach (auto act
; actor
.acs
.actions
) {
149 if (auto sp
= cast(AnimActionSpr
)act
) {
150 if (sp
.spr
.length
== 0) continue;
151 cacheSprite(actor
.tpl
.base
, sp
.spr
);
157 ImgSprite
findSprite (string path
, string name
=null) nothrow @nogc {
158 if (path
.length
+name
.length
+5 > 256) return null;
159 char[256] namebuf
= void;
160 auto nm
= buildCacheName(namebuf
, path
, name
);
161 if (auto sp
= nm
in sprites
) return *sp
;
166 // ////////////////////////////////////////////////////////////////////////// //
167 public void initActors (LevelMap map
) {
169 foreach (ref tg
; map
.things
) {
170 auto act
= new Actor();
173 if (tg
.type
>= ThingId
.FirstMonster
&& tg
.type
<= ThingId
.LastMonster
) {
174 act
.tpl
= monTpls
[tg
.type
-ThingId
.FirstMonster
];
175 } else if (tg
.type
>= ThingId
.FirstItem
&& tg
.type
<= ThingId
.LastItem
) {
177 if (act
.tpl
is null) continue;
178 act
.radius
= act
.tpl
.radius
;
179 act
.height
= act
.tpl
.height
;
180 act
.acs
= act
.tpl
.acs
;
181 act
.acsSetState("sleep");
182 cacheSpritesForActor(act
);
188 public void doActorTick (Actor actor
, LevelMap map
) {
189 if (actor
is null) return;
190 if (actor
.dead
) return;
195 public void doAllActorTicks (LevelMap map
) {
196 foreach (auto actor
; actors
) doActorTick(actor
, map
);