#include <string.h>
#include <errno.h>
#include <unistd.h>
+#include <math.h>
#include <time.h>
#include <SDL.h>
#include "level.h"
#include "scene.h"
#include "collision.h"
+#include "tile.h"
+#include "particlesystem.h"
/* extern variables */
{
for (x = 0; x < current_level.width; x++)
{
- if (current_level.tiles[y][x] >= '0' && current_level.tiles[y][x] <= '9')
+ if (current_level.dn_tiles[y][x] >= '0' && current_level.dn_tiles[y][x] <= '9')
{
- add_bad_guy(x * 32, y * 32, static_cast<BadGuyKind>(current_level.tiles[y][x] - '0'));
- current_level.tiles[y][x] = '.';
+ add_bad_guy(x * 32, y * 32, static_cast<BadGuyKind>(current_level.dn_tiles[y][x] - '0'));
+ current_level.dn_tiles[y][x] = 0;
}
}
}
+}
+void activate_particle_systems(void)
+{
+ printf("PSys: %s\n", current_level.particle_system.c_str());
+ if(current_level.particle_system == "clouds")
+ {
+ particle_systems.push_back(new CloudParticleSystem);
+ }
+ else if(current_level.particle_system == "snow")
+ {
+ particle_systems.push_back(new SnowParticleSystem);
+ }
+ else if(current_level.particle_system != "")
+ {
+ st_abort("unknown particle system specified in level", "");
+ }
}
/* --- GAME EVENT! --- */
case SDLK_f:
if(debug_fps)
debug_fps = false;
- else
+ else
debug_fps = true;
- break;
+ break;
default:
break;
}
arrays_free();
arrays_init();
activate_bad_guys();
+ activate_particle_systems();
level_free_gfx();
level_load_gfx(¤t_level);
level_free_song();
bad_guys[i].action();
}
+ /* update particle systems */
+ std::vector<ParticleSystem*>::iterator p;
+ for(p = particle_systems.begin(); p != particle_systems.end(); ++p)
+ {
+ (*p)->simulate(frame_ratio);
+ }
+
/* Handle all possible collisions. */
collision_handler();
void game_draw(void)
{
+int y,x;
+
/* Draw screen: */
if (tux.dying && (global_frame_counter % 4) == 0)
clearscreen(255, 255, 255);
}
}
- // Draw background:
- for (int y = 0; y < 15; ++y)
- for (int x = 0; x < 21; ++x)
- drawshape(32*x - fmodf(scroll_x, 32), y * 32,
- current_level.tiles[y][x + (int)(scroll_x / 32)]);
+ /* Draw particle systems (background) */
+ std::vector<ParticleSystem*>::iterator p;
+ for(p = particle_systems.begin(); p != particle_systems.end(); ++p)
+ {
+ (*p)->draw(scroll_x, 0, 0);
+ }
+
+ /* Draw background: */
+
+ for (y = 0; y < 15; ++y)
+ {
+ for (x = 0; x < 21; ++x)
+ {
+ drawshape(32*x - fmodf(scroll_x, 32), y * 32,
+ current_level.bg_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
+ }
+ }
+
+ /* Draw interactive tiles: */
+
+ for (y = 0; y < 15; ++y)
+ {
+ for (x = 0; x < 21; ++x)
+ {
+ drawshape(32*x - fmodf(scroll_x, 32), y * 32,
+ current_level.ia_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
+ }
+ }
+
+ /* (Bouncy bricks): */
for (unsigned int i = 0; i < bouncy_bricks.size(); ++i)
bouncy_brick_draw(&bouncy_bricks[i]);
for (unsigned int i = 0; i < broken_bricks.size(); ++i)
broken_brick_draw(&broken_bricks[i]);
+ /* Draw foreground: */
+
+ for (y = 0; y < 15; ++y)
+ {
+ for (x = 0; x < 21; ++x)
+ {
+ drawshape(32*x - fmodf(scroll_x, 32), y * 32,
+ current_level.fg_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
+ }
+ }
+
+ /* Draw particle systems (foreground) */
+ for(p = particle_systems.begin(); p != particle_systems.end(); ++p)
+ {
+ (*p)->draw(scroll_x, 0, 1);
+ }
+
drawstatus();
if(game_pause)
menu_process_current();
/* (Update it all!) */
-
updatescreen();
-
-
}
/* --- GAME LOOP! --- */
level_load_gfx(¤t_level);
activate_bad_guys();
+ activate_particle_systems();
level_load_song(¤t_level);
tux.init();
if(st_gl_mode == ST_GL_LOAD_GAME)
loadgame(levelnb);
-
/* --- MAIN GAME LOOP!!! --- */
jump = false;
while (SDL_PollEvent(&event))
- {}
+ {}
game_draw();
do
frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
if(frame_ratio > 1.5) /* Quick hack to correct the unprecise CPU clocks a little bit. */
frame_ratio = 1.5 + (frame_ratio - 1.5) * 0.85;
-
+
if(!timer_check(&frame_timer))
{
timer_start(&frame_timer,25);
/* == -1: continues */
return 0;
}
- /* --z;
- }*/
+ /* --z;
+ }*/
}
else
{
last_update_time = update_time;
update_time = st_get_ticks();
-
/* Pause till next frame, if the machine running the game is too fast: */
/* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
/* Draw a tile on the screen: */
-void drawshape(float x, float y, unsigned char c)
+void drawshape(float x, float y, unsigned int c)
{
int z;
+ Tile* ptile = TileManager::instance()->get
+ (c);
+ if(ptile)
+ {
+ if(ptile->images.size() > 1)
+ {
+ texture_draw(&ptile->images[( ((global_frame_counter*25) / ptile->anim_speed) % (ptile->images.size()))],x,y);
+ }
+ else
+ {
+ texture_draw(&ptile->images[0],x,y);
+ }
+ }
+
+ /*
if (c == 'X' || c == 'x')
texture_draw(&img_brick[0], x, y);
else if (c == 'Y' || c == 'y')
texture_draw(&img_flag[z], x + 16, y);
}
else if (c == '&')
- texture_draw(&img_water, x, y);
+ texture_draw(&img_water, x, y);*/
+
}
/* What shape is at some position? */
-unsigned char shape(float x, float y)
+unsigned int shape(float x, float y)
{
int xx, yy;
- unsigned char c;
+ unsigned int c;
yy = ((int)y / 32);
xx = ((int)x / 32);
if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
{
- c = current_level.tiles[yy][xx];
+ c = current_level.ia_tiles[yy][xx];
}
else
c = '.';
bool issolid(float x, float y)
{
- return (isbrick(x, y) ||
- isice(x, y) ||
- (shape(x, y) == '[') ||
- (shape(x, y) == '=') ||
- (shape(x, y) == ']') ||
- (shape(x, y) == 'A') ||
- (shape(x, y) == 'B') ||
- (shape(x, y) == '!') ||
- (shape(x, y) == 'a'));
+ Tile* tile = TileManager::instance()->get
+ (shape(x,y));
+ if(tile)
+ {
+ if(tile->solid == true)
+ return true;
+ else
+ return false;
+ }
+ else
+ {
+ return false;
+ }
}
/* Is it a brick? */
bool isbrick(float x, float y)
{
- return (shape(x, y) == 'X' ||
- shape(x, y) == 'x' ||
- shape(x, y) == 'Y' ||
- shape(x, y) == 'y');
+ Tile* tile = TileManager::instance()->get
+ (shape(x,y));
+ if(tile)
+ {
+ if(tile->brick == true)
+ return true;
+ else
+ return false;
+ }
+ else
+ {
+ return false;
+ }
}
bool isice(float x, float y)
{
- return (shape(x, y) == '#');
+ Tile* tile = TileManager::instance()->get
+ (shape(x,y));
+ if(tile)
+ {
+ if(tile->ice == true)
+ return true;
+ else
+ return false;
+ }
+ else
+ {
+ return false;
+ }
}
/* Is it a full box? */
bool isfullbox(float x, float y)
{
- return (shape(x, y) == 'A' ||
- shape(x, y) == 'B' ||
- shape(x, y) == '!');
+ Tile* tile = TileManager::instance()->get
+ (shape(x,y));
+ if(tile)
+ {
+ if(tile->fullbox == true)
+ return true;
+ else
+ return false;
+ }
+ else
+ {
+ return false;
+ }
}
/* Break a brick: */
}
if (distro_counter <= 0)
- level_change(¤t_level,x, y, 'a');
+ level_change(¤t_level,x, y, TM_IA, 'a');
play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
score = score + SCORE_DISTRO;
{
/* Get rid of it: */
- level_change(¤t_level,x, y,'.');
+ level_change(¤t_level,x, y, TM_IA, '.');
}
}
/* Empty the box: */
- level_change(¤t_level,x, y, 'a');
+ level_change(¤t_level,x, y, TM_IA, 'a');
}
{
if (shape(x, y) == '$')
{
- level_change(¤t_level,x, y, '.');
+ level_change(¤t_level,x, y, TM_IA, '.');
play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
if (bounciness == BOUNCE)
arrays_free();
arrays_init();
activate_bad_guys();
+ activate_particle_systems();
level_free_gfx();
level_load_gfx(¤t_level);
level_free_song();
bool isice(float x, float y);
bool isfullbox(float x, float y);
bool rectcollision(base_type* one, base_type* two);
-void drawshape(float x, float y, unsigned char c);
-unsigned char shape(float x, float y);
+void drawshape(float x, float y, unsigned int c);
+unsigned int shape(float x, float y);
void bumpbrick(float x, float y);
void trygrabdistro(float x, float y, int bounciness);
void trybreakbrick(float x, float y);
for(i = 0; i < 15; ++i)
{
- plevel->tiles[i] = (unsigned int*) malloc((plevel->width+1)*sizeof(unsigned int));
- plevel->tiles[i][plevel->width] = (unsigned int) '\0';
+ plevel->ia_tiles[i] = (unsigned int*) malloc((plevel->width+1)*sizeof(unsigned int));
+ plevel->ia_tiles[i][plevel->width] = (unsigned int) '\0';
for(y = 0; y < plevel->width; ++y)
- plevel->tiles[i][y] = (unsigned int) '.';
- plevel->tiles[i][plevel->width] = (unsigned int) '\0';
+ plevel->ia_tiles[i][y] = (unsigned int) '.';
+ plevel->ia_tiles[i][plevel->width] = (unsigned int) '\0';
+
+ plevel->bg_tiles[i] = (unsigned int*) malloc((plevel->width+1)*sizeof(unsigned int));
+ plevel->bg_tiles[i][plevel->width] = (unsigned int) '\0';
+ for(y = 0; y < plevel->width; ++y)
+ plevel->bg_tiles[i][y] = (unsigned int) '.';
+ plevel->bg_tiles[i][plevel->width] = (unsigned int) '\0';
+
+ plevel->fg_tiles[i] = (unsigned int*) malloc((plevel->width+1)*sizeof(unsigned int));
+ plevel->fg_tiles[i][plevel->width] = (unsigned int) '\0';
+ for(y = 0; y < plevel->width; ++y)
+ plevel->fg_tiles[i][y] = (unsigned int) '.';
+ plevel->fg_tiles[i][plevel->width] = (unsigned int) '\0';
+
+ plevel->dn_tiles[i] = (unsigned int*) malloc((plevel->width+1)*sizeof(unsigned int));
+ plevel->dn_tiles[i][plevel->width] = (unsigned int) '\0';
+ for(y = 0; y < plevel->width; ++y)
+ plevel->dn_tiles[i][y] = (unsigned int) '.';
+ plevel->dn_tiles[i][plevel->width] = (unsigned int) '\0';
}
}
int level_load(st_level* plevel, const char* filename)
{
- int x, y;
+ int x, y, j;
FILE * fi;
lisp_object_t* root_obj = 0;
fi = fopen(filename, "r");
printf("World: Parse Error in file %s", filename);
}
- vector<int> vi;
+ vector<int> ia_tm;
+ vector<int> dn_tm;
+ vector<int> bg_tm;
+ vector<int> fg_tm;
if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-level") == 0)
{
LispReader reader(lisp_cdr(root_obj));
-
+
reader.read_int("width", &plevel->width);
reader.read_int("time", &plevel->time_left);
reader.read_int("bkgd_red", &plevel->bkgd_red);
reader.read_string("theme", &plevel->theme);
reader.read_string("music", &plevel->song_title);
reader.read_string("background", &plevel->bkgd_image);
- reader.read_int_vector("tilemap", &vi);
+ reader.read_string("particle_system", &plevel->particle_system);
+ reader.read_int_vector("background-tm", &bg_tm);
+ reader.read_int_vector("interactive-tm", &ia_tm);
+ reader.read_int_vector("dynamic-tm", &dn_tm);
+ reader.read_int_vector("foreground-tm", &fg_tm);
}
-
-
+
+
int i;
for( i = 0; i < 15; ++i)
- plevel->tiles[i] = (unsigned int*) calloc((plevel->width +1) , sizeof(unsigned int) );
+ {
+ plevel->dn_tiles[i] = (unsigned int*) calloc((plevel->width +1) , sizeof(unsigned int) );
+ plevel->ia_tiles[i] = (unsigned int*) calloc((plevel->width +1) , sizeof(unsigned int) );
+ plevel->bg_tiles[i] = (unsigned int*) calloc((plevel->width +1) , sizeof(unsigned int) );
+ plevel->fg_tiles[i] = (unsigned int*) calloc((plevel->width +1) , sizeof(unsigned int) );
+ }
+
+ i = j = 0;
+ for(vector<int>::iterator it = ia_tm.begin(); it != ia_tm.end(); ++it, ++i)
+ {
+
+ plevel->ia_tiles[j][i] = (*it);
+ if(i == plevel->width - 1)
+ {
+ i = -1;
+ ++j;
+ }
+ }
+
+ i = j = 0;
+ for(vector<int>::iterator it = dn_tm.begin(); it != dn_tm.end(); ++it, ++i)
+ {
+
+ plevel->dn_tiles[j][i] = (*it);
+ if(i == plevel->width - 1)
+ {
+ i = -1;
+ ++j;
+ }
+ }
+
+ i = j = 0;
+ for(vector<int>::iterator it = bg_tm.begin(); it != bg_tm.end(); ++it, ++i)
+ {
+
+ plevel->bg_tiles[j][i] = (*it);
+ if(i == plevel->width - 1)
+ {
+ i = -1;
+ ++j;
+ }
+ }
- i = 0;
- int j = 0;
- for(vector<int>::iterator it = vi.begin(); it != vi.end(); ++it, ++i)
+ i = j = 0;
+ for(vector<int>::iterator it = fg_tm.begin(); it != fg_tm.end(); ++it, ++i)
{
- plevel->tiles[j][i] = (*it);
+ plevel->fg_tiles[j][i] = (*it);
if(i == plevel->width - 1)
{
i = -1;
/* Set the global gravity to the latest loaded level's gravity */
gravity = plevel->gravity;
- /* Mark the end position of this level! - Is a bit wrong here thought */
+ /* Mark the end position of this level! - Is a bit wrong here thought * /
for (y = 0; y < 15; ++y)
{
endpos = x*32;
}
}
- }
+ }*/
fclose(fi);
return 0;
}
- /* Write header: */
- fprintf(fi,";SuperTux-Level\n");
- fprintf(fi,"(supertux-level\n");
-
- fprintf(fi," (name \"%s\")\n", plevel->name.c_str());
- fprintf(fi," (theme \"%s\")\n", plevel->theme.c_str());
- fprintf(fi," (music \"%s\")\n", plevel->song_title.c_str());
- fprintf(fi," (background \"%s\")\n", plevel->bkgd_image.c_str());
- fprintf(fi," (bkgd_red %d)\n", plevel->bkgd_red);
- fprintf(fi," (bkgd_green %d)\n", plevel->bkgd_green);
- fprintf(fi," (bkgd_blue %d)\n", plevel->bkgd_blue);
- fprintf(fi," (time %d)\n", plevel->time_left);
- fprintf(fi," (width %d)\n", plevel->width);
- fprintf(fi," (gravity %2.1f)\n", plevel->gravity);
- fprintf(fi," (tilemap ");
-
+ /* Write header: */
+ fprintf(fi,";SuperTux-Level\n");
+ fprintf(fi,"(supertux-level\n");
+
+ fprintf(fi," (name \"%s\")\n", plevel->name.c_str());
+ fprintf(fi," (theme \"%s\")\n", plevel->theme.c_str());
+ fprintf(fi," (music \"%s\")\n", plevel->song_title.c_str());
+ fprintf(fi," (background \"%s\")\n", plevel->bkgd_image.c_str());
+ fprintf(fi," (particle_system \"%s\")\n", plevel->particle_system.c_str());
+ fprintf(fi," (bkgd_red %d)\n", plevel->bkgd_red);
+ fprintf(fi," (bkgd_green %d)\n", plevel->bkgd_green);
+ fprintf(fi," (bkgd_blue %d)\n", plevel->bkgd_blue);
+ fprintf(fi," (time %d)\n", plevel->time_left);
+ fprintf(fi," (width %d)\n", plevel->width);
+ fprintf(fi," (gravity %2.1f)\n", plevel->gravity);
+ fprintf(fi," (background-tm ");
+
+ for(y = 0; y < 15; ++y)
+ {
+ for(i = 0; i < plevel->width; ++i)
+ fprintf(fi," %d ", plevel->bg_tiles[y][i]);
+ }
+
+ fprintf( fi,")\n");
+ fprintf(fi," (interactive-tm ");
+
for(y = 0; y < 15; ++y)
{
- for(i = 0; i < plevel->width; ++i)
- fprintf(fi," %d ", plevel->tiles[y][i]);
+ for(i = 0; i < plevel->width; ++i)
+ fprintf(fi," %d ", plevel->ia_tiles[y][i]);
}
-
- fprintf( fi,")");
- fprintf( fi,")\n");
+
+ fprintf( fi,")\n");
+ fprintf(fi," (dynamic-tm ");
+
+ for(y = 0; y < 15; ++y)
+ {
+ for(i = 0; i < plevel->width; ++i)
+ fprintf(fi," %d ", plevel->dn_tiles[y][i]);
+ }
+
+ fprintf( fi,")\n");
+ fprintf(fi," (foreground-tm ");
+
+ for(y = 0; y < 15; ++y)
+ {
+ for(i = 0; i < plevel->width; ++i)
+ fprintf(fi," %d ", plevel->fg_tiles[y][i]);
+ }
+
+ fprintf( fi,")");
+ fprintf( fi,")\n");
fclose(fi);
}
{
int i;
for(i=0; i < 15; ++i)
- free(plevel->tiles[i]);
+ free(plevel->bg_tiles[i]);
+ for(i=0; i < 15; ++i)
+ free(plevel->ia_tiles[i]);
+ for(i=0; i < 15; ++i)
+ free(plevel->dn_tiles[i]);
+ for(i=0; i < 15; ++i)
+ free(plevel->fg_tiles[i]);
plevel->name.clear();
plevel->theme.clear();
texture_load(ptexture, fname, use_alpha);
}
+void tilemap_change_size(unsigned int** tilemap[15], int w, int old_w)
+{
+ int j,y;
+ for(y = 0; y < 15; ++y)
+ {
+ *tilemap[y] = (unsigned int*) realloc(*tilemap[y],(w+1)*sizeof(unsigned int));
+ if(w > old_w)
+ for(j = 0; j < w - old_w; ++j)
+ *tilemap[y][old_w+j] = 0;
+ *tilemap[y][w] = 0;
+ }
+}
+
+/* Change the size of a level (width) */
+void level_change_size (st_level* plevel, int new_width)
+{
+ int y;
+
+ if(new_width < 21)
+ new_width = 21;
+ tilemap_change_size((unsigned int***)&plevel->ia_tiles,new_width,plevel->width);
+ tilemap_change_size((unsigned int***)&plevel->dn_tiles,new_width,plevel->width);
+ tilemap_change_size((unsigned int***)&plevel->bg_tiles,new_width,plevel->width);
+ tilemap_change_size((unsigned int***)&plevel->fg_tiles,new_width,plevel->width);
+ plevel->width = new_width;
+
+}
+
/* Edit a piece of the map! */
-void level_change(st_level* plevel, float x, float y, unsigned char c)
+void level_change(st_level* plevel, float x, float y, int tm, unsigned int c)
{
int xx, yy;
xx = ((int)x / 32);
if (yy >= 0 && yy < 15 && xx >= 0 && xx <= plevel->width)
- plevel->tiles[yy][xx] = c;
+ {
+ switch(tm)
+ {
+ case 0:
+ plevel->bg_tiles[yy][xx] = c;
+ case 1:
+ plevel->ia_tiles[yy][xx] = c;
+ case 2:
+ plevel->dn_tiles[yy][xx] = c;
+ case 4:
+ plevel->fg_tiles[yy][xx] = c;
+ }
+ }
}
/* Free music data for this level: */
std::string theme;
std::string song_title;
std::string bkgd_image;
- unsigned int* tiles[15];
+ std::string particle_system;
+ unsigned int* bg_tiles[15]; /* Tiles in the background */
+ unsigned int* ia_tiles[15]; /* Tiles which can interact in the game (solids for example)*/
+ unsigned int* dn_tiles[15]; /* Dynamic tiles (bad guys and moving platforms for example)*/
+ unsigned int* fg_tiles[15]; /* Tiles in the foreground */
int time_left;
int bkgd_red;
int bkgd_green;
float gravity;
};
+enum {
+ TM_BG,
+ TM_IA,
+ TM_DN,
+ TM_FG
+ };
+
extern texture_type img_bkgd, img_bkgd_tile[2][4], img_solid[4], img_brick[2];
void level_default (st_level* plevel);
void level_save (st_level* plevel, const char * subset, int level);
void level_free (st_level* plevel);
void level_load_gfx (st_level* plevel);
-void level_change (st_level* plevel, float x, float y, unsigned char c);
+void level_change (st_level* plevel, float x, float y, int tm, unsigned int c);
+void level_change_size (st_level* plevel, int new_width);
void level_load_song(st_level* plevel);
void level_free_gfx();
void level_load_image(texture_type* ptexture, std::string theme, const char * file, int use_alpha);
void le_drawlevel();
void le_drawinterface();
void le_checkevents();
-void le_change(float x, float y, unsigned char c);
+void le_change(float x, float y, int tm, unsigned int c);
void le_testlevel();
void le_showhelp();
void le_set_defaults(void);
for (y = 0; y < 15; ++y)
for (x = 0; x < le_current_level->width; ++x)
- if (le_current_level->tiles[y][x] >= '0' && le_current_level->tiles[y][x] <= '9')
- add_bad_guy(x * 32, y * 32, static_cast<BadGuyKind>(le_current_level->tiles[y][x] - '0'));
+ if (le_current_level->dn_tiles[y][x] >= '0' && le_current_level->dn_tiles[y][x] <= '9')
+ add_bad_guy(x * 32, y * 32, static_cast<BadGuyKind>(le_current_level->dn_tiles[y][x] - '0'));
+
+
+
}
void le_set_defaults()
le_current_level->song_title = string_list_active(level_settings_menu->item[4].list);
- i = le_current_level->width;
- le_current_level->width = atoi(level_settings_menu->item[6].input);
- if(le_current_level->width < i)
- {
- if(le_current_level->width < 21)
- le_current_level->width = 21;
- for(y = 0; y < 15; ++y)
- {
- le_current_level->tiles[y] = (unsigned int*) realloc(le_current_level->tiles[y],(le_current_level->width+1)*sizeof(unsigned int));
- le_current_level->tiles[y][le_current_level->width] = (unsigned int) '\0';
- }
- }
- else if(le_current_level->width > i)
- {
- for(y = 0; y < 15; ++y)
- {
- le_current_level->tiles[y] = (unsigned int*) realloc(le_current_level->tiles[y],(le_current_level->width+1)*sizeof(unsigned int));
- for(j = 0; j < le_current_level->width - i; ++j)
- le_current_level->tiles[y][i+j] = (unsigned int) '.';
- le_current_level->tiles[y][le_current_level->width] = (unsigned int) '\0';
- }
- }
+ level_change_size(le_current_level, atoi(level_settings_menu->item[6].input));
le_current_level->time_left = atoi(level_settings_menu->item[7].input);
le_current_level->gravity = atof(level_settings_menu->item[8].input);
le_current_level->bkgd_red = atoi(level_settings_menu->item[9].input);
for (y = 0; y < 15; ++y)
for (x = 0; x < 20; ++x)
{
- drawshape(x * 32 - ((int)pos_x % 32), y * 32,
- le_current_level->tiles[y][x + (int)(pos_x / 32)]);
+ drawshape(x * 32 - ((int)pos_x % 32), y * 32, le_current_level->ia_tiles[y][x + (int)(pos_x / 32)]);
/* draw whats inside stuff when cursor is selecting those */
/* (draw them all the time - is this the right behaviour?) */
- switch(le_current_level->tiles[y][x + (int)(pos_x/32)])
+ switch(le_current_level->ia_tiles[y][x + (int)(pos_x/32)])
{
case 'B':
texture_draw(&img_mints, x * 32 - ((int)pos_x % 32), y*32);
if(le_mouse_pressed[LEFT])
{
- le_change(cursor_x, cursor_y, le_current_tile);
+ le_change(cursor_x, cursor_y, TM_IA, le_current_tile);
}
}
}
fillrect(x1*32-pos_x, y1*32,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
}
-void le_change(float x, float y, unsigned char c)
+void le_change(float x, float y, int tm, unsigned int c)
{
if(le_current_level != NULL)
{
switch(le_selection_mode)
{
case CURSOR:
- level_change(le_current_level,x,y,c);
+ level_change(le_current_level,x,y,tm,c);
yy = ((int)y / 32);
xx = ((int)x / 32);
for(xx = x1; xx <= x2; xx++)
for(yy = y1; yy <= y2; yy++)
{
- level_change(le_current_level, xx*32, yy*32, c);
+ level_change(le_current_level, xx*32, yy*32, tm, c);
if(c == '0') // if it's a bad guy
add_bad_guy(xx*32, yy*32, BAD_BSOD);
--- /dev/null
+// $Id$
+//
+// SuperTux
+// Copyright (C) 2004 Matthias Braun <matze@braunis.de>
+//
+// This program 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.
+//
+// This program 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 this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#include "particlesystem.h"
+
+#include <iostream>
+#include <math.h>
+#include "globals.h"
+#include "scene.h"
+
+ParticleSystem::ParticleSystem()
+{
+ virtual_width = screen->w;
+ virtual_height = screen->h;
+}
+
+ParticleSystem::~ParticleSystem()
+{
+ std::vector<Particle*>::iterator i;
+ for(i = particles.begin(); i != particles.end(); ++i) {
+ delete *i;
+ }
+}
+
+void ParticleSystem::draw(float scrollx, float scrolly, int layer)
+{
+ std::vector<Particle*>::iterator i;
+ for(i = particles.begin(); i != particles.end(); ++i) {
+ Particle* particle = *i;
+ if(particle->layer != layer)
+ continue;
+
+ // remap x,y coordinates onto screencoordinates
+ float x = fmodf(particle->x - scrollx, virtual_width);
+ if(x < 0) x += virtual_width;
+ float y = fmodf(particle->y - scrolly, virtual_height);
+ if(y < 0) y += virtual_height;
+ float xmax = fmodf(x + particle->texture->w, virtual_width);
+ float ymax = fmodf(y + particle->texture->h, virtual_height);
+
+ // particle on screen
+ if(x >= screen->w && xmax >= screen->w)
+ continue;
+ if(y >= screen->h && ymax >= screen->h)
+ continue;
+
+ if(x > screen->w) x -= virtual_width;
+ if(y > screen->h) y -= virtual_height;
+ texture_draw(particle->texture, x, y);
+ }
+}
+
+SnowParticleSystem::SnowParticleSystem()
+{
+ texture_load(&snowimages[0], datadir+"/images/shared/snow0.png", USE_ALPHA);
+ texture_load(&snowimages[1], datadir+"/images/shared/snow1.png", USE_ALPHA);
+ texture_load(&snowimages[2], datadir+"/images/shared/snow2.png", USE_ALPHA);
+
+ virtual_width = screen->w * 2;
+
+ // create some random snowflakes
+ size_t snowflakecount = size_t(virtual_width/10.0);
+ for(size_t i=0; i<snowflakecount; ++i) {
+ SnowParticle* particle = new SnowParticle;
+ particle->x = rand() % int(virtual_width);
+ particle->y = rand() % screen->h;
+ particle->layer = i % 2;
+ int snowsize = rand() % 3;
+ particle->texture = &snowimages[snowsize];
+ particle->speed = 0.01 + snowsize/50.0 + (rand()%(int)gravity/15.0);
+
+ particles.push_back(particle);
+ }
+}
+
+SnowParticleSystem::~SnowParticleSystem()
+{
+ for(int i=0;i<3;++i)
+ texture_free(&snowimages[i]);
+}
+
+void SnowParticleSystem::simulate(float elapsed_time)
+{
+ std::vector<Particle*>::iterator i;
+ for(i = particles.begin(); i != particles.end(); ++i) {
+ SnowParticle* particle = (SnowParticle*) *i;
+ particle->y += particle->speed * elapsed_time;
+ if(particle->y > screen->h) {
+ particle->y = 0;
+ particle->x = rand() % int(virtual_width);
+ }
+ }
+}
+
+CloudParticleSystem::CloudParticleSystem()
+{
+ texture_load(&cloudimage, datadir + "/images/shared/cloud.png", USE_ALPHA);
+
+ virtual_width = 5000.0;
+
+ // create some random clouds
+ for(size_t i=0; i<15; ++i) {
+ CloudParticle* particle = new CloudParticle;
+ particle->x = rand() % int(virtual_width);
+ particle->y = rand() % int((float) screen->h * 0.3333);
+ particle->layer = 0;
+ particle->texture = &cloudimage;
+ particle->speed = -float(250 + rand() % 200) / 1000.0;
+
+ particles.push_back(particle);
+ }
+}
+
+CloudParticleSystem::~CloudParticleSystem()
+{
+ texture_free(&cloudimage);
+}
+
+void CloudParticleSystem::simulate(float elapsed_time)
+{
+ std::vector<Particle*>::iterator i;
+ for(i = particles.begin(); i != particles.end(); ++i) {
+ CloudParticle* particle = (CloudParticle*) *i;
+ particle->x += particle->speed * elapsed_time;
+ }
+}
--- /dev/null
+// $Id$
+//
+// SuperTux
+// Copyright (C) 2004 Matthias Braun <matze@braunis.de>
+//
+// This program 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.
+//
+// This program 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 this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#ifndef SUPERTUX_PARTICLESYSTEM_H
+#define SUPERTUX_PARTICLESYSTEM_H
+
+#include <vector>
+#include "texture.h"
+
+/**
+ * This is the base class for particle systems. It is responsible for storing a
+ * set of particles with each having an x- and y-coordinate the number of the
+ * layer where it should be drawn and a texture.
+ * The coordinate system used here is a virtual one. It would be a bad idea to
+ * populate whole levels with particles. So we're using a virtual rectangle
+ * here that is tiled onto the level when drawing. This rectangle has the size
+ * (virtual_width, virtual_height). We're using modulo on the particle
+ * coordinates, so when a particle leaves left, it'll reenter at the right
+ * side.
+ *
+ * Classes that implement a particle system should subclass from this class,
+ * initialize particles in the constructor and move them in the simulate
+ * function.
+ */
+class ParticleSystem
+{
+public:
+ ParticleSystem();
+ virtual ~ParticleSystem();
+
+ void draw(float scrollx, float scrolly, int layer);
+
+ virtual void simulate(float elapsed_time) = 0;
+
+protected:
+ class Particle
+ {
+ public:
+ virtual ~Particle()
+ { }
+
+ float x, y;
+ int layer;
+ texture_type* texture;
+ };
+
+ std::vector<Particle*> particles;
+ float virtual_width, virtual_height;
+};
+
+class SnowParticleSystem : public ParticleSystem
+{
+public:
+ SnowParticleSystem();
+ virtual ~SnowParticleSystem();
+
+ virtual void simulate(float elapsed_time);
+
+private:
+ class SnowParticle : public Particle
+ {
+ public:
+ float speed;
+ };
+
+ texture_type snowimages[3];
+};
+
+class CloudParticleSystem : public ParticleSystem
+{
+public:
+ CloudParticleSystem();
+ virtual ~CloudParticleSystem();
+
+ virtual void simulate(float elapsed_time);
+
+private:
+ class CloudParticle : public Particle
+ {
+ public:
+ float speed;
+ };
+
+ texture_type cloudimage;
+};
+
+#endif
+
}
if (distro_counter <= 0)
- level_change(¤t_level,base.x,base.y - 1, 'a');
-
+ level_change(¤t_level,base.x,base.y - 1, TM_IA, 'a');
+
play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
score = score + SCORE_DISTRO;
distros++;
}
if (distro_counter <= 0)
- level_change(¤t_level,base.x+ 31, base.y, 'a');
+ level_change(¤t_level,base.x+ 31, base.y, TM_IA, 'a');
play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
score = score + SCORE_DISTRO;
#include "world.h"
#include "special.h"
#include "level.h"
+#include "particlesystem.h"
#define FRAME_RATE 10 // 100 Frames per second (10ms)
extern timer_type super_bkgd_timer;
extern float scroll_x;
-extern int global_frame_counter;
+extern unsigned int global_frame_counter;
extern std::vector<bouncy_distro_type> bouncy_distros;
extern std::vector<broken_brick_type> broken_bricks;
extern std::vector<bouncy_brick_type> bouncy_bricks;
extern std::vector<floating_score_type> floating_scores;
extern std::vector<upgrade_type> upgrades;
extern std::vector<bullet_type> bullets;
+extern std::vector<ParticleSystem*> particle_systems;
extern Player tux;
extern texture_type img_box_full, img_box_empty, img_mints, img_coffee, img_super_bkgd, img_red_glow;
extern timer_type time_left;
return true;
}
-/* Makes sure a directory is created in either the SuperTux base directory or the SuperTux base directory.*/
+/* Makes sure a directory is created in either the SuperTux home directory or the SuperTux base directory.*/
int fcreatedir(const char* relative_dir)
{
char path[1024];
void texture_draw_sdl(texture_type* ptexture, float x, float y, bool update)
{
-
SDL_Rect dest;
dest.x = (int)x;
--- /dev/null
+//
+// C++ Implementation: tile
+//
+// Description:
+//
+//
+// Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#include "tile.h"
+#include "assert.h"
+
+TileManager* TileManager::instance_ = 0;
+
+TileManager::TileManager()
+{
+ std::string filename = datadir + "images/tilesets/main.stgt";
+ load_tileset(filename);
+}
+
+void TileManager::load_tileset(std::string filename)
+{
+ lisp_object_t* root_obj = lisp_read_from_file(filename);
+
+ if (!root_obj)
+ st_abort("Couldn't load file", filename);
+
+ if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-tiles") == 0)
+ {
+ lisp_object_t* cur = lisp_cdr(root_obj);
+ int tileset_id = 0;
+
+ while(!lisp_nil_p(cur))
+ {
+ lisp_object_t* element = lisp_car(cur);
+
+ if (strcmp(lisp_symbol(lisp_car(element)), "tile") == 0)
+ {
+ int id = 0;
+ std::vector<std::string> filenames;
+
+ Tile* tile = new Tile;
+ tile->solid = false;
+ tile->brick = false;
+ tile->ice = false;
+ tile->fullbox = false;
+ tile->alpha = 0;
+ tile->anim_speed = 25;
+
+ LispReader reader(lisp_cdr(element));
+ reader.read_int("id", &id);
+ reader.read_bool("solid", &tile->solid);
+ reader.read_bool("brick", &tile->brick);
+ reader.read_bool("ice", &tile->ice);
+ reader.read_bool("fullbox", &tile->fullbox);
+ reader.read_int("alpha", (int*)&tile->alpha);
+ reader.read_int("anim-speed", &tile->anim_speed);
+ reader.read_string_vector("images", &filenames);
+
+ for(std::vector<std::string>::iterator it = filenames.begin(); it != filenames.end(); ++it)
+ {
+ texture_type cur_image;
+ tile->images.push_back(cur_image);
+ texture_load(&tile->images[tile->images.size()-1],
+ datadir + "images/tilesets/" + (*it),
+ USE_ALPHA);
+ }
+
+ if (id+tileset_id >= int(tiles.size()))
+ tiles.resize(id+tileset_id+1);
+
+ tiles[id+tileset_id] = tile;
+ }
+ else if (strcmp(lisp_symbol(lisp_car(element)), "tileset") == 0)
+ {
+ LispReader reader(lisp_cdr(element));
+ std::string filename;
+ reader.read_string("file", &filename);
+ filename = datadir + "images/tilesets/" + filename;
+ load_tileset(filename);
+ }
+ else if (strcmp(lisp_symbol(lisp_car(element)), "properties") == 0)
+ {
+ LispReader reader(lisp_cdr(element));
+ reader.read_int("id", &tileset_id);
+ tileset_id *= 1000;
+ }
+ else
+ {
+ puts("Unhandled symbol");
+ }
+
+ cur = lisp_cdr(cur);
+ }
+ }
+ else
+ {
+ assert(0);
+ }
+}
--- /dev/null
+//
+// C++ Interface: tile
+//
+// Description:
+//
+//
+// Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef TILE_H
+#define TILE_H
+
+#include <vector>
+#include "texture.h"
+#include "globals.h"
+#include "lispreader.h"
+#include "setup.h"
+
+/**
+Tile Class
+*/
+struct Tile
+{
+std::vector<texture_type> images;
+bool solid;
+bool brick;
+bool ice;
+bool fullbox;
+int anim_speed;
+unsigned char alpha;
+};
+
+class TileManager
+{
+private:
+ TileManager();
+ std::vector<Tile*> tiles;
+ static TileManager* instance_ ;
+ void load_tileset(std::string filename);
+
+public:
+ static TileManager* instance() { return instance_ ? instance_ : instance_ = new TileManager(); }
+ Tile* get(unsigned int id) { if( id < tiles.size()) { return tiles[id]; } else { return NULL; } } ;
+
+};
+
+#endif