Win32 dialog box, icon and installer
[tennix.git] / graphics.c
blobe472c49bb819aa704fe1a6bd09dad4cffd0a0ced
2 /**
4 * Tennix! SDL Port
5 * Copyright (C) 2003, 2007 Thomas Perl <thp@perli.net>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 * MA 02110-1301, USA.
22 **/
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <math.h>
28 #include "tennix.h"
29 #include "graphics.h"
30 #include "input.h"
32 static Image* images;
34 static SDL_Surface *buffer;
36 static Uint32 fading_start = 0;
38 #include "data/graphics_data.c"
39 static const ResourceData graphics[] = {
40 RESOURCE(court),
41 RESOURCE(shadow),
42 RESOURCE(player_racket),
43 RESOURCE(ground),
44 RESOURCE(ball),
45 RESOURCE(menu),
46 RESOURCE(smallish_font),
47 RESOURCE(dkc2),
48 RESOURCE(referee),
49 RESOURCE(ctt_hard),
50 RESOURCE(ctt_clay),
51 RESOURCE(ctt_grass)
54 void init_graphics( const char *data_dir) {
55 int i;
56 SDL_Surface* data;
57 SDL_Surface* tmp;
59 #ifndef MACOSX
60 tmp = IMG_Load_RW( SDL_RWFromConstMem( icon, sizeof(icon)), 1);
61 if( tmp != NULL) {
62 SDL_WM_SetIcon( tmp, NULL);
63 SDL_FreeSurface( tmp);
65 #endif
67 images = (Image*)calloc( GR_COUNT, sizeof( Image));
69 for( i=0; i<GR_COUNT; i++) {
70 tmp = IMG_Load_RW( SDL_RWFromConstMem( graphics[i].data, graphics[i].size), 1);
71 if( !tmp) {
72 fprintf( stderr, "Error: %s\n", SDL_GetError());
73 continue;
76 if( GRAPHICS_IS_FONT(i)) {
77 /* Convert to RGB w/ colorkey=black for opacity support */
78 SDL_SetColorKey( tmp, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB( tmp->format, 0, 0, 0));
79 data = SDL_ConvertSurface( tmp, screen->format, SDL_SRCCOLORKEY | SDL_RLEACCEL);
80 } else {
81 /* Convert to RGBA for alpha channel from PNG */
82 data = SDL_DisplayFormatAlpha( tmp);
84 SDL_FreeSurface( tmp);
86 if( !data) {
87 fprintf( stderr, "Error: %s\n", SDL_GetError());
88 continue;
90 images[i].data = data;
93 buffer = SDL_CreateRGBSurface( SDL_HWSURFACE, WIDTH, HEIGHT, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
95 if( buffer == NULL) {
96 fprintf( stderr, "Cannot create buffer surface: %s\n", SDL_GetError());
100 void uninit_graphics() {
101 int i;
103 for( i=0; i<GR_COUNT; i++) {
104 SDL_FreeSurface( images[i].data);
107 if( buffer != NULL) {
108 SDL_FreeSurface( buffer);
111 free( images);
114 int get_image_width( unsigned int id) {
115 return images[id].data->w;
118 int get_image_height( unsigned int id) {
119 return images[id].data->h;
122 int get_sprite_width( unsigned int id, int items) {
123 return images[id].data->w / items;
126 void show_sprite( unsigned int id, int pos, int items, int x_offset, int y_offset, int opacity) {
127 SDL_Surface *bitmap;
128 SDL_Rect src, dst;
130 bitmap = images[id].data;
132 if( !bitmap) return;
134 SDL_SetAlpha( bitmap, SDL_SRCALPHA | SDL_RLEACCEL, opacity);
136 dst.w = src.w = bitmap->w/items;
137 dst.h = src.h = bitmap->h;
138 src.x = src.w*pos;
139 src.y = 0;
140 dst.x = x_offset;
141 dst.y = y_offset;
143 SDL_BlitSurface( bitmap, &src, screen, &dst);
146 void fill_image( unsigned int id, int x, int y, int w, int h) {
147 SDL_Surface *bitmap;
148 SDL_Rect src, dst;
149 int dx = 0, dy = 0, cx, cy;
151 if( id >= GR_COUNT) return;
153 bitmap = images[id].data;
154 src.x = src.y = 0;
156 while( dy < h) {
157 src.h = dst.h = cy = (h-dy > bitmap->h)?(bitmap->h):(h-dy);
158 dst.y = y+dy;
160 dx = 0;
161 while( dx < w) {
162 src.w = dst.w = cx = (w-dx > bitmap->w)?(bitmap->w):(w-dx);
163 dst.x = x+dx;
165 SDL_BlitSurface( bitmap, &src, screen, &dst);
167 dx += cx;
170 dy += cy;
174 void line_horiz( int y, Uint8 r, Uint8 g, Uint8 b) {
175 Uint32 color = SDL_MapRGB( screen->format, r, g, b);
176 SDL_Rect rect;
178 rect.x = 0;
179 rect.w = screen->w;
180 rect.y = y;
181 rect.h = 1;
183 SDL_FillRect( screen, &rect, color);
186 void line_vert( int x, Uint8 r, Uint8 g, Uint8 b) {
187 Uint32 color = SDL_MapRGB( screen->format, r, g, b);
188 SDL_Rect rect;
190 rect.x = x;
191 rect.w = 1;
192 rect.y = 0;
193 rect.h = screen->h;
195 SDL_FillRect( screen, &rect, color);
198 void rectangle( int x, int y, int w, int h, Uint8 r, Uint8 g, Uint8 b) {
199 Uint32 color = SDL_MapRGB( screen->format, r, g, b);
200 SDL_Rect rect;
202 rect.x = x;
203 rect.y = y;
204 rect.w = w;
205 rect.h = h;
207 SDL_FillRect( screen, &rect, color);
210 void draw_button( int x, int y, int w, int h, Uint8 r, Uint8 g, Uint8 b, char pressed) {
211 float diff = (pressed?1.0-BUTTON_HIGHLIGHT:1.0+BUTTON_HIGHLIGHT);
212 int border = BUTTON_BORDER;
213 rectangle( x, y, w, h, r*diff, g*diff, b*diff);
214 rectangle( x+border, y+border, w-border, h-border, r/diff, g/diff, b/diff);
215 rectangle( x+border, y+border, w-2*border, h-2*border, r, g, b);
218 void draw_button_text( char* s, int x, int y, int w, int h, Uint8 r, Uint8 g, Uint8 b, char pressed) {
219 int font_x, font_y;
220 pressed = pressed?1:0;
221 draw_button( x, y, w, h, r, g, b, pressed);
222 font_x = x + w/2 - font_get_string_width( GR_SMALLISH_FONT, s)/2 + pressed*BUTTON_BORDER;
223 font_y = y + h/2 - get_image_height( GR_SMALLISH_FONT)/2 + pressed*BUTTON_BORDER;
224 font_draw_string( GR_SMALLISH_FONT, s, font_x, font_y, 0, 0);
227 void show_image( unsigned int id, int x_offset, int y_offset, int opacity) {
228 show_sprite( id, 0, 1, x_offset, y_offset, opacity);
231 void clearscr() {
232 SDL_Rect rect;
234 rect.x = 0;
235 rect.y = 0;
236 rect.w = WIDTH;
237 rect.h = HEIGHT;
239 SDL_FillRect( screen, &rect, SDL_MapRGB( screen->format, 0, 0, 0));
242 void updatescr() {
243 int ticks = SDL_GetTicks();
245 if( ticks < fading_start+FADE_DURATION) {
246 SDL_SetAlpha( buffer, SDL_SRCALPHA | SDL_RLEACCEL, 255-255*(ticks-fading_start)/FADE_DURATION);
247 SDL_BlitSurface( buffer, NULL, screen, NULL);
250 SDL_UpdateRect( screen, 0, 0, 0, 0);
251 SDL_Flip( screen);
254 void start_fade() {
255 SDL_BlitSurface( screen, NULL, buffer, NULL);
256 fading_start = SDL_GetTicks();
259 int is_fading() {
260 return SDL_GetTicks() < fading_start+FADE_DURATION;
263 int font_get_metrics( unsigned int id, char ch, int* xp, int* wp) {
264 SDL_Surface *bitmap;
265 int pos, x = -1, w = 0;
266 int search_pos = 0, search_x = 0;
267 Uint8 red, green, blue;
269 if( id >= GR_COUNT) return 0;
271 pos = toupper( ch) - ' '; /* ' ' = first character in font bitmap */
273 bitmap = images[id].data;
275 SDL_LockSurface( bitmap);
276 while( search_x < bitmap->w) {
277 GET_PIXEL_RGB( bitmap, search_x, 0, &red, &green, &blue);
279 /* Increase pos counter if we have a "marker" pixel (255,0,255) */
280 if( red > 250 && green < 10 && blue > 250) {
281 search_pos++;
282 if( search_pos == pos) {
283 x = search_x;
284 } else if( search_pos == pos + 1) {
285 w = search_x - x;
286 break;
290 search_x++;
292 SDL_UnlockSurface( bitmap);
294 if( wp != NULL) (*wp) = w;
295 if( xp != NULL) (*xp) = x;
297 return w;
300 int font_draw_char( unsigned int id, char ch, int x_offset, int y_offset) {
301 SDL_Surface *bitmap;
302 SDL_Rect src, dst;
303 int x = -1, w = 0;
305 font_get_metrics( id, ch, &x, &w);
306 if( x == -1) return w;
308 bitmap = images[id].data;
310 dst.w = src.w = w;
311 dst.h = src.h = bitmap->h - 1;
312 src.x = x;
313 src.y = 1;
314 dst.x = x_offset;
315 dst.y = y_offset;
317 SDL_BlitSurface( bitmap, &src, screen, &dst);
319 return src.w;
322 void font_draw_string_alpha( unsigned int id, const char* s, int x_offset, int y_offset, int start, int animation, int opacity) {
323 int y = y_offset;
324 int x = x_offset;
325 int i;
326 float xw = 0.0, xw_diff;
327 SDL_Surface *bitmap;
329 if( id > GR_COUNT) return;
331 bitmap = images[id].data;
332 SDL_SetAlpha( bitmap, SDL_SRCALPHA | SDL_RLEACCEL, opacity);
334 if( animation & ANIMATION_BUNGEE) {
335 xw = (25.0*sinf( start/10.0));
336 xw_diff = 0.0;
337 x -= xw / 2;
340 if( animation & ANIMATION_PENDULUM) {
341 x -= (int)(20.0*sinf( start/20.0));
344 for( i=0; i<strlen(s); i++) {
345 if( animation & ANIMATION_WAVE) {
346 y = y_offset + (int)(3.0*sinf( start/10.0 + x/30.0));
348 x += font_draw_char( id, s[i], x, y);
349 if( animation & ANIMATION_BUNGEE) {
350 xw_diff += xw/strlen(s);
351 if( xw_diff > 1.0 || xw_diff < -1.0) {
352 x += (int)(xw_diff);
353 if( xw_diff > 1.0) {
354 xw_diff -= 1.0;
355 } else {
356 xw_diff += 1.0;
363 int font_get_string_width( unsigned int id, const char* s) {
364 int w = 0, i;
366 for( i=0; i<strlen(s); i++) {
367 w += font_get_metrics( id, s[i], NULL, NULL);
370 return w;
373 void draw_line_faded( int x1, int y1, int x2, int y2, int r, int g, int b, int r2, int g2, int b2) {
374 float step, dx, dy, x = x1, y = y1;
375 int i;
376 char fade = (r!=r2 || g!=g2 || b!=b2);
378 step = (float)(abs(x2-x1)>abs(y2-y1)?abs(x2-x1):abs(y2-y1));
379 dx = (float)(x2-x1) / step;
380 dy = (float)(y2-y1) / step;
382 SDL_LockSurface( screen);
383 for( i=0; i<step; i++) {
384 x += dx;
385 y += dy;
386 if( x < 0.0 || x >= WIDTH || y < 0.0 || y >= HEIGHT) {
387 continue;
389 if( fade) {
390 SET_PIXEL_RGB( screen, (int)x, (int)y, (r*(step-i)+r2*i)/step, (g*(step-i)+g2*i)/step, (b*(step-i)+b2*i)/step);
391 } else {
392 SET_PIXEL_RGB( screen, (int)x, (int)y, r, g, b);
395 SDL_UnlockSurface( screen);