From d9b90d8a8e4529f34df71ba34751de577969f6fc Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Sat, 9 Mar 2019 16:20:06 +0100 Subject: [PATCH] 3D:: two-player uses split screen --- basegraph.cpp | 52 +++++++++++++++++++++++++++++++++++++++++- graph.cpp | 11 +++++++-- hyper.h | 7 ++++-- hypgraph.cpp | 7 ++++-- racing.cpp | 62 +++++++++------------------------------------------ shmup.cpp | 12 +++++----- system.cpp | 4 +--- 7 files changed, 87 insertions(+), 68 deletions(-) diff --git a/basegraph.cpp b/basegraph.cpp index e13d9729..ebadb1c9 100644 --- a/basegraph.cpp +++ b/basegraph.cpp @@ -265,7 +265,7 @@ void display_data::set_projection(int ed, bool apply_models) { eyewidth_translate(ed); if(dim3) { - glhr::projection_multiply(glhr::frustum(current_display->tanfov, current_display->tanfov * vid.yres / vid.xres)); + glhr::projection_multiply(glhr::frustum(current_display->tanfov, current_display->tanfov * cd->ysize / cd->xsize)); glhr::projection_multiply(glhr::scale(1, -1, -1)); current_display->scrdist_text = cd->ysize; } @@ -1254,4 +1254,54 @@ int calcfps() { return (1000 * CFPS) / ret; } +namespace subscreens { + + vector player_displays; + bool in; + int current_player; + + bool is_current_player(int id) { + if(!in) return true; + return id == current_player; + } + + void prepare() { + int N = multi::players; + if(N > 1) { + player_displays.resize(N, *current_display); + int qrows[10] = {1, 1, 1, 1, 2, 2, 2, 3, 3, 3}; + int rows = qrows[N]; + int cols = (N + rows - 1) / rows; + for(int i=0; i c(current_display, &player_displays[p]); + what(); + } + in = false; + return true; + } + return false; + } + + } + } diff --git a/graph.cpp b/graph.cpp index d455e378..13c7d2be 100644 --- a/graph.cpp +++ b/graph.cpp @@ -6174,15 +6174,22 @@ void drawfullmap() { void gamescreen(int _darken) { - if(subscreen_split([=] () { + if(subscreens::split([=] () { calcparam(); current_display->set_projection(0, false); current_display->set_viewport(0); compute_graphical_distance(); gamescreen(_darken); })) { + if(racing::on) return; + // create the gmatrix current_display->set_projection(0, false); - current_display->set_viewport(0); + current_display->set_viewport(0); + View = subscreens::player_displays[0].view_matrix; + viewctr = subscreens::player_displays[0].view_center; + just_gmatrix = true; + currentmap->draw(); + just_gmatrix = false; return; } diff --git a/hyper.h b/hyper.h index dc2b8e21..4c61982a 100644 --- a/hyper.h +++ b/hyper.h @@ -4902,8 +4902,6 @@ namespace racing { void displayScore(eLand l); } -bool subscreen_split(reaction_t for_each_subscreen); - #else // static bool on = false: emits a warning @@ -4925,5 +4923,10 @@ bool no_barriers_in_radius(cell *c, int rad); extern ld extra_generation_distance; +namespace subscreens { + void prepare(); + bool split(reaction_t for_each_subscreen); + } + } diff --git a/hypgraph.cpp b/hypgraph.cpp index d780c105..583efe22 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -987,13 +987,16 @@ void spinEdge(ld aspd) { void centerpc(ld aspd) { + if(subscreens::split([=] () {centerpc(aspd);})) return; + #if CAP_CRYSTAL if(geometry == gCrystal) crystal::centerrug(aspd); #endif if(shmup::on && DIM == 3 && vid.sspeed > -5) { - transmatrix at = ggmatrix(shmup::pc[0]->base) * shmup::pc[0]->at * cpush(2, -vid.yshift); + int id = subscreens::in ? subscreens::current_player : 0; + transmatrix at = ggmatrix(shmup::pc[id]->base) * shmup::pc[id]->at * cpush(2, -vid.yshift); View = inverse(at) * View; #if CAP_RACING if(racing::on) racing::set_view(); @@ -1057,7 +1060,7 @@ void centerpc(ld aspd) { void optimizeview() { - subscreen_split(optimizeview); + if(subscreens::split(optimizeview)) return; #if CAP_ANIMATIONS if(centerover.at && inmirror(centerover.at)) { diff --git a/racing.cpp b/racing.cpp index d2bff9bf..dcc04a18 100644 --- a/racing.cpp +++ b/racing.cpp @@ -643,22 +643,20 @@ bool inrec = false; ld race_angle = 90; -int current_player; - void set_view() { + multi::cpid = subscreens::in ? subscreens::current_player : 0; + if(race_start_tick == 0) race_start_tick = ticks + 5000; - if(subscreen_split(set_view)) return; - - shmup::monster *who = shmup::pc[current_player]; + shmup::monster *who = shmup::pc[multi::cpid]; if(!inrec) { const transmatrix T = who->at; ld alpha = -atan2(T * C0); ld distance = hdist0(T * C0); ld beta = -atan2(xpush(-distance) * spin(-alpha) * T * Cx1); - current_history[current_player].emplace_back(ghostmoment{ticks - race_start_tick, rti_id[who->base], + current_history[multi::cpid].emplace_back(ghostmoment{ticks - race_start_tick, rti_id[who->base], angle_to_uchar(alpha), frac_to_uchar(distance / distance_multiplier), angle_to_uchar(beta), @@ -1092,29 +1090,6 @@ auto hooks1 = else return named_functionality(); }); -vector player_displays; -bool in_subscreen; - -void prepare_subscreens() { - int N = multi::players; - if(N > 1) { - player_displays.resize(N, *current_display); - int qrows[10] = {1, 1, 1, 1, 2, 2, 2, 3, 3, 3}; - int rows = qrows[N]; - int cols = (N + rows - 1) / rows; - for(int i=0; i > scoreboard; void uploadScore() { @@ -1153,7 +1128,7 @@ void displayScore(eLand l) { } void race_won() { - if(!race_finish_tick[current_player]) { + if(!race_finish_tick[multi::cpid]) { int result = ticks - race_start_tick; int losers = 0; int place = 1; @@ -1161,9 +1136,9 @@ void race_won() { for(auto& ghost: ghostset()[specialland]) if(ghost.result < result) place++; else losers++; for(auto& ghost: oghostset()[specialland]) if(ghost.result < result) place++; else losers++; - if(place == 1 && losers) trophy[current_player] = 0xFFD500FF; - if(place == 2) trophy[current_player] = 0xFFFFC0FF; - if(place == 3) trophy[current_player] = 0x967444FF; + if(place == 1 && losers) trophy[multi::cpid] = 0xFFD500FF; + if(place == 2) trophy[multi::cpid] = 0xFFFFC0FF; + if(place == 3) trophy[multi::cpid] = 0x967444FF; if(place + losers > 1) addMessage(XLAT("Finished the race! Time: %1, place: %2 out of %3", racetimeformat(result), its(place), its(place+losers))); @@ -1173,7 +1148,7 @@ void race_won() { if(place == 1 && losers && official_race) achievement_gain("RACEWON", rg::racing); - race_finish_tick[current_player] = ticks; + race_finish_tick[multi::cpid] = ticks; charstyle gcs = getcs(); for(color_t *x: {&gcs.skincolor, &gcs.haircolor, &gcs.dresscolor, &gcs.swordcolor, &gcs.dresscolor2}) { for(int a=1; a<4; a++) @@ -1196,7 +1171,7 @@ void race_won() { } subtrack.resize(ngh); - subtrack.emplace_back(ghost{gcs, result, race_checksum, time(NULL), current_history[current_player]}); + subtrack.emplace_back(ghost{gcs, result, race_checksum, time(NULL), current_history[multi::cpid]}); sort(subtrack.begin(), subtrack.end(), [] (const ghost &g1, const ghost &g2) { return g1.result < g2.result; }); if(isize(subtrack) > ghosts_to_save && ghosts_to_save > 0) subtrack.resize(ghosts_to_save); @@ -1340,21 +1315,4 @@ void add_debug(cell *c) { } -bool subscreen_split(reaction_t what) { - using namespace racing; - if(!racing::on) return false; - if(in_subscreen) return false; - if(!player_displays.empty()) { - in_subscreen = true; - int& p = current_player; - for(p = 0; p < multi::players; p++) { - dynamicval c(current_display, &player_displays[p]); - what(); - } - in_subscreen = false; - return true; - } - return false; - } - } diff --git a/shmup.cpp b/shmup.cpp index a5d5a5b8..9c0f055f 100644 --- a/shmup.cpp +++ b/shmup.cpp @@ -1582,7 +1582,7 @@ void movePlayer(monster *m, int delta) { cpid = m->pid; #if CAP_RACING - if(racing::on && cpid != racing::current_player) return; + if(racing::on && cpid != subscreens::current_player) return; #endif double mturn = 0, mgo = 0, mdx = 0, mdy = 0; @@ -1753,7 +1753,7 @@ void movePlayer(monster *m, int delta) { playerturn[cpid] = mgo * SCALE * delta / 200; playerturny[cpid] = mturn * SCALE * delta / 200; - if(!lctrlclick) { + if(!lctrlclick && cpid == 0) { playerturn[cpid] += mouseaim_x; playerturny[cpid] += mouseaim_y; mouseaim_x = mouseaim_y = 0; @@ -3112,7 +3112,7 @@ hookset *hooks_turn; void turn(int delta) { - if(subscreen_split( [delta] () { turn(delta); })) return; + if(racing::on && subscreens::split( [delta] () { turn(delta); })) return; if(callhandlers(false, hooks_turn, delta)) return; if(!shmup::on) return; @@ -3463,16 +3463,16 @@ bool drawMonster(const transmatrix& V, cell *c, const transmatrix*& Vboat, trans switch(m->type) { case moPlayer: playerfound = true; - cpid = m->pid; - if(!hide_player()) { + if(!hide_player() || !subscreens::is_current_player(m->pid)) { + dynamicval d(cpid, m->pid); if(DIM == 3) view = view * spin(-M_PI/2); drawPlayerEffects(view, c, true); if(m->inBoat) m->footphase = 0; if(mapeditor::drawplayer) drawMonsterType(moPlayer, c, view, 0xFFFFFFC0, m->footphase); } - if(keyresult[cpid]) { + if(subscreens::is_current_player(m->pid) && keyresult[cpid]) { hyperpoint h = keytarget(cpid); if(DIM == 2) queuechr(h, vid.fsize, '+', iinf[keyresult[cpid]].color); diff --git a/system.cpp b/system.cpp index 43f63f3e..e0d2232c 100644 --- a/system.cpp +++ b/system.cpp @@ -1366,9 +1366,7 @@ void start_game() { #if CAP_TEXTURE texture::config.remap(); #endif -#if CAP_RACING - racing::prepare_subscreens(); -#endif + subscreens::prepare(); } void restart_game(char switchWhat) {