void object_dynamic_tick(object *obj) { obj->age++; if(obj->attached_to != NULL) { object_set_pos(obj, object_get_pos(obj->attached_to)); object_set_direction(obj, object_get_direction(obj->attached_to)); } // Check if object still needs to be halted if(obj->halt_ticks > 0) { obj->halt_ticks--; obj->halt = (obj->halt_ticks > 0); } // Run animation player if(obj->cur_animation != NULL && obj->halt == 0) { for(int i = 0; i < obj->stride; i++) player_run(obj); } // Tick object implementation if(obj->dynamic_tick != NULL) { obj->dynamic_tick(obj); } // Handle screen shakes, V & H if(obj->sprite_state.screen_shake_vertical > 0) { obj->gs->screen_shake_vertical = obj->sprite_state.screen_shake_vertical * 4; obj->sprite_state.screen_shake_vertical = 0; } if(obj->sprite_state.screen_shake_horizontal > 0) { obj->gs->screen_shake_horizontal = obj->sprite_state.screen_shake_horizontal * 4; obj->sprite_state.screen_shake_horizontal = 0; } }
void object_render_shadow(object *obj) { if(obj->cur_sprite == NULL || !obj->cast_shadow) { return; } // Scale of the sprite on Y axis should be less than the // height of the sprite because of light position float scale_y = 0.25f; // Determine X int flipmode = obj->sprite_state.flipmode; int x = obj->pos.x + obj->cur_sprite->pos.x + obj->sprite_state.o_correction.x; if(object_get_direction(obj) == OBJECT_FACE_LEFT) { x = (obj->pos.x + obj->sprite_state.o_correction.x) - obj->cur_sprite->pos.x - object_get_size(obj).x; flipmode ^= FLIP_HORIZONTAL; } // Determine Y float temp = object_h(obj) * scale_y; int y = 190 - temp - (object_h(obj) - temp) / 2; // Render shadow object twice with different offsets, so that // the shadows seem a bit blobbier and shadow-y for(int i = 0; i < 2; i++) { video_render_sprite_flip_scale_opacity_tint( obj->cur_sprite->data, x+i, y+i, BLEND_ALPHA, obj->pal_offset, flipmode, scale_y, 50, color_create(0,0,0,255)); } }
int ai_block_projectile(controller *ctrl, ctrl_event **ev) { ai *a = ctrl->data; object *o = ctrl->har; iterator it; object **o_tmp; vector_iter_begin(&a->active_projectiles, &it); while((o_tmp = iter_next(&it)) != NULL) { object *o_prj = *o_tmp; if(projectile_get_owner(o_prj) == o) { continue; } if(o_prj->cur_sprite && maybe(a->difficulty)) { vec2i pos_prj = vec2i_add(object_get_pos(o_prj), o_prj->cur_sprite->pos); vec2i size_prj = object_get_size(o_prj); if (object_get_direction(o_prj) == OBJECT_FACE_LEFT) { pos_prj.x = object_get_pos(o_prj).x + ((o_prj->cur_sprite->pos.x * -1) - size_prj.x); } if(fabsf(pos_prj.x - o->pos.x) < 120) { a->cur_act = (o->direction == OBJECT_FACE_RIGHT ? ACT_DOWN|ACT_LEFT : ACT_DOWN|ACT_RIGHT); controller_cmd(ctrl, a->cur_act, ev); return 1; } } } return 0; }
int console_cmd_har(game_state *gs, int argc, char **argv) { // change har if(argc == 2) { int i; if(strtoint(argv[1], &i)) { if(i < 0 || i > 10) { return 1; } game_player *player = game_state_get_player(gs, 0); if (scene_load_har(game_state_get_scene(gs), 0, player->har_id)) { return 1; } object *har_obj = game_player_get_har(player); vec2i pos = object_get_pos(har_obj); int hd = object_get_direction(har_obj); object *obj = malloc(sizeof(object)); object_create(obj, gs, pos, vec2f_create(0,0)); player->har_id = i; if(har_create(obj, game_state_get_scene(gs)->af_data[0], hd, player->har_id, player->pilot_id, 0)) { object_free(obj); free(obj); return 1; } // Set HAR to controller and game_player game_state_add_object(gs, obj, RENDER_LAYER_MIDDLE, 0, 0); game_state_del_object(gs, har_obj); // Set HAR for player game_player_set_har(player, obj); game_player_get_ctrl(player)->har = obj; game_player_get_har(player)->animation_state.enemy = game_player_get_har(game_state_get_player(gs, 1)); game_player_get_har(game_state_get_player(gs, 1))->animation_state.enemy = game_player_get_har(player); maybe_install_har_hooks(game_state_get_scene(gs)); return 0; } } return 1; }
void object_render(object *obj) { // Stop here if cur_sprite is NULL if(obj->cur_sprite == NULL) return; // Set current surface obj->cur_surface = obj->cur_sprite->data; // Something to ease the pain ... player_sprite_state *rstate = &obj->sprite_state; // Position int y = obj->pos.y + obj->cur_sprite->pos.y + rstate->o_correction.y; int x = obj->pos.x + obj->cur_sprite->pos.x + rstate->o_correction.x; if(object_get_direction(obj) == OBJECT_FACE_LEFT) { x = obj->pos.x - obj->cur_sprite->pos.x + rstate->o_correction.x - object_get_size(obj).x; } // Flip to face the right direction int flipmode = rstate->flipmode; if(obj->direction == OBJECT_FACE_LEFT) { flipmode ^= FLIP_HORIZONTAL; } // Blend start / blend finish uint8_t opacity = rstate->blend_finish; if(rstate->duration > 0) { float moment = (float)rstate->timer / (float)rstate->duration; float d = ((float)rstate->blend_finish - (float)rstate->blend_start) * moment; opacity = rstate->blend_start + d; } // Default Tint color color tint = color_create(0xFF, 0xFF, 0xFF, 0xFF); // These two force set the sprite color, so handle them first if(obj->video_effects & EFFECT_SHADOW) { tint = color_create(0x20, 0x20, 0x20, 0xFF); } if(obj->video_effects & EFFECT_DARK_TINT) { tint = color_create(0x60, 0x60, 0x60, 0xFF); } if(obj->video_effects & EFFECT_STASIS) { opacity = 128; } // This changes the tint depending on position, so handle next if(obj->video_effects & EFFECT_POSITIONAL_LIGHTING) { float p = (x > 160) ? 320 - x : x; float shade = 0.65f + p / 320; if(shade > 1.0f) shade = 1.0f; tint.r *= shade; tint.g *= shade; tint.b *= shade; } // Render video_render_sprite_flip_scale_opacity_tint( obj->cur_surface, x, y, rstate->blendmode, obj->pal_offset, flipmode, obj->y_percent, opacity, tint); }
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_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--; } if(obj->enemy_slide_state.timer > 0) { obj->enemy_slide_state.duration++; obj->pos.x = state->enemy->pos.x + obj->enemy_slide_state.dest.x; obj->pos.y = state->enemy->pos.y + obj->enemy_slide_state.dest.y; obj->enemy_slide_state.timer--; } // Not sure what this does const sd_script_frame *frame = sd_script_get_frame_at(&state->parser, state->current_tick); // Animation has ended ? if(frame == NULL) { if(state->repeat) { player_reset(obj); frame = sd_script_get_frame_at(&state->parser, state->current_tick); } else if(obj->finish != NULL) { obj->cur_sprite = NULL; obj->finish(obj); return; } else { obj->cur_sprite = NULL; state->finished = 1; return; } } // Handle frame state->entered_frame = 0; if(frame == NULL) { DEBUG("Something went wery wrong!"); // We shouldn't really get here, unless stringparser messes something up badly } else { // If frame changed, do something if(sd_script_frame_changed(&state->parser, state->previous_tick, state->current_tick)) { state->entered_frame = 1; player_clear_frame(obj); // Tick management if(sd_script_isset(frame, "d")) { if(!obj->animation_state.disable_d) { state->previous_tick = sd_script_get(frame, "d")-1; state->current_tick = sd_script_get(frame, "d"); } } // Hover flag if(sd_script_isset(frame, "h")) { rstate->disable_gravity = 1; } else { rstate->disable_gravity = 0; } if(sd_script_isset(frame, "ua")) { obj->animation_state.enemy->sprite_state.disable_gravity = 1; } // Animation creation command if(sd_script_isset(frame, "m") && state->spawn != NULL) { int mx = 0; if (sd_script_isset(frame, "mrx")) { int mrx = sd_script_get(frame, "mrx"); int mm = sd_script_isset(frame, "mm") ? sd_script_get(frame, "mm") : mrx; mx = random_int(&obj->rand_state, 320 - 2*mm) + mrx; DEBUG("randomized mx as %d", mx); } else if(sd_script_isset(frame, "mx")) { mx = obj->start.x + (sd_script_get(frame, "mx") * object_get_direction(obj)); } int my = 0; if (sd_script_isset(frame, "mry")) { int mry = sd_script_get(frame, "mry"); int mm = sd_script_isset(frame, "mm") ? sd_script_get(frame, "mm") : mry; my = random_int(&obj->rand_state, 320 - 2*mm) + mry; DEBUG("randomized my as %d", my); } else if(sd_script_isset(frame, "my")) { my = obj->start.y + sd_script_get(frame, "my"); } int mg = sd_script_isset(frame, "mg") ? sd_script_get(frame, "mg") : 0; state->spawn( obj, sd_script_get(frame, "m"), vec2i_create(mx, my), mg, state->spawn_userdata); } // Animation deletion if(sd_script_isset(frame, "md") && state->destroy != NULL) { state->destroy(obj, sd_script_get(frame, "md"), state->destroy_userdata); } // Music playback if(sd_script_isset(frame, "smo")) { if(sd_script_get(frame, "smo") == 0) { music_stop(); return; } music_play(PSM_END + (sd_script_get(frame, "smo") - 1)); } if(sd_script_isset(frame, "smf")) { music_stop(); } // Sound playback if(sd_script_isset(frame, "s")) { float pitch = PITCH_DEFAULT; float volume = VOLUME_DEFAULT * (settings_get()->sound.sound_vol/10.0f); float panning = PANNING_DEFAULT; if(sd_script_isset(frame, "sf")) { int p = clamp(sd_script_get(frame, "sf"), -16, 239); pitch = clampf((p/239.0f)*3.0f + 1.0f, PITCH_MIN, PITCH_MAX); } if(sd_script_isset(frame, "l")) { int v = clamp(sd_script_get(frame, "l"), 0, 100); volume = (v / 100.0f) * (settings_get()->sound.sound_vol/10.0f); } if(sd_script_isset(frame, "sb")) { panning = clamp(sd_script_get(frame, "sb"), -100, 100) / 100.0f; } int sound_id = obj->sound_translation_table[sd_script_get(frame, "s")] - 1; sound_play(sound_id, volume, panning, pitch); } // Blend mode stuff if(sd_script_isset(frame, "b1")) { rstate->method_flags &= 0x2000; } if(sd_script_isset(frame, "b2")) { rstate->method_flags &= 0x4000; } if(sd_script_isset(frame, "bb")) { rstate->method_flags &= 0x0010; rstate->blend_finish = sd_script_get(frame, "bb"); rstate->screen_shake_vertical = sd_script_get(frame, "bb"); } if(sd_script_isset(frame, "be")) { rstate->method_flags &= 0x0800; } if(sd_script_isset(frame, "bf")) { rstate->method_flags &= 0x0001; rstate->blend_finish = sd_script_get(frame, "bf"); } if(sd_script_isset(frame, "bh")) { rstate->method_flags &= 0x0040; } if(sd_script_isset(frame, "bl")) { rstate->method_flags &= 0x0008; rstate->blend_finish = sd_script_get(frame, "bl"); rstate->screen_shake_horizontal = sd_script_get(frame, "bl"); } if(sd_script_isset(frame, "bm")) { rstate->method_flags &= 0x0100; rstate->blend_finish = sd_script_get(frame, "bm"); } if(sd_script_isset(frame, "bj")) { rstate->method_flags &= 0x0400; rstate->blend_finish = sd_script_get(frame, "bj"); } if(sd_script_isset(frame, "bs")) { rstate->blend_start = sd_script_get(frame, "bs"); } if(sd_script_isset(frame, "bu")) { rstate->method_flags &= 0x8000; } if(sd_script_isset(frame, "bw")) { rstate->method_flags &= 0x0080; } if(sd_script_isset(frame, "bx")) { rstate->method_flags &= 0x0002; } // Palette tricks if(sd_script_isset(frame, "bpd")) { rstate->pal_ref_index = sd_script_get(frame, "bpd"); } if(sd_script_isset(frame, "bpn")) { rstate->pal_entry_count = sd_script_get(frame, "bpn"); } if(sd_script_isset(frame, "bps")) { rstate->pal_start_index = sd_script_get(frame, "bps"); } if(sd_script_isset(frame, "bpf")) { // Exact values come from master.dat if(game_state_get_player(obj->gs, 0)->har == obj) { rstate->pal_start_index = 1; rstate->pal_entry_count = 47; } else { rstate->pal_start_index = 48; rstate->pal_entry_count = 48; } } if(sd_script_isset(frame, "bpp")) { rstate->pal_end = sd_script_get(frame, "bpp") * 4; rstate->pal_begin = sd_script_get(frame, "bpp") * 4; } if(sd_script_isset(frame, "bpb")) { rstate->pal_begin = sd_script_get(frame, "bpb") * 4; } if(sd_script_isset(frame, "bz")) { rstate->pal_tint = 1; } // The following is a hack. We don't REALLY know what these tags do. // However, they are only used in CREDITS.BK, so we can just interpret // then as we see fit, as long as stuff works. if(sd_script_isset(frame, "bc") && frame->tick_len >= 50) { rstate->blend_start = 0; } else if(sd_script_isset(frame, "bd") && frame->tick_len >= 30) { rstate->blend_finish = 0; } // Handle movement if(sd_script_isset(frame, "ox")) { DEBUG("changing X from %f to %f", obj->pos.x, obj->pos.x+sd_script_get(frame, "ox")); /*obj->pos.x += sd_script_get(frame, "ox");*/ } if(sd_script_isset(frame, "oy")) { DEBUG("changing Y from %f to %f", obj->pos.y, obj->pos.y+sd_script_get(frame, "oy")); /*obj->pos.y += sd_script_get(frame, "oy");*/ } if (sd_script_isset(frame, "bm")) { // hack because we don't have 'walk to other HAR' implemented obj->pos.x = state->enemy->pos.x; obj->pos.y = state->enemy->pos.y; player_next_frame(state->enemy); } if (sd_script_isset(frame, "v")) { int x = 0, y = 0; if(sd_script_isset(frame, "y-")) { y = sd_script_get(frame, "y-") * -1; } else if(sd_script_isset(frame, "y+")) { y = sd_script_get(frame, "y+"); } if(sd_script_isset(frame, "x-")) { x = sd_script_get(frame, "x-") * -1 * object_get_direction(obj); } else if(sd_script_isset(frame, "x+")) { x = sd_script_get(frame, "x+") * object_get_direction(obj); } if (x || y) { DEBUG("x vel %d, y vel %d", x, y); obj->vel.x += x; obj->vel.y += y; } } if (sd_script_isset(frame, "bu") && obj->vel.y < 0.0f) { float x_dist = dist(obj->pos.x, 160); // assume that bu is used in conjunction with 'vy-X' and that we want to land in the center of the arena obj->slide_state.vel.x = x_dist / (obj->vel.y*-2); obj->slide_state.timer = obj->vel.y*-2; } // handle scaling on the Y axis if(sd_script_isset(frame, "y")) { obj->y_percent = sd_script_get(frame, "y") / 100.0f; } if (sd_script_isset(frame, "e")) { // x,y relative to *enemy's* position int x = 0, y = 0; if(sd_script_isset(frame, "y-")) { y = sd_script_get(frame, "y-") * -1; } else if(sd_script_isset(frame, "y+")) { y = sd_script_get(frame, "y+"); } if(sd_script_isset(frame, "x-")) { x = sd_script_get(frame, "x-") * -1 * object_get_direction(obj); } else if(sd_script_isset(frame, "x+")) { x = sd_script_get(frame, "x+") * object_get_direction(obj); } if (x || y) { obj->enemy_slide_state.timer = frame->tick_len; obj->enemy_slide_state.duration = 0; obj->enemy_slide_state.dest.x = x; obj->enemy_slide_state.dest.y = y; /*DEBUG("ENEMY Slide object %d for (x,y) = (%f,%f) for %d ticks. (%d,%d)", obj->cur_animation->id, obj->enemy_slide_state.dest.x, obj->enemy_slide_state.dest.y, param->duration, x, y);*/ } } if (sd_script_isset(frame, "v") == 0 && sd_script_isset(frame, "e") == 0 && (sd_script_isset(frame, "x+") || sd_script_isset(frame, "y+") || sd_script_isset(frame, "x-") || sd_script_isset(frame, "y-"))) { // check for relative X interleaving int x = 0, y = 0; if(sd_script_isset(frame, "y-")) { y = sd_script_get(frame, "y-") * -1; } else if(sd_script_isset(frame, "y+")) { y = sd_script_get(frame, "y+"); } if(sd_script_isset(frame, "x-")) { x = sd_script_get(frame, "x-") * -1 * object_get_direction(obj); } else if(sd_script_isset(frame, "x+")) { x = sd_script_get(frame, "x+") * object_get_direction(obj); } obj->slide_state.timer = frame->tick_len; obj->slide_state.vel.x = (float)x; obj->slide_state.vel.y = (float)y; /*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(sd_script_isset(frame, "x=") || sd_script_isset(frame, "y=")) { obj->slide_state.vel = vec2f_create(0,0); } if(sd_script_isset(frame, "x=")) { obj->pos.x = obj->start.x + (sd_script_get(frame, "x=") * object_get_direction(obj)); // Find frame ID by tick int frame_id = sd_script_next_frame_with_tag(&state->parser, "x=", state->current_tick); // Handle it! if(frame_id >= 0) { int mr = sd_script_get_tick_pos_at_frame(&state->parser, frame_id); int r = mr - state->current_tick; int next_x = sd_script_get(sd_script_get_frame(&state->parser, frame_id), "x="); int slide = obj->start.x + (next_x * object_get_direction(obj)); if(slide != obj->pos.x) { obj->slide_state.vel.x = dist(obj->pos.x, slide) / (float)(frame->tick_len + r); obj->slide_state.timer = frame->tick_len + r; /*DEBUG("Slide object %d for X = %f for a total of %d ticks.",*/ /*obj->cur_animation->id,*/ /*obj->slide_state.vel.x,*/ /*param->duration + r);*/ } } } if(sd_script_isset(frame, "y=")) { obj->pos.y = obj->start.y + sd_script_get(frame, "y="); // Find frame ID by tick int frame_id = sd_script_next_frame_with_tag(&state->parser, "y=", state->current_tick); // handle it! if(frame_id >= 0) { int mr = sd_script_get_tick_pos_at_frame(&state->parser, frame_id); int r = mr - state->current_tick; int next_y = sd_script_get(sd_script_get_frame(&state->parser, frame_id), "y="); int slide = next_y + obj->start.y; if(slide != obj->pos.y) { obj->slide_state.vel.y = dist(obj->pos.y, slide) / (float)(frame->tick_len + r); obj->slide_state.timer = frame->tick_len + r; /*DEBUG("Slide object %d for Y = %f for a total of %d ticks.",*/ /*obj->cur_animation->id,*/ /*obj->slide_state.vel.y,*/ /*param->duration + r);*/ } } } if(sd_script_isset(frame, "as")) { // make the object move around the screen in a circular motion until end of frame obj->orbit = 1; } else { obj->orbit = 0; } if(sd_script_isset(frame, "q")) { // Enable hit on the current and the next n-1 frames. obj->hit_frames = sd_script_get(frame, "q"); } if(obj->hit_frames > 0) { obj->can_hit = 1; obj->hit_frames--; } if(sd_script_isset(frame, "at")) { // set the object's X position to be behind the opponent obj->pos.x = obj->animation_state.enemy->pos.x + (15 * object_get_direction(obj)); } if(sd_script_isset(frame, "ar")) { DEBUG("flipping direction %d -> %d", object_get_direction(obj), object_get_direction(obj) *-1); // reverse direction object_set_direction(obj, object_get_direction(obj) * -1); DEBUG("flipping direction now %d", object_get_direction(obj)); } // Set render settings if(frame->sprite < 25) { object_select_sprite(obj, frame->sprite); if(obj->cur_sprite != NULL) { rstate->duration = frame->tick_len; rstate->blendmode = sd_script_isset(frame, "br") ? BLEND_ADDITIVE : BLEND_ALPHA; if(sd_script_isset(frame, "r")) { rstate->flipmode ^= FLIP_HORIZONTAL; } if(sd_script_isset(frame, "f")) { rstate->flipmode ^= FLIP_VERTICAL; } } } else { object_select_sprite(obj, -1); } } } // Animation ticks state->previous_tick = state->current_tick; if(state->reverse) { state->current_tick--; } else { state->current_tick++; } // Sprite ticks rstate->timer++; // All done. return; }