1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-12-25 01:20:37 +00:00

nilrider:: can now fly off surface

This commit is contained in:
Zeno Rogue 2024-08-18 13:06:04 +02:00
parent 04b8287dbe
commit 448c08e925
3 changed files with 81 additions and 26 deletions

View File

@ -389,6 +389,8 @@ void level::init() {
start.where = mappt(startx+.5, starty+.5, 1); start.where = mappt(startx+.5, starty+.5, 1);
start.t = 0; start.t = 0;
start.timer = 0; start.timer = 0;
start.on_surface = this;
start.sstime = -100;
current = start; current = start;
println(hlog, "start.where = ", start.where); println(hlog, "start.where = ", start.where);
println(hlog, "current.where = ", current.where, " : ", hr::format("%p", &current)); println(hlog, "current.where = ", current.where, " : ", hr::format("%p", &current));

View File

@ -11,9 +11,16 @@ struct timestamp {
ld heading_angle; /**< the current heading angle */ ld heading_angle; /**< the current heading angle */
ld vel; /**< the current velocity in units per second */ ld vel; /**< the current velocity in units per second */
ld circpos; /**< controls the wheel graphics */ ld circpos; /**< controls the wheel graphics */
ld slope; /**< the current slope */ ld slope; /**< the current slope, as angle */
ld chg_slope; /**< slope used at surface state change */
ld gfx_slope; /**< current slope used by graphics */
ld t; /**< planning spline parameter */ ld t; /**< planning spline parameter */
ld timer = 0; /**< the timer, in seconds */ ld timer = 0; /**< the timer, in seconds */
level *on_surface;/**< pointer to the sub-level if we are currently on the surface, nullptr otherwise */
ld sstime; /**< when did we leave or enter surface? for smoothing gfx_slope */
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 */
flagtype collected_triangles; /**< a bitset which shows which triangles are collected */ flagtype collected_triangles; /**< a bitset which shows which triangles are collected */
flagtype goals; /**< a bitset which shows which goals are complete */ flagtype goals; /**< a bitset which shows which goals are complete */
@ -25,6 +32,7 @@ struct timestamp {
void draw_instruments(level*); void draw_instruments(level*);
ld energy_in_squares(); ld energy_in_squares();
bool collect(level*); bool collect(level*);
bool out_of_surface(level*);
void be_consistent(); void be_consistent();
}; };

View File

@ -82,10 +82,16 @@ void timestamp::draw_unilcycle(const shiftmatrix& V) {
bool tick_debug = false; bool tick_debug = false;
bool timestamp::out_of_surface(level *lev) {
auto xy = lev->get_xy_i(where);
char ch = lev->mapchar(xy);
return ch == '!';
}
bool timestamp::collect(level *lev) { bool timestamp::collect(level *lev) {
auto xy = lev->get_xy_i(where); auto xy = lev->get_xy_i(where);
char ch = lev->mapchar(xy); char ch = lev->mapchar(xy);
if(ch == 'r' || ch == '!') return false; if(ch == 'r') return false;
if(ch == '*') { if(ch == '*') {
for(int i=0; i<isize(lev->triangles); i++) { for(int i=0; i<isize(lev->triangles); i++) {
auto& t = lev->triangles[i]; auto& t = lev->triangles[i];
@ -143,30 +149,63 @@ void timestamp::be_consistent() {
bool timestamp::tick(level *lev) { bool timestamp::tick(level *lev) {
if(!collect(lev)) return false; if(on_surface && !collect(lev)) return false;
const ld eps = slope_eps; const ld eps = slope_eps;
hyperpoint wnext = where; if(on_surface) {
wnext[0] += cos(heading_angle) * eps; hyperpoint wnext = where;
wnext[1] += sin(heading_angle) * eps; wnext[0] += cos(heading_angle) * eps;
wnext[2] = lev->surface(wnext); wnext[1] += sin(heading_angle) * eps;
wnext[2] = lev->surface(wnext);
wnext = gpushxto0(where) * wnext; wnext = gpushxto0(where) * wnext;
slope = atan(wnext[2] / eps); slope = atan(wnext[2] / eps);
auto ovel = vel; if(out_of_surface(lev)) {
on_surface = nullptr;
vel -= sin(slope) * gravity / tps; sstime = timer; chg_slope = gfx_slope;
if(vel < 0) { flyvel = wnext * vel / hypot_d(3, wnext);
vel = 0; flyvel[3] = 0;
if(ovel == 0) return false; }
} }
auto mvel = (vel + ovel) / 2; if(on_surface) {
where[0] += cos(heading_angle) * mvel * cos(slope) / tps; auto ovel = vel;
where[1] += sin(heading_angle) * mvel * cos(slope) / tps;
where[2] = lev->surface(where); vel -= sin(slope) * gravity / tps;
circpos += mvel / whrad / tps; 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[2] = lev->surface(where);
circvel = mvel / whrad;
}
else {
auto oflyvel = flyvel;
flyvel = rgpushxto0(where) * flyvel;
flyvel[2] -= gravity / tps / 2;
// todo rewrite geodesic_step to take gravity into account into RK4 correctly
flyvel /= tps;
nisot::geodesic_step(where, flyvel);
flyvel *= tps;
flyvel[2] -= gravity / tps / 2;
auto mflyvel = (flyvel + oflyvel) / 2;
heading_angle = atan2(mflyvel[1], mflyvel[0]);
flyvel = gpushxto0(where) * flyvel;
mflyvel = gpushxto0(where) * mflyvel;
slope = atan(mflyvel[2] / hypot_d(2, mflyvel));
vel = hypot_d(3, flyvel);
}
circpos += circvel / tps;
timer += 1. / tps; timer += 1. / tps;
return true; return true;
@ -195,7 +234,8 @@ void timestamp::centerview(level *lev) {
transmatrix T = View; transmatrix T = View;
ld gfx_slope = binsearch(-90*degree, min(slope, min_gfx_slope), [&] (ld slope) { gfx_slope = min_gfx_slope;
if(on_surface) gfx_slope = binsearch(-90*degree, min(slope, min_gfx_slope), [&] (ld slope) {
View = T; View = T;
rotate_view(cspin(1, 2, slope)); rotate_view(cspin(1, 2, slope));
for(int i=0; i<8; i++) { for(int i=0; i<8; i++) {
@ -209,6 +249,11 @@ void timestamp::centerview(level *lev) {
return false; return false;
}, 10); }, 10);
if(timer < sstime + 1) {
ld t = timer - sstime;
gfx_slope = lerp(chg_slope, gfx_slope, t * t * (3 - 2*t));
}
View = T; View = T;
rotate_view(cspin(1, 2, gfx_slope)); rotate_view(cspin(1, 2, gfx_slope));
shift_view(ztangent(whdist * lev->scale)); shift_view(ztangent(whdist * lev->scale));