X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=lib%2Fspecial%2Fsprite.cpp;h=9bd8a989bfad1205770f7ece5d0e03884ea6561b;hb=f5849145d99db1e654d7219933672587a3d2f2e5;hp=94e0153216633450c46d07bc74375aa378893ecf;hpb=d88eb6fed051a3c6bea58857955ec5d902e63e04;p=supertux.git diff --git a/lib/special/sprite.cpp b/lib/special/sprite.cpp index 94e015321..9bd8a989b 100644 --- a/lib/special/sprite.cpp +++ b/lib/special/sprite.cpp @@ -39,6 +39,8 @@ Sprite::Sprite(lisp_object_t* cur) name = lisp_string(data); else if(token == "action") parse_action(reader); + else + std::cerr << "Warning: Unknown sprite field: " << token << std::endl; } if(name.empty()) @@ -68,8 +70,8 @@ Sprite::parse_action(LispReader& lispreader) if(!lispreader.read_string("name", action->name)) if(!actions.empty()) Termination::abort("Error: If there are more than one action, they need names!", ""); - lispreader.read_int("x-hotspot", action->x_hotspot); - lispreader.read_int("y-hotspot", action->y_hotspot); + lispreader.read_int("x-offset", action->x_hotspot); + lispreader.read_int("y-offset", action->y_hotspot); lispreader.read_float("fps", action->fps); std::vector images; @@ -82,8 +84,6 @@ Sprite::parse_action(LispReader& lispreader) new Surface(datadir + "/images/" + images[i], true)); } - action->frame_delay = 1000.0f/action->fps; - actions[action->name] = action; } @@ -93,37 +93,129 @@ Sprite::init_defaults(Action* act) act->x_hotspot = 0; act->y_hotspot = 0; act->fps = 10; - act->frame_delay = 1000.0f/act->fps; - time = 0; + + start_animation(-1); } void -Sprite::set_action(std::string& act) +Sprite::set_action(std::string act) { +if(!next_action.empty() && animation_loops > 0) + { + next_action = act; + return; + } Actions::iterator i = actions.find(act); +if(i == actions.end()) + { + std::cerr << "Warning: Action '" << act << "' not found on Sprite '" << name << "'\n"; + return; + } action = i->second; } void -Sprite::update(float /*delta*/) +Sprite::start_animation(int loops) { - //time += 10*delta; - //std::cout << "Delta: " << delta << std::endl; +reset(); +animation_loops = loops; } void -Sprite::draw(DrawingContext& context, const Vector& pos, int layer, - Uint32 drawing_effect) +Sprite::reset() { - time = SDL_GetTicks(); - unsigned int frame = get_current_frame(); +frame = 0; +last_tick = SDL_GetTicks(); +animation_reversed = false; +next_action.clear(); +} + +bool +Sprite::check_animation() +{ +return animation_loops; +} + +void +Sprite::reverse_animation(bool reverse) +{ +animation_reversed = reverse; + +if(animation_reversed) + frame = get_frames()-1; +else + frame = 0; +} + +void +Sprite::update() +{ +if(animation_loops == 0) + return; - if (frame < action->surfaces.size()) +float frame_inc = (action->fps/1000.0) * (SDL_GetTicks() - last_tick); +last_tick = SDL_GetTicks(); + +if(animation_reversed) + frame -= frame_inc; +else + frame += frame_inc; + +if(animation_reversed) { - Surface* surface = action->surfaces[frame]; - - context.draw_surface(surface, pos - Vector(action->x_hotspot, action->y_hotspot), layer, drawing_effect); + float excedent = frame - 0; + if((int)excedent < 0 || excedent >= get_frames()) + { // last case can happen when not used reverse_animation() + frame = get_frames() - 1; + if(animation_loops > 0) + { + animation_loops--; + if(animation_loops == 0 && !next_action.empty()) + { + set_action(next_action); + start_animation(-1); + } + } + + if(fabsf(excedent) < get_frames()) + frame += excedent; + } } +else + { + float excedent = frame - action->surfaces.size(); + if((int)excedent >= 0) + { + frame = 0; + if(animation_loops > 0) + { + animation_loops--; + if(animation_loops == 0 && !next_action.empty()) + { + set_action(next_action); + start_animation(-1); + } + } + + if(excedent < get_frames()) + frame += excedent; + } + } +} + +void +Sprite::draw(DrawingContext& context, const Vector& pos, int layer, + Uint32 drawing_effect) +{ + update(); + + if((int)frame >= get_frames() || (int)frame < 0) + std::cerr << "Warning: frame out of range: " << (int)frame + << "/" << get_frames() << " at sprite: " << get_name() + << "/" << get_action_name() << std::endl; + else + context.draw_surface(action->surfaces[(int)frame], + pos - Vector(action->x_hotspot, action->y_hotspot), layer, drawing_effect); } #if 0 @@ -138,29 +230,16 @@ Sprite::draw_part(float sx, float sy, float x, float y, float w, float h) } #endif -void -Sprite::reset() -{ - time = 0; -} - -int -Sprite::get_current_frame() const -{ - unsigned int frame = static_cast(fmodf(time, action->surfaces.size()*action->frame_delay)/action->frame_delay); - return frame % action->surfaces.size(); -} - int -Sprite::get_width() const +Sprite::get_width() { - return action->surfaces[get_current_frame()]->w; + return action->surfaces[get_frame()]->w; } int -Sprite::get_height() const +Sprite::get_height() { - return action->surfaces[get_current_frame()]->h; + return action->surfaces[get_frame()]->h; } /* EOF */