Tennix 0.3.3: Dynamic Text Engine
[tennix.git] / graphics.c
blobf905d860e3689d57204f58fd4a740d6089dfef12
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 <math.h>
27 #include "tennix.h"
28 #include "graphics.h"
29 #include "input.h"
31 static Image* images;
33 static SDL_Surface *buffer;
35 static Uint32 fading_start = 0;
37 static const char* filenames[] = {
38 "court.png",
39 "shadow.png",
40 "player-racket.png",
41 "ground.png",
42 "ball.png",
43 "score.png",
44 "menu.png",
45 "animation.png",
46 "smallish-font.png"
49 static const char* smallish_font_chars = " !\"#----()'+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz";
51 void init_graphics( const char *data_dir) {
52 int i;
53 SDL_Surface* data;
54 SDL_Surface* tmp;
55 char temp[MAXPATHLEN];
57 #ifndef MACOSX
58 strcpy( temp, data_dir);
59 strcat( temp, "icon.png");
60 tmp = IMG_Load( temp);
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 strcpy( temp, data_dir);
71 strcat( temp, filenames[i]);
72 tmp = IMG_Load( temp);
73 if( !tmp) {
74 fprintf( stderr, "Error: %s\n", SDL_GetError());
75 continue;
78 SDL_SetColorKey( tmp, SDL_SRCCOLORKEY, SDL_MapRGB( tmp->format, 0, 0, 0));
79 data = SDL_DisplayFormatAlpha( tmp);
80 SDL_FreeSurface( tmp);
82 if( !data) {
83 fprintf( stderr, "Error: %s\n", SDL_GetError());
84 continue;
86 images[i].data = data;
89 buffer = SDL_CreateRGBSurface( SDL_HWSURFACE, WIDTH, HEIGHT, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
91 if( buffer == NULL) {
92 fprintf( stderr, "Cannot create buffer surface: %s\n", SDL_GetError());
96 void uninit_graphics() {
97 int i;
99 for( i=0; i<GR_COUNT; i++) {
100 SDL_FreeSurface( images[i].data);
103 if( buffer != NULL) {
104 SDL_FreeSurface( buffer);
107 free( images);
110 void show_sprite( unsigned int id, int pos, int items, int x_offset, int y_offset, int opacity) {
111 SDL_Surface *bitmap;
112 SDL_Rect src, dst;
114 bitmap = images[id].data;
116 if( !bitmap) return;
118 SDL_SetAlpha( bitmap, SDL_SRCALPHA | SDL_RLEACCEL, opacity);
120 dst.w = src.w = bitmap->w/items;
121 dst.h = src.h = bitmap->h;
122 src.x = src.w*pos;
123 src.y = 0;
124 dst.x = x_offset;
125 dst.y = y_offset;
127 SDL_BlitSurface( bitmap, &src, screen, &dst);
130 void line_horiz( int y, Uint8 r, Uint8 g, Uint8 b) {
131 Uint32 color = SDL_MapRGB( screen->format, r, g, b);
132 SDL_Rect rect;
134 rect.x = 0;
135 rect.w = screen->w;
136 rect.y = y;
137 rect.h = 1;
139 SDL_FillRect( screen, &rect, color);
142 void line_vert( int x, Uint8 r, Uint8 g, Uint8 b) {
143 Uint32 color = SDL_MapRGB( screen->format, r, g, b);
144 SDL_Rect rect;
146 rect.x = x;
147 rect.w = 1;
148 rect.y = 0;
149 rect.h = screen->h;
151 SDL_FillRect( screen, &rect, color);
154 void rectangle( int x, int y, int w, int h, Uint8 r, Uint8 g, Uint8 b) {
155 Uint32 color = SDL_MapRGB( screen->format, r, g, b);
156 SDL_Rect rect;
158 rect.x = x;
159 rect.y = y;
160 rect.w = w;
161 rect.h = h;
163 SDL_FillRect( screen, &rect, color);
166 void show_image( unsigned int id, int x_offset, int y_offset, int opacity) {
167 show_sprite( id, 0, 1, x_offset, y_offset, opacity);
170 void show_digit( int zahl, int x_offset, int y_offset, int opacity) {
171 show_sprite( GR_SCORE, zahl, 11, x_offset, y_offset, opacity);
174 void introimage( unsigned int id) {
175 int i;
177 for( i=0; i<256; i+=10) {
178 clearscr();
179 show_image( id, 0, 0, i);
180 updatescr();
181 SDL_Delay( 30);
184 //SDL_Delay( 500);
185 wait_keypress();
187 for( i=255; i>=0; i-=10) {
188 clearscr();
189 show_image( id, 0, 0, i);
190 updatescr();
191 SDL_Delay( 30);
194 clearscr();
197 void clearscr() {
198 SDL_Rect rect;
200 rect.x = 0;
201 rect.y = 0;
202 rect.w = WIDTH;
203 rect.h = HEIGHT;
205 SDL_FillRect( screen, &rect, SDL_MapRGB( screen->format, 0, 0, 0));
208 void updatescr() {
209 int ticks = SDL_GetTicks();
211 if( ticks < fading_start+FADE_DURATION) {
212 SDL_SetAlpha( buffer, SDL_SRCALPHA | SDL_RLEACCEL, 255-255*(ticks-fading_start)/FADE_DURATION);
213 SDL_BlitSurface( buffer, NULL, screen, NULL);
216 SDL_UpdateRect( screen, 0, 0, 0, 0);
217 SDL_Flip( screen);
220 void start_fade() {
221 SDL_BlitSurface( screen, NULL, buffer, NULL);
222 fading_start = SDL_GetTicks();
225 int is_fading() {
226 return SDL_GetTicks() < fading_start+FADE_DURATION;
229 int font_get_metrics( unsigned int id, char ch, int* xp, int* wp) {
230 SDL_Surface *bitmap;
231 SDL_PixelFormat *fmt;
232 int pos, x = -1, w = 0;
233 int search_pos = 0, search_x = 0;
234 Uint8 red, green, blue;
235 Uint32 pixel;
237 if( id > GR_COUNT) return 0;
239 ch = tolower( ch);
241 if( ch == ' ') {
242 w = 5;
243 } else {
244 for( pos = 0; pos < strlen( smallish_font_chars); pos++) {
245 if( smallish_font_chars[pos] == ch)
246 break;
249 if( pos == strlen( smallish_font_chars)) {
250 return 0;
253 bitmap = images[id].data;
254 fmt = bitmap->format;
256 SDL_LockSurface( bitmap);
257 while( search_x < bitmap->w) {
258 pixel = *( (Uint32*)(bitmap->pixels + search_x*fmt->BytesPerPixel));
259 red = (Uint8)(((pixel & fmt->Rmask) >> fmt->Rshift) << fmt->Rloss);
260 green = (Uint8)(((pixel & fmt->Gmask) >> fmt->Gshift) << fmt->Gloss);
261 blue = (Uint8)(((pixel & fmt->Bmask) >> fmt->Bshift) << fmt->Bloss);
263 /* Increase pos counter if we have a "marker" pixel (255,0,255) */
264 if( red == 255 && green == 0 && blue == 255) {
265 search_pos++;
266 if( search_pos == pos) {
267 x = search_x;
268 } else if( search_pos == pos + 1) {
269 w = search_x - x;
270 break;
274 search_x++;
276 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, xw;
312 if( animation & ANIMATION_SPACING) {
313 xw = (int)fabsf((15.0*sinf( start/10.0 + x_offset/30.0)));
314 x -= xw;
317 if( animation & ANIMATION_SKIP_TWO) {
318 x -= (strlen(s)*(int)(2.0*sinf( start / 10.0)))/2;
321 for( i=0; i<strlen(s); i++) {
322 if( animation & ANIMATION_WAVE) {
323 y = y_offset + (int)(3.0*sinf( start/10.0 + x/30.0));
325 x += font_draw_char( id, s[i], x, y);
326 if( animation & ANIMATION_SKIP_TWO) {
327 x += (int)(2.0*sinf( start / 10.0));
329 if( animation & ANIMATION_SPACING) {
330 x += (int)(xw/strlen(s));
335 int font_get_string_width( unsigned int id, char* s) {
336 int w = 0, i;
338 for( i=0; i<strlen(s); i++) {
339 w += font_get_metrics( id, s[i], NULL, NULL);
342 return w;