mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-11-23 13:07:16 +00:00
bouncing off trampolines and returning to surface
This commit is contained in:
parent
81ea54746b
commit
25bbd96a72
@ -391,6 +391,7 @@ void level::init() {
|
||||
start.timer = 0;
|
||||
start.on_surface = this;
|
||||
start.sstime = -100;
|
||||
start.last_tramp = -100;
|
||||
current = start;
|
||||
println(hlog, "start.where = ", start.where);
|
||||
println(hlog, "current.where = ", current.where, " : ", hr::format("%p", ¤t));
|
||||
|
@ -6,6 +6,9 @@ using namespace rogueviz;
|
||||
|
||||
struct level;
|
||||
|
||||
/** ticks per second */
|
||||
inline const ld tps = 1000;
|
||||
|
||||
struct timestamp {
|
||||
hyperpoint where; /**< the current position of the unicycle */
|
||||
ld heading_angle; /**< the current heading angle */
|
||||
@ -22,11 +25,16 @@ struct timestamp {
|
||||
hyperpoint flyvel;/**< velocity vector if we are not on any surface */
|
||||
ld circvel; /**< how fast the wheel is rotating if we are not on any surface, per second */
|
||||
|
||||
ld last_draw; /**< when was gfx_slope computed */
|
||||
ld last_tramp; /**< time of last trampoline */
|
||||
ld tramp_head; /**< heading_angle at the moment of last trampoline */
|
||||
|
||||
|
||||
flagtype collected_triangles; /**< a bitset which shows which triangles are collected */
|
||||
flagtype goals; /**< a bitset which shows which goals are complete */
|
||||
flagtype failed; /**< a bitset which shows which goals are failed */
|
||||
|
||||
bool tick(level*);/**< one tick of the simulation -- returns false if the unicycle has stopped or crashed */
|
||||
bool tick(level*, ld timeleft = 1. / tps);/**< one tick of the simulation -- returns false if the unicycle has stopped or crashed */
|
||||
void centerview(level*);
|
||||
void draw_unilcycle(const shiftmatrix&);
|
||||
void draw_instruments(level*);
|
||||
@ -34,6 +42,9 @@ struct timestamp {
|
||||
bool collect(level*);
|
||||
bool out_of_surface(level*);
|
||||
void be_consistent();
|
||||
|
||||
bool check_crashes_rec(level*, hyperpoint owhere, hyperpoint oflyvel, ld timeleft);
|
||||
bool check_crashes(level*, hyperpoint owhere, hyperpoint oflyvel, ld timeleft);
|
||||
};
|
||||
|
||||
struct planpoint {
|
||||
@ -191,6 +202,8 @@ struct level {
|
||||
bool handle_planning(int sym, int uni);
|
||||
void solve();
|
||||
|
||||
hyperpoint surface_point(hyperpoint h) { h[2] = surface(h); return h; }
|
||||
|
||||
xy_float get_xy_f(hyperpoint h);
|
||||
xy_int get_xy_i(hyperpoint h) { return pfloor(get_xy_f(h)); }
|
||||
char mapchar(xy_int p);
|
||||
@ -198,9 +211,6 @@ struct level {
|
||||
char mapchar(hyperpoint h) { return mapchar(pfloor(get_xy_f(h))); }
|
||||
};
|
||||
|
||||
/** ticks per second */
|
||||
inline const ld tps = 1000;
|
||||
|
||||
/** wheel radius */
|
||||
inline ld whrad = 0.05;
|
||||
|
||||
|
@ -147,7 +147,7 @@ void timestamp::be_consistent() {
|
||||
heading_angle = int_to_heading(heading_to_int(heading_angle));
|
||||
}
|
||||
|
||||
bool timestamp::tick(level *lev) {
|
||||
bool timestamp::tick(level *lev, ld time_left) {
|
||||
|
||||
if(on_surface && !collect(lev)) return false;
|
||||
const ld eps = slope_eps;
|
||||
@ -169,48 +169,128 @@ bool timestamp::tick(level *lev) {
|
||||
}
|
||||
}
|
||||
|
||||
timer += time_left;
|
||||
|
||||
if(on_surface) {
|
||||
auto ovel = vel;
|
||||
|
||||
vel -= sin(slope) * gravity / tps;
|
||||
vel -= sin(slope) * gravity * time_left;
|
||||
if(vel < 0) {
|
||||
vel = 0;
|
||||
if(ovel == 0) return false;
|
||||
}
|
||||
|
||||
auto mvel = (vel + ovel) / 2;
|
||||
where[0] += cos(heading_angle) * mvel * cos(slope) / tps;
|
||||
where[1] += sin(heading_angle) * mvel * cos(slope) / tps;
|
||||
where[0] += cos(heading_angle) * mvel * cos(slope) * time_left;
|
||||
where[1] += sin(heading_angle) * mvel * cos(slope) * time_left;
|
||||
where[2] = lev->surface(where);
|
||||
circvel = mvel / whrad;
|
||||
}
|
||||
|
||||
else {
|
||||
auto owhere = where;
|
||||
auto oflyvel = flyvel;
|
||||
flyvel = rgpushxto0(where) * flyvel;
|
||||
flyvel[2] -= gravity / tps / 2;
|
||||
flyvel[2] -= gravity * time_left / 2;
|
||||
|
||||
// todo rewrite geodesic_step to take gravity into account into RK4 correctly
|
||||
flyvel /= tps;
|
||||
flyvel *= time_left;
|
||||
nisot::geodesic_step(where, flyvel);
|
||||
flyvel *= tps;
|
||||
flyvel /= time_left;
|
||||
|
||||
flyvel[2] -= gravity / tps / 2;
|
||||
flyvel[2] -= gravity * time_left / 2;
|
||||
auto mflyvel = (flyvel + oflyvel) / 2;
|
||||
heading_angle = atan2(mflyvel[1], mflyvel[0]);
|
||||
auto new_heading_angle = atan2(mflyvel[1], mflyvel[0]);
|
||||
if(timer >= last_tramp + 0.5) heading_angle = new_heading_angle;
|
||||
else {
|
||||
while(new_heading_angle < heading_angle - M_PI) new_heading_angle += TAU;
|
||||
while(new_heading_angle > heading_angle + M_PI) new_heading_angle -= TAU;
|
||||
auto oh = heading_angle;
|
||||
heading_angle = lerp(heading_angle, new_heading_angle, ilerp(timer - time_left, last_tramp + 0.5, timer));
|
||||
println(hlog, oh, " _ ", new_heading_angle, " -> ", heading_angle);
|
||||
}
|
||||
|
||||
|
||||
flyvel = gpushxto0(where) * flyvel;
|
||||
mflyvel = gpushxto0(where) * mflyvel;
|
||||
slope = atan(mflyvel[2] / hypot_d(2, mflyvel));
|
||||
|
||||
vel = hypot_d(3, flyvel);
|
||||
|
||||
if(check_crashes_rec(lev, owhere, oflyvel, time_left)) return false;
|
||||
}
|
||||
|
||||
circpos += circvel / tps;
|
||||
circpos += circvel * time_left;
|
||||
|
||||
timer += 1. / tps;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool timestamp::check_crashes(level* lev, hyperpoint owhere, hyperpoint oflyvel, ld time_left) {
|
||||
ld oz = lev->surface(owhere);
|
||||
ld z = lev->surface(where);
|
||||
if(owhere[2] > oz && where[2] < z) {
|
||||
|
||||
auto xy = lev->get_xy_i(where);
|
||||
char ch = lev->mapchar(xy);
|
||||
if(ch == '!') return false;
|
||||
|
||||
string s0 = ""; s0 += ch;
|
||||
|
||||
ld part = binsearch(0, 1, [&] (ld p) {
|
||||
hyperpoint h = lerp(owhere, where, p);
|
||||
return h[2] < lev->surface(h);
|
||||
});
|
||||
|
||||
println(hlog, "CRASHED INTO ", s0, " AT PART = ", part);
|
||||
timer -= time_left * (1 - part);
|
||||
|
||||
where = lerp(owhere, where, part);
|
||||
flyvel = lerp(oflyvel, flyvel, part);
|
||||
|
||||
/* tangent vectors */
|
||||
hyperpoint dx = gpushxto0(where) * lev->surface_point(rgpushxto0(where) * point31(slope_eps, 0, 0));
|
||||
hyperpoint dy = gpushxto0(where) * lev->surface_point(rgpushxto0(where) * point31(0, slope_eps, 0));
|
||||
hyperpoint dz = point30(0, 0, slope_eps);
|
||||
|
||||
/* orthonormalize */
|
||||
dx = dx / hypot_d(3, dx);
|
||||
dy = dy - dot_d(3, dx, dy) * dy;
|
||||
dy = dy / hypot_d(3, dy);
|
||||
dz = dz - dot_d(3, dx, dz) * dx;
|
||||
dz = dz - dot_d(3, dy, dz) * dy;
|
||||
dz = dz / hypot_d(3, dz); dz[3] = 0;
|
||||
|
||||
println(hlog, "dx = ", dx);
|
||||
println(hlog, "dy = ", dy);
|
||||
println(hlog, "dz = ", dz);
|
||||
|
||||
if(ch == 'T') {
|
||||
/* reflect off the trampoline */
|
||||
flyvel = flyvel - dot_d(3, flyvel, dz) * dz * 2;
|
||||
last_tramp = timer;
|
||||
tramp_head = heading_angle;
|
||||
}
|
||||
|
||||
else {
|
||||
/* waste some energy */
|
||||
flyvel = flyvel - dot_d(3, flyvel, dz) * dz;
|
||||
vel = hypot_d(3, flyvel);
|
||||
on_surface = lev;
|
||||
}
|
||||
|
||||
tick(lev, time_left * (1 - part));
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool timestamp::check_crashes_rec(level* l, hyperpoint owhere, hyperpoint oflyvel, ld time_left) {
|
||||
if(check_crashes(l, owhere, oflyvel, time_left)) return true;
|
||||
for(auto s: l->sublevels) if(check_crashes(s, owhere, oflyvel, time_left)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void timestamp::centerview(level *lev) {
|
||||
// static bool once = false; if(once) return; once = true;
|
||||
|
||||
@ -233,6 +313,8 @@ void timestamp::centerview(level *lev) {
|
||||
set_view(w, front, up);
|
||||
|
||||
transmatrix T = View;
|
||||
|
||||
if(last_draw <= sstime) min_gfx_slope = gfx_slope;
|
||||
|
||||
gfx_slope = min_gfx_slope;
|
||||
if(on_surface) gfx_slope = binsearch(-90*degree, min(slope, min_gfx_slope), [&] (ld slope) {
|
||||
@ -254,6 +336,8 @@ void timestamp::centerview(level *lev) {
|
||||
gfx_slope = lerp(chg_slope, gfx_slope, t * t * (3 - 2*t));
|
||||
}
|
||||
|
||||
last_draw = timer;
|
||||
|
||||
View = T;
|
||||
rotate_view(cspin(1, 2, gfx_slope));
|
||||
shift_view(ztangent(whdist * lev->scale));
|
||||
|
Loading…
Reference in New Issue
Block a user