Resources in binary support, button drawing functions
[tennix.git] / graphics.c
blobbc3a81d7264c611facd307f65bb2e8845ac23557
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)
50 void init_graphics( const char *data_dir) {
51 int i;
52 SDL_Surface* data;
53 SDL_Surface* tmp;
55 #ifndef MACOSX
56 tmp = IMG_Load_RW( SDL_RWFromConstMem( icon, sizeof(icon)), 1);
57 if( tmp != NULL) {
58 SDL_WM_SetIcon( tmp, NULL);
59 SDL_FreeSurface( tmp);
61 #endif
63 images = (Image*)calloc( GR_COUNT, sizeof( Image));
65 for( i=0; i<GR_COUNT; i++) {
66 tmp = IMG_Load_RW( SDL_RWFromConstMem( graphics[i].data, graphics[i].size), 1);
67 if( !tmp) {
68 fprintf( stderr, "Error: %s\n", SDL_GetError());
69 continue;
72 SDL_SetColorKey( tmp, SDL_SRCCOLORKEY, SDL_MapRGB( tmp->format, 0, 0, 0));
73 data = SDL_DisplayFormatAlpha( tmp);
74 SDL_FreeSurface( tmp);
76 if( !data) {
77 fprintf( stderr, "Error: %s\n", SDL_GetError());
78 continue;
80 images[i].data = data;
83 buffer = SDL_CreateRGBSurface( SDL_HWSURFACE, WIDTH, HEIGHT, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
85 if( buffer == NULL) {
86 fprintf( stderr, "Cannot create buffer surface: %s\n", SDL_GetError());
90 void uninit_graphics() {
91 int i;
93 for( i=0; i<GR_COUNT; i++) {
94 SDL_FreeSurface( images[i].data);
97 if( buffer != NULL) {
98 SDL_FreeSurface( buffer);
101 free( images);
104 int get_image_width( unsigned int id) {
105 return images[id].data->w;
108 int get_image_height( unsigned int id) {
109 return images[id].data->h;
112 int get_sprite_width( unsigned int id, int items) {
113 return images[id].data->w / items;
116 void show_sprite( unsigned int id, int pos, int items, int x_offset, int y_offset, int opacity) {
117 SDL_Surface *bitmap;
118 SDL_Rect src, dst;
120 bitmap = images[id].data;
122 if( !bitmap) return;
124 SDL_SetAlpha( bitmap, SDL_SRCALPHA | SDL_RLEACCEL, opacity);
126 dst.w = src.w = bitmap->w/items;
127 dst.h = src.h = bitmap->h;
128 src.x = src.w*pos;
129 src.y = 0;
130 dst.x = x_offset;
131 dst.y = y_offset;
133 SDL_BlitSurface( bitmap, &src, screen, &dst);
136 void line_horiz( int y, Uint8 r, Uint8 g, Uint8 b) {
137 Uint32 color = SDL_MapRGB( screen->format, r, g, b);
138 SDL_Rect rect;
140 rect.x = 0;
141 rect.w = screen->w;
142 rect.y = y;
143 rect.h = 1;
145 SDL_FillRect( screen, &rect, color);
148 void line_vert( int x, Uint8 r, Uint8 g, Uint8 b) {
149 Uint32 color = SDL_MapRGB( screen->format, r, g, b);
150 SDL_Rect rect;
152 rect.x = x;
153 rect.w = 1;
154 rect.y = 0;
155 rect.h = screen->h;
157 SDL_FillRect( screen, &rect, color);
160 void rectangle( int x, int y, int w, int h, Uint8 r, Uint8 g, Uint8 b) {
161 Uint32 color = SDL_MapRGB( screen->format, r, g, b);
162 SDL_Rect rect;
164 rect.x = x;
165 rect.y = y;
166 rect.w = w;
167 rect.h = h;
169 SDL_FillRect( screen, &rect, color);
172 void draw_button( int x, int y, int w, int h, Uint8 r, Uint8 g, Uint8 b, char pressed) {
173 float diff = (pressed?1.0-BUTTON_HIGHLIGHT:1.0+BUTTON_HIGHLIGHT);
174 int border = BUTTON_BORDER;
175 rectangle( x, y, w, h, r*diff, g*diff, b*diff);
176 rectangle( x+border, y+border, w-border, h-border, r/diff, g/diff, b/diff);
177 rectangle( x+border, y+border, w-2*border, h-2*border, r, g, b);
180 void draw_button_text( char* s, int x, int y, int w, int h, Uint8 r, Uint8 g, Uint8 b, char pressed) {
181 int font_x, font_y;
182 pressed = pressed?1:0;
183 draw_button( x, y, w, h, r, g, b, pressed);
184 font_x = x + w/2 - font_get_string_width( GR_SMALLISH_FONT, s)/2 + pressed*BUTTON_BORDER;
185 font_y = y + h/2 - get_image_height( GR_SMALLISH_FONT)/2 + pressed*BUTTON_BORDER;
186 font_draw_string( GR_SMALLISH_FONT, s, font_x, font_y, 0, 0);
189 void show_image( unsigned int id, int x_offset, int y_offset, int opacity) {
190 show_sprite( id, 0, 1, x_offset, y_offset, opacity);
193 void introimage( unsigned int id) {
194 int i;
196 for( i=0; i<256; i+=10) {
197 clearscr();
198 show_image( id, 0, 0, i);
199 updatescr();
200 SDL_Delay( 30);
203 //SDL_Delay( 500);
204 wait_keypress();
206 for( i=255; i>=0; i-=10) {
207 clearscr();
208 show_image( id, 0, 0, i);
209 updatescr();
210 SDL_Delay( 30);
213 clearscr();
216 void clearscr() {
217 SDL_Rect rect;
219 rect.x = 0;
220 rect.y = 0;
221 rect.w = WIDTH;
222 rect.h = HEIGHT;
224 SDL_FillRect( screen, &rect, SDL_MapRGB( screen->format, 0, 0, 0));
227 void updatescr() {
228 int ticks = SDL_GetTicks();
230 if( ticks < fading_start+FADE_DURATION) {
231 SDL_SetAlpha( buffer, SDL_SRCALPHA | SDL_RLEACCEL, 255-255*(ticks-fading_start)/FADE_DURATION);
232 SDL_BlitSurface( buffer, NULL, screen, NULL);
235 SDL_UpdateRect( screen, 0, 0, 0, 0);
236 SDL_Flip( screen);
239 void start_fade() {
240 SDL_BlitSurface( screen, NULL, buffer, NULL);
241 fading_start = SDL_GetTicks();
244 int is_fading() {
245 return SDL_GetTicks() < fading_start+FADE_DURATION;
248 int font_get_metrics( unsigned int id, char ch, int* xp, int* wp) {
249 SDL_Surface *bitmap;
250 int pos, x = -1, w = 0;
251 int search_pos = 0, search_x = 0;
252 Uint8 red, green, blue;
254 if( id > GR_COUNT) return 0;
256 pos = toupper( ch) - ' '; /* ' ' = first character in font bitmap */
258 bitmap = images[id].data;
260 SDL_LockSurface( bitmap);
261 while( search_x < bitmap->w) {
262 GET_PIXEL_RGB( bitmap, search_x, 0, &red, &green, &blue);
264 /* Increase pos counter if we have a "marker" pixel (255,0,255) */
265 if( red > 250 && green < 10 && blue > 250) {
266 search_pos++;
267 if( search_pos == pos) {
268 x = search_x;
269 } else if( search_pos == pos + 1) {
270 w = search_x - x;
271 break;
275 search_x++;
277 SDL_UnlockSurface( bitmap);
279 if( wp != NULL) (*wp) = w;
280 if( xp != NULL) (*xp) = x;
282 return w;
285 int font_draw_char( unsigned int id, char ch, int x_offset, int y_offset) {
286 SDL_Surface *bitmap;
287 SDL_Rect src, dst;
288 int x = -1, w = 0;
290 font_get_metrics( id, ch, &x, &w);
291 if( x == -1) return w;
293 bitmap = images[id].data;
295 dst.w = src.w = w;
296 dst.h = src.h = bitmap->h - 1;
297 src.x = x;
298 src.y = 1;
299 dst.x = x_offset;
300 dst.y = y_offset;
302 SDL_BlitSurface( bitmap, &src, screen, &dst);
304 return src.w;
307 void font_draw_string( unsigned int id, char* s, int x_offset, int y_offset, int start, int animation) {
308 int y = y_offset;
309 int x = x_offset;
310 int i;
311 float xw = 0.0, xw_diff;
313 if( animation & ANIMATION_BUNGEE) {
314 xw = (25.0*sinf( start/10.0));
315 xw_diff = 0.0;
316 x -= xw / 2;
319 if( animation & ANIMATION_PENDULUM) {
320 x -= (int)(20.0*sinf( start/20.0));
323 for( i=0; i<strlen(s); i++) {
324 if( animation & ANIMATION_WAVE) {
325 y = y_offset + (int)(3.0*sinf( start/10.0 + x/30.0));
327 x += font_draw_char( id, s[i], x, y);
328 if( animation & ANIMATION_BUNGEE) {
329 xw_diff += xw/strlen(s);
330 if( xw_diff > 1.0 || xw_diff < -1.0) {
331 x += (int)(xw_diff);
332 if( xw_diff > 1.0) {
333 xw_diff -= 1.0;
334 } else {
335 xw_diff += 1.0;
342 int font_get_string_width( unsigned int id, char* s) {
343 int w = 0, i;
345 for( i=0; i<strlen(s); i++) {
346 w += font_get_metrics( id, s[i], NULL, NULL);
349 return w;
352 void draw_line_faded( int x1, int y1, int x2, int y2, int r, int g, int b, int r2, int g2, int b2) {
353 float step, dx, dy, x = x1, y = y1;
354 int i;
355 char fade = (r!=r2 || g!=g2 || b!=b2);
357 step = (float)(abs(x2-x1)>abs(y2-y1)?abs(x2-x1):abs(y2-y1));
358 dx = (float)(x2-x1) / step;
359 dy = (float)(y2-y1) / step;
361 SDL_LockSurface( screen);
362 for( i=0; i<step; i++) {
363 x += dx;
364 y += dy;
365 if( x < 0.0 || x >= WIDTH || y < 0.0 || y >= HEIGHT) {
366 continue;
368 if( fade) {
369 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);
370 } else {
371 SET_PIXEL_RGB( screen, (int)x, (int)y, r, g, b);
374 SDL_UnlockSurface( screen);