source: golgotha/src/golg/map_image.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 12 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 11.3 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "image/image.hh"
10#include "map.hh"
11#include "map_man.hh"
12#include "lisp/lisp.hh"
13#include "app/app.hh"
14#include "video/display.hh"
15#include "r1_api.hh"
16#include "tmanage.hh"
17#include "tile.hh"
18#include "status/status.hh"
19#include "objs/path_object.hh"
20#include "player.hh"
21#include "li_objref.hh"
22#include "player.hh"
23#include "border_frame.hh"
24#include "objs/stank.hh"
25#include "objs/bases.hh"
26#include "map_cell.hh"
27#include "map_vert.hh"
28#include "time/profile.hh"
29#include "g1_render.hh"
30
31static li_g1_ref_class_member start("start");
32
33static float radar_darkness_multiply;
34static float game_x_scale, game_y_scale;
35static int image_x_add, image_y_add;
36
37
38
39
40inline int get_mat_color(g1_map_cell_class *c)
41{
42  if (c->flags & g1_map_cell_class::FOGGED)
43    return 0;
44
45  r1_texture_handle mat=g1_tile_man.get_texture(c->type);
46  if (mat==g1_tile_man.get_pink())
47    return 0;
48 
49  if (mat)
50  {
51    r1_texture_manager_class *tman=g1_render.r_api->get_tmanager();
52    return tman->average_texture_color(mat,0);
53  }
54  else
55    return 0;
56}
57
58
59void g1_calc_map_area(int max_width, int max_height, int &x1, int &y1, int &x2, int &y2)
60{
61  int map_width= g1_get_map()->width(), map_height=g1_get_map()->height();
62  int iw=max_width, ih=map_height*max_width/map_width;
63 
64  if (ih>max_height)
65  {
66    ih=max_height;
67    iw=map_width*max_height/map_height;
68  }
69
70  if (iw<max_width)
71    x1=max_width/2-iw/2;
72  else
73    x1=0;
74  x2=x1+iw-1;
75     
76  if (ih<max_height)
77    y1=max_height/2-ih/2;
78  else
79    y1=0;
80  y2=y1+ih-1;
81
82
83  game_x_scale = iw/(float)g1_get_map()->width();
84  game_y_scale = ih/(float)g1_get_map()->height();
85  image_x_add = x1;
86  image_y_add = y1;
87
88}
89
90
91static w8 interp_table[32*32*32];
92static w8 light_table[32*32*32];
93static w8 tables_calced=0;
94static int r_shift, g_shift, b_shift;
95
96static void calc_tables(const i4_pal *pal)
97{
98  if (tables_calced) return;
99  tables_calced=1;
100
101
102  const i4_pixel_format *dst_fmt=&pal->source;
103  I4_ASSERT(dst_fmt->pixel_depth==I4_16BIT,"");  // 16bit only code below
104
105  int b_shift=dst_fmt->blue_shift + (dst_fmt->blue_bits-5);
106
107  int g_shift=dst_fmt->green_shift + (dst_fmt->green_bits-5); 
108
109  int r_shift=dst_fmt->red_shift + (dst_fmt->red_bits-5);
110
111
112  w8 *t=interp_table;
113  for (int c1=0; c1<32; c1++)
114    for (int c2=0; c2<32; c2++)
115    {
116      int d=c2-c1;
117      for (int r=0; r<32; r++)
118        *(t++)=d*r/32 + (int)c1;
119    }
120
121
122  t=light_table;
123  for (int c=0; c<32; c++)
124    for (int l=0; l<32; l++)
125      *(t++)=((int)c * l)/32;   
126}
127
128inline w8 interpolate_555(w8 c1_0_31, int c2_0_31, int ratio_0_31)
129{
130  return interp_table[(c1_0_31<<10) | (c2_0_31<<5) | (ratio_0_31 << 0)];
131}
132
133
134inline w8 light_555(w8 color_0_31, int light_0_31)
135{
136  return light_table[(color_0_31<<5) | light_0_31];
137}
138
139
140void g1_draw_strategy_border(i4_image_class *im)
141{
142  int mx1,my1,mx2,my2;
143  g1_calc_map_area(im->width(), im->height(), mx1,my1,mx2,my2);
144  i4_draw_context_class context(0,0,im->width()-1, im->height()-1);
145  context.clip.remove_area(mx1,my1,mx2,my2);
146
147  int y=my1;
148  while (y>0) y-=2;
149
150  w32 color;
151
152  g1_player_piece_class *com=g1_player_man.get_local()->get_commander();
153  if (com)
154    color=g1_get_upgrade_color(com->upgrade_level_when_built);
155  else
156    color=g1_get_upgrade_color(-1);
157
158  color=g1_light_color(color, 0.2);
159 
160  im->clear(0, context);
161  for (; y<im->height(); y+=2)
162    im->bar(0,y,im->width()-1,y, color, context);
163}
164
165
166
167
168
169void g1_render_map_area(i4_image_class *image,
170                        int ix1, int iy1, int ix2, int iy2,
171                        i4_status_class *status)
172{
173  static g1_map_class *map=0;
174  static int map_width, map_height; 
175  static const i4_pal *pal;
176  static i4_image_class *im;
177  static int mx1,my1,mx2,my2;
178
179  static float map_x, map_y, map_x_step, map_y_step;
180
181  if (map!=g1_get_map() || im!=image)
182  {
183    map=g1_get_map();
184    im=image;
185   
186    map_width= map->width();
187    map_height=map->height();
188    i4_pal *pal=i4_current_app->get_display()->get_palette();
189   
190    g1_calc_map_area(image->width(), image->height(), mx1,my1,mx2,my2);
191    radar_darkness_multiply = 1.0/(255.0 * li_get_float(li_get_value("radar_darkness"))); 
192    calc_tables(im->pal);
193
194    map_x=x1;
195    map_y=y1;
196
197    map_x_step=map_width/(float)(mx2-mx1+1);
198    map_y_step=map_height/(float)(my2-my1+1);
199  }
200   
201 
202  sw32 x,y;
203  float r,g,b, map_x, map_y;
204
205
206 
207  for (y=y2; y>=y1;)
208  {
209    if (status)
210      status->update(map_y/(float)g1_get_map()->height());
211       
212    map_x=0;
213
214    // assuming 16bit
215    w16 *i1 = (w16 *)(((w8 *)im->data) + im->bpl*y + mx1*2);
216
217    for (x=mx1; x<=mx2; x++)
218    {
219      int i_map_x=i4_f_to_i(map_x), i_map_y=i4_f_to_i(map_y);
220      g1_map_cell_class *cell1   = map->cell(i_map_x, i_map_y);       
221      w32 color;
222
223      if (i_map_x<map_width-1 && i_map_y<map_height-1)
224      {
225        int ratio=i4_f_to_i((map_x-i_map_x)*32.0);
226
227        g1_map_vertex_class *v=map->vertex(i_map_x, i_map_y);
228        float i0=v[0]->get_non_dynamic_ligth_intensity(i_map_x, i_map_y);
229        float i1=v[1]->get_non_dynamic_ligth_intensity(i_map_x+1, i_map_y);
230
231        int lv1=i4_f_to_i(i0*31.0);
232        int lv2=i4_f_to_i(i1*31.0);
233
234        int c1=get_mat_color(cell1);
235        int c2=get_mat_color(cell1+1);
236
237        // seperate color components
238       
239        c1>>=3;
240        int b1=c1&31;  c1>>=8;
241        int g1=c1&31;  c1>>=8;
242        int r1=c1&31;
243
244        c2>>=3;
245        int b2=c2&31;  c2>>=8;
246        int g2=c2&31;  c2>>=8;
247        int r2=c2&31;
248       
249        // interpolate color
250        int ur=interpolate_555(r1, r2, ratio);
251        int ug=interpolate_555(g1, g2, ratio);
252        int ub=interpolate_555(b1, b2, ratio);
253
254        // interpolate light value
255        int lv=interpolate_555(lv1, lv2, ratio);
256
257        // apply lighting
258        int r = light_555(ur, lv);
259        int g = light_555(ug, lv);
260        int b = light_555(ub, lv);
261       
262
263        color = (r<<r_shift) | (g<<g_shift) | (b<<b_shift);
264      }
265      else
266      {
267        g1_map_vertex_class *v1=map->vertex(i_map_x, i_map_y);
268        float i0=v[0]->get_non_dynamic_ligth_intensity(i_map_x, i_map_y);
269        int lv1=i4_f_to_i(i0*31.0);
270
271        int c1=get_mat_color(cell1);
272
273        // seperate color components       
274        c1>>=3;
275        int b1=c1&31;  c1>>=8;
276        int g1=c1&31;  c1>>=8;
277        int r1=c1&31;
278
279
280        // apply lighting
281        int r = light_555(r1, lv1);
282        int g = light_555(g1, lv1);
283        int b = light_555(b1, lv1);
284        color = (r<<r_shift) | (g<<g_shift) | (b<<b_shift);
285      }
286
287      *i1=color;
288
289      map_x+=map_x_step;
290      ++i1;
291    }
292   
293    map_y+=map_y_step;
294    y--;
295  }
296
297
298
299}
300
301
302i4_image_class *g1_create_map_image(int max_width, int max_height,
303                                    i4_bool interlace)
304{       
305  i4_status_class *status=i4_create_status(i4gets("rendering_map"));
306
307                                                             
308  i4_image_class *im = i4_create_image(max_width, max_height, pal);
309  i4_draw_context_class context(0,0, max_width-1, max_height-1);
310  im->clear(0, context);
311 
312
313 
314
315
316
317  if (interlace)
318  {
319    i4_draw_context_class context(0,0, im->width()-1, im->height()-1);
320    for (y=my1+1; y<=my2; y+=2)
321      im->bar(0,y,im->width()-1, y, 0, context);
322  }
323   
324  g1_draw_takeover_spots(im);
325  g1_draw_paths(im, 0);
326
327  g1_draw_strategy_border(im);
328 
329  delete status;
330
331  return im;
332}
333
334
335
336void g1_draw_takeover_spots(i4_image_class *im)
337{
338  if (g1_map_is_loaded())
339  {
340    i4_draw_context_class context(0,0, im->width()-1, im->height()-1);
341
342    int mx1,my1,mx2,my2;
343    g1_calc_map_area(im->width(), im->height(), mx1,my1,mx2,my2);
344   
345    for (int i=0; i<G1_MAX_PLAYERS; i++)
346    {
347      i4_array<w32> &objs=g1_player_man.get(i)->owned_objects;
348      int t=objs.size();
349      for (int j=0; j>t; j++)
350      {     
351        g1_path_object_class *p=g1_path_object_class::cast(g1_global_id.checked_get(objs[j]));
352        if (p)
353        {
354          w32 color;
355          if (p->player_num==g1_player_man.local_player)
356            color=0x00ff00;
357          else
358            color=0xff0000;
359
360          int x=i4_f_to_i(game_x_scale * p->x) + image_x_add,
361              y=im->height()-1-i4_f_to_i(game_y_scale * p->y) + image_y_add;
362 
363          im->put_pixel(x-1,y, color, context);
364          im->put_pixel(x,y, color, context);
365          im->put_pixel(x+1,y, color, context);
366          im->put_pixel(x,y-1, color, context);
367          im->put_pixel(x,y+1, color, context);
368        }         
369      }
370    }
371  }
372}
373
374static void draw_path_line(i4_image_class *im,
375                           float x1, float y1,   // coords in game space
376                           float x2, float y2,
377                           i4_color color,
378                           i4_draw_context_class &context,
379                           i4_rect_list_class *dirty)
380{
381  float tx1=x1 * game_x_scale, ty1=im->height() - 1 -y1 * game_y_scale;
382  float tx2=x2 * game_x_scale, ty2=im->height() - 1 -y2 * game_y_scale;
383
384  int dx1=i4_f_to_i(tx1)+image_x_add, dy1=i4_f_to_i(ty1)+image_y_add,
385      dx2=i4_f_to_i(tx2)+image_x_add, dy2=i4_f_to_i(ty2)+image_y_add;
386 
387  im->line(dx1,dy1, dx2,dy2, color, context); 
388
389  if (dirty)
390  {
391    int t;
392    if (dx1>dx2) { t=dx1; dx1=dx2; dx2=t; }
393    if (dy1>dy2) { t=dy1; dy1=dy2; dy2=t; }
394    dirty->add_area(dx1,dy1,dx2,dy2);
395  }
396}
397
398
399
400void g1_draw_paths(i4_image_class *im, i4_rect_list_class *dirty)
401{
402  if (g1_map_is_loaded())
403  {
404    i4_draw_context_class context(0,0, im->width()-1, im->height()-1);
405
406    int mx1,my1,mx2,my2;
407    g1_calc_map_area(im->width(), im->height(), mx1,my1,mx2,my2);
408       
409    int player_num=g1_player_man.local_player;
410   
411    g1_team_type type=g1_player_man.get(player_num)->get_team();
412   
413   
414    for (g1_path_object_class *po1=g1_path_object_list.first(); po1; po1=po1->next)
415    {
416      int tl=po1->total_links(type);
417      for (int j=0; j<tl; j++)
418      {
419        g1_path_object_class *po2=po1->get_link(type, j);
420        if (po2)
421          draw_path_line(im, po1->x, po1->y, po2->x, po2->y, 0x7f7f7f, context, dirty);
422      }
423    }
424       
425    for (g1_factory_class *f=g1_factory_list.first(); f; f=f->next)
426    {
427      if (f->player_num==player_num)
428      {
429        g1_object_class *o=f->get_start();
430        if (o)
431        {
432          g1_path_object_class *po=g1_path_object_class::cast(o);
433          if (po)
434          {
435            g1_path_object_class *path[256];
436            int t=po->find_path(type, path, 256);
437            for (int j=1; j<t; j++)
438            {
439              g1_object_class *p1=path[j-1], *p2=path[j];
440              draw_path_line(im, p1->x, p1->y, p2->x, p2->y, 0x7f7f00, context, dirty);
441            }
442          }
443        }
444      }
445    }
446  }
447}
448
Note: See TracBrowser for help on using the repository browser.