original 1.0.1 release
[xwelltris.git] / src / sdl / sdlwelldrawing.cxx
blobe6326821cccd42e1312373f00ce416511022e6b6
1 // docm_prefix(///)
2 /****************************************************************************
3 * Copyright (C) 2002 by Leo Khramov
4 * email: leo@xnc.dubna.su
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 ****************************************************************************/
16 // $Id: sdlwelldrawing.cxx,v 1.4 2003/02/21 11:40:33 leo Exp $
18 /// module description
19 /// SDL implementation of WellDrawing class - drawing routines for the game.
20 /// Draw field on pixmap, then maps it to the screen. Uses dirty rectangles
21 /// algorithm for mapping areas to screen from pixmap
23 #include "sdlwelldrawing.h"
24 #include "sdlwellengine.h"
25 #include "sdl_gfxprimitives.h"
27 //===========================================================================
28 /// global SDLWellDrawingEngine()
29 /// constructor of the class - init's variables.
30 /// tags SDLWellDrawingEngine
31 SDLWellDrawingEngine::SDLWellDrawingEngine(SDLWellEngine* myengine)
33 engine=myengine;
34 if(engine==0)
35 engine=static_cast<SDLWellEngine*>(default_well_engine);
36 mainw=engine->get_main_window();
37 colors=engine->get_colors();
38 RGBA=engine->get_RGBA();
41 //===========================================================================
42 /// global init(int n_fields, int idx, int idy, unsigned il, unsigned ih)
43 /// init fields - creates x pixmaps and gcs
44 /// tags SDLWellDrawingEngine
45 void SDLWellDrawingEngine::init(int inum_fields, int idx, int idy,
46 unsigned int il, unsigned int ih)
49 int i;
50 SDL_Surface *surface;
52 WellDrawingEngine::init(inum_fields,idx,idy,il,ih);
53 fields=new SDL_Surface*;
55 fg_color=colors[GridColor];
57 for(i=0;i<1;i++)
59 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
60 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, l, h, 32,
61 0xff000000,
62 0x00ff0000,
63 0x0000ff00,
64 0x000000ff);
65 #else
66 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, l, h, 32,
67 0x000000ff,
68 0x0000ff00,
69 0x00ff0000,
70 0xff000000);
71 #endif
73 fields[i]=SDL_DisplayFormat(surface);
74 SDL_FreeSurface(surface);
75 if(fields[i]>0)
76 clear_field(i);
78 bg_color=colors[BackColor];
79 fg_color=colors[GridColor];
82 //===========================================================================
83 /// global draw_square(int color_idx, int i, int j)
84 /// Draw square (floor polygon) on all fields with given color
85 /// tags SDLWellDrawingEngine
86 void SDLWellDrawingEngine::draw_square(int color, int i, int j)
88 int idx=current_id,sign_x13,sign_y13,sign_x24,sign_y24;
90 Uint8 *rcolor=&RGBA[color*4];
92 sign_x13= points[idx].base_points[i+1][j+1].x -
93 points[idx].base_points[i][j].x;
94 sign_x13= sign_x13 ? (sign_x13>0 ? 1 : -1) : 0;
96 sign_y13= points[idx].base_points[i+1][j+1].y -
97 points[idx].base_points[i][j].y;
98 sign_y13= sign_y13 ? (sign_y13>0 ? 1 : -1) : 0;
100 sign_x24= points[idx].base_points[i][j+1].x -
101 points[idx].base_points[i+1][j].x;
102 sign_x24= sign_x24 ? (sign_x24>0 ? 1 : -1) : 0;
104 sign_y24= points[idx].base_points[i][j+1].y -
105 points[idx].base_points[i+1][j].y;
106 sign_y24= sign_y24 ? (sign_y24>0 ? 1 : -1) : 0;
108 trap_x[0] = points[idx].base_points[i][j].x+sign_x13;
109 trap_y[0] = points[idx].base_points[i][j].y+sign_y13;
110 trap_x[1] = points[idx].base_points[i+1][j].x+sign_x24;
111 trap_y[1] = points[idx].base_points[i+1][j].y+sign_y24;
112 trap_x[2] = points[idx].base_points[i+1][j+1].x-sign_x13;
113 trap_y[2] = points[idx].base_points[i+1][j+1].y-sign_y13;
114 trap_x[3] = points[idx].base_points[i][j+1].x-sign_x24;
115 trap_y[3] = points[idx].base_points[i][j+1].y-sign_y24;
117 filledPolygonRGBA(*fields, trap_x, trap_y, MAX_SIDES,
118 rcolor[0],
119 rcolor[1],
120 rcolor[2],
121 rcolor[3]
124 //Now draw the grid
125 trap_x[0] = points[idx].base_points[i][j].x;
126 trap_y[0] = points[idx].base_points[i][j].y;
127 trap_x[1] = points[idx].base_points[i+1][j].x;
128 trap_y[1] = points[idx].base_points[i+1][j].y;
129 trap_x[2] = points[idx].base_points[i+1][j+1].x;
130 trap_y[2] = points[idx].base_points[i+1][j+1].y;
131 trap_x[3] = points[idx].base_points[i][j+1].x;
132 trap_y[3] = points[idx].base_points[i][j+1].y;
134 polygonRGBA(*fields, trap_x, trap_y, MAX_SIDES,
135 RGBA[GridColor2*4],
136 RGBA[GridColor2*4+1],
137 RGBA[GridColor2*4+2],
138 RGBA[GridColor2*4+3]
141 new_dirty_rec(delta_x,delta_y);
142 dirty_add_xy(trap_x[0],trap_y[0]);
143 dirty_add_xy(trap_x[1],trap_y[1]);
144 dirty_add_xy(trap_x[2],trap_y[2]);
145 dirty_add_xy(trap_x[3],trap_y[3]);
146 finish_dirty_rec();
149 //===========================================================================
150 /// global draw_trapazoid(int color_idx, int i,int j)
151 /// draw trapazoid - wall polygon with given color
152 /// tags SDLWellDrawingEngine
153 void SDLWellDrawingEngine::draw_trapazoid(int color, int i, int j)
155 SDL_Surface *win=*fields;
156 int idx=current_id,sign_x13,sign_y13,sign_x24,sign_y24;
158 Uint8 *rcolor=&RGBA[color*4];
161 sign_x13= points[idx].wall_points[i+1][j+1].x -
162 points[idx].wall_points[i][j].x;
163 sign_x13= sign_x13 ? (sign_x13>0 ? 1 : -1) : 0;
165 sign_y13= points[idx].wall_points[i+1][j+1].y -
166 points[idx].wall_points[i][j].y;
167 sign_y13= sign_y13 ? (sign_y13>0 ? 1 : -1) : 0;
169 sign_x24= points[idx].wall_points[i][j+1].x -
170 points[idx].wall_points[i+1][j].x;
171 sign_x24= sign_x24 ? (sign_x24>0 ? 1 : -1) : 0;
173 sign_y24= points[idx].wall_points[i][j+1].y -
174 points[idx].wall_points[i+1][j].y;
175 sign_y24= sign_y24 ? (sign_y24>0 ? 1 : -1) : 0;
178 w=i/MASDL_WIDTH;
179 dbgprintf(("trapazoid [%2d][%2d] = [%d - %d],[%d - %d]\n",i,j,
180 points[idx].wall_points[i+1][j+1].x,
181 points[idx].wall_points[i][j].x,
182 points[idx].wall_points[i+1][j+1].y,
183 points[idx].wall_points[i][j].y));
185 dbgprintf(("trapazoid2[%2d][%2d] = [%d - %d],[%d - %d]\n",i,j,
186 points[idx].wall_points[i][j+1].x,
187 points[idx].wall_points[i+1][j].x,
188 points[idx].wall_points[i][j+1].y,
189 points[idx].wall_points[i+1][j].y));
190 dbgprintf(("trapazoid [%2d][%2d] = [%d][%d],[%d][%d]\n",i,j,
191 sign_x13,sign_y13,sign_x24,sign_y24));
195 trap_x[0] = points[idx].wall_points[i][j].x+sign_x13;
196 trap_y[0] = points[idx].wall_points[i][j].y+sign_y13;
197 trap_x[1] = points[idx].wall_points[i+1][j].x+sign_x24;
198 trap_y[1] = points[idx].wall_points[i+1][j].y+sign_y24;
199 trap_x[2] = points[idx].wall_points[i+1][j+1].x-sign_x13;
200 trap_y[2] = points[idx].wall_points[i+1][j+1].y-sign_y13;
201 trap_x[3] = points[idx].wall_points[i][j+1].x-sign_x24;
202 trap_y[3] = points[idx].wall_points[i][j+1].y-sign_y24;
203 filledPolygonRGBA(win, trap_x, trap_y, MAX_SIDES,
204 rcolor[0],
205 rcolor[1],
206 rcolor[2],
207 rcolor[3]
209 //Now draw the grid
210 trap_x[0] = points[idx].wall_points[i][j].x;
211 trap_y[0] = points[idx].wall_points[i][j].y;
212 trap_x[1] = points[idx].wall_points[i+1][j].x;
213 trap_y[1] = points[idx].wall_points[i+1][j].y;
214 trap_x[2] = points[idx].wall_points[i+1][j+1].x;
215 trap_y[2] = points[idx].wall_points[i+1][j+1].y;
216 trap_x[3] = points[idx].wall_points[i][j+1].x;
217 trap_y[3] = points[idx].wall_points[i][j+1].y;
218 polygonRGBA(win, trap_x, trap_y, MAX_SIDES,
219 RGBA[GridColor*4],
220 RGBA[GridColor*4+1],
221 RGBA[GridColor*4+2],
222 RGBA[GridColor*4+3]
225 if(idx==current_id)
227 new_dirty_rec(delta_x,delta_y);
228 dirty_add_xy(trap_x[0],trap_y[0]);
229 dirty_add_xy(trap_x[1],trap_y[1]);
230 dirty_add_xy(trap_x[2],trap_y[2]);
231 dirty_add_xy(trap_x[3],trap_y[3]);
232 finish_dirty_rec();
236 //===========================================================================
237 /// global draw_grid()
238 /// draw grid - all wall and floor polygons
239 /// tags SDLWellDrawingEngine
240 void SDLWellDrawingEngine::draw_grid()
242 int idx,i,j;
243 SDL_Surface* win;
244 idx=current_id;
246 win=*fields;
248 for(i=0;i<MAX_PERIMETER;i++)
249 for(j=0;j<MAX_DEPTH;j++)
251 lineRGBA(win,points[idx].wall_points[i][j].x,
252 points[idx].wall_points[i][j].y,
253 points[idx].wall_points[i][j+1].x,
254 points[idx].wall_points[i][j+1].y,
255 RGBA[GridColor*4],
256 RGBA[GridColor*4+1],
257 RGBA[GridColor*4+2],
258 RGBA[GridColor*4+3]
260 lineRGBA(win,points[idx].wall_points[i][j].x,
261 points[idx].wall_points[i][j].y,
262 points[idx].wall_points[i+1][j].x,
263 points[idx].wall_points[i+1][j].y,
264 RGBA[GridColor*4],
265 RGBA[GridColor*4+1],
266 RGBA[GridColor*4+2],
267 RGBA[GridColor*4+3]
270 for(i=0;i<MAX_WIDTH+1;i++)
271 for(j=0;j<MAX_WIDTH+1;j++)
273 if(j==0 || j==MAX_WIDTH)
274 fg_color=GridColor2*4;
275 else
276 fg_color=GridColor*4;
278 if(i<MAX_WIDTH)
279 lineRGBA(win,points[idx].base_points[i][j].x,
280 points[idx].base_points[i][j].y,
281 points[idx].base_points[i+1][j].x,
282 points[idx].base_points[i+1][j].y,
283 RGBA[fg_color],
284 RGBA[fg_color+1],
285 RGBA[fg_color+2],
286 RGBA[fg_color+3]
289 if(i==0 || i==MAX_WIDTH)
290 fg_color=GridColor2*4;
291 else
292 fg_color=GridColor*4;
294 if(j<MAX_WIDTH)
295 lineRGBA(win,points[idx].base_points[i][j].x,
296 points[idx].base_points[i][j].y,
297 points[idx].base_points[i][j+1].x,
298 points[idx].base_points[i][j+1].y,
299 RGBA[fg_color],
300 RGBA[fg_color+1],
301 RGBA[fg_color+2],
302 RGBA[fg_color+3]
305 flush_field(*fields, 0, 0, l, h);
308 //===========================================================================
309 /// global clear_field(int i)
310 /// clear field with given index with BackColor (black)
311 /// tags SDLWellDrawingEngine
312 void SDLWellDrawingEngine::clear_field(int)
314 boxRGBA(*fields, 0, 0, l, h,
315 RGBA[BackColor*4],
316 RGBA[BackColor*4+1],
317 RGBA[BackColor*4+2],
318 RGBA[BackColor*4+3]
320 flush_field(*fields, 0, 0, l, h);
323 //===========================================================================
324 /// global flush_all()
325 /// copy all the field with current_id to the screen
326 /// tags SDLWellDrawingEngine
327 void SDLWellDrawingEngine::flush_all()
329 SDL_Rect src,dest;
330 src.x = 0;
331 src.y = 0;
332 src.w = l;
333 src.h = h;
334 dest.x = delta_x;
335 dest.y = delta_y;
336 dest.w = l;
337 dest.h = h;
338 SDL_BlitSurface(*fields, &src, mainw, &dest);
339 /* Update the changed portion of the screen */
340 SDL_UpdateRects(mainw, 1, &dest);
343 //===========================================================================
344 /// global flush_field()
345 /// copy all the field with current_id to the screen
346 /// tags SDLWellDrawingEngine
347 void SDLWellDrawingEngine::flush_field(SDL_Surface* win,
348 int ix, int iy,
349 int il, int ih)
351 SDL_Rect dest;
352 dest.x = ix;
353 dest.y = iy;
354 dest.w = il;
355 dest.h = ih;
356 /* Update the changed portion of the screen */
357 SDL_UpdateRects(win, 1, &dest);
360 //===========================================================================
361 /// global flush_field()
362 /// copy all the field with current_id to the screen
363 /// tags SDLWellDrawingEngine
364 void SDLWellDrawingEngine::field_sync()
366 flush_field(*fields, 0, 0, l, h);
368 //===========================================================================
369 /// global sync()
370 /// flush event in SDL queue
371 /// tags SDLWellDrawingEngine
372 void SDLWellDrawingEngine::sync()
374 //Nothing to do
375 // flush_field(*fields, 0, 0, l, h);
378 //===========================================================================
379 /// global flush_dirty()
380 /// copy list of dirty rectangle areas to the screen
381 /// tags SDLWellDrawingEngine
382 void SDLWellDrawingEngine::flush_dirty()
384 SDL_Rect *from, *to;
385 int idx=0;
387 if(!get_max_dirties())
388 return;
390 from=new SDL_Rect[get_max_dirties()];
391 to =new SDL_Rect[get_max_dirties()];
393 DirtyList *plist;
397 plist=dirty_list.get_next();
398 if(plist)
400 DirtyRect& drec=plist->get_object();
401 //Here we need to draw dirty rec on the screen -> will be in overloaded childs
402 from[idx].x=drec.get_src_x();
403 from[idx].y=drec.get_src_y();
404 from[idx].w=to[idx].w=drec.l;
405 from[idx].h=to[idx].h=drec.h;
406 to[idx].x=drec.get_dest_x();
407 to[idx].y=drec.get_dest_y();
409 SDL_BlitSurface(*fields, &from[idx], mainw, &to[idx]);
410 plist->del_self();
411 delete plist;
412 idx++;
414 } while(plist);
416 SDL_UpdateRects(mainw, idx, to);
418 delete from;
419 delete to;
422 //===========================================================================
423 /// global key_to_action(void* event)
424 /// convert keys to actions in the game
425 /// tags SDLWellDrawingEngine
426 Actions SDLWellDrawingEngine::key_to_action(void* event)
428 SDL_Event *ev=(SDL_Event*)event;
429 switch(ev->key.keysym.sym)
431 case SDLK_KP4:
432 case SDLK_LEFT:
433 case SDLK_j:
434 return RIGHT;
436 case SDLK_KP6:
437 case SDLK_RIGHT:
438 case SDLK_l:
439 return LEFT;
441 case SDLK_UP:
442 case SDLK_DOWN:
443 case SDLK_KP5:
444 case SDLK_k:
445 return ROTATE;
447 case SDLK_SPACE:
448 case SDLK_KP0:
449 return DROP;
451 case SDLK_BREAK:
452 case SDLK_PAUSE:
453 case SDLK_p:
454 return PAUSE_GAME;
456 case SDLK_F10:
457 case SDLK_q:
458 case SDLK_ESCAPE:
459 return END_GAME;
461 case SDLK_KP_MULTIPLY:
462 return OUTER_ROTATION;
464 case SDLK_KP_PLUS:
465 return LEVEL_UP;
467 case SDLK_KP_MINUS:
468 return LEVEL_DOWN;
471 return NOTHING;
475 //===========================================================================
476 /// global draw_line(...)
477 /// draw line with given coords and color
478 /// tags SDLWellDrawingEngine
479 void SDLWellDrawingEngine::draw_line(int x1, int y1, int x2, int y2, int color_idx,
480 Canvas where)
482 Uint8 *color=&RGBA[color_idx*4];
483 switch(where)
485 case screen:
486 lineRGBA(mainw,x1,y1,x2,y2,
487 color[0],
488 color[1],
489 color[2],
490 color[3]
492 break;
493 case pixmap:
494 lineRGBA(*fields,x1,y1,x2,y2,
495 color[0],
496 color[1],
497 color[2],
498 color[3]
500 break;
504 //===========================================================================
505 /// global draw_rect(...)
506 /// draw rectangle with given coords and color
507 /// tags SDLWellDrawingEngine
508 void SDLWellDrawingEngine::draw_rect(int x1, int y1,
509 unsigned int il,
510 unsigned int ih, int color_idx,
511 Canvas where)
513 Uint8 *color=&RGBA[color_idx*4];
514 switch(where)
516 case screen:
517 rectangleRGBA(mainw,x1,y1,x1+il-1,y1+ih-1,
518 color[0],
519 color[1],
520 color[2],
521 color[3]
523 flush_field(mainw, x1,y1, il, ih);
524 break;
525 case pixmap:
526 rectangleRGBA(*fields,x1,y1,x1+il-1,y1+ih-1,
527 color[0],
528 color[1],
529 color[2],
530 color[3]
532 flush_field(*fields, x1,y1, il, ih);
533 break;
537 //===========================================================================
538 /// global fill_rect(...)
539 /// fill rectangle with given coords and color
540 /// tags SDLWellDrawingEngine
541 void SDLWellDrawingEngine::fill_rect(int x1, int y1,
542 unsigned int il,
543 unsigned int ih, int color_idx,
544 Canvas where)
546 Uint8 *color=&RGBA[color_idx*4];
547 switch(where)
549 case screen:
550 boxRGBA(mainw,x1,y1,x1+il-1,y1+ih-1,
551 color[0],
552 color[1],
553 color[2],
554 color[3]
556 flush_field(mainw, x1,y1, il, ih);
557 break;
558 case pixmap:
559 boxRGBA(*fields,x1,y1,x1+il-1,y1+ih-1,
560 color[0],
561 color[1],
562 color[2],
563 color[3]
565 flush_field(*fields, x1,y1, il, ih);
566 break;
570 //===========================================================================
571 /// global pixmap_copy(Geo*)
572 /// copy part of image to the screen
573 /// tags SDLWellDrawingEngine
574 void SDLWellDrawingEngine::pixmap_copy(Geo *pgeo)
576 SDL_Rect src,dest;
577 if(pgeo->im==imNone)
578 return;
580 src.x=pgeo->fromx;
581 src.y=pgeo->fromy;
582 src.w=dest.w=pgeo->l;
583 src.h=dest.h=pgeo->h;
584 dest.x=pgeo->tox;
585 dest.y=pgeo->toy;
587 SDL_BlitSurface(engine->get_pixmap_of_image(pgeo->im),
588 &src, *fields, &dest);
589 SDL_UpdateRects(*fields, 1, &dest);