public static void sol_body_v(float[] v, s_file fp, s_body bp) { if (bp.m_pi >= 0 && fp.m_pv[bp.m_pi].m_f != 0) { s_path pp = fp.m_pv[bp.m_pi]; s_path pq = fp.m_pv[pp.m_pi]; Vec3.v_sub(v, pq.m_p, pp.m_p); Vec3.v_scl(v, v, 1.0f / pp.m_t); if (pp.m_s != 0) { Vec3.v_scl(v, v, derp(bp.m_t / pp.m_t)); } } else { v[0] = 0.0f; v[1] = 0.0f; v[2] = 0.0f; } }
public static void sol_body_p(float[] p, s_file fp, s_body bp) { float[] v = new float[3]; if (bp.m_pi >= 0) { s_path pp = fp.m_pv[bp.m_pi]; s_path pq = fp.m_pv[pp.m_pi]; if (pp.m_s != 0) { Vec3.v_sub(v, pq.m_p, pp.m_p); Vec3.v_mad(p, pp.m_p, v, erp(bp.m_t / pp.m_t)); } else { Vec3.v_sub(v, pq.m_p, pp.m_p); Vec3.v_mad(p, pp.m_p, v, bp.m_t / pp.m_t); } } else { p[0] = 0.0f; p[1] = 0.0f; p[2] = 0.0f; } }
public static void sol_load_path(IntPtr fin, s_path pp) { Binary.get_array(fin, pp.m_p, 3); Binary.get_float(fin, ref pp.m_t); Binary.get_index(fin, ref pp.m_pi); Binary.get_index(fin, ref pp.m_f); Binary.get_index(fin, ref pp.m_s); }
/* * Compute the positions of all bodies after DT seconds have passed. */ public static void sol_body_step(s_file fp, float dt) { int i; for (i = 0; i < fp.m_bc; i++) { s_body bp = fp.m_bv[i];// + i; if (bp.m_pi >= 0) { s_path pp = fp.m_pv[bp.m_pi]; if (pp.m_f != 0) { //volatile float t = bp.m_t; bp.m_t = (t += dt); if (t >= pp.m_t) { bp.m_t = 0; bp.m_pi = pp.m_pi; cmd.type = cmd_type.CMD_BODY_TIME; cmd.bodytime.bi = i; cmd.bodytime.t = bp.m_t; sol_cmd_enq(cmd); cmd.type = cmd_type.CMD_BODY_PATH; cmd.bodypath.bi = i; cmd.bodypath.pi = bp.m_pi; sol_cmd_enq(cmd); } } } } }
public static void game_run_cmd(Command cmd) { /* * Neverball <= 1.5.1 does not send explicit tilt axes, rotation * happens directly around view vectors. So for compatibility if * at the time of receiving tilt angles we have not yet received * the tilt axes, we use the view vectors. */ float[] f = new float[3]; if (client_state != 0) { s_ball[] up; float dt; int i; switch (cmd.type) { case cmd_type.CMD_END_OF_UPDATE: game_run_cmd_got_tilt_axes = 0; if (first_update != 0) { first_update = 0; break; } /* Compute gravity for particle effects. */ if (status == (int)GAME.GAME_GOAL) { game_common.game_tilt_grav(f, game_run_cmd_gup, tilt); } else { game_common.game_tilt_grav(f, game_run_cmd_gdn, tilt); } /* Step particle, goal and jump effects. */ if (ups > 0) { dt = 1.0f / (float)ups; if (goal_e != 0 && goal_k < 1.0f) { goal_k += dt; } if (jump_b != 0) { jump_dt += dt; if (1.0f < jump_dt) { jump_b = 0; } } Part.part_step(f, dt); } break; case cmd_type.CMD_MAKE_BALL: /* Allocate a new ball and mark it as the current ball. */ up = new s_ball[file.m_uc + 1]; { for (i = 0; i < file.m_uc; i++) { up[i] = file.m_uv[i]; } up[file.m_uc] = new s_ball(); } { file.m_uv = up; curr_ball = file.m_uc; file.m_uc++; } break; case cmd_type.CMD_MAKE_ITEM: /* Allocate and initialise a new item. */ { s_item[] hp = new s_item[file.m_hc + 1]; { for (i = 0; i < file.m_hc; i++) { hp[i] = file.m_hv[i]; } } { s_item h = new s_item(); Vec3.v_cpy(h.m_p, cmd.mkitem.p); h.m_t = cmd.mkitem.t; h.m_n = cmd.mkitem.n; file.m_hv = hp; file.m_hv[file.m_hc] = h; file.m_hc++; } } break; case cmd_type.CMD_PICK_ITEM: /* Set up particle effects and discard the item. */ { s_item hp = file.m_hv[cmd.pkitem.hi]; Item.item_color(hp, f); Part.part_burst(hp.m_p, f); hp.m_t = Solid.ITEM_NONE; } break; case cmd_type.CMD_TILT_ANGLES: if (game_run_cmd_got_tilt_axes == 0) { game_common.game_tilt_axes(tilt, view_e); } tilt.rx = cmd.tiltangles.x; tilt.rz = cmd.tiltangles.z; break; case cmd_type.CMD_SOUND: /* Play the sound, then free its file name. */ if (cmd.sound.n != null) { Audio.audio_play(cmd.sound.n, cmd.sound.a); /* * FIXME Command memory management should be done * elsewhere and done properly. */ cmd.sound.n = null; } break; case cmd_type.CMD_TIMER: timer = cmd.timer.t; break; case cmd_type.CMD_STATUS: status = cmd.status.t; break; case cmd_type.CMD_COINS: coins = cmd.coins.n; break; case cmd_type.CMD_JUMP_ENTER: jump_b = 1; jump_e = 0; jump_dt = 0.0f; break; case cmd_type.CMD_JUMP_EXIT: jump_e = 1; break; case cmd_type.CMD_BODY_PATH: file.m_bv[cmd.bodypath.bi].m_pi = cmd.bodypath.pi; break; case cmd_type.CMD_BODY_TIME: file.m_bv[cmd.bodytime.bi].m_t = cmd.bodytime.t; break; case cmd_type.CMD_GOAL_OPEN: /* * Enable the goal and make sure it's fully visible if * this is the first update. */ if (goal_e == 0) { goal_e = 1; goal_k = first_update != 0 ? 1.0f : 0.0f; } break; case cmd_type.CMD_SWCH_ENTER: file.m_xv[cmd.swchenter.xi].m_e = 1; break; case cmd_type.CMD_SWCH_TOGGLE: file.m_xv[cmd.swchtoggle.xi].m_f = file.m_xv[cmd.swchtoggle.xi].m_f == 0 ? 1 : 0; break; case cmd_type.CMD_SWCH_EXIT: file.m_xv[cmd.swchexit.xi].m_e = 0; break; case cmd_type.CMD_UPDATES_PER_SECOND: ups = cmd.ups.n; break; case cmd_type.CMD_BALL_RADIUS: file.m_uv[curr_ball].m_r = cmd.ballradius.r; break; case cmd_type.CMD_CLEAR_ITEMS: if (file.m_hv != null) { file.m_hv = null; } file.m_hc = 0; break; case cmd_type.CMD_CLEAR_BALLS: if (file.m_uv != null) { file.m_uv = null; } file.m_uc = 0; break; case cmd_type.CMD_BALL_POSITION: Vec3.v_cpy(file.m_uv[curr_ball].m_p, cmd.ballpos.p); break; case cmd_type.CMD_BALL_BASIS: Vec3.v_cpy(file.m_uv[curr_ball].m_e[0], cmd.ballbasis.e[0]); Vec3.v_cpy(file.m_uv[curr_ball].m_e[1], cmd.ballbasis.e[1]); Vec3.v_crs(file.m_uv[curr_ball].m_e[2], file.m_uv[curr_ball].m_e[0], file.m_uv[curr_ball].m_e[1]); break; case cmd_type.CMD_VIEW_POSITION: Vec3.v_cpy(view_p, cmd.viewpos.p); break; case cmd_type.CMD_VIEW_CENTER: Vec3.v_cpy(view_c, cmd.viewcenter.c); break; case cmd_type.CMD_VIEW_BASIS: Vec3.v_cpy(view_e[0], cmd.viewbasis.e[0]); Vec3.v_cpy(view_e[1], cmd.viewbasis.e[1]); Vec3.v_crs(view_e[2], view_e[0], view_e[1]); break; case cmd_type.CMD_CURRENT_BALL: curr_ball = cmd.currball.ui; break; case cmd_type.CMD_PATH_FLAG: file.m_pv[cmd.pathflag.pi].m_f = cmd.pathflag.f; break; case cmd_type.CMD_STEP_SIMULATION: /* * Simulate body motion. * * This is done on the client side due to replay file size * concerns and isn't done as part of cmd_type.CMD_END_OF_UPDATE to * match the server state as closely as possible. Body * time is still synchronised with the server on a * semi-regular basis and path indices are handled through * cmd_type.CMD_BODY_PATH, thus this code doesn't need to be as * sophisticated as sol_body_step. */ dt = cmd.stepsim.dt; for (i = 0; i < file.m_bc; i++) { s_body bp = file.m_bv[i]; // + i; if (bp.m_pi >= 0) { s_path pp = file.m_pv[bp.m_pi]; if (pp.m_f != 0) { bp.m_t += dt; } } } break; case cmd_type.CMD_MAP: /* * Note if the loaded map matches the server's * expectations. (No, this doesn't actually load a map, * yet. Something else somewhere else does.) */ cmd.map.name = null; game_compat_map = version_x == cmd.map.version.x ? 1 : 0; break; case cmd_type.CMD_TILT_AXES: game_run_cmd_got_tilt_axes = 1; Vec3.v_cpy(tilt.x, cmd.tiltaxes.x); Vec3.v_cpy(tilt.z, cmd.tiltaxes.z); break; case cmd_type.CMD_NONE: case cmd_type.CMD_MAX: break; } } }