namespace hr { namespace ads_game { cross_result findflat(shiftpoint h) { return cross0(current * rgpushxto0(h)); } void draw_game_cell(cell *cs, ads_matrix V, ld plev) { auto g = PIA( hybrid::get_where(cs) ); adjust_to_zero(V, g, plev); auto c = g.first; cross_result center; vector hlist; hybrid::in_actual([&]{ for(int i=0; i<=c->type; i++) { hyperpoint ha = hybrid::get_corner(c, i, 2, 0); hlist.push_back(findflat(V * ha)); } center = findflat(V * C0); }); if(1) { ld d = hdist0(center.h); if(d < vctr_dist) vctr_dist = d, new_vctr = PIA( hybrid::get_at(c, 0) ), new_vctrV = V; } auto& ci = ci_at[c]; if(ci.mpd_terrain > 0) { if(!gen_budget) return; gen_budget--; } gen_terrain(c, ci); gen_rocks(c, ci, 0); auto& t = ci.type; if(t == wtGate) { ld minv = hlist[0].shift; ld maxv = hlist[0].shift; for(auto& h: hlist) { ld v = h.shift; if(v < minv) minv = v; if(v > maxv) maxv = v; } auto draw_slice = [&] (ld a, ld b, color_t col) { vector slice; for(int i=0; itype; i++) { if(hlist[i].shift >= a && hlist[i].shift <= b) slice.push_back(hlist[i].h); if((hlist[i].shift < a) ^ (hlist[i+1].shift < a)) { ld p = ilerp(hlist[i].shift, hlist[i+1].shift, a); hyperpoint h1 = lerp(hlist[i].h, hlist[i+1].h, p); slice.push_back(h1); } if((hlist[i].shift > b) ^ (hlist[i+1].shift > b)) { ld p = ilerp(hlist[i].shift, hlist[i+1].shift, b); hyperpoint h1 = lerp(hlist[i].h, hlist[i+1].h, p); slice.push_back(h1); } if(hlist[i+1].shift < a && hlist[i].shift > b) swap((&slice.back())[-1], slice.back()); } if(isize(slice) < 3) return; for(auto e: slice) curvepoint(e); curvepoint(slice[0]); queuecurve(shiftless(Id), 0xFFFFFFFF, col, PPR::LINE); }; for(int v=floor(minv); v> 8, 0); queuecurve(shiftless(Id), 0x101010FF, col, PPR::WALL); } if(view_proper_times) { string str = format(tformat, center.shift / TAU); queuestr(shiftless(rgpushxto0(center.h)), .1, str, 0xFF4040, 8); } for(auto& r: ci.rocks) { auto& rock = *r; hybrid::in_actual([&]{ dynamicval b(geometry, gRotSpace); auto h = V * rock.at; rock.pt_main = cross0(current * h); }); if(rock.pt_main.shift < rock.life_start || rock.pt_main.shift > rock.life_end) continue; displayed.push_back(&rock); rock.pts.clear(); auto& shape = *rock.shape; for(int i=0; i visited; queue> dq; auto visit = [&] (cell *c, const ads_matrix& V) { auto w = hybrid::get_where(c); if(visited.count(w.first)) return; visited.insert(w.first); dq.emplace(c, V); }; hybrid::in_actual([&] { dynamicval b(geometry, gRotSpace); visit(vctr, vctrV); vctr_dist = HUGE_VAL; }); int i = 0; while(!dq.empty()) { i++; if(i > 1000) break; auto& p = dq.front(); cell *c = p.first; ads_matrix V = p.second; dq.pop(); draw_game_cell(c, V, plev); hybrid::in_actual([&] { for(int i=0; itype-2; i++) { cell *c2 = c->cmove(i); auto V1 = V * currentmap->adj(c, i); optimize_shift(V1); visit(c2, V1); } }); } if(!game_over && !paused) { poly_outline = 0xFF; color_t shipcolor = 0x2020FFFF; if(ship_pt < invincibility_pt) { ld u = (invincibility_pt-ship_pt) / how_much_invincibility; poly_outline = gradient(shipcolor, rsrc_color[rtHull], 0, 0.5 + cos(5*u*TAU), 1); } queuepolyat(shiftless(spin(ang*degree) * Id), shShip, shipcolor, PPR::LINE); poly_outline = 0xFF; if(view_proper_times) { string str = format(tformat, ship_pt / TAU); queuestr(shiftless(Id), .1, str, 0xFFFFFF, 8); } } if(paused && view_proper_times) { string str = format(tformat, view_pt / TAU); queuestr(shiftless(Id), .1, str, 0xFFFF00, 8); } } } }}