Perform minor random cleanup.
[runemen.git] / src / draw.c
blobc0aaea7d7223acdbb1bf4d1723173eb24105b915
1 #include <SDL.h>
3 #include "libs/SDL_inprint/SDL2_inprint.h"
5 #include "game.h"
6 #include "ui.h"
7 #include "draw.h"
8 #include "rune.h"
10 SDL_Renderer *mainRenderer = NULL;
12 SDL_Texture *tiles;
13 SDL_Texture *uibg;
14 SDL_Texture *small_font;
15 SDL_Texture *mid_font;
16 SDL_Texture *large_font;
18 SDL_Color white = { 0xFF, 0xFF, 0xFF, 255 };
19 SDL_Color black = { 0x00, 0x00, 0x00, 255 };
20 SDL_Color brown = { 0x6c, 0x44, 0x1c, 255 };
21 SDL_Color yellow = { 0xFF, 0xFF, 0x00, 255};
23 SDL_Color reds[16];
25 Uint32 state_colors[4] = {
26 0xFFFFFF, 0xFF0000, 0x0000FF, 0x00FF00,
29 void SDL_InitSine() {
31 SDL_Color start = { 0xFF, 0x00, 0x00 };
32 SDL_Color end = { 0x66, 0x11, 0x11 };
34 SDL_ComputeGradient(reds, 16, &start, &end);
38 void MY_LineRect(SDL_Renderer *dst, SDL_Rect *dr, SDL_Color *color)
40 SDL_SetRenderDrawColor(dst, color->r, color->g, color->b, color->a);
41 SDL_RenderDrawRect(dst, dr);
44 void MY_PutPixel(SDL_Renderer *dest, Uint32 x, Sint32 y, SDL_Color *col)
46 SDL_SetRenderDrawColor(dest, col->r, col->g, col->b, col->a);
47 SDL_RenderDrawPoint(dest, x, y);
50 void MY_DrawVector(SDL_Renderer *surface, Sint32 x, Sint32 y, float a, int len, SDL_Color *color)
52 int i;
53 SDL_Rect *clip = NULL;//-&surface->clip_rect;
54 float c = cosf(a * M_PI / 180);
55 float s = sinf(a * M_PI / 180);
56 for (i = 0; i < len; i++)
58 int nx = (int)(x + i * c);
59 int ny = (int)(y + i * s);
61 if (!clip || SDL_InBounds(nx, ny, clip))
63 MY_PutPixel(surface, nx, ny, color);
68 void MY_DrawLine(SDL_Renderer *dst, Sint32 x1, Sint32 y1, Sint32 x2, Sint32 y2, SDL_Color *color)
70 Sint32 dx = x2 - x1;
71 Sint32 dy = y2 - y1;
72 double angle = atan2(dy, dx) * 180 / M_PI;
73 double distance = sqrt( (dx*dx) + (dy*dy) );
75 SDL_SetRenderDrawColor(dst, color->r, color->g, color->b, color->a);
76 //SDL_RenderDrawLine(dst, x1, y1, x2, y2);
77 MY_DrawVector(dst, x1, y1, (float)angle, (int)distance, color);
80 void SDL_AlphaFill(SDL_Renderer *dest, Uint32 x, Sint32 y, Uint32 w, Uint32 h, SDL_Color *color)
82 SDL_Rect dst = { x, y, w, h };
83 //SDL_SetRenderDrawBlendMode(dest, SDL_BLENDMODE_BLEND);
84 SDL_SetRenderDrawColor(dest, color->r, color->g, color->b, color->a);
85 SDL_RenderFillRect(dest, &dst);
87 #define PIXEL_BY_PIXEL
88 void MY_DrawSineWave(SDL_Renderer *surface, Sint32 x, Sint32 y, float a, int len, SDL_Color *col)
90 float i;
91 SDL_Rect *clip = NULL;//&surface->clip_rect;
92 float c = cosf(a * M_PI / 180);
93 float s = sinf(a * M_PI / 180);
94 float AMP = 2;
95 float WAV = 4;
97 #ifndef PIXEL_BY_PIXEL
98 int count = 0; SDL_Point points[1024];
99 #endif
100 int freq = ui.freq;
102 int colorquant = 16;//((len+1) / 16);
104 for (i = 0; i < len; i+= 0.5)//0.1)
106 int j = (int)(freq) % colorquant;
108 int nx = (int)(x + i * c);
109 int ny = (int)(y + i * s);
110 ny += ( cosf( (freq+i) / WAV) * AMP );
111 nx += ( sinf( (freq+i) / WAV) * AMP );
112 #ifndef PIXEL_BY_PIXEL
113 points[count].x = nx;
114 points[count].y = ny;
115 count++;
116 if (count >= sizeof(points) - 2) break;
117 continue;
118 #else
119 if (!clip || SDL_InBounds(nx, ny, clip))
121 MY_PutPixel(surface, nx, ny, &reds[j]);
122 //SDL_AlphaFill(surface, nx, ny, 2, 2, color);
124 #endif
126 #ifndef PIXEL_BY_PIXEL
127 SDL_SetRenderDrawColor(surface, col->r, col->g, col->b, col->a);
128 SDL_RenderDrawPoints(surface, points, count);
129 #endif
131 void MY_DrawSine(SDL_Renderer *dst, Sint32 x1, Sint32 y1, Sint32 x2, Sint32 y2, SDL_Color *color)
133 Sint32 dx = x2 - x1;
134 Sint32 dy = y2 - y1;
135 double angle = atan2(dy, dx) * 180 / M_PI;
136 double distance = sqrt( (dx*dx) + (dy*dy) );
138 MY_DrawSineWave(dst, x1, y1, (float)angle, (int)distance, color);
141 int unit_icon(unit_t *u) {
142 if (u->link == NULL) /* Either rune lord either free man */
143 if (u->ref_counts == 0) return 0; /* FREE MAN */
144 else return 3; /* RUNE LORD */
145 else /* Either a vector either a devotee */
146 if (u->ref_counts == 0) return 1; /* DEVOTEE */
147 else return 2; /* VECTOR */
150 /* RUNE printf */
151 int rprintf(SDL_Renderer *renderer, Uint32 x, Uint32 y, char *fmt, ...) {
152 char buffer[1024];
154 va_list argptr;
155 va_start(argptr, fmt);
157 vsnprintf(buffer, sizeof(buffer), fmt, argptr);
159 va_end(argptr);
161 inprint(renderer, buffer, x, y);
163 return 0;
167 /* One tile */
168 void draw_tile(SDL_Renderer *screen, Uint8 id, Uint8 frame, Uint32 x, Uint32 y) {
169 SDL_Rect src = { frame * 16, id * 16 , 16, 16 };
170 SDL_Rect dst = { x, y, 16, 16 };
171 SDL_RenderCopy(screen, tiles, &src, &dst);
173 /* W & H tile */
174 void draw_ctile(SDL_Renderer *screen, Uint8 id, Uint8 frame, Uint32 x, Uint32 y, Uint8 w, Uint8 h) {
175 SDL_Rect src = { frame * 16, id * 16 , 16 * w, 16 * h };
176 SDL_Rect dst = { x, y, 16 * w, 16 * h };
177 SDL_RenderCopy(screen, tiles, &src, &dst);
179 /* Stretched tile */
180 void draw_stile(SDL_Renderer *screen, Uint8 id, Uint8 frame, Uint32 x, Uint32 y, Uint8 w, Uint8 h, Uint8 sw, Uint8 sh) {
181 SDL_Rect src = { frame * TILE_W, id * TILE_W , w * TILE_W, h * TILE_H };
182 SDL_Rect dst = { x, y, sw * TILE_W, sh * TILE_H };
183 SDL_RenderCopy(screen, tiles, &src, &dst);
186 /* W & H tile on sx/sy source */
187 void draw_btile(SDL_Renderer *screen, Uint32 sy, Uint32 sx, Uint32 x, Uint32 y, Uint8 w, Uint8 h) {
188 SDL_Rect src = { sx, sy, 16 * w, 16 * h };
189 SDL_Rect dst = { x, y, 16 * w, 16 * h };
190 SDL_RenderCopy(screen, tiles, &src, &dst);
193 void draw_visual(SDL_Renderer *renderer, Uint8 *refs[], animation_t *a, Uint32 x, Uint32 y) {
194 int i;
196 SDL_Rect dst = { x, y, a->plane.w, a->plane.h };
197 //start with base plane...
198 SDL_Rect src = { a->plane.x, a->plane.y, a->plane.w, a->plane.h };
200 //...offset by each modifier axis
201 for (i = 0; i < a->num_axises; i++) {
202 Uint8 ask = a->axis_modifier[i];
203 Uint8 ref = *(refs[ask]);
204 src.x += ref * a->axis_offset[i].w + a->axis_offset[i].x;
205 src.y += ref * a->axis_offset[i].h + a->axis_offset[i].y;
208 SDL_RenderCopy(renderer, a->image, &src, &dst);
213 void draw_blackbox(SDL_Renderer *screen, Uint32 x, Uint32 y, Uint32 w, Uint32 h) {
214 // Uint32 brown = SDL_MapRGB(screen->format, 0x6c, 0x44, 0x1c);
216 SDL_Rect box = { x, y, w, h };
218 SDL_SetRenderDrawColor(screen, 0, 0, 0, 255);
219 SDL_RenderFillRect(screen, &box);
221 /*box.x++;
222 box.y++;
223 box.w-=2;
224 box.h-=2;*/
226 SDL_SetRenderDrawColor(screen, brown.r, brown.g, brown.b, 255);
227 SDL_RenderDrawRect(screen, &box);
231 ///////////
233 void draw_pools(SDL_Renderer *screen) {
235 SDL_Color redish = { 0xff, 0, 0, 0x33 };
236 SDL_Color greenish = { 0, 0xff, 0, 0x33 };
237 SDL_Color black = { 0, 0, 0, 0xAA };
238 SDL_Color white = { 0xff, 0xff, 0xff, 0xEE };
240 int i;
241 for (i = 0 ; i < num_pools; i++) {
242 pool_t *pool = &pools[i];
243 unit_t *head = pool->head;
245 Uint32 x = head->x * TILE_W - TILE_W;
246 Uint32 y = head->y * TILE_H - TILE_H;
248 x -= (i % 4) * 8;
249 y -= (i % 4) * 16;
251 x = x - ui.vx + game_map.x;
252 y = y - ui.vy + game_map.y;
254 SDL_Rect mini = { x, y, 64, 10 };
256 SDL_AlphaFill(screen, x, y, mini.w, mini.h, &black);
257 MY_LineRect(screen, &mini, &redish);
259 // draw_tile(screen, TILE_STAT_Y, TILE_STAT_X + pool->stat, x , y);
261 int links = 0;
262 /* Draw kids overlays */
263 //unit_t *lim = (head->link == pool->tail ? NULL : pool->head);
264 unit_t *it = pool->tail;
265 while (it) {
266 Uint32 sx = it->x * TILE_W + it->ox - ui.vx + game_map.x;
267 Uint32 sy = it->y * TILE_H + it->oy - ui.vy + game_map.y;
269 MY_DrawLine(screen, sx + 8, sy + 4, x, y + mini.h/2, &redish);
271 it = it->link;
272 if (it == head) break;
273 links++;
276 infont(small_font);
277 incolor1(&white);
278 rprintf(screen, x + 3, y + 1, "%02d %s:%03d", links+1, stat_names[pool->stat], pool->pool);
280 Uint32 sx = head->x * TILE_W + it->ox - ui.vx + game_map.x;
281 Uint32 sy = head->y * TILE_H + it->oy - ui.vy + game_map.y;
283 MY_DrawLine(screen, sx + 8, sy + 4, x + mini.w/2, y + mini.h/2, &greenish);
287 //TODO: remove
288 infont(large_font);
290 void draw_paths(SDL_Renderer *screen, Sint8 sel, Uint16 x, Uint16 y) {
291 #ifdef DEBUG_PATHFIND
292 int i,j;
293 if (sel == -1) return;
294 unit_t *su = &units[sel];
295 for (j = 0; j < LEVEL_H; j++) {
296 for (i = 0; i < LEVEL_W; i++) {
297 Uint32 pos = j * LEVEL_W + i;
298 Uint32 tx = i * TILE_W;
299 Uint32 ty = j * TILE_H;
300 char buf[16];
301 char vd = '>' - 1;
302 if (su->prev[pos] == -1) vd = '!';
303 else if (su->prev[pos] - pos == -1) vd = '<';
304 else if (su->prev[pos] - pos < -1) vd = '^';
305 else if (su->prev[pos] - pos > 1) vd = 'v';
307 infont(small_font);
308 incolor(0x00FFFFFF, 0);
309 rprintf(screen, tx, ty, "%ld%c", (su->d[pos]/25 > 9 ? 9 : su->d[pos]/25), vd);
311 //Uint32 color = SDL_MapRGBA(screen->format,
312 SDL_Color color = { su->d[pos], su->d[pos], su->d[pos], su->d[pos] };
313 SDL_AlphaFill(screen, tx + x, ty + y, TILE_W, TILE_H, &color);
317 //TODO: remove
318 infont(large_font);
319 #endif
321 void draw_overlays(SDL_Renderer *screen, Sint8 sel, Uint8 flip, Uint8 block, unit_t *from) {
322 if (sel == -1) return;
323 int i;
324 if (block == 0) for (i = 0; i < num_units; i++) units[i].block = 0;
325 unit_t *su = &units[sel];
326 Uint32 sx = su->x * TILE_W + su->ox - ui.vx + game_map.x;
327 Uint32 sy = su->y * TILE_H + su->oy - ui.vy + game_map.y;
328 su->block = 1;
329 Uint32 colors[16] = { 0x00FF0033, 0xFF000033 };
330 for (i = 0; i < num_units; i++) {
331 unit_t *u = &units[i];
332 Uint32 x = u->x * TILE_W + u->ox - ui.vx + game_map.x;
333 Uint32 y = u->y * TILE_H + u->oy - ui.vy + game_map.y;
335 if (u->tile == 0 || u == from) continue;
336 if (u->link == su ) {
337 MY_DrawSine(screen, sx + 8, sy + 4, x + 8, y + 4, reds);//colors[flip]);
338 //SDL_DrawLine(screen, sx + 8, sy + 4, x + 8, y + 4, colors[flip]);
339 if (!u->block) draw_overlays(screen, i, flip, 1, su);
341 if (su->link == u) {
342 MY_DrawSine(screen, x + 8, y + 4, sx + 8, sy + 4, reds);//colors[1 - flip]);
343 //SDL_DrawLine(screen, sx + 8, sy + 4, x + 8, y + 4, colors[flip]);
344 if (!u->block) draw_overlays(screen, i, flip, 1, su);
349 void draw_goldbox(SDL_Renderer *screen, Uint32 x, Uint32 y, Uint8 tile, int val) {
350 Uint32 w = 72;
351 Uint32 h = 14;
353 char gold[16];
354 snprintf(gold, sizeof(gold), "% 7d", val);
356 SDL_Rect border = { x, y, w, h };
357 SDL_Rect filler = { x+1, y+1, w-2, h-2 };
359 SDL_SetRenderDrawColor(screen, 0, 0, 0, 255); //black
360 SDL_RenderFillRect(screen, &filler);
362 SDL_SetRenderDrawColor(screen, brown.r, brown.g, brown.b, 255);//brown
363 SDL_RenderDrawRect(screen, &border);
365 incolor(0x00FFFFFF, 0);
366 inprint(screen, gold, x+14, y+3);
368 draw_tile(screen, TILE_RES_Y, TILE_RES_X + tile, x+4, y+4);
371 void draw_buildset(SDL_Renderer *screen) {
373 int x = buildbox.x;
374 int y = buildbox.y;
376 int i;
377 for (i = 0; i < HMENU_ITEMS; i++) {
379 house_p *m = &bhouses[i];
381 int hover = 0;
382 int pushin_x = 1;
383 int pushin_y = 1;
384 if (ui.builder == i) {
385 hover = 2;
386 pushin_x = 0;
387 pushin_y = 0;
389 else {
390 if (ui.hover == overBuildButton && ui.hover_id == i)
392 hover = 1;
396 draw_tile(screen, TILE_BTN_Y + 1, TILE_BTN_X + hover, x, y);
397 draw_tile(screen, 0, m->icon + 1, x - pushin_x, y - pushin_y);
399 x += 17;
400 if (x >= buildbox.x + buildbox.w - TILE_W/2) {
401 x = buildbox.x;
402 y += 17;
407 void draw_minimap(SDL_Renderer *screen) {
408 Uint32 w = minimap.w;
409 Uint32 h = minimap.h;
411 Uint32 x = minimap.x;
412 Uint32 y = minimap.y;
414 // draw_blackbox(screen, x, y, w, h);
416 x += 1;
417 y += 1;
418 w -= 2;
419 h -= 2;
421 SDL_Rect dem = { x, y, w, h };
422 SDL_SetRenderDrawColor(screen, 0x11, 0x33, 0x11, 255);
423 SDL_RenderFillRect(screen, &dem);
425 int zY = h / level_h;
426 int zX = w / level_w;
428 int rw = level_w * zX;
429 int rh = level_h * zY;
431 int offX = w % level_w / 2;
432 int offY = h % level_h / 2;
434 x += offX;
435 y += offY;
437 int i;
438 for (i = 0; i < num_units; i++) {
439 unit_t *u = &units[i];
440 unit_p *proto = &bunits[u->tile];
442 SDL_Color *color;
444 color = &factions[u->faction].color;
446 if (ui.unit == i) {
447 color = &white;
449 SDL_Rect trg = { x + u->x * zX, y + (u->y-(proto->h-1)) * zY, proto->w * zX, proto->h * zY };
450 SDL_SetRenderDrawColor(screen, color->r, color->g, color->b, 255);
451 SDL_RenderFillRect(screen, &trg);
453 for (i = 0; i < num_houses; i++) {
454 house_t *h = &houses[i];
456 SDL_Color color;
457 color.a = 255;
458 color.r = 0; color.g = 0; color.b = 0xff;
459 if (ui.house == i) {
460 color.r = 0xff; color.g = 0xff; color.b = 0xff;
462 SDL_Rect trg = { x + h->x * zX, y + (h->y) * zY, h->w * zX, h->h * zY };
463 SDL_SetRenderDrawColor(screen, color.r, color.g, color.b, color.a);
464 SDL_RenderFillRect(screen, &trg);
466 int j;
467 for (j = 0; j < LEVEL_H; j++) {
468 for (i = 0; i < LEVEL_W; i++) {
469 if (fog[j][i]) {
470 SDL_Rect trg = { x + i * zX, y + j * zY, zX, zY };
471 SDL_SetRenderDrawColor(screen, 0,0,0, 255);
472 SDL_RenderFillRect(screen, &trg);
477 int vx = (x) + ui.vx / (TILE_W / zX);
478 int vy = (y) + ui.vy / (TILE_H / zY);
480 int vw = rw / ((float)level_w * TILE_W / (game_map.w - 1)) + 1;
481 int vh = rh / ((float)level_h * TILE_H / (game_map.h - 1)) + 1;
483 //SDL_Rect vport = { vx, vy, vw, vh }; // Most accurate
484 //SDL_Rect vport = { vx - offX, vy - offY, vw + offX * 2, vh + offY * 2 }; // Prettiest
485 SDL_Rect vport = { vx - 1, vy - 1, vw + 2, vh + 2 }; // Middle ground
487 MY_LineRect(screen, &vport, &white);
489 MY_LineRect(screen, &minimap, &brown);
493 void draw_unitname(SDL_Renderer *screen, unit_t *u, Uint32 y, Uint8 offset) {
494 unit_p *p = &bunits[u->tile];
495 Uint32 x = ui.log_width - PANE_WIDTH;
497 //draw_blackbox(screen, x, y+2, w, h);
499 /* :( draw face in bad way */
500 if (!u->tile) draw_tile(screen, 0, 0, x, y);
501 else
502 draw_visual(screen, u->axis_refs, &p->face, x, y - (p->h-1)*TILE_H);
504 incolor1(&bunits[u->tile].color);
505 incolor(0x00ffffff, 0);
506 inprint(screen, u->name, x + 17, y + offset);
507 //inprint(screen, bunits[u->tile].title, x + 17, y+8+3);
510 void draw_pinbox(SDL_Renderer *screen) {
512 Uint32 x = pinbox.x;
513 Uint32 y = pinbox.y;
515 SDL_Rect pinbtn = { 0, 0, 16, 16 };
517 int i, highlight_pin;
518 for (i = 0; i < num_units; i++) {
519 unit_t *u = &units[i];
520 if (u->tile && u->pin) {
522 /* Draw name */
523 draw_unitname(screen, u, y, 6);
525 /* Draw pin */
526 pinbtn.x = x + 120;
527 pinbtn.y = y + 4;
529 highlight_pin = 0;
530 if (ui.hover == overListPin && ui.hover_id == i) highlight_pin = 1;
532 draw_tile(screen, TILE_UICO_Y, TILE_UICO_X + 5 - highlight_pin, pinbtn.x, pinbtn.y);
534 y += 16;
540 void draw_housebox(SDL_Renderer *screen) {
542 Uint32 w = selbox.w;
543 Uint32 ph = selbox.h;
545 Uint32 x = selbox.x;
546 Uint32 y = selbox.y;
548 draw_blackbox(screen, x, y, w, ph);
550 x += BOX_PADDING;
551 y += BOX_PADDING;
552 //w -= BOX_PADDING * 2;
553 //h -= BOX_PADDING * 2;
555 house_t *h = &houses[ui.house];
556 house_p *p = &bhouses[h->tile];
558 draw_tile(screen, 0, h->tile+1, x, y); /* house icon */
559 y += 3; /* small offset after icon */
561 incolor(0x00FFFFFF, 0);
563 infont(large_font);
564 inprint(screen, "Something", x + 17, y);
565 y += 8;
567 infont(large_font);
568 inprint(screen, p->title, x + 17, y);
569 y += 8;
571 infont(small_font);
572 rprintf(screen, x + 17, y, "HP: %d/%d", h->hp, h->max_hp);
573 y += 8;
576 /* visitors */
577 int i, j = 0;
578 for (i = 0; i < num_units; i++) {
579 unit_t *u = &units[i];
580 if (u->visiting != h) continue;
582 infont(mid_font);
583 draw_unitname(screen, u, y, 2);
585 incolor(0x00999999, 0);
586 infont(small_font);
587 rprintf(screen, x + 17, y + 8 + 2, "PROG: %d (%d gold)", u->progress, u->gold);
589 j++;
590 y += 16;
593 infont(large_font);
598 void draw_unitbox(SDL_Renderer *screen) {
600 Uint32 w = selbox.w;
601 Uint32 h = selbox.h;
603 Uint32 x = selbox.x;
604 Uint32 y = selbox.y;
606 draw_blackbox(screen, x, y, w, h);
608 x += BOX_PADDING;
609 y += BOX_PADDING;
610 w -= BOX_PADDING * 2;
611 h -= BOX_PADDING * 2;
613 unit_t *u = &units[ui.unit];
614 unit_p *p = &bunits[u->tile];
616 int icon = unit_icon(u);
618 /* :( draw face in bad way */
619 if (!u->tile) draw_tile(screen, 0, 0, x, y);
620 else
621 draw_visual(screen, u->axis_refs, &p->face, x, y - (p->h-1)*TILE_H);
623 /* Print name */
624 inprint(screen, u->name, x + 17, y + 3);
625 incolor1(&bunits[u->tile].color);
626 inprint(screen, bunits[u->tile].title, x + 17, y+8+3);
628 /* Draw pin */
629 draw_tile(screen, TILE_UICO_Y, TILE_UICO_X + 4 + u->pin, unitpin.x, unitpin.y);
631 /* Print state (and draw icon) */
632 draw_tile(screen, TILE_UICO_Y, TILE_UICO_X + icon, x + 26, y + 114);
633 incolor(state_colors[icon], 0);
634 inprint(screen, state_names[icon], x + 16 + 17, y+110+3);
635 incolor(0xFFFFFFFF, 0);
637 x += BOX_PADDING;
638 y += BOX_PADDING;
639 w -= BOX_PADDING * 2;
640 h -= BOX_PADDING * 2;
642 /* Draw stats */
643 int i;
644 int hover;
645 for (i = 0; i < MAX_STAT; i++) {
646 hover = 0;
647 y += 14;
648 if (ui.stat == i) hover = 2;
649 else {
650 if (ui.hover == overUnitStat && ui.hover_id == i) {
651 hover = 1;
654 if (u->link != NULL) hover = -1;
655 //if (u->link && u->link_stat == i) hover = 0;
656 draw_tile(screen, TILE_BTN_Y, TILE_BTN_X + hover, x , y);
658 draw_tile(screen, TILE_STAT_Y, TILE_STAT_X + i, x , y);
659 incolor(0xFFFFFF,0);
660 rprintf(screen, x + 17, y + 3, "%02d", u->base_stat[i]);
662 Uint32 col;
663 if (u->calc_stat[i] > u->base_stat[i]) col = 0x00FF00;
664 else if (u->calc_stat[i] < u->base_stat[i]) col = 0xFF0000;
665 else col = 0xFFFFFF;
667 incolor(col,0);
668 rprintf(screen, x + 17*2 + 7, y + 3, "%02d", u->calc_stat[i]);
671 /* Draw skills */
672 y -= 14 * MAX_STAT;
673 x += 64;
674 for (i = 0; i < MAX_STAT; i++) {
675 int tile = i;
676 hover = 0;
677 y += 14;
678 int hx = 0;
679 int hy = 0;
680 if (ui.btn == i) { hover = 2; hx = 1; hy = 1; }
681 else {
682 if (ui.hover == overUnitSkill && ui.hover_id == i) {
683 hover = 1;
687 /* Hack -- perception can take 2 different icons */
688 if (i == 4 && p->perc != Smell) tile += 1;
690 /* Hack -- offset "speech" icon by 1 */
691 if (i == 5) tile += 1;
693 if (u->tile != U_PEASANT) hover = -1;
694 draw_tile(screen, TILE_BTN_Y, TILE_BTN_X + hover, x, y);
696 draw_tile(screen, TILE_STAT_Y + 3, TILE_STAT_X + tile, x+hx, y+hy);
698 rprintf(screen, x + 17, y + 3, "%02d %02d", 2, 2);
703 void draw_hintbox(SDL_Renderer *screen) {
705 Uint32 w = PANE_WIDTH;
706 Uint32 h = 128;
708 Uint32 x = ui.log_width - w;
709 Uint32 y = hintbox.y;
711 draw_blackbox(screen, x, y, w, h);
713 x += BOX_PADDING;
714 y += BOX_PADDING;
715 w -= BOX_PADDING * 2;
716 h -= BOX_PADDING * 2;
718 /* Hack -- minus 1 pixel */
719 x -= 1;
721 if (ui.hintType == 0) { // Building
723 house_p *h = &bhouses[ui.hint];
725 infont(large_font);
726 incolor(0xffffff, 0);
727 inprint(screen, h->title, x, y);
731 if (ui.hintType == 1) { // Stat
733 infont(large_font);
734 incolor(0xffffff, 0);
735 inprint(screen, stat_long_names[ui.hint], x, y);
737 y += 32;
738 infont(small_font);
739 incolor(0x999999, 0);
740 inprint(screen, stat_descriptions[ui.hint], x, y);
742 y += 32;
743 infont(mid_font);
744 incolor(0xffffff, 0);
745 rprintf(screen, x, y, "1 forcible (100 blood ore)");
748 /* TODO: remove this */
749 infont(large_font);
752 void draw_forcible(SDL_Renderer *screen) {
753 draw_tile(screen, 22, 4, ui.x, ui.y);
755 unit_t *u = &units[ui.unit];
756 Uint32 x = u->x * TILE_W + u->ox - ui.vx + game_map.x;
757 Uint32 y = u->y * TILE_H + u->oy - ui.vy + game_map.y;
759 MY_DrawSine(screen, ui.x, ui.y, x + TILE_W/2, y + TILE_H/4, reds);
761 if (ui.hover == overUnit) {
762 unit_t *u2 = &units[ui.hover_id];
763 Uint8 ok = 1;
764 if (u2 == u) ok = 0;
765 SDL_Color color = { 0, 0, 0, 0x33 };
766 if (ok) color.g = 0xFF;
767 else color.r = 0xFF;
768 SDL_AlphaFill(screen,
769 u2->x * TILE_W + u2->ox - ui.vx + game_map.x,
770 u2->y * TILE_H + u2->oy - ui.vy + game_map.y, TILE_W, TILE_H, &color);
774 void draw_builder(SDL_Renderer *screen) {
776 SDL_Color color = { 0, 0, 0, 0x33 };
777 house_p *h = &bhouses[ui.builder];
779 /* For mouse-less devices, show the whole grid */
780 if (ui.no_mouse) {
781 //int i, j;
783 return;
786 if (ui.hover_xcollide) color.r = 0xFF; /* colliding, make it red */
787 else color.g = 0xFF; /* not colliding, make it green */
789 SDL_AlphaFill(screen,
790 ui.hover_tx * TILE_W - ui.vx + game_map.x,
791 ui.hover_ty * TILE_H - ui.vy + game_map.y,
792 h->w * TILE_W, h->h * TILE_H, &color);
795 void draw_selector(SDL_Renderer *screen, Uint8 top, Uint32 x, Uint32 y, Uint8 w, Uint8 h) {
796 if (w > 2) {
797 if (top) draw_stile(screen, TILE_SEL_Y, TILE_SEL_X + 2, x, y + (h-1)*TILE_H, 2, 1, w, h);
798 else draw_stile(screen, TILE_SEL_Y, TILE_SEL_X + 4, x, y + (h-1)*TILE_H, 2, 1, w, h);
800 else if (w == 2) {
801 if (top) draw_ctile(screen, TILE_SEL_Y, TILE_SEL_X + 2, x, y + (h-1)*TILE_H, 2, 1);
802 else draw_ctile(screen, TILE_SEL_Y, TILE_SEL_X + 4, x, y + (h-1)*TILE_H, 2, 1);
803 } else {
804 if (top) draw_tile(screen, TILE_SEL_Y, TILE_SEL_X, x, y + (h-1)*TILE_H);
805 else draw_tile(screen, TILE_SEL_Y, TILE_SEL_X + 1, x, y + (h-1)*TILE_H);
809 void draw_unbuilt_house(SDL_Renderer *screen, house_t *h, int sel) {
811 Uint32 x = h->x * TILE_W - ui.vx + game_map.x;
812 Uint32 y = h->y * TILE_H - ui.vy + game_map.y;
813 Uint32 pix_w = h->w * TILE_W;
814 Uint32 pix_h = h->h * TILE_H;
815 Uint8 tile = h->tile;
817 house_p *bp = &bhouses[tile];
819 if (sel) draw_selector(screen, 1, x, y, h->w, h->h);
821 draw_btile(screen,
822 bp->body.plane.y + bp->unbuilt.y,
823 bp->body.plane.x + bp->unbuilt.x,
824 x, y, h->w, h->h);
826 SDL_Rect built;
828 built.x = bp->body.plane.x + bp->body.axis_offset[0].x;
829 built.y = bp->body.plane.y + bp->body.axis_offset[0].y;
831 int prop = h->hp * 100 / h->max_hp;
832 int pix_vert = pix_w * prop / 100;
833 int pix_horz = pix_h * prop / 100;
834 //printf("Percent built: %d (in pix: %d)\n", prop, pix);
836 SDL_Rect src = { built.x + (pix_w - pix_vert), built.y, pix_vert, TILE_H * h->h };
837 SDL_Rect dst = { x + (pix_w - pix_vert), y, pix_vert, TILE_H * h->h };
838 SDL_RenderCopy(screen, tiles, &src, &dst);
841 SDL_Rect src = { built.x, built.y + (pix_h - pix_horz), TILE_W * h->w, pix_horz };
842 SDL_Rect dst = { x, y + (pix_h - pix_horz), TILE_W * h->w, pix_horz };
843 SDL_RenderCopy(screen, tiles, &src, &dst);
846 if (sel) draw_selector(screen, 0, x, y, h->w, h->h);
849 inline void draw_house(SDL_Renderer *screen, house_t *h, Uint32 x, Uint32 y) {
850 house_p *p = &bhouses[h->tile];
851 draw_visual(screen, h->axis_refs, &p->body, x, y);
854 void draw_houses(SDL_Renderer *screen) {
855 int i;
856 for (i = 0; i < num_houses; i++) {
857 house_t *h = &houses[i];
858 //if (h->tile == 0) continue;
859 Uint32 x = h->x * TILE_W - ui.vx + game_map.x;
860 Uint32 y = h->y * TILE_H - ui.vy + game_map.y;
862 if (h->built == 0) { draw_unbuilt_house(screen, h, (ui.house==i)); continue; }
864 house_p *bp = &bhouses[h->tile];
866 if (ui.house == i) draw_selector(screen, 1, x, y, h->w, h->h);
868 draw_visual(screen, h->axis_refs, &bp->body, x, y);
870 if (ui.house == i) draw_selector(screen, 0, x, y, h->w, h->h);
874 inline void draw_unit(SDL_Renderer *screen, unit_t *u, Uint32 x, Uint32 y) {
875 unit_p *p = &bunits[u->tile];
876 draw_visual(screen, u->axis_refs, &p->body, x, y);
879 void draw_units(SDL_Renderer *screen) {
880 int i;
881 for (i = 0; i < num_units; i++) {
882 unit_t *u = &units[i];
883 unit_p *proto = &bunits[u->tile];
885 Uint32 x = u->x * TILE_W + u->ox - ui.vx + game_map.x;
886 Uint32 y = u->y * TILE_H + u->oy - ui.vy + game_map.y;
888 if (proto->h <= 0) {
889 fprintf(stderr, "Very bad unit (%p)'%s' -- [%d,%d -- %d,%d]!\n", proto, proto->id,
890 proto->body.plane.x, proto->body.plane.y, proto->w, proto->h);
891 exit(-1);
894 y -= TILE_H * (proto->h - 1);
896 if (u->visiting) continue;
898 if (ui.unit == i) draw_selector(screen, 1, x, y, proto->w, proto->h);
900 //draw_unit(screen, u, x, y);
901 draw_visual(screen, u->axis_refs, &proto->body, x, y);
903 if (ui.unit == i) draw_selector(screen, 0, x, y, proto->w, proto->h);
905 draw_tile(screen, TILE_UICO_Y, TILE_UICO_X + unit_icon(u), x, y);
907 if (u->baloon)
908 draw_tile(screen, TILE_BALOON_Y, TILE_BALOON_X + u->baloon, x - 7, y - 7);
914 int foglet(int x, int y) {
915 int mask[3][3] = { { 1 } };
916 if (y > 0) {
917 if (x > 0) mask[0][0] = fog[y - 1][x - 1];
918 mask[0][1] = fog[y - 1][x];
919 if (x < LEVEL_W) mask[0][2] = fog[y - 1][x + 1];
921 if (y < LEVEL_H) {
922 if (x > 0) mask[2][0] = fog[y + 1][x - 1];
923 mask[2][1] = fog[y + 1][x];
924 if (x < LEVEL_W) mask[2][2] = fog[y + 1][x + 1];
926 if (x > 0) {
927 mask[1][0] = fog[y][x - 1];
929 if (x < LEVEL_W) {
930 mask[1][2] = fog[y][x + 1];
932 if (fog[y][x] == 0) return 0;
934 if (!fog[y-1][x] && !fog[y+1][x-1] && !fog[y+1][x+1]) return 0;
935 if (!fog[y][x-1] && !fog[y-1][x+1] && !fog[y+1][x+1]) return 0;
936 if (!fog[y][x+1] && !fog[y-1][x-1] && !fog[y+1][x-1]) return 0;
937 if (!fog[y+1][x] && !fog[y-1][x-1] && !fog[y-1][x+1]) return 0;
938 if (!fog[y-1][x] && !fog[y][x-1] && !fog[y+1][x+1]) return 0;
939 if (!fog[y+1][x] && !fog[y][x+1] && !fog[y-1][x-1]) return 0;
940 if (!fog[y+1][x] && !fog[y][x-1] && !fog[y-1][x+1]) return 0;
941 if (!fog[y-1][x] && !fog[y][x+1] && !fog[y+1][x-1]) return 0;
943 if (!fog[y+1][x-1] && !fog[y-1][x+1] && !fog[y+1][x+1] && fog[y][x-1] && fog[y-1][x] ) return 11;
944 if (!fog[y+1][x-1] && !fog[y][x+1] && fog[y][x-1] && fog[y-1][x] ) return 11;
945 if (!fog[y-1][x+1] && !fog[y+1][x] && fog[y][x-1] && fog[y-1][x] ) return 11;
946 if (!fog[y+1][x] && !fog[y][x+1] && fog[y][x-1] && fog[y-1][x] ) return 11;
948 if (!fog[y-1][x-1] && !fog[y+1][x-1] && !fog[y-1][x+1] && fog[y-1][x] && fog[y+1][x] ) return 19;
949 if (!fog[y-1][x+1] && !fog[y][x-1] && fog[y][x+1] && fog[y+1][x] ) return 19;
950 if (!fog[y+1][x-1] && !fog[y-1][x] && fog[y][x+1] && fog[y+1][x] ) return 19;
951 if (!fog[y-1][x] && !fog[y][x-1] && fog[y][x+1] && fog[y+1][x] ) return 19;
953 if (!fog[y-1][x-1] && !fog[y+1][x+1] && fog[y-1][x+1] && !fog[y+1][x] && fog[y][x+1] && fog[y-1][x] ) return 13;
954 if (!fog[y-1][x-1] && !fog[y+1][x] && fog[y][x+1] && fog[y-1][x] ) return 13;
955 if (!fog[y+1][x+1] && !fog[y][x-1] && fog[y][x+1] && fog[y-1][x] ) return 13;
956 if (!fog[y][x-1] && !fog[y+1][x] && fog[y][x+1] && fog[y-1][x] ) return 13;
958 if (!fog[y-1][x-1] && !fog[y+1][x+1] && !fog[y-1][x+1] && fog[y][x-1] && fog[y+1][x] ) return 17;
959 if (!fog[y][x+1] && !fog[y-1][x] && fog[y][x-1] && fog[y+1][x] ) return 17;
960 if (!fog[y-1][x-1] && !fog[y][x+1] && fog[y][x-1] && fog[y+1][x] ) return 17;
961 if (!fog[y+1][x+1] && !fog[y-1][x] && fog[y][x-1] && fog[y+1][x] ) return 17;
963 if (fog[y][x-1] == 0 && fog[y][x+1] == 0) return 0;
964 if (fog[y-1][x] == 0 && fog[y+1][x] == 0) return 0;
966 if (fog[y-1][x] && fog[y+1][x]) {
967 if (!fog[y-1][x-1] && !fog[y+1][x+1] && fog[y-1][x+1]) return 14;
968 if (!fog[y+1][x-1] && !fog[y-1][x+1] && fog[y+1][x+1]) return 16;
971 if (fog[y - 1][x + 1] && fog[y][x - 1] && fog[y][x + 1] && !fog[y + 1][x - 1] && !fog[y + 1][x + 1]) return 2;
972 if (fog[y + 1][x + 1] && fog[y][x - 1] && fog[y][x + 1] && !fog[y - 1][x - 1] && !fog[y - 1][x + 1]) return 8;
973 if (fog[y - 1][x] && fog[y + 1][x] && !fog[y - 1][x + 1] && !fog[y + 1][x + 1]) return 4;
974 if (fog[y - 1][x] && fog[y + 1][x] && !fog[y - 1][x - 1] && !fog[y + 1][x - 1]) return 6;
976 if (fog[y][x + 1] && fog[y + 1][x] && !fog[y + 1][x + 1]) return 1;
977 if (fog[y][x - 1] && fog[y + 1][x] && !fog[y + 1][x - 1]) return 3;
978 if (fog[y][x + 1] && fog[y - 1][x] && !fog[y - 1][x + 1]) return 7;
979 if (fog[y][x - 1] && fog[y - 1][x] && !fog[y - 1][x - 1]) return 9;
981 if (!fog[y][x + 1]) return 4;
982 if (!fog[y][x - 1]) return 6;
983 if (!fog[y - 1][x]) return 8;
984 if (!fog[y + 1][x]) return 2;
986 return 5;
988 void draw_scent(SDL_Renderer *screen) {
990 int tx, ty;
991 for (ty = 0; ty < LEVEL_H; ty++) {
992 for (tx = 0; tx < LEVEL_W; tx++) {
994 Uint32 x = tx * TILE_W - ui.vx + game_map.x;
995 Uint32 y = ty * TILE_H - ui.vy + game_map.y;
996 int n;
997 SDL_Color color = { 0xff, 0xff, 0x00, 0x33 };
998 color.b = scent_human[ty][tx]/10;
1000 for (n = 0; n < scent_human[ty][tx]/16; n++)
1002 SDL_AlphaFill(screen, x + rand()%TILE_W/4, y + rand()%TILE_H/4, TILE_W, TILE_H, &color);
1007 void draw_fog(SDL_Renderer *screen) {
1009 int tx, ty;
1010 Uint8 fols_x[20] = {-1, 0, 1, 2, 0, 1, 2, 0, 1, 2, 1, 0, 1, 2, 0, 1, 2, 0, 1, 2 };
1011 Uint8 fols_y[20] = { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 1, 3, 3, 3, 4, 4, 4, 5, 5, 5 };
1013 for (ty = 0; ty < LEVEL_H; ty++) {
1014 for (tx = 0; tx < LEVEL_W; tx++) {
1016 Uint32 x = tx * TILE_W - ui.vx + game_map.x;
1017 Uint32 y = ty * TILE_H - ui.vy + game_map.y;
1019 Uint8 f = foglet(tx, ty);
1020 fog[ty][tx] = f;
1022 draw_tile(screen, TILE_FOG_Y + fols_y[f], TILE_FOG_X + fols_x[f], x, y);
1028 void draw_log(SDL_Renderer *renderer, log_t *log) {
1030 int i;
1032 Uint32 y = ui.log_height - 16;
1034 for (i = 0; i < 16; i++) {
1036 //incolor(log->color[i], 0);
1037 infont(mid_font);
1038 incolor(0xffffffff, 0);
1039 inprint(renderer, log->message[i], 0, y);
1041 y -= 16;
1044 infont(large_font);