3 // SuperTux - A Jump'n Run
4 // Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (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.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #include "SDL_image.h"
32 #include <sys/types.h>
40 #include "drawing_context.h"
43 /* Needed for line calculations */
44 #define SGN(x) ((x)>0 ? 1 : ((x)==0 ? 0:(-1)))
45 #define ABS(x) ((x)>0 ? (x) : (-x))
49 /** Fades the given surface into a black one. If fade_out is true, it will fade out, else
53 void fade(Surface *surface, int seconds, bool fade_out);
55 void fade(const std::string& surface, int seconds, bool fade_out)
57 Surface* sur = new Surface(datadir + surface, IGNORE_ALPHA);
58 fade(sur, seconds, fade_out);
62 void fade(Surface *surface, int seconds, bool fade_out)
70 int cur_time, old_time;
71 cur_time = SDL_GetTicks();
73 while(alpha >= 0 && alpha < 256)
75 surface->draw(0,0,(int)alpha);
79 cur_time = SDL_GetTicks();
81 /* Calculate the next alpha value */
82 float calc = (float) ((cur_time - old_time) / seconds);
91 /* 'Stolen' from the SDL documentation.
92 * Set the pixel at (x, y) to the given value
93 * NOTE: The surface must be locked before calling this!
95 void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
97 int bpp = surface->format->BytesPerPixel;
98 /* Here p is the address to the pixel we want to set */
99 Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
108 *(Uint16 *)p = pixel;
112 if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
114 p[0] = (pixel >> 16) & 0xff;
115 p[1] = (pixel >> 8) & 0xff;
121 p[1] = (pixel >> 8) & 0xff;
122 p[2] = (pixel >> 16) & 0xff;
127 *(Uint32 *)p = pixel;
132 /* Draw a single pixel on the screen. */
133 void drawpixel(int x, int y, Uint32 pixel)
135 /* Lock the screen for direct access to the pixels */
136 if ( SDL_MUSTLOCK(screen) )
138 if ( SDL_LockSurface(screen) < 0 )
140 fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError());
145 if(!(x < 0 || y < 0 || x > screen->w || y > screen->h))
146 putpixel(screen, x, y, pixel);
148 if ( SDL_MUSTLOCK(screen) )
150 SDL_UnlockSurface(screen);
152 /* Update just the part of the display that we've changed */
153 SDL_UpdateRect(screen, x, y, 1, 1);
156 void drawline(int x1, int y1, int x2, int y2, int r, int g, int b, int a)
162 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
163 glColor4ub(r, g, b,a);
175 /* Basic unantialiased Bresenham line algorithm */
176 int lg_delta, sh_delta, cycle, lg_step, sh_step;
177 Uint32 color = SDL_MapRGBA(screen->format, r, g, b, a);
181 lg_step = SGN(lg_delta);
182 lg_delta = ABS(lg_delta);
183 sh_step = SGN(sh_delta);
184 sh_delta = ABS(sh_delta);
185 if (sh_delta < lg_delta)
187 cycle = lg_delta >> 1;
190 drawpixel(x1, y1, color);
192 if (cycle > lg_delta)
199 drawpixel(x1, y1, color);
201 cycle = sh_delta >> 1;
204 drawpixel(x1, y1, color);
206 if (cycle > sh_delta)
213 drawpixel(x1, y1, color);
220 /* --- FILL A RECT --- */
222 void fillrect(float x, float y, float w, float h, int r, int g, int b, int a)
239 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
240 glColor4ub(r, g, b,a);
245 glVertex2f(x+w, y+h);
254 SDL_Surface *temp = NULL;
263 temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel,
264 screen->format->Rmask,
265 screen->format->Gmask,
266 screen->format->Bmask,
267 screen->format->Amask);
275 SDL_FillRect(temp, &src, SDL_MapRGB(screen->format, r, g, b));
277 SDL_SetAlpha(temp, SDL_SRCALPHA, a);
279 SDL_BlitSurface(temp,0,screen,&rect);
281 SDL_FreeSurface(temp);
284 SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, r, g, b));
293 #define LOOP_DELAY 20.0
295 void fadeout(int fade_time)
297 float alpha_inc = 256 / (fade_time / LOOP_DELAY);
303 fillrect(0, 0, screen->w, screen->h, 0,0,0, (int)alpha_inc); // left side
305 DrawingContext context; // ugly...
306 context.do_drawing();
308 SDL_Delay(int(LOOP_DELAY));
311 fillrect(0, 0, screen->w, screen->h, 0, 0, 0, 255);
313 DrawingContext context;
314 context.draw_text_center(white_text, "Loading...",
315 Vector(0, screen->h/2), LAYER_FOREGROUND1);
316 context.do_drawing();
319 void shrink_fade(const Vector& point, int fade_time)
321 float left_inc = point.x / ((float)fade_time / LOOP_DELAY);
322 float right_inc = (screen->w - point.x) / ((float)fade_time / LOOP_DELAY);
323 float up_inc = point.y / ((float)fade_time / LOOP_DELAY);
324 float down_inc = (screen->h - point.y) / ((float)fade_time / LOOP_DELAY);
326 float left_cor = 0, right_cor = 0, up_cor = 0, down_cor = 0;
328 while(left_cor < point.x && right_cor < screen->w - point.x &&
329 up_cor < point.y && down_cor < screen->h - point.y)
331 left_cor += left_inc;
332 right_cor += right_inc;
334 down_cor += down_inc;
336 fillrect(0, 0, left_cor, screen->h, 0,0,0); // left side
337 fillrect(screen->w - right_cor, 0, right_cor, screen->h, 0,0,0); // right side
338 fillrect(0, 0, screen->w, up_cor, 0,0,0); // up side
339 fillrect(0, screen->h - down_cor, screen->w, down_cor+1, 0,0,0); // down side
340 DrawingContext context; // ugly...
341 context.do_drawing();
343 SDL_Delay(int(LOOP_DELAY));