1 /*****************************************************************************
2 * This file is part of gfxprim library. *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
19 * Copyright (C) 2009-2015 Cyril Hrubis <metan@ucw.cz> *
21 *****************************************************************************/
25 #include "bogoman_map.h"
26 #include "bogoman_debug.h"
28 #include "bogoman_render.h"
30 struct render_colors
{
31 /* global background */
37 /* frames around things */
54 GP_Pixel particle_dir
;
57 static struct render_colors colors
;
59 static void init_colors(GP_Pixmap
*pixmap
, struct render_colors
*colors
)
61 colors
->bg
= GP_RGBToPixmapPixel(0xee, 0xee, 0xee, pixmap
);
62 colors
->player
= GP_RGBToPixmapPixel(0x00, 0xee, 0x00, pixmap
);
63 colors
->frames
= GP_RGBToPixmapPixel(0x00, 0x00, 0x00, pixmap
);
64 colors
->diamond
= GP_RGBToPixmapPixel(0x00, 0x00, 0xee, pixmap
);
65 colors
->wall
= GP_RGBToPixmapPixel(0x66, 0x66, 0x66, pixmap
);
66 colors
->moveable
= GP_RGBToPixmapPixel(0xff, 0xff, 0x60, pixmap
);
67 colors
->edible
= GP_RGBToPixmapPixel(0xff, 0x7f, 0x50, pixmap
);
68 colors
->particle
= GP_RGBToPixmapPixel(0xff, 0xff, 0x00, pixmap
);
69 colors
->particle_dir
= GP_RGBToPixmapPixel(0xff, 0x44, 0x00, pixmap
);
72 static void render_none(struct bogoman_render
*render
,
73 unsigned int x
, unsigned int y
,
74 struct bogoman_map_elem
*elem
)
76 unsigned int w
= render
->map_elem_size
;
80 GP_FillRectXYWH(render
->pixmap
, x
, y
, w
, w
, colors
.bg
);
83 static void render_player(struct bogoman_render
*render
,
84 unsigned int x
, unsigned int y
,
85 struct bogoman_map_elem
*elem
)
87 unsigned int w
= render
->map_elem_size
;
91 GP_FillRectXYWH(render
->pixmap
, x
, y
, w
, w
, colors
.bg
);
93 GP_FillCircle(render
->pixmap
, x
+ w
/2, y
+ w
/2, w
/2 - 1, colors
.player
);
94 GP_FillRing(render
->pixmap
, x
+ w
/2, y
+ w
/2, w
/2 - 1, w
/2 - 2, colors
.frames
);
97 static void render_wall(struct bogoman_render
*render
,
98 unsigned int x
, unsigned int y
,
99 struct bogoman_map_elem
*elem
)
101 unsigned int w
= render
->map_elem_size
;
103 GP_FillRectXYWH(render
->pixmap
, x
, y
, w
, w
, colors
.wall
);
105 if (!(elem
->flags
& BOGOMAN_LEFT
)) {
106 GP_VLineXYH(render
->pixmap
, x
, y
, w
, colors
.frames
);
107 GP_VLineXYH(render
->pixmap
, x
+1, y
, w
, colors
.frames
);
110 if (!(elem
->flags
& BOGOMAN_RIGHT
)) {
111 GP_VLineXYH(render
->pixmap
, x
+ w
- 1, y
, w
, colors
.frames
);
112 GP_VLineXYH(render
->pixmap
, x
+ w
- 2, y
, w
, colors
.frames
);
115 if (!(elem
->flags
& BOGOMAN_UP
)) {
116 GP_HLineXYW(render
->pixmap
, x
, y
, w
, colors
.frames
);
117 GP_HLineXYW(render
->pixmap
, x
, y
+1, w
, colors
.frames
);
120 if (!(elem
->flags
& BOGOMAN_DOWN
)) {
121 GP_HLineXYW(render
->pixmap
, x
, y
+ w
- 1, w
, colors
.frames
);
122 GP_HLineXYW(render
->pixmap
, x
, y
+ w
- 2, w
, colors
.frames
);
126 static void render_diamond(struct bogoman_render
*render
,
127 unsigned int x
, unsigned int y
,
128 struct bogoman_map_elem
*elem
)
130 unsigned int w
= render
->map_elem_size
;
132 GP_FillRectXYWH(render
->pixmap
, x
, y
, w
, w
, colors
.bg
);
136 GP_FillTetragon(render
->pixmap
, x
+ w
/2, y
, x
+ w
- 1, y
+ w
/2,
137 x
+ w
/2, y
+ w
- 1, x
, y
+ w
/2, colors
.diamond
);
139 GP_Tetragon(render
->pixmap
, x
+ w
/2, y
, x
+ w
- 1, y
+ w
/2,
140 x
+ w
/2, y
+ w
- 1, x
, y
+ w
/2, colors
.frames
);
141 GP_Tetragon(render
->pixmap
, x
+ w
/2, y
+1, x
+ w
- 2, y
+ w
/2,
142 x
+ w
/2, y
+ w
- 2, x
+1, y
+ w
/2, colors
.frames
);
145 static void render_moveable(struct bogoman_render
*render
,
146 unsigned int x
, unsigned int y
,
147 struct bogoman_map_elem
*elem
)
149 unsigned int w
= render
->map_elem_size
;
153 GP_FillRectXYWH(render
->pixmap
, x
, y
, w
, w
, colors
.bg
);
155 GP_FillRectXYWH(render
->pixmap
, x
+ 1, y
+ 1, w
- 2, w
- 2, colors
.moveable
);
156 GP_RectXYWH(render
->pixmap
, x
+ 1, y
+ 1, w
- 2, w
- 2, colors
.frames
);
157 GP_RectXYWH(render
->pixmap
, x
+ 2, y
+ 2, w
- 4, w
- 4, colors
.frames
);
160 static void render_edible(struct bogoman_render
*render
,
161 unsigned int x
, unsigned int y
,
162 struct bogoman_map_elem
*elem
)
164 unsigned int w
= render
->map_elem_size
;
168 GP_FillRectXYWH(render
->pixmap
, x
, y
, w
, w
, colors
.bg
);
170 GP_FillRectXYWH(render
->pixmap
, x
+ 1, y
+ 1, w
- 2, w
- 2, colors
.edible
);
173 static void render_particle(struct bogoman_render
*render
,
174 unsigned int x
, unsigned int y
,
175 struct bogoman_map_elem
*elem
)
177 unsigned int w
= render
->map_elem_size
;
178 int dir
= elem
->flags
& BOGOMAN_DIRECTION_MASK
;
180 GP_FillRectXYWH(render
->pixmap
, x
, y
, w
, w
, colors
.bg
);
182 switch (elem
->flags
& ~BOGOMAN_DIRECTION_MASK
) {
183 case BOGOMAN_PARTICLE_ROUND
:
184 GP_FillCircle(render
->pixmap
, x
+ w
/2, y
+ w
/2, w
/2-1, colors
.particle
);
185 GP_FillRing(render
->pixmap
, x
+ w
/2, y
+ w
/2, w
/2 - 1, w
/2 - 2, colors
.frames
);
187 case BOGOMAN_PARTICLE_SQUARE
:
188 GP_FillRectXYWH(render
->pixmap
, x
+1, y
+1, w
-2, w
-2, colors
.particle
);
189 GP_RectXYWH(render
->pixmap
, x
+1, y
+1, w
-2, w
-2, colors
.frames
);
190 GP_RectXYWH(render
->pixmap
, x
+2, y
+2, w
-4, w
-4, colors
.frames
);
196 GP_FillTriangle(render
->pixmap
, x
+ w
/4, y
+ w
/2,
197 x
+ 5*w
/8, y
+ w
/4, x
+ 5*w
/8, y
+ 3*w
/4, colors
.particle_dir
);
198 GP_Triangle(render
->pixmap
, x
+ w
/4, y
+ w
/2,
199 x
+ 5*w
/8, y
+ w
/4, x
+ 5*w
/8, y
+ 3*w
/4, colors
.frames
);
202 GP_FillTriangle(render
->pixmap
, x
+ 3*w
/4, y
+ w
/2,
203 x
+ 3*w
/8, y
+ w
/4, x
+ 3*w
/8, y
+ 3*w
/4, colors
.particle_dir
);
204 GP_Triangle(render
->pixmap
, x
+ 3*w
/4, y
+ w
/2,
205 x
+ 3*w
/8, y
+ w
/4, x
+ 3*w
/8, y
+ 3*w
/4, colors
.frames
);
208 GP_FillTriangle(render
->pixmap
, x
+ w
/2, y
+ w
/4,
209 x
+ w
/4, y
+ 5*w
/8, x
+ 3*w
/4, y
+ 5*w
/8, colors
.particle_dir
);
210 GP_Triangle(render
->pixmap
, x
+ w
/2, y
+ w
/4,
211 x
+ w
/4, y
+ 5*w
/8, x
+ 3*w
/4, y
+ 5*w
/8, colors
.frames
);
214 GP_FillTriangle(render
->pixmap
, x
+ w
/2, y
+ 3*w
/4,
215 x
+ w
/4, y
+ 3*w
/8, x
+ 3*w
/4, y
+ 3*w
/8, colors
.particle_dir
);
216 GP_Triangle(render
->pixmap
, x
+ w
/2, y
+ 3*w
/4,
217 x
+ w
/4, y
+ 3*w
/8, x
+ 3*w
/4, y
+ 3*w
/8, colors
.frames
);
222 static void (*renders
[])(struct bogoman_render
*render
,
223 unsigned int x
, unsigned int y
,
224 struct bogoman_map_elem
*elem
) =
235 static void render_elem(struct bogoman_render
*render
,
236 unsigned int x
, unsigned int y
,
239 struct bogoman_map_elem
*elem
;
242 elem
= bogoman_get_map_elem(render
->map
, x
, y
);
247 if (flags
& BOGOMAN_RENDER_DIRTY
)
251 cx
= (x
- render
->map_x_offset
) * render
->map_elem_size
;
252 cy
= (y
- render
->map_y_offset
) * render
->map_elem_size
;
254 if (elem
->id
> BOGOMAN_MAX
)
255 WARN("Invalid elem ID %u at %ux%u\n", elem
->id
, x
, y
);
257 renders
[elem
->id
](render
, cx
, cy
, elem
);
259 if (flags
& BOGOMAN_RENDER_DIRTY
&& render
->backend
) {
260 GP_BackendUpdateRect(render
->backend
, cx
, cy
,
261 cx
+ render
->map_elem_size
,
262 cy
+ render
->map_elem_size
);
266 void bogoman_render(struct bogoman_render
*render
, int flags
)
271 init_colors(render
->pixmap
, &colors
);
273 if (flags
& BOGOMAN_RENDER_ALL
)
274 GP_Fill(render
->pixmap
, colors
.bg
);
276 for (y
= render
->map_x_offset
; y
< render
->map
->h
; y
++) {
277 for (x
= render
->map_x_offset
; x
< render
->map
->w
; x
++)
278 render_elem(render
, x
, y
, flags
);
281 if (flags
& BOGOMAN_RENDER_ALL
&& render
->backend
)
282 GP_BackendFlip(render
->backend
);