/* * * Copyright (c) 1994, 2002, 2003 Johannes Prix * Copyright (c) 1994, 2002 Reinhard Prix * * * This file is part of Freedroid * * Freedroid is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Freedroid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Freedroid; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * */ /* ---------------------------------------------------------------------- * This file contains all the functions managing the lighting inside * the freedroidRPG game window, i.e. the 'light radius' of the Tux and * of other light emanating objects. * ---------------------------------------------------------------------- */ #define _light_c #include "system.h" #include "defs.h" #include "struct.h" #include "global.h" #include "map.h" #include "proto.h" #include "colodefs.h" #include "SDL_rotozoom.h" //-------------------- // #define MAX_NUMBER_OF_LIGHT_SOURCES 100 moderately_finepoint light_sources [ MAX_NUMBER_OF_LIGHT_SOURCES ] ; int light_source_strengthes [ MAX_NUMBER_OF_LIGHT_SOURCES ] ; int light_strength_buffer [ 64 ] [ 48 ] ; int IsLightPassable ( float x , float y , int z, finepoint step ) { Level PassLevel = curShip . AllLevels [ z ] ; int x_tile_start, y_tile_start; int x_tile_end, y_tile_end; int x_tile, y_tile; //-------------------- // We take a look whether the position given in the parameter is // blocked by an obstacle ON ANY SQUARE WITHIN A 3x3 TILE RECTANGLE. // if(step.x > 0 && step.y > 0) { x_tile_start = rintf ( x ) -1 ; y_tile_start = rintf ( y ) - 1; x_tile_end = x_tile_start + 2 ; y_tile_end = y_tile_start + 2 ; } else { x_tile_start = rintf ( x ) -1 ; y_tile_start = rintf ( y ) -1 ; x_tile_end = x_tile_start + 2 ; y_tile_end = y_tile_start + 2 ; } if ( x_tile_start < 0 ) x_tile_start = 0 ; if ( y_tile_start < 0 ) y_tile_start = 0 ; if ( x_tile_end >= PassLevel -> xlen ) x_tile_end = PassLevel->xlen -1 ; if ( y_tile_end >= PassLevel -> ylen ) y_tile_end = PassLevel->ylen -1 ; for ( x_tile = x_tile_start ; x_tile < x_tile_end ; x_tile ++ ) { // DebugPrintf ( 0 , " %d " , x_tile ); for ( y_tile = y_tile_start ; y_tile < y_tile_end ; y_tile ++ ) { if ( position_collides_with_obstacles_on_square ( x , y , x_tile , y_tile , PassLevel ) ) return ( FALSE ); } } return ( TRUE ) ; } /* ---------------------------------------------------------------------- * This function tests, if a Robot can go a direct straigt line from * x1 y1 to x2 y2 without hitting a wall or another obstacle. * * The return value is TRUE or FALSE accoringly. * ----------------------------------------------------------------------*/ int DirectLineLightable( float x1 , float y1 , float x2 , float y2 , int z ) { float LargerDistance; int Steps; int i; finepoint step; finepoint CheckPosition; static int first_call = TRUE; static int step_multiplier = -1 ; // something completely absurd... int steps_for_this_obstacle; static int key_obstacle_type = -1 ; //-------------------- // First we determine the amount of steps we need to take // such that we can't oversee any walls or something. // if ( fabsf(x1-x2) > fabsf (y1-y2) ) LargerDistance = fabsf(x1-x2); else LargerDistance=fabsf(y1-y2); //-------------------- // The larger distance must be used to compute the steps nescessary // for good passability check. i.e. passability check such that no // movement completely through an obstacle will be possible. // // The number of steps must of course be multiplied with the minimum // number of steps for one floor tile, which has been calibrated // (hopefully sensibly) above. // Steps = LargerDistance * 3 ; if ( Steps <= 1 ) Steps = 2 ; // return TRUE; //-------------------- // We determine the step size when walking from (x1,y1) to (x2,y2) in Steps number of steps // step.x = (x2 - x1) / ( float ) Steps; step.y = (y2 - y1) / ( float ) Steps; // DebugPrintf( 2 , "\n%s(): step.x=%f step.y=%f." , __FUNCTION__ , step.x , step.y ); //-------------------- // We start from position (x1, y1) // CheckPosition . x = x1; CheckPosition . y = y1; for ( i = 0 ; i < Steps + 1 ; i++ ) { int x = CheckPosition . x; int y = CheckPosition . y; Level PassLevel = curShip . AllLevels [ z ] ; int x_tile_start, y_tile_start; int x_tile_end, y_tile_end; int x_tile, y_tile; //-------------------- // We take a look whether the position given in the parameter is // blocked by an obstacle ON ANY SQUARE WITHIN A 3x3 TILE RECTANGLE. // if(!IsLightPassable(CheckPosition.x, CheckPosition.y, z, step)) return FALSE; CheckPosition.x += step.x; CheckPosition.y += step.y; } DebugPrintf( 1 , "\n%s(): Connection analysis revealed : FREE!" , __FUNCTION__ ); return TRUE; }; // int DirectLineWalkable( float x1 , float y1 , float x2 , float y2 ) /* ---------------------------------------------------------------------- * There might be some obstacles that emit some light. Yet, we can't * go through all the obstacle list of a level every frame at sufficiently * low cost. Therefore we create a reduced list of light emitters for * usage in the light computation code. * ---------------------------------------------------------------------- */ void update_light_list ( int player_num ) { int i; Level light_level = curShip . AllLevels [ Me [ player_num ] . pos . z ] ; int map_x, map_y, map_x_end, map_y_end, map_x_start, map_y_start ; int glue_index; int obs_index; int next_light_emitter_index; obstacle* emitter; int blast; //-------------------- // At first we fill out the light sources array with 'empty' information, // i.e. such positions, that won't affect our location for sure. // for ( i = 0 ; i < MAX_NUMBER_OF_LIGHT_SOURCES ; i ++ ) { light_sources [ i ] . x = -200 ; light_sources [ i ] . y = -200 ; light_source_strengthes [ i ] = 0 ; } //-------------------- // Now we fill in the Tux position as the very first light source, that will // always be present. // light_sources [ 0 ] . x = Me [ player_num ] . pos . x ; light_sources [ 0 ] . y = Me [ player_num ] . pos . y ; light_source_strengthes [ 0 ] = light_level -> light_radius_bonus + Me [ player_num ] . light_bonus_from_tux ; //-------------------- // We must not in any case tear a hole into the beginning of // the list though... // if ( light_source_strengthes [ 0 ] <= 0 ) light_source_strengthes [ 0 ] = 1; next_light_emitter_index = 1 ; //-------------------- // Now we can fill in any explosions, that are currently going on. // These will typically emanate a lot of light. // for ( blast = 0 ; blast < MAXBLASTS ; blast ++ ) { if ( ! ( AllBlasts [ blast ] . type == DRUIDBLAST ) ) continue ; light_sources [ next_light_emitter_index ] . x = AllBlasts [ blast ] . pos . x ; light_sources [ next_light_emitter_index ] . y = AllBlasts [ blast ] . pos . y ; //-------------------- // We add some light strength according to the phase of the blast // light_source_strengthes [ next_light_emitter_index ] = 20 - AllBlasts [ blast ] . phase / 2 ; if ( light_source_strengthes [ next_light_emitter_index ] < 0 ) light_source_strengthes [ next_light_emitter_index ] = 1 ; next_light_emitter_index ++ ; //-------------------- // We must not write beyond the bounds of our light sources array! // if ( next_light_emitter_index >= MAX_NUMBER_OF_LIGHT_SOURCES - 1 ) { GiveStandardErrorMessage ( __FUNCTION__ , "\ WARNING! End of light sources array reached!", NO_NEED_TO_INFORM, IS_WARNING_ONLY ); return; } } //-------------------- // Now we can fill in the remaining light sources of this level. // First we do all the obstacles: // map_x_start = Me [ player_num ] . pos . x - 12 ; map_y_start = Me [ player_num ] . pos . y - 12 ; map_x_end = Me [ player_num ] . pos . x + 12 ; map_y_end = Me [ player_num ] . pos . y + 12 ; if ( map_x_start < 0 ) map_x_start = 0 ; if ( map_y_start < 0 ) map_y_start = 0 ; if ( map_x_end >= light_level -> xlen ) map_x_end = light_level -> xlen - 1 ; if ( map_y_end >= light_level -> ylen ) map_y_end = light_level -> ylen - 1 ; for ( map_x = map_x_start ; map_x < map_x_end ; map_x ++ ) { for ( map_y = map_y_start ; map_y < map_y_end ; map_y ++ ) { for ( glue_index = 0 ; glue_index < MAX_OBSTACLES_GLUED_TO_ONE_MAP_TILE ; glue_index ++ ) { //-------------------- // end of obstacles glued to here? great->next square // if ( light_level -> map [ map_y ] [ map_x ] . obstacles_glued_to_here [ glue_index ] == (-1) ) break; obs_index = light_level -> map [ map_y ] [ map_x ] . obstacles_glued_to_here [ glue_index ] ; emitter = & ( light_level -> obstacle_list [ obs_index ] ); if ( obstacle_map [ emitter -> type ] . emitted_light_strength == 0 ) continue; //-------------------- // Now we know that this one needs to be inserted! // light_sources [ next_light_emitter_index ] . x = emitter -> pos . x ; light_sources [ next_light_emitter_index ] . y = emitter -> pos . y ; light_source_strengthes [ next_light_emitter_index ] = obstacle_map [ emitter -> type ] . emitted_light_strength ; next_light_emitter_index ++ ; //-------------------- // We must not write beyond the bounds of our light sources array! // if ( next_light_emitter_index >= MAX_NUMBER_OF_LIGHT_SOURCES - 1 ) { GiveStandardErrorMessage ( __FUNCTION__ , "\ WARNING! End of light sources array reached!", NO_NEED_TO_INFORM, IS_WARNING_ONLY ); return; } } } } //-------------------- // Now we can proceed with the enemies: They should give light too, // even if only in small amounts... // occasionally_update_first_and_last_bot_indices ( ) ; for ( i = first_index_of_bot_on_level [ Me [ player_num ] . pos . z ] ; i < last_index_of_bot_on_level [ Me [ player_num ] . pos . z ] ; i ++ ) { if ( AllEnemys [ i ] . Status == INFOUT ) continue; if ( Me [ 0 ] . pos . z != AllEnemys [ i ] . pos . z ) continue ; if ( fabsf ( Me [ 0 ] . pos . x - AllEnemys [ i ] . pos . x ) >= 12 ) continue ; if ( fabsf ( Me [ 0 ] . pos . y - AllEnemys [ i ] . pos . y ) >= 12 ) continue ; //-------------------- // Now we know that this one needs to be inserted! // light_sources [ next_light_emitter_index ] . x = AllEnemys [ i ] . pos . x ; light_sources [ next_light_emitter_index ] . y = AllEnemys [ i ] . pos . y ; light_source_strengthes [ next_light_emitter_index ] = -14 ; next_light_emitter_index ++ ; //-------------------- // We must not write beyond the bounds of our light sources array! // if ( next_light_emitter_index >= MAX_NUMBER_OF_LIGHT_SOURCES - 1 ) { GiveStandardErrorMessage ( __FUNCTION__ , "\ WARNING! End of light sources array reached!", NO_NEED_TO_INFORM, IS_WARNING_ONLY ); return; } } }; // void update_light_list ( int player_num ) /* ---------------------------------------------------------------------- * This function is used to find the light intensity at any given point * on the map. * ---------------------------------------------------------------------- */ int calculate_light_strength ( moderately_finepoint target_pos ) { int final_darkness = NUMBER_OF_SHADOW_IMAGES; int i; float xdist; float ydist; float light_vec_len; //-------------------- // Now that the light sources array is fully set up, we can start // to compute the individual light strength at any given position // for ( i = 0 ; i < MAX_NUMBER_OF_LIGHT_SOURCES ; i ++ ) { //-------------------- // Now if we've reached the end of the current list of light // sources, then we can stop immediately. // if ( light_source_strengthes [ i ] == 0 ) { if ( final_darkness < -curShip . AllLevels [ Me [ 0 ] . pos . z ] -> minimum_light_value ) return ( final_darkness ); else return ( -curShip . AllLevels [ Me [ 0 ] . pos . z ] -> minimum_light_value ); } //-------------------- // We could of course use a maximum function to find out the proper light at // any place. But maybe addition of light would be better, so we use the latter // code. // // If the sign of the inequality determines the outcome already, then we need not // do anything else. This might save a lot of computation time... and also it // allows to take the square of the inequality after that SAFELY!!! // if ( final_darkness + light_source_strengthes [ i ] <= 0 ) continue; //-------------------- // This function is time-critical, simply because it's used a lot every frame for // the light radius. Therefore we avoid square roots here and use squared for the // inequality now. Let's see if that has some numerical advantage already... // xdist = light_sources [ i ] . x - target_pos . x ; ydist = light_sources [ i ] . y - target_pos . y ; if ( ( xdist * xdist + ydist * ydist ) * 4.0 * 4.0 < ( final_darkness + light_source_strengthes [ i ] ) * ( final_darkness + light_source_strengthes [ i ] ) ) { //-------------------- // Let's try something different here: We now do some passability // checking as well! Cool! But only for the very first light source // /*float */light_vec_len = sqrt(xdist * xdist + ydist * ydist); if ( light_vec_len > 0.5 ) { if ( curShip . AllLevels [ Me [ 0 ] . pos . z ] -> use_underground_lighting ) { if ( ! DirectLineLightable( light_sources [ i ] . x , light_sources [ i ] . y , target_pos . x , target_pos . y , Me [ 0 ] . pos . z ) ) continue; } } final_darkness = (int) ( light_vec_len * 4.0 ) - light_source_strengthes [ i ] ; } } if ( final_darkness < -curShip . AllLevels [ Me [ 0 ] . pos . z ] -> minimum_light_value ) return ( final_darkness ); else return ( -curShip . AllLevels [ Me [ 0 ] . pos . z ] -> minimum_light_value ); }; // int calculate_light_strength ( moderately_finepoint target_pos ) /* ---------------------------------------------------------------------- * When the light radius (i.e. the shadow values for the floor) has been * set up, the shadows usually are very 'hard' in the sense that extreme * darkness can be right next to very bright light. This does not look * very real. Therefore we 'soften' the shadow a bit, by allowing only * a limited step size from one shadow square to the next. Of course * these changes have to be propagated, so we run through the whole * shadow grid twice and propagate in 'both' directions. * The hardness of the shadow can be controlled in the definition of * MAX_LIGHT_STEP. Higher values will lead to harder shadows, while * lower values will give very smooth and flourescent shadows propagating * even a bit under walls (which doesn't look too good). 4 seems like * a reasonable setting. * ---------------------------------------------------------------------- */ void soften_light_distribution ( void ) { int x , y ; #define MAX_LIGHT_STEP 3 //-------------------- // Now that the light buffer has been set up properly, we can start to // smoothen it out a bit. We do so in the direction of more light. // for ( x = 1 ; x < (64-1) ; x ++ ) { for ( y = 1 ; y < (48-1) ; y ++ ) { if ( light_strength_buffer [ x + 1 ] [ y ] > light_strength_buffer [ x ] [ y ] + MAX_LIGHT_STEP ) light_strength_buffer [ x + 1 ] [ y ] = light_strength_buffer [ x ] [ y ] + MAX_LIGHT_STEP ; if ( light_strength_buffer [ x ] [ y + 1 ] > light_strength_buffer [ x ] [ y ] + MAX_LIGHT_STEP ) light_strength_buffer [ x ] [ y + 1 ] = light_strength_buffer [ x ] [ y ] + MAX_LIGHT_STEP ; if ( light_strength_buffer [ x + 1 ] [ y + 1 ] > light_strength_buffer [ x ] [ y ] + MAX_LIGHT_STEP ) light_strength_buffer [ x + 1 ] [ y + 1 ] = light_strength_buffer [ x ] [ y ] + MAX_LIGHT_STEP ; } } // now the same again, this time from right to left for ( x = (64-2) ; x > 1 ; x -- ) { for ( y = ( 48 - 2 ) ; y > 1 ; y -- ) { if ( light_strength_buffer [ x - 1 ] [ y ] > light_strength_buffer [ x ] [ y ] + MAX_LIGHT_STEP ) light_strength_buffer [ x - 1 ] [ y ] = light_strength_buffer [ x ] [ y ] + MAX_LIGHT_STEP ; if ( light_strength_buffer [ x ] [ y - 1 ] > light_strength_buffer [ x ] [ y ] + MAX_LIGHT_STEP ) light_strength_buffer [ x ] [ y - 1 ] = light_strength_buffer [ x ] [ y ] + MAX_LIGHT_STEP ; if ( light_strength_buffer [ x - 1 ] [ y - 1 ] > light_strength_buffer [ x ] [ y ] + MAX_LIGHT_STEP ) light_strength_buffer [ x - 1 ] [ y - 1 ] = light_strength_buffer [ x ] [ y ] + MAX_LIGHT_STEP ; } } }; // void soften_light_distribution ( void ) /* ---------------------------------------------------------------------- * This function is used to find the light intensity at any given point * on the map. * ---------------------------------------------------------------------- */ void set_up_light_strength_buffer ( void ) { int x ; int y ; moderately_finepoint target_pos ; int screen_x ; int screen_y ; const float xrat = ( GameConfig . screen_width / 64 ) ; const float yrat = ( GameConfig . screen_height / 48 ) ; for ( x = 0 ; x < 64 ; x ++ ) { for ( y = 0 ; y < 48 ; y ++ ) { screen_x = ( x - 32 ) * xrat; screen_y = ( y - 24 ) * yrat; target_pos . x = translate_pixel_to_map_location ( 0 , screen_x , screen_y , TRUE ) ; target_pos . y = translate_pixel_to_map_location ( 0 , screen_x , screen_y , FALSE ) ; light_strength_buffer [ x ] [ y ] = calculate_light_strength ( target_pos ); } } soften_light_distribution(); }; // void set_up_light_strength_buffer ( void ) /* ---------------------------------------------------------------------- * This function is used to find the light intensity at any given point * on the map. * ---------------------------------------------------------------------- */ int get_light_strength ( moderately_finepoint target_pos ) { int x , y ; x = translate_map_point_to_screen_pixel_x ( target_pos . x , target_pos . y ); y = translate_map_point_to_screen_pixel_y ( target_pos . x , target_pos . y ); x = ( x * 64 ) / GameConfig . screen_width ; y = ( y * 48 ) / GameConfig . screen_height ; if ( ( x < 0 ) || ( y < 0 ) || ( x >= 64 ) || ( y >= 48 ) ) { //-------------------- // If a request reaches outside the prepared buffer, we use the // nearest point, if we can get it easily, otherwise we'll use // blackness by default. // if ( ( x >= 0 ) && ( x < 64 ) ) { if ( y >= 48 ) return ( light_strength_buffer [ x ] [ 47 ] ); if ( y < 0 ) return ( light_strength_buffer [ x ] [ 0 ] ); } if ( ( y >= 0 ) && ( y < 48 ) ) { if ( x >= 64 ) return ( light_strength_buffer [ 63 ] [ y ] ); if ( x < 0 ) return ( light_strength_buffer [ 0 ] [ y ] ); } return ( NUMBER_OF_SHADOW_IMAGES ); } return ( light_strength_buffer [ x ] [ y ] ); }; // int get_light_strength ( moderately_finepoint target_pos ) /* ---------------------------------------------------------------------- * This function should blit the shadows on the floor, that are used to * generate the impression of a 'light radius' around the players * character. * ---------------------------------------------------------------------- */ void blit_classic_SDL_light_radius( void ) { static int first_call = TRUE ; int i, j ; char fpath[2048]; char constructed_file_name[2000]; int our_height, our_width, our_max_height, our_max_width; int light_strength; moderately_finepoint target_pos; static int pos_x_grid [ (int)(MAX_FLOOR_TILES_VISIBLE_AROUND_TUX * ( 1.0 / LIGHT_RADIUS_CHUNK_SIZE ) * 2) ] [ (int)(MAX_FLOOR_TILES_VISIBLE_AROUND_TUX * ( 1.0 / LIGHT_RADIUS_CHUNK_SIZE ) * 2 ) ] ; static int pos_y_grid [ (int)(MAX_FLOOR_TILES_VISIBLE_AROUND_TUX * ( 1.0 / LIGHT_RADIUS_CHUNK_SIZE ) * 2) ] [ (int)(MAX_FLOOR_TILES_VISIBLE_AROUND_TUX * ( 1.0 / LIGHT_RADIUS_CHUNK_SIZE ) * 2 ) ] ; static SDL_Rect target_rectangle; int chunk_size_x; int chunk_size_y; int window_offset_x; SDL_Surface* tmp; //-------------------- // If the darkness chunks have not yet been loaded, we load them... // if ( first_call ) { first_call = FALSE; for ( i = 0 ; i < NUMBER_OF_SHADOW_IMAGES ; i ++ ) { sprintf ( constructed_file_name , "light_radius_chunks/iso_light_radius_darkness_%04d.png" , i + 1 ); find_file (constructed_file_name , GRAPHICS_DIR , fpath, 0 ); get_iso_image_from_file_and_path ( fpath , & ( light_radius_chunk [ i ] ) , TRUE ) ; tmp = light_radius_chunk [ i ] . surface ; light_radius_chunk [ i ] . surface = SDL_DisplayFormatAlpha ( light_radius_chunk [ i ] . surface ) ; SDL_FreeSurface ( tmp ) ; } pos_x_grid [ 0 ] [ 0 ] = translate_map_point_to_screen_pixel_x ( Me [ 0 ] . pos . x - ( FLOOR_TILES_VISIBLE_AROUND_TUX ) , Me [ 0 ] . pos . y - ( FLOOR_TILES_VISIBLE_AROUND_TUX ) ) - 10 ; pos_y_grid [ 0 ] [ 0 ] = translate_map_point_to_screen_pixel_y ( Me [ 0 ] . pos . x - ( FLOOR_TILES_VISIBLE_AROUND_TUX ) , Me [ 0 ] . pos . y - ( FLOOR_TILES_VISIBLE_AROUND_TUX ) ) - 42 ; chunk_size_x = 26 /2 + 1 ; chunk_size_y = 14 /2 ; for ( i = 0 ; i < (int)(FLOOR_TILES_VISIBLE_AROUND_TUX * ( 1.0 / LIGHT_RADIUS_CHUNK_SIZE ) * 2) ; i ++ ) { for ( j = 0 ; j < (int)(FLOOR_TILES_VISIBLE_AROUND_TUX * ( 1.0 / LIGHT_RADIUS_CHUNK_SIZE ) * 2) ; j ++ ) { pos_x_grid [ i ] [ j ] = pos_x_grid [ 0 ] [ 0 ] + ( i - j ) * chunk_size_x ; pos_y_grid [ i ] [ j ] = pos_y_grid [ 0 ] [ 0 ] + ( i + j ) * chunk_size_y ; } } } //-------------------- // Now it's time to apply the light radius // our_max_width = FLOOR_TILES_VISIBLE_AROUND_TUX * ( 1.0 / LIGHT_RADIUS_CHUNK_SIZE ) * 2 ; our_max_height = our_max_width; window_offset_x = - ( GameConfig . screen_width / 2 ) + UserCenter_x ; for ( our_height = 0 ; our_height < our_max_height ; our_height ++ ) { for ( our_width = 0 ; our_width < our_max_width ; our_width ++ ) { if ( our_width % LIGHT_RADIUS_CRUDENESS_FACTOR ) continue; if ( our_height % LIGHT_RADIUS_CRUDENESS_FACTOR ) continue; target_pos . x = Me [ 0 ] . pos . x - ( FLOOR_TILES_VISIBLE_AROUND_TUX ) + our_width * LIGHT_RADIUS_CHUNK_SIZE ; target_pos . y = Me [ 0 ] . pos . y - ( FLOOR_TILES_VISIBLE_AROUND_TUX ) + our_height * LIGHT_RADIUS_CHUNK_SIZE; light_strength = get_light_strength ( target_pos ) ; if ( light_strength >= NUMBER_OF_SHADOW_IMAGES ) light_strength = NUMBER_OF_SHADOW_IMAGES -1 ; if ( light_strength <= 0 ) continue ; // blit_iso_image_to_map_position ( light_radius_chunk [ light_strength ] , target_pos . x , target_pos . y ); target_rectangle . x = pos_x_grid [ our_width ] [ our_height ] + window_offset_x ; target_rectangle . y = pos_y_grid [ our_width ] [ our_height ] ; our_SDL_blit_surface_wrapper( light_radius_chunk [ light_strength ] . surface , NULL , Screen, &target_rectangle ); } } }; // void blit_classic_SDL_light_radius( void ) /* ---------------------------------------------------------------------- * FreedroidRPG does some light/shadow computations and then draws some * shadows/light on the floor. There is a certain amount of light around * the Tux. This light is called the 'light radius'. * * This function is supposed to compute all light/shadow values for the * the floor and then draw the light radius on the floor. Note, that * this is something completely different from the prerendered shadows * that are to be blitted for obstacles, when they are exposed to * daylight. * ---------------------------------------------------------------------- */ void blit_light_radius ( void ) { //-------------------- // Before making any reference to the light, it's best to // first calculate the values in the light buffer, because // those will be used when drawing the light radius. // set_up_light_strength_buffer ( ); if ( use_open_gl ) { // blit_open_gl_light_radius (); // blit_open_gl_cheap_light_radius (); blit_open_gl_stretched_texture_light_radius (); } else { blit_classic_SDL_light_radius(); } }; // void blit_light_radius ( void ) #undef _light_c