X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fgameobjs.cpp;h=ce71deeded1fdc3ef206511d75f90511c2420479;hb=6c61f312a1f5a768e202195ca18ed5a51974bdcc;hp=10b87c391daaf7748bb2486768e3ac044eb58d7d;hpb=9be8218763c8956455cea3c362c19f35916384f3;p=supertux.git diff --git a/src/gameobjs.cpp b/src/gameobjs.cpp index 10b87c391..ce71deede 100644 --- a/src/gameobjs.cpp +++ b/src/gameobjs.cpp @@ -18,224 +18,176 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // 02111-1307, USA. + #include #include -#include "world.h" +#include + +#include "app/globals.h" #include "tile.h" +#include "tile_manager.h" #include "gameloop.h" #include "gameobjs.h" -#include "sprite_manager.h" +#include "special/sprite_manager.h" #include "resources.h" -#include "level.h" +#include "sector.h" +#include "tilemap.h" +#include "video/drawing_context.h" +#include "camera.h" -void -BouncyDistro::init(float x, float y) +BouncyDistro::BouncyDistro(const Vector& pos) + : position(pos) { - base.x = x; - base.y = y; - base.ym = -2; + ym = -2; } void -BouncyDistro::action(double frame_ratio) +BouncyDistro::action(float elapsed_time) { - base.y = base.y + base.ym * frame_ratio; + position.y += ym * elapsed_time; - base.ym += 0.1 * frame_ratio; - - if (base.ym >= 0) - { - std::vector::iterator i - = std::find(World::current()->bouncy_distros.begin(), - World::current()->bouncy_distros.end(), - this); - if (i != World::current()->bouncy_distros.end()) - World::current()->bouncy_distros.erase(i); - } + ym += 0.1 * elapsed_time; // not framerate independent... but who really cares + if(ym >= 0) + remove_me(); } void -BouncyDistro::draw() +BouncyDistro::draw(DrawingContext& context) { - img_distro[0]->draw(base.x - scroll_x, - base.y - scroll_y); + context.draw_surface(img_distro[0], position, LAYER_OBJECTS); } -void -BrokenBrick::init(Tile* tile_, float x, float y, float xm, float ym) +BrokenBrick::BrokenBrick(Tile* ntile,const Vector& pos, const Vector& nmovement) + : tile(ntile), position(pos), movement(nmovement) { - tile = tile_; - base.x = x; - base.y = y; - base.xm = xm; - base.ym = ym; - - timer.init(true); timer.start(200); } void -BrokenBrick::action(double frame_ratio) +BrokenBrick::action(float elapsed_time) { - base.x = base.x + base.xm * frame_ratio; - base.y = base.y + base.ym * frame_ratio; + position += movement * elapsed_time; if (!timer.check()) - { - std::vector::iterator i - = std::find(World::current()->broken_bricks.begin(), - World::current()->broken_bricks.end(), - this); - if (i != World::current()->broken_bricks.end()) - World::current()->broken_bricks.erase(i); - } + remove_me(); } void -BrokenBrick::draw() -{ - SDL_Rect src, dest; - src.x = rand() % 16; - src.y = rand() % 16; - src.w = 16; - src.h = 16; - - dest.x = (int)(base.x - scroll_x); - dest.y = (int)(base.y - scroll_y); - dest.w = 16; - dest.h = 16; - +BrokenBrick::draw(DrawingContext& context) +{ if (tile->images.size() > 0) - tile->images[0]->draw_part(src.x,src.y,dest.x,dest.y,dest.w,dest.h); + context.draw_surface_part(tile->images[0], + Vector(rand() % 16, rand() % 16), + Vector(16, 16), + position, LAYER_OBJECTS + 1); } -void -BouncyBrick::init(float x, float y) -{ - base.x = x; - base.y = y; - offset = 0; - offset_m = -BOUNCY_BRICK_SPEED; - shape = World::current()->get_level()->gettileid(x, y); +BouncyBrick::BouncyBrick(const Vector& pos) + : position(pos), offset(0), offset_m(-BOUNCY_BRICK_SPEED), + shape(Sector::current()->solids->get_tile_id_at(pos)) +{ + shape.hidden = true; } void -BouncyBrick::action(double frame_ratio) +BouncyBrick::action(float elapsed_time) { - offset = (offset + offset_m * frame_ratio); + offset += offset_m * elapsed_time; /* Go back down? */ if (offset < -BOUNCY_BRICK_MAX_OFFSET) offset_m = BOUNCY_BRICK_SPEED; - /* Stop bouncing? */ if (offset >= 0) { - std::vector::iterator i - = std::find(World::current()->bouncy_bricks.begin(), - World::current()->bouncy_bricks.end(), - this); - if (i != World::current()->bouncy_bricks.end()) - World::current()->bouncy_bricks.erase(i); + shape.hidden = false; + remove_me(); } } void -BouncyBrick::draw() +BouncyBrick::draw(DrawingContext& context) { - SDL_Rect dest; - - if (base.x >= scroll_x - 32 && - base.x <= scroll_x + screen->w) - { - dest.x = (int)(base.x - scroll_x); - dest.y = (int)(base.y - scroll_y); - dest.w = 32; - dest.h = 32; - - Level* plevel = World::current()->get_level(); - - // FIXME: overdrawing hack to clean the tile from the screen to - // paint it later at on offseted position - if(plevel->bkgd_image[0] == '\0') - { - fillrect(base.x - scroll_x, base.y - scroll_y, - 32,32, - plevel->bkgd_top.red, plevel->bkgd_top.green, plevel->bkgd_top.blue, 0); -// FIXME: doesn't respect the gradient, futhermore is this necessary at all?? - } - else - { - int s = ((int)scroll_x / 2)%640; - plevel->img_bkgd->draw_part(dest.x + s, dest.y, - dest.x, dest.y,dest.w,dest.h); - } + TileManager::instance()-> + draw_tile(context, shape.id, position + Vector(0, offset), LAYER_TILES+1); +} - Tile::draw(base.x - scroll_x, - base.y - scroll_y + offset, - shape); - } +FloatingText::FloatingText(const Vector& pos, const std::string& text_) + : position(pos), text(text_) +{ + timer.start(1000); + position.x -= text.size() * 8; } -void -FloatingScore::init(float x, float y, int s) +FloatingText::FloatingText(const Vector& pos, int score) + : position(pos) { - base.x = x; - base.y = y - 16; - timer.init(true); timer.start(1000); - value = s; + + // turn int into a string + char str[10]; + snprintf(str, 10, "%d", score); + text = str; + + position.x -= text.size() * 8; } void -FloatingScore::action(double frame_ratio) +FloatingText::action(float elapsed_time) { - base.y = base.y - 2 * frame_ratio; + position.y -= 1.4 * elapsed_time; if(!timer.check()) - { - std::vector::iterator i - = std::find(World::current()->floating_scores.begin(), - World::current()->floating_scores.end(), - this); - if (i != World::current()->floating_scores.end()) - World::current()->floating_scores.erase(i); - } + remove_me(); } +#define FADING_TIME 350 + void -FloatingScore::draw() +FloatingText::draw(DrawingContext& context) { - char str[10]; - sprintf(str, "%d", value); - gold_text->draw(str, (int)base.x + 16 - strlen(str) * 8, (int)base.y, 1); + // make an alpha animation when disapearing + int alpha; + if(timer.get_left() < FADING_TIME) + alpha = timer.get_left() * 255 / FADING_TIME; + else + alpha = 255; + + context.push_transform(); + context.set_alpha(alpha); + + context.draw_text(gold_text, text, position, LEFT_ALLIGN, LAYER_OBJECTS+1); + + context.pop_transform(); } /* Trampoline */ -#define TRAMPOLINE_FRAMES 4 -Sprite *img_trampoline[TRAMPOLINE_FRAMES]; +Sprite *img_trampoline; -void load_object_gfx() +Trampoline::Trampoline(LispReader& reader) { - char sprite_name[16]; + reader.read_float("x", base.x); + reader.read_float("y", base.y); + base.width = 32; + base.height = 32; + power = 7.5; + reader.read_float("power", power); - for (int i = 0; i < TRAMPOLINE_FRAMES; i++) - { - sprintf(sprite_name, "trampoline-%i", i+1); - img_trampoline[i] = sprite_manager->load(sprite_name); - } + frame = 0; + mode = M_NORMAL; + physic.reset(); } -void -Trampoline::init(float x, float y) +Trampoline::Trampoline(float x, float y) { base.x = x; base.y = y; base.width = 32; base.height = 32; + power = 7.5; frame = 0; mode = M_NORMAL; @@ -243,18 +195,27 @@ Trampoline::init(float x, float y) } void -Trampoline::draw() +Trampoline::write(LispWriter& writer) { - img_trampoline[frame]->draw((int)base.x, (int)base.y); + writer.start_list("trampoline"); - frame = 0; + writer.write_float("x", base.x); + writer.write_float("y", base.y); + writer.write_float("power", power); - if (debug_mode) - fillrect(base.x - scroll_x, base.y - scroll_y, base.width, base.height, 75, 75, 0, 150); + writer.end_list("trampoline"); } void -Trampoline::action(double frame_ratio) +Trampoline::draw(DrawingContext& context) +{ + img_trampoline->set_frame(frame); + img_trampoline->draw(context, base, LAYER_OBJECTS); + frame = 0; +} + +void +Trampoline::action(float frame_ratio) { // TODO: Remove if we're too far off the screen @@ -279,7 +240,7 @@ Trampoline::action(double frame_ratio) { /* FIXME: The trampoline object shouldn't know about pplayer objects. */ /* If we're holding the iceblock */ - Player& tux = *World::current()->get_tux(); + Player& tux = *Sector::current()->player; Direction dir = tux.dir; if(dir == RIGHT) @@ -300,11 +261,17 @@ Trampoline::action(double frame_ratio) } } - physic.apply(frame_ratio, base.x, base.y); + physic.apply(frame_ratio, base.x, base.y, Sector::current()->gravity); collision_swept_object_map(&old_base, &base); } void +Trampoline::collision(const MovingObject&, int) +{ + // comes later +} + +void Trampoline::collision(void *p_c_object, int c_object, CollisionType type) { Player* pplayer_c = NULL; @@ -331,8 +298,10 @@ Trampoline::collision(void *p_c_object, int c_object, CollisionType type) else frame = 0; - if (squish_amount < 20) + if (squish_amount < 20) { pplayer_c->physic.set_velocity_y(power); + pplayer_c->fall_mode = Player::TRAMPOLINE_JUMP; + } else if (pplayer_c->physic.get_velocity_y() < 0) pplayer_c->physic.set_velocity_y(-squish_amount/32); } @@ -345,139 +314,237 @@ Trampoline::collision(void *p_c_object, int c_object, CollisionType type) } } +/* Flying Platform */ -/* Object Manager */ -//--------------------------------------------------------------------------- +Sprite *img_flying_platform; -ObjectManager::ObjectManager() +FlyingPlatform::FlyingPlatform(LispReader& reader) { - std::string filename = datadir + "/images/tilesets/supertux.stbg"; - load_badguys(filename); + reader.read_int_vector("x", pos_x); + reader.read_int_vector("y", pos_y); + + velocity = 2.0; + reader.read_float("velocity", velocity); + + base.x = pos_x[0]; + base.y = pos_y[0]; + base.width = 96; + base.height = 40; + + point = 0; + move = false; + + float x = pos_x[point+1] - pos_x[point]; + float y = pos_y[point+1] - pos_y[point]; + vel_x = x*velocity / sqrt(x*x + y*y); + vel_y = -(velocity - vel_x); + + frame = 0; } -ObjectManager::~ObjectManager() +FlyingPlatform::FlyingPlatform(int x, int y) { - for(std::vector::iterator i = badguys.begin(); i != badguys.end(); ++i) { - delete *i; - } +base.x = x; +base.y = y; +point = 0; +move = false; +} + +void +FlyingPlatform::write(LispWriter& writer) +{ + writer.start_list("flying-trampoline"); + + writer.write_int_vector("x", pos_x); + writer.write_int_vector("y", pos_y); + writer.write_float("velocity", velocity); + + writer.end_list("flying-trampoline"); } -void ObjectManager::load_badguys(std::string filename) +void +FlyingPlatform::draw(DrawingContext& context) +{ + img_flying_platform->draw(context, base, LAYER_OBJECTS); +} + +void +FlyingPlatform::action(float frame_ratio) { + // TODO: Remove if we're too far off the screen + +if(!move) + return; + +if((unsigned)point+1 != pos_x.size()) + { + if(((pos_x[point+1] > pos_x[point] && base.x >= pos_x[point+1]) || + (pos_x[point+1] < pos_x[point] && base.x <= pos_x[point+1]) || + pos_x[point] == pos_x[point+1]) && + ((pos_y[point+1] > pos_y[point] && base.y >= pos_y[point+1]) || + (pos_y[point+1] < pos_y[point] && base.y <= pos_y[point+1]) || + pos_y[point] == pos_y[point+1])) + { + point++; + + float x = pos_x[point+1] - pos_x[point]; + float y = pos_y[point+1] - pos_y[point]; + vel_x = x*velocity / sqrt(x*x + y*y); + vel_y = -(velocity - vel_x); + } + } +else // last point + { + // point = 0; + // reverse vector + return; + } /* - lisp_object_t* root_obj = lisp_read_from_file(filename); +if(pos_x[point+1] > base.x) + base.x += velocity * frame_ratio; +else if(pos_x[point+1] < base.x) + base.x -= velocity * frame_ratio; + +if(pos_y[point+1] > base.y) + base.y += velocity * frame_ratio; +else if(pos_y[point+1] < base.y) + base.y -= velocity * frame_ratio; +*/ + +base.x += vel_x * frame_ratio; +base.y += vel_y * frame_ratio; +} - if (!root_obj) - st_abort("Couldn't load file", filename); +void +FlyingPlatform::collision(const MovingObject&, int) +{ + // comes later +} + +void +FlyingPlatform::collision(void *p_c_object, int c_object, CollisionType type) +{ +(void) p_c_object; +(void) type; - if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-badguys") == 0) +// Player* pplayer_c = NULL; + switch (c_object) + { + case CO_PLAYER: +// pplayer_c = (Player*) p_c_object; + move = true; + + break; + + default: + break; + + } +} + +Sprite *img_smoke_cloud; + +SmokeCloud::SmokeCloud(const Vector& pos) + : position(pos) +{ + timer.start(300); +} + +void +SmokeCloud::action(float elapsed_time) +{ + position.y -= 1.2 * elapsed_time; + + if(!timer.check()) + remove_me(); +} + +void +SmokeCloud::draw(DrawingContext& context) +{ + img_smoke_cloud->draw(context, position, LAYER_OBJECTS+1); +} + +Particles::Particles(const Vector& epicenter, int min_angle, int max_angle, const Vector& initial_velocity, const Vector& acceleration, int number, Color color_, int size_, int life_time, int drawing_layer_) + : accel(acceleration), color(color_), size(size_), drawing_layer(drawing_layer_) +{ + if(life_time == 0) { - lisp_object_t* cur = lisp_cdr(root_obj); - - while(!lisp_nil_p(cur)) - { - lisp_object_t* element = lisp_car(cur); - - if (strcmp(lisp_symbol(lisp_car(element)), "badguy") == 0) - { - - - Tile* tile = new Tile; - tile->id = -1; - tile->solid = false; - tile->brick = false; - tile->ice = false; - tile->water = false; - tile->fullbox = false; - tile->distro = false; - tile->goal = false; - tile->data = 0; - tile->next_tile = 0; - tile->anim_speed = 25; - - LispReader reader(lisp_cdr(element)); - assert(reader.read_int("id", &tile->id)); - reader.read_bool("solid", &tile->solid); - reader.read_bool("brick", &tile->brick); - reader.read_bool("ice", &tile->ice); - reader.read_bool("water", &tile->water); - reader.read_bool("fullbox", &tile->fullbox); - reader.read_bool("distro", &tile->distro); - reader.read_bool("goal", &tile->goal); - reader.read_int("data", &tile->data); - reader.read_int("anim-speed", &tile->anim_speed); - reader.read_int("next-tile", &tile->next_tile); - reader.read_string_vector("images", &tile->filenames); - reader.read_string_vector("editor-images", &tile->editor_filenames); - - for(std::vector::iterator it = tile-> - filenames.begin(); - it != tile->filenames.end(); - ++it) - { - Surface* cur_image; - tile->images.push_back(cur_image); - tile->images[tile->images.size()-1] = new Surface( - datadir + "/images/tilesets/" + (*it), - USE_ALPHA); - } - for(std::vector::iterator it = tile->editor_filenames.begin(); - it != tile->editor_filenames.end(); - ++it) - { - Surface* cur_image; - tile->editor_images.push_back(cur_image); - tile->editor_images[tile->editor_images.size()-1] = new Surface( - datadir + "/images/tilesets/" + (*it), - USE_ALPHA); - } - - if (tile->id + tileset_id >= int(tiles.size()) - ) - tiles.resize(tile->id + tileset_id+1); - - tiles[tile->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)), "tilegroup") == 0) - { - TileGroup new_; - LispReader reader(lisp_cdr(element)); - reader.read_string("name", &new_.name); - reader.read_int_vector("tiles", &new_.tiles); - if(!tilegroups_) - tilegroups_ = new std::set; - tilegroups_->insert(new_).first; - } - 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); - } + live_forever = true; } else { - assert(0); + live_forever = false; + timer.start(life_time); } - lisp_free(root_obj); -*/ + // create particles + for(int p = 0; p < number; p++) + { + Particle* particle = new Particle; + particle->pos = epicenter; + + float angle = ((rand() % (max_angle-min_angle))+min_angle) + * (M_PI / 180); // convert to radius + particle->vel.x = /*fabs*/(sin(angle)) * initial_velocity.x; +// if(angle >= M_PI && angle < M_PI*2) +// particle->vel.x *= -1; // work around to fix signal + particle->vel.y = /*fabs*/(cos(angle)) * initial_velocity.y; +// if(angle >= M_PI_2 && angle < 3*M_PI_2) +// particle->vel.y *= -1; + + particles.push_back(particle); + } +} + +Particles::~Particles() +{ + // free particles + for(std::vector::iterator i = particles.begin(); + i < particles.end(); i++) + delete (*i); +} + +void +Particles::action(float elapsed_time) +{ + Vector camera = Sector::current()->camera->get_translation(); + + // update particles + for(std::vector::iterator i = particles.begin(); i < particles.end(); i++) + { + (*i)->pos.x += (*i)->vel.x * elapsed_time; + (*i)->pos.y += (*i)->vel.y * elapsed_time; + + (*i)->vel.x += accel.x * elapsed_time; + (*i)->vel.y += accel.y * elapsed_time; + + if((*i)->pos.x < camera.x || (*i)->pos.x > screen->w + camera.x || + (*i)->pos.y < camera.y || (*i)->pos.y > screen->h + camera.y) + { + delete (*i); + particles.erase(i); + } + } + + if((!timer.check() && !live_forever) || particles.size() == 0) + remove_me(); } -/* EOF */ +void +Particles::draw(DrawingContext& context) +{ + // draw particles + for(std::vector::iterator i = particles.begin(); i < particles.end(); i++) + { + context.draw_filled_rect((*i)->pos, Vector(size,size), color, drawing_layer); + } +} +void load_object_gfx() +{ + img_trampoline = sprite_manager->load("trampoline"); + img_trampoline->start_animation(0); + img_flying_platform = sprite_manager->load("flying_platform"); + img_smoke_cloud = sprite_manager->load("stomp"); +}