Tennix 0.4.0
[tennix.git] / graphics.c
blobc84e1ede720053d9079394fde197e49ad74f56ce
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)
51 void init_graphics( const char *data_dir) {
52 int i;
53 SDL_Surface* data;
54 SDL_Surface* tmp;
56 #ifndef MACOSX
57 tmp = IMG_Load_RW( SDL_RWFromConstMem( icon, sizeof(icon)), 1);
58 if( tmp != NULL) {
59 SDL_WM_SetIcon( tmp, NULL);
60 SDL_FreeSurface( tmp);
62 #endif
64 images = (Image*)calloc( GR_COUNT, sizeof( Image));
66 for( i=0; i<GR_COUNT; i++) {
67 tmp = IMG_Load_RW( SDL_RWFromConstMem( graphics[i].data, graphics[i].size), 1);
68 if( !tmp) {
69 fprintf( stderr, "Error: %s\n", SDL_GetError());
70 continue;
73 SDL_SetColorKey( tmp, SDL_SRCCOLORKEY, SDL_MapRGB( tmp->format, 0, 0, 0));
74 data = SDL_DisplayFormatAlpha( tmp);
75 SDL_FreeSurface( tmp);
77 if( !data) {
78 fprintf( stderr, "Error: %s\n", SDL_GetError());
79 continue;
81 images[i].data = data;
84 buffer = SDL_CreateRGBSurface( SDL_HWSURFACE, WIDTH, HEIGHT, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
86 if( buffer == NULL) {
87 fprintf( stderr, "Cannot create buffer surface: %s\n", SDL_GetError());
91 void uninit_graphics() {
92 int i;
94 for( i=0; i<GR_COUNT; i++) {
95 SDL_FreeSurface( images[i].data);
98 if( buffer != NULL) {
99 SDL_FreeSurface( buffer);
102 free( images);
105 int get_image_width( unsigned int id) {
106 return images[id].data->w;
109 int get_image_height( unsigned int id) {
110 return images[id].data->h;
113 int get_sprite_width( unsigned int id, int items) {
114 return images[id].data->w / items;
117 void show_sprite( unsigned int id, int pos, int items, int x_offset, int y_offset, int opacity) {
118 SDL_Surface *bitmap;
119 SDL_Rect src, dst;
121 bitmap = images[id].data;
123 if( !bitmap) return;
125 SDL_SetAlpha( bitmap, SDL_SRCALPHA | SDL_RLEACCEL, opacity);
127 dst.w = src.w = bitmap->w/items;
128 dst.h = src.h = bitmap->h;
129 src.x = src.w*pos;
130 src.y = 0;
131 dst.x = x_offset;
132 dst.y = y_offset;
134 SDL_BlitSurface( bitmap, &src, screen, &dst);
137 void line_horiz( int y, Uint8 r, Uint8 g, Uint8 b) {
138 Uint32 color = SDL_MapRGB( screen->format, r, g, b);
139 SDL_Rect rect;
141 rect.x = 0;
142 rect.w = screen->w;
143 rect.y = y;
144 rect.h = 1;
146 SDL_FillRect( screen, &rect, color);
149 void line_vert( int x, Uint8 r, Uint8 g, Uint8 b) {
150 Uint32 color = SDL_MapRGB( screen->format, r, g, b);
151 SDL_Rect rect;
153 rect.x = x;
154 rect.w = 1;
155 rect.y = 0;
156 rect.h = screen->h;
158 SDL_FillRect( screen, &rect, color);
161 void rectangle( int x, int y, int w, int h, Uint8 r, Uint8 g, Uint8 b) {
162 Uint32 color = SDL_MapRGB( screen->format, r, g, b);
163 SDL_Rect rect;
165 rect.x = x;
166 rect.y = y;
167 rect.w = w;
168 rect.h = h;
170 SDL_FillRect( screen, &rect, color);
173 void draw_button( int x, int y, int w, int h, Uint8 r, Uint8 g, Uint8 b, char pressed) {
174 float diff = (pressed?1.0-BUTTON_HIGHLIGHT:1.0+BUTTON_HIGHLIGHT);
175 int border = BUTTON_BORDER;
176 rectangle( x, y, w, h, r*diff, g*diff, b*diff);
177 rectangle( x+border, y+border, w-border, h-border, r/diff, g/diff, b/diff);
178 rectangle( x+border, y+border, w-2*border, h-2*border, r, g, b);
181 void draw_button_text( char* s, int x, int y, int w, int h, Uint8 r, Uint8 g, Uint8 b, char pressed) {
182 int font_x, font_y;
183 pressed = pressed?1:0;
184 draw_button( x, y, w, h, r, g, b, pressed);
185 font_x = x + w/2 - font_get_string_width( GR_SMALLISH_FONT, s)/2 + pressed*BUTTON_BORDER;
186 font_y = y + h/2 - get_image_height( GR_SMALLISH_FONT)/2 + pressed*BUTTON_BORDER;
187 font_draw_string( GR_SMALLISH_FONT, s, font_x, font_y, 0, 0);
190 void show_image( unsigned int id, int x_offset, int y_offset, int opacity) {
191 show_sprite( id, 0, 1, x_offset, y_offset, opacity);
194 void introimage( unsigned int id) {
195 int i;
197 for( i=0; i<256; i+=10) {
198 clearscr();
199 show_image( id, 0, 0, i);
200 updatescr();
201 SDL_Delay( 30);
204 //SDL_Delay( 500);
205 wait_keypress();
207 for( i=255; i>=0; i-=10) {
208 clearscr();
209 show_image( id, 0, 0, i);
210 updatescr();
211 SDL_Delay( 30);
214 clearscr();
217 void clearscr() {
218 SDL_Rect rect;
220 rect.x = 0;
221 rect.y = 0;
222 rect.w = WIDTH;
223 rect.h = HEIGHT;
225 SDL_FillRect( screen, &rect, SDL_MapRGB( screen->format, 0, 0, 0));
228 void updatescr() {
229 int ticks = SDL_GetTicks();
231 if( ticks < fading_start+FADE_DURATION) {
232 SDL_SetAlpha( buffer, SDL_SRCALPHA | SDL_RLEACCEL, 255-255*(ticks-fading_start)/FADE_DURATION);
233 SDL_BlitSurface( buffer, NULL, screen, NULL);
236 SDL_UpdateRect( screen, 0, 0, 0, 0);
237 SDL_Flip( screen);
240 void start_fade() {
241 SDL_BlitSurface( screen, NULL, buffer, NULL);
242 fading_start = SDL_GetTicks();
245 int is_fading() {
246 return SDL_GetTicks() < fading_start+FADE_DURATION;
249 int font_get_metrics( unsigned int id, char ch, int* xp, int* wp) {
250 SDL_Surface *bitmap;
251 int pos, x = -1, w = 0;
252 int search_pos = 0, search_x = 0;
253 Uint8 red, green, blue;
255 if( id > GR_COUNT) return 0;
257 pos = toupper( ch) - ' '; /* ' ' = first character in font bitmap */
259 bitmap = images[id].data;
261 SDL_LockSurface( bitmap);
262 while( search_x < bitmap->w) {
263 GET_PIXEL_RGB( bitmap, search_x, 0, &red, &green, &blue);
265 /* Increase pos counter if we have a "marker" pixel (255,0,255) */
266 if( red > 250 && green < 10 && blue > 250) {
267 search_pos++;
268 if( search_pos == pos) {
269 x = search_x;
270 } else if( search_pos == pos + 1) {
271 w = search_x - x;
272 break;
276 search_x++;
278 SDL_UnlockSurface( bitmap);
280 if( wp != NULL) (*wp) = w;
281 if( xp != NULL) (*xp) = x;
283 return w;
286 int font_draw_char( unsigned int id, char ch, int x_offset, int y_offset) {
287 SDL_Surface *bitmap;
288 SDL_Rect src, dst;
289 int x = -1, w = 0;
291 font_get_metrics( id, ch, &x, &w);
292 if( x == -1) return w;
294 bitmap = images[id].data;
296 dst.w = src.w = w;
297 dst.h = src.h = bitmap->h - 1;
298 src.x = x;
299 src.y = 1;
300 dst.x = x_offset;
301 dst.y = y_offset;
303 SDL_BlitSurface( bitmap, &src, screen, &dst);
305 return src.w;
308 void font_draw_string( unsigned int id, char* s, int x_offset, int y_offset, int start, int animation) {
309 int y = y_offset;
310 int x = x_offset;
311 int i;
312 float xw = 0.0, xw_diff;
314 if( animation & ANIMATION_BUNGEE) {
315 xw = (25.0*sinf( start/10.0));
316 xw_diff = 0.0;
317 x -= xw / 2;
320 if( animation & ANIMATION_PENDULUM) {
321 x -= (int)(20.0*sinf( start/20.0));
324 for( i=0; i<strlen(s); i++) {
325 if( animation & ANIMATION_WAVE) {
326 y = y_offset + (int)(3.0*sinf( start/10.0 + x/30.0));
328 x += font_draw_char( id, s[i], x, y);
329 if( animation & ANIMATION_BUNGEE) {
330 xw_diff += xw/strlen(s);
331 if( xw_diff > 1.0 || xw_diff < -1.0) {
332 x += (int)(xw_diff);
333 if( xw_diff > 1.0) {
334 xw_diff -= 1.0;
335 } else {
336 xw_diff += 1.0;
343 int font_get_string_width( unsigned int id, char* s) {
344 int w = 0, i;
346 for( i=0; i<strlen(s); i++) {
347 w += font_get_metrics( id, s[i], NULL, NULL);
350 return w;
353 void draw_line_faded( int x1, int y1, int x2, int y2, int r, int g, int b, int r2, int g2, int b2) {
354 float step, dx, dy, x = x1, y = y1;
355 int i;
356 char fade = (r!=r2 || g!=g2 || b!=b2);
358 step = (float)(abs(x2-x1)>abs(y2-y1)?abs(x2-x1):abs(y2-y1));
359 dx = (float)(x2-x1) / step;
360 dy = (float)(y2-y1) / step;
362 SDL_LockSurface( screen);
363 for( i=0; i<step; i++) {
364 x += dx;
365 y += dy;
366 if( x < 0.0 || x >= WIDTH || y < 0.0 || y >= HEIGHT) {
367 continue;
369 if( fade) {
370 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);
371 } else {
372 SET_PIXEL_RGB( screen, (int)x, (int)y, r, g, b);
375 SDL_UnlockSurface( screen);