sd_stringparser* sd_stringparser_create() { sd_stringparser *parser = (sd_stringparser*)malloc(sizeof(sd_stringparser)); parser->is_frame_ready = 0; memset(&parser->current_frame, 0, sizeof(sd_stringparser_frame)); parser->current_frame.parser = parser; parser->frame_list = malloc(sizeof(frame_list)); memset(parser->frame_list, 0 , sizeof(frame_list)); parser->string = 0; sd_stringparser_reset(parser); return parser; }
int sd_stringparser_set_string(sd_stringparser *parser, const char *string) { if(parser->string) free(parser->string); parser->string = sd_strdup(string); sd_stringparser_reset(parser); int frames=0; parse_string(parser, cb_count_frame, NULL, &frames); sd_framelist_resize(parser->frame_list, frames); // ignore animation string that does not contain frame letters if(frames > 0) { frames = 0; parse_string(parser, cb_set_frame, NULL, &frames); // now store the tags and params into the frame struct frames = 0; parse_string(parser, cb_count_frame, cb_store_tag, &frames); return 0; } return SD_ANIM_INVALID_STRING; }
void player_run(object *obj) { // Some vars for easier life player_animation_state *state = &obj->animation_state; player_sprite_state *rstate = &obj->sprite_state; if(state->finished) return; // Handle slide operation if(obj->slide_state.timer > 0) { obj->pos.x += obj->slide_state.vel.x; obj->pos.y += obj->slide_state.vel.y; obj->slide_state.timer--; } // Not sure what this does int run_ret; if(state->end_frame == UINT32_MAX) { run_ret = sd_stringparser_run( state->parser, state->ticks - 1); } else { run_ret = sd_stringparser_run_frames( state->parser, state->ticks - 1, state->end_frame); } // Handle frame if(run_ret == 0) { // Handle frame switch sd_stringparser_frame *param = &state->parser->current_frame; sd_stringparser_frame n_param; sd_stringparser_frame *f = param; sd_stringparser_frame *n = &n_param; int real_frame = param->letter - 65; // Do something if animation is finished! if(param->is_animation_end) { if(state->repeat) { player_reset(obj); sd_stringparser_run(state->parser, state->ticks - 1); real_frame = param->letter - 65; } else if(obj->finish != NULL) { obj->cur_sprite = NULL; obj->finish(obj); return; } else { obj->cur_sprite = NULL; state->finished = 1; return; } } // If frame changed, do something if(param->id != state->previous) { player_clear_frame(obj); // Tick management if(isset(f, "d")) { cmd_tickjump(obj, get(f, "d")); sd_stringparser_reset(state->parser); } // Animation management if(isset(f, "m") && state->spawn != NULL) { int mx = isset(f, "mx") ? get(f, "mx") : 0; int my = isset(f, "my") ? get(f, "my") : 0; int mg = isset(f, "mg") ? get(f, "mg") : 0; DEBUG("Spawning %d, with g = %d, pos = (%d,%d)", get(f, "m"), mg, mx, my); state->spawn( obj, get(f, "m"), vec2i_create(mx, my), mg, state->spawn_userdata); } if(isset(f, "md") && state->destroy != NULL) { state->destroy(obj, get(f, "md"), state->destroy_userdata); } // Music playback if(isset(f, "smo")) { cmd_music_on(get(f, "smo")); } if(isset(f, "smf")) { cmd_music_off(); } // Sound playback if(isset(f, "s")) { float pitch = PITCH_DEFAULT; float volume = VOLUME_DEFAULT * (settings_get()->sound.sound_vol/10.0f); float panning = PANNING_DEFAULT; if(isset(f, "sf")) { int p = clamp(get(f, "sf"), -16, 239); pitch = clampf((p/239.0f)*3.0f + 1.0f, PITCH_MIN, PITCH_MAX); } if(isset(f, "l")) { int v = clamp(get(f, "l"), 0, 100); volume = (v / 100.0f) * (settings_get()->sound.sound_vol/10.0f); } if(isset(f, "sb")) { panning = clamp(get(f, "sb"), -100, 100) / 100.0f; } int sound_id = obj->sound_translation_table[get(f, "s")] - 1; sound_play(sound_id, volume, panning, pitch); } // Blend mode stuff if(isset(f, "b1")) { rstate->method_flags &= 0x2000; } if(isset(f, "b2")) { rstate->method_flags &= 0x4000; } if(isset(f, "bb")) { rstate->method_flags &= 0x0010; rstate->blend_finish = get(f, "bb"); } if(isset(f, "be")) { rstate->method_flags &= 0x0800; } if(isset(f, "bf")) { rstate->method_flags &= 0x0001; rstate->blend_finish = get(f, "bf"); } if(isset(f, "bh")) { rstate->method_flags &= 0x0040; } if(isset(f, "bl")) { rstate->method_flags &= 0x0008; rstate->blend_finish = get(f, "bl"); } if(isset(f, "bm")) { rstate->method_flags &= 0x0100; rstate->blend_finish = get(f, "bm"); } if(isset(f, "bj")) { rstate->method_flags &= 0x0400; rstate->blend_finish = get(f, "bj"); } if(isset(f, "bs")) { rstate->blend_start = get(f, "bs"); } if(isset(f, "bu")) { rstate->method_flags &= 0x8000; } if(isset(f, "bw")) { rstate->method_flags &= 0x0080; } if(isset(f, "bx")) { rstate->method_flags &= 0x0002; } // Palette tricks if(isset(f, "bpd")) { rstate->pal_ref_index = get(f, "bpd"); } if(isset(f, "bpn")) { rstate->pal_entry_count = get(f, "bpn"); } if(isset(f, "bps")) { rstate->pal_start_index = get(f, "bps"); } if(isset(f, "bpb")) { rstate->pal_begin = get(f, "bpb"); } if(isset(f, "bpd")) { rstate->pal_end = get(f, "bpd"); } if(isset(f, "bz")) { rstate->pal_tint = get(f, "bz"); } // Handle movement if (isset(f, "v")) { int x = 0, y = 0; if(isset(f, "y-")) { y = get(f, "y-") * -1; } else if(isset(f, "y+")) { y = get(f, "y+"); } if(isset(f, "x-")) { x = get(f, "x-") * -1 * object_get_direction(obj); } else if(isset(f, "x+")) { x = get(f, "x+") * object_get_direction(obj); } if (x || y) { obj->vel.x += x; obj->vel.y += y; } } // handle scaling on the Y axis if(isset(f, "y")) { obj->y_percent = get(f, "y") / 100.0f; } if (isset(f, "e")) { // x,y relative to *enemy's* position int x = 0, y = 0; if(isset(f, "y-")) { y = get(f, "y-") * -1; } else if(isset(f, "y+")) { y = get(f, "y+"); } if(isset(f, "x-")) { x = get(f, "x-") * -1 * object_get_direction(obj); } else if(isset(f, "x+")) { x = get(f, "x+") * object_get_direction(obj); } float x_dist = dist(obj->pos.x, state->enemy_x + x); float y_dist = dist(obj->pos.y, state->enemy_y + y); obj->slide_state.timer = param->duration; obj->slide_state.vel.x = x_dist / (float)param->duration; obj->slide_state.vel.y = y_dist / (float)param->duration; DEBUG("Slide object %d for (x,y) = (%f,%f) for %d ticks.", obj->cur_animation->id, obj->slide_state.vel.x, obj->slide_state.vel.y, param->duration); } if (isset(f, "v") == 0 && isset(f, "e") == 0 && (isset(f, "x+") || isset(f, "y+") || isset(f, "x-") || isset(f, "y-"))) { // check for relative X interleaving int x = 0, y = 0; if(isset(f, "y-")) { y = get(f, "y-") * -1; } else if(isset(f, "y+")) { y = get(f, "y+"); } if(isset(f, "x-")) { x = get(f, "x-") * -1 * object_get_direction(obj); } else if(isset(f, "x+")) { x = get(f, "x+") * object_get_direction(obj); } obj->slide_state.timer = param->duration; obj->slide_state.vel.x = (float)x / (float)param->duration; obj->slide_state.vel.y = (float)y / (float)param->duration; DEBUG("Slide object %d for (x,y) = (%f,%f) for %d ticks.", obj->cur_animation->id, obj->slide_state.vel.x, obj->slide_state.vel.y, param->duration); } // Check if next frame contains X=nnn or Y=nnn if(!param->is_final_frame) { sd_stringparser_peek(state->parser, param->id + 1, &n_param); int slide = 0; float xpos = obj->pos.x; float ypos = obj->pos.y; if(isset(n, "x=") || isset(n, "y=")) { obj->slide_state.vel = vec2f_create(0,0); } if(isset(n, "x=")) { slide = get(n, "x="); if(object_get_direction(obj) == OBJECT_FACE_LEFT) { // if the sprite is flipped horizontally, adjust the X coordinates slide = 320 - slide; } if(slide != xpos) { obj->slide_state.vel.x = dist(xpos, slide) / (float)param->duration; obj->slide_state.timer = param->duration; DEBUG("Slide object %d for X = %f for a total of %d ticks.", obj->cur_animation->id, obj->slide_state.vel.x, param->duration); } } if(isset(n, "y=")) { slide = get(n, "y="); if(slide != ypos) { obj->slide_state.vel.y = dist(ypos, slide) / (float)param->duration; obj->slide_state.timer = param->duration; DEBUG("Slide object %d for Y = %f for a total of %d ticks.", obj->cur_animation->id, obj->slide_state.vel.y, param->duration); } } } // Set render settings if(real_frame < 25) { object_select_sprite(obj, real_frame); if(obj->cur_sprite != NULL) { rstate->duration = param->duration; rstate->blendmode = isset(f, "br") ? BLEND_ADDITIVE : BLEND_ALPHA; if(isset(f, "r")) { rstate->flipmode ^= FLIP_HORIZONTAL; } if(isset(f, "f")) { rstate->flipmode ^= FLIP_VERTICAL; } } } else { obj->cur_sprite = NULL; } } state->previous = param->id; } // Animation ticks if(state->reverse) { state->ticks--; } else { state->ticks++; } // Sprite ticks rstate->timer++; // All done. return; }
void player_reset(object *obj) { obj->animation_state.ticks = 1; obj->animation_state.finished = 0; obj->animation_state.previous = -1; sd_stringparser_reset(obj->animation_state.parser); }