Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Sprite.cpp
Go to the documentation of this file.
1 /* Project nGenEx
2  Destroyer Studios LLC
3  Copyright © 1997-2004. All Rights Reserved.
4 
5  SUBSYSTEM: nGenEx.lib
6  FILE: Sprite.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Sprite (Polygon) Object
13 */
14 
15 #include "MemDebug.h"
16 #include "Sprite.h"
17 #include "Bitmap.h"
18 #include "Camera.h"
19 #include "Polygon.h"
20 #include "Video.h"
21 #include "Game.h"
22 
23 // +--------------------------------------------------------------------+
24 
26 : w(0), h(0), nframes(0), own_frames(0),
27 frames(0), frame_index(0), frame_time(100), loop(0), shade(1.0),
28 angle(0.0), blend_mode(4), filter(1), vset(4), poly(0)
29 {
30  trans = true;
31 
33  for (int i = 0; i < 4; i++) {
35  }
36 
37  vset.tu[0] = 0.0f;
38  vset.tv[0] = 0.0f;
39  vset.tu[1] = 1.0f;
40  vset.tv[1] = 0.0f;
41  vset.tu[2] = 1.0f;
42  vset.tv[2] = 1.0f;
43  vset.tu[3] = 0.0f;
44  vset.tv[3] = 1.0f;
45 
46  poly.nverts = 4;
47  poly.vertex_set = &vset;
48  poly.material = &mtl;
49  poly.verts[0] = 0;
50  poly.verts[1] = 1;
51  poly.verts[2] = 2;
52  poly.verts[3] = 3;
53 }
54 
55 // +--------------------------------------------------------------------+
56 
57 Sprite::Sprite(Bitmap* animation, int length, int repeat, int share)
58 : w(0), h(0), nframes(0), own_frames(0),
59 frames(0), frame_index(0), frame_time(67), loop(0), shade(1.0),
60 angle(0.0), blend_mode(4), filter(1), vset(4), poly(0)
61 {
62  trans = true;
63  SetAnimation(animation, length, repeat, share);
64 
66  for (int i = 0; i < 4; i++) {
68  }
69 
70  vset.tu[0] = 0.0f;
71  vset.tv[0] = 0.0f;
72  vset.tu[1] = 1.0f;
73  vset.tv[1] = 0.0f;
74  vset.tu[2] = 1.0f;
75  vset.tv[2] = 1.0f;
76  vset.tu[3] = 0.0f;
77  vset.tv[3] = 1.0f;
78 
79  poly.nverts = 4;
80  poly.vertex_set = &vset;
81  poly.material = &mtl;
82  poly.verts[0] = 0;
83  poly.verts[1] = 1;
84  poly.verts[2] = 2;
85  poly.verts[3] = 3;}
86 
87 // +--------------------------------------------------------------------+
88 
90 {
91  if (own_frames) {
92  if (nframes == 1)
93  delete frames;
94  else
95  delete [] frames;
96  }
97 }
98 
99 // +--------------------------------------------------------------------+
100 
101 void
102 Sprite::Scale(double scale)
103 {
104  if (scale >= 0) {
105  w = (int) (scale * w);
106  h = (int) (scale * h);
107 
108  radius = (float) ((w>h) ? w : h) / 2.0f;
109  }
110 }
111 
112 // +--------------------------------------------------------------------+
113 
114 void
115 Sprite::Rescale(double scale)
116 {
117  if (scale >= 0 && Frame()) {
118  w = (int) (scale * Frame()->Width());
119  h = (int) (scale * Frame()->Height());
120 
121  radius = (float) ((w>h) ? w : h) / 2.0f;
122  }
123 }
124 
125 // +--------------------------------------------------------------------+
126 
127 void
128 Sprite::Reshape(int w1, int h1)
129 {
130  if (w1 >= 0 && h1 >= 0 && Frame()) {
131  w = w1;
132  h = h1;
133 
134  radius = (float) ((w>h) ? w : h) / 2.0f;
135  }
136 }
137 
138 // +--------------------------------------------------------------------+
139 
140 void
141 Sprite::SetAnimation(Bitmap* animation, int length, int repeat, int share)
142 {
143  if (animation) {
144  strncpy_s(name, animation->GetFilename(), 31);
145  name[31] = 0;
146 
147  if (own_frames) {
148  if (nframes == 1)
149  delete frames;
150  else
151  delete [] frames;
152  }
153 
154  w = animation->Width();
155  h = animation->Height();
156 
157  radius = (float) ((w>h) ? w : h) / 2.0f;
158 
159  own_frames = !share;
160  nframes = length;
161  frames = animation;
162  frame_index = 0;
163 
164  if (repeat) {
165  loop = 1;
166  life = -1;
167  }
168  else {
169  loop = 0;
170  life = nframes;
171  }
172 
174  }
175 }
176 
177 // +--------------------------------------------------------------------+
178 
179 void
180 Sprite::SetTexCoords(const double* uv_interleaved)
181 {
182  if (uv_interleaved) {
183  vset.tu[0] = (float) uv_interleaved[0];
184  vset.tv[0] = (float) uv_interleaved[1];
185  vset.tu[1] = (float) uv_interleaved[2];
186  vset.tv[1] = (float) uv_interleaved[3];
187  vset.tu[2] = (float) uv_interleaved[4];
188  vset.tv[2] = (float) uv_interleaved[5];
189  vset.tu[3] = (float) uv_interleaved[6];
190  vset.tv[3] = (float) uv_interleaved[7];
191  }
192  else {
193  vset.tu[0] = 0.0f;
194  vset.tv[0] = 0.0f;
195  vset.tu[1] = 1.0f;
196  vset.tv[1] = 0.0f;
197  vset.tu[2] = 1.0f;
198  vset.tv[2] = 1.0f;
199  vset.tu[3] = 0.0f;
200  vset.tv[3] = 1.0f;
201  }
202 }
203 
204 // +--------------------------------------------------------------------+
205 
206 double
208 {
209  return 1000.0 / (double) frame_time;
210 }
211 
212 void
214 {
215  if (rate > 0.001 && rate < 100) {
216  frame_time = (int) (1000.0 / rate);
217  }
218 }
219 
220 // +--------------------------------------------------------------------+
221 
222 void
224 {
225  if (n >= 0 && n < nframes)
226  frame_index = n;
227 }
228 
229 // +--------------------------------------------------------------------+
230 
231 Bitmap*
233 {
234  return frames + frame_index;
235 }
236 
237 // +--------------------------------------------------------------------+
238 
239 void
240 Sprite::Render(Video* video, DWORD flags)
241 {
242  if (shade < 0.001 || hidden || !visible || !video)
243  return;
244 
245  if (blend_mode == 2 && !(flags & Graphic::RENDER_ALPHA))
246  return;
247 
248  if (blend_mode == 4 && !(flags & Graphic::RENDER_ADDITIVE))
249  return;
250 
251  if (life > 0 || loop) {
252  const Camera* camera = video->GetCamera();
253  Matrix orient(camera->Orientation());
254  Vec3 nrm(camera->vpn() * -1);
255  ColorValue white((float) shade, (float) shade, (float) shade, (float) shade);
256  DWORD diff = white.ToColor().Value();
257 
258  orient.Roll(angle);
259 
260  Vec3 vx = Vec3((float) orient(0,0),
261  (float) orient(0,1),
262  (float) orient(0,2)) * (float) (w/2.0f);
263 
264  Vec3 vy = Vec3((float) orient(1,0),
265  (float) orient(1,1),
266  (float) orient(1,2)) * (float) (h/2.0f);
267 
268  vset.loc[0] = loc - vx + vy;
269  vset.nrm[0] = nrm;
270  vset.diffuse[0] = diff;
271 
272  vset.loc[1] = loc + vx + vy;
273  vset.nrm[1] = nrm;
274  vset.diffuse[1] = diff;
275 
276  vset.loc[2] = loc + vx - vy;
277  vset.nrm[2] = nrm;
278  vset.diffuse[2] = diff;
279 
280  vset.loc[3] = loc - vx - vy;
281  vset.nrm[3] = nrm;
282  vset.diffuse[3] = diff;
283 
284  if (luminous) {
285  mtl.Ka = Color::Black;
286  mtl.Kd = Color::Black;
287  mtl.Ks = Color::Black;
288  mtl.Ke = white;
289  mtl.tex_diffuse = Frame();
290  mtl.tex_emissive = Frame();
291  mtl.blend = blend_mode;
293  }
294 
295  else {
296  mtl.Ka = white;
297  mtl.Kd = white;
298  mtl.Ks = Color::Black;
299  mtl.Ke = Color::Black;
300  mtl.tex_diffuse = Frame();
301  mtl.tex_emissive = 0;
302  mtl.blend = blend_mode;
304  }
305 
306  video->DrawPolys(1, &poly);
307  }
308 
309  memset(&screen_rect, 0, sizeof(Rect));
310 }
311 
312 // +--------------------------------------------------------------------+
313 
314 void
316 {
317  if (shade < 0.001 || hidden || !visible || !video)
318  return;
319 
320  ColorValue white((float) shade, (float) shade, (float) shade, (float) shade);
321  DWORD diff = white.ToColor().Value();
322 
323  double ca = cos(Angle());
324  double sa = sin(Angle());
325 
326  double w2 = Width() / 2.0;
327  double h2 = Height() / 2.0;
328 
329  vset.s_loc[0].x = (float) (loc.x + (-w2*ca - -h2*sa) - 0.5);
330  vset.s_loc[0].y = (float) (loc.y + (-w2*sa + -h2*ca) - 0.5);
331  vset.s_loc[0].z = 0.0f;
332  vset.rw[0] = 1.0f;
333  vset.diffuse[0] = diff;
334 
335  vset.s_loc[1].x = (float) (loc.x + ( w2*ca - -h2*sa) - 0.5);
336  vset.s_loc[1].y = (float) (loc.y + ( w2*sa + -h2*ca) - 0.5);
337  vset.s_loc[1].z = 0.0f;
338  vset.rw[1] = 1.0f;
339  vset.diffuse[1] = diff;
340 
341  vset.s_loc[2].x = (float) (loc.x + ( w2*ca - h2*sa) - 0.5);
342  vset.s_loc[2].y = (float) (loc.y + ( w2*sa + h2*ca) - 0.5);
343  vset.s_loc[2].z = 0.0f;
344  vset.rw[2] = 1.0f;
345  vset.diffuse[2] = diff;
346 
347  vset.s_loc[3].x = (float) (loc.x + (-w2*ca - h2*sa) - 0.5);
348  vset.s_loc[3].y = (float) (loc.y + (-w2*sa + h2*ca) - 0.5);
349  vset.s_loc[3].z = 0.0f;
350  vset.rw[3] = 1.0f;
351  vset.diffuse[3] = diff;
352 
353  mtl.Kd = white;
354  mtl.tex_diffuse = Frame();
355  mtl.blend = blend_mode;
356 
357  video->DrawScreenPolys(1, &poly, blend_mode);
358 }
359 
360 // +--------------------------------------------------------------------+
361 
362 void
364 {
365  if (life > 0 || loop) {
366  DWORD time = Game::RealTime();
367  while (time - last_time > frame_time) {
368  life--;
369  frame_index++;
370  if (frame_index >= nframes)
371  frame_index = 0;
372 
374  }
375 
376  if (life < 0 && !loop)
377  life = 0;
378  }
379 }
380