mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-04-01 00:07:02 +00:00
3D:: two-player uses split screen
This commit is contained in:
parent
1f4afeeeb4
commit
d9b90d8a8e
@ -265,7 +265,7 @@ void display_data::set_projection(int ed, bool apply_models) {
|
|||||||
eyewidth_translate(ed);
|
eyewidth_translate(ed);
|
||||||
|
|
||||||
if(dim3) {
|
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));
|
glhr::projection_multiply(glhr::scale(1, -1, -1));
|
||||||
current_display->scrdist_text = cd->ysize;
|
current_display->scrdist_text = cd->ysize;
|
||||||
}
|
}
|
||||||
@ -1254,4 +1254,54 @@ int calcfps() {
|
|||||||
return (1000 * CFPS) / ret;
|
return (1000 * CFPS) / ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace subscreens {
|
||||||
|
|
||||||
|
vector<display_data> 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<N; i++) {
|
||||||
|
auto& pd = player_displays[i];
|
||||||
|
pd.xmin = (i % cols) * 1. / cols;
|
||||||
|
pd.xmax = ((i % cols) + 1.) / cols;
|
||||||
|
pd.ymin = (i / cols) * 1. / rows;
|
||||||
|
pd.ymax = ((i / cols) + 1.) / rows;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
player_displays.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool split(reaction_t what) {
|
||||||
|
using namespace racing;
|
||||||
|
if(in) return false;
|
||||||
|
if(!racing::on && !(shmup::on && DIM == 3)) return false;
|
||||||
|
if(!player_displays.empty()) {
|
||||||
|
in = true;
|
||||||
|
int& p = current_player;
|
||||||
|
for(p = 0; p < multi::players; p++) {
|
||||||
|
dynamicval<display_data*> c(current_display, &player_displays[p]);
|
||||||
|
what();
|
||||||
|
}
|
||||||
|
in = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6174,15 +6174,22 @@ void drawfullmap() {
|
|||||||
|
|
||||||
void gamescreen(int _darken) {
|
void gamescreen(int _darken) {
|
||||||
|
|
||||||
if(subscreen_split([=] () {
|
if(subscreens::split([=] () {
|
||||||
calcparam();
|
calcparam();
|
||||||
current_display->set_projection(0, false);
|
current_display->set_projection(0, false);
|
||||||
current_display->set_viewport(0);
|
current_display->set_viewport(0);
|
||||||
compute_graphical_distance();
|
compute_graphical_distance();
|
||||||
gamescreen(_darken);
|
gamescreen(_darken);
|
||||||
})) {
|
})) {
|
||||||
|
if(racing::on) return;
|
||||||
|
// create the gmatrix
|
||||||
current_display->set_projection(0, false);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
7
hyper.h
7
hyper.h
@ -4902,8 +4902,6 @@ namespace racing {
|
|||||||
void displayScore(eLand l);
|
void displayScore(eLand l);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool subscreen_split(reaction_t for_each_subscreen);
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// static bool on = false: emits a warning
|
// 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;
|
extern ld extra_generation_distance;
|
||||||
|
|
||||||
|
namespace subscreens {
|
||||||
|
void prepare();
|
||||||
|
bool split(reaction_t for_each_subscreen);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -987,13 +987,16 @@ void spinEdge(ld aspd) {
|
|||||||
|
|
||||||
void centerpc(ld aspd) {
|
void centerpc(ld aspd) {
|
||||||
|
|
||||||
|
if(subscreens::split([=] () {centerpc(aspd);})) return;
|
||||||
|
|
||||||
#if CAP_CRYSTAL
|
#if CAP_CRYSTAL
|
||||||
if(geometry == gCrystal)
|
if(geometry == gCrystal)
|
||||||
crystal::centerrug(aspd);
|
crystal::centerrug(aspd);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(shmup::on && DIM == 3 && vid.sspeed > -5) {
|
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;
|
View = inverse(at) * View;
|
||||||
#if CAP_RACING
|
#if CAP_RACING
|
||||||
if(racing::on) racing::set_view();
|
if(racing::on) racing::set_view();
|
||||||
@ -1057,7 +1060,7 @@ void centerpc(ld aspd) {
|
|||||||
|
|
||||||
void optimizeview() {
|
void optimizeview() {
|
||||||
|
|
||||||
subscreen_split(optimizeview);
|
if(subscreens::split(optimizeview)) return;
|
||||||
|
|
||||||
#if CAP_ANIMATIONS
|
#if CAP_ANIMATIONS
|
||||||
if(centerover.at && inmirror(centerover.at)) {
|
if(centerover.at && inmirror(centerover.at)) {
|
||||||
|
62
racing.cpp
62
racing.cpp
@ -643,22 +643,20 @@ bool inrec = false;
|
|||||||
|
|
||||||
ld race_angle = 90;
|
ld race_angle = 90;
|
||||||
|
|
||||||
int current_player;
|
|
||||||
|
|
||||||
void set_view() {
|
void set_view() {
|
||||||
|
|
||||||
|
multi::cpid = subscreens::in ? subscreens::current_player : 0;
|
||||||
|
|
||||||
if(race_start_tick == 0) race_start_tick = ticks + 5000;
|
if(race_start_tick == 0) race_start_tick = ticks + 5000;
|
||||||
|
|
||||||
if(subscreen_split(set_view)) return;
|
shmup::monster *who = shmup::pc[multi::cpid];
|
||||||
|
|
||||||
shmup::monster *who = shmup::pc[current_player];
|
|
||||||
|
|
||||||
if(!inrec) {
|
if(!inrec) {
|
||||||
const transmatrix T = who->at;
|
const transmatrix T = who->at;
|
||||||
ld alpha = -atan2(T * C0);
|
ld alpha = -atan2(T * C0);
|
||||||
ld distance = hdist0(T * C0);
|
ld distance = hdist0(T * C0);
|
||||||
ld beta = -atan2(xpush(-distance) * spin(-alpha) * T * Cx1);
|
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),
|
angle_to_uchar(alpha),
|
||||||
frac_to_uchar(distance / distance_multiplier),
|
frac_to_uchar(distance / distance_multiplier),
|
||||||
angle_to_uchar(beta),
|
angle_to_uchar(beta),
|
||||||
@ -1092,29 +1090,6 @@ auto hooks1 =
|
|||||||
else return named_functionality();
|
else return named_functionality();
|
||||||
});
|
});
|
||||||
|
|
||||||
vector<display_data> 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<N; i++) {
|
|
||||||
auto& pd = player_displays[i];
|
|
||||||
pd.xmin = (i % cols) * 1. / cols;
|
|
||||||
pd.xmax = ((i % cols) + 1.) / cols;
|
|
||||||
pd.ymin = (i / cols) * 1. / rows;
|
|
||||||
pd.ymax = ((i / cols) + 1.) / rows;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
player_displays.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
map<string, map<eLand, int> > scoreboard;
|
map<string, map<eLand, int> > scoreboard;
|
||||||
|
|
||||||
void uploadScore() {
|
void uploadScore() {
|
||||||
@ -1153,7 +1128,7 @@ void displayScore(eLand l) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void race_won() {
|
void race_won() {
|
||||||
if(!race_finish_tick[current_player]) {
|
if(!race_finish_tick[multi::cpid]) {
|
||||||
int result = ticks - race_start_tick;
|
int result = ticks - race_start_tick;
|
||||||
int losers = 0;
|
int losers = 0;
|
||||||
int place = 1;
|
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: ghostset()[specialland]) if(ghost.result < result) place++; else losers++;
|
||||||
for(auto& ghost: oghostset()[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 == 1 && losers) trophy[multi::cpid] = 0xFFD500FF;
|
||||||
if(place == 2) trophy[current_player] = 0xFFFFC0FF;
|
if(place == 2) trophy[multi::cpid] = 0xFFFFC0FF;
|
||||||
if(place == 3) trophy[current_player] = 0x967444FF;
|
if(place == 3) trophy[multi::cpid] = 0x967444FF;
|
||||||
|
|
||||||
if(place + losers > 1)
|
if(place + losers > 1)
|
||||||
addMessage(XLAT("Finished the race! Time: %1, place: %2 out of %3", racetimeformat(result), its(place), its(place+losers)));
|
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)
|
if(place == 1 && losers && official_race)
|
||||||
achievement_gain("RACEWON", rg::racing);
|
achievement_gain("RACEWON", rg::racing);
|
||||||
|
|
||||||
race_finish_tick[current_player] = ticks;
|
race_finish_tick[multi::cpid] = ticks;
|
||||||
charstyle gcs = getcs();
|
charstyle gcs = getcs();
|
||||||
for(color_t *x: {&gcs.skincolor, &gcs.haircolor, &gcs.dresscolor, &gcs.swordcolor, &gcs.dresscolor2}) {
|
for(color_t *x: {&gcs.skincolor, &gcs.haircolor, &gcs.dresscolor, &gcs.swordcolor, &gcs.dresscolor2}) {
|
||||||
for(int a=1; a<4; a++)
|
for(int a=1; a<4; a++)
|
||||||
@ -1196,7 +1171,7 @@ void race_won() {
|
|||||||
}
|
}
|
||||||
subtrack.resize(ngh);
|
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; });
|
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)
|
if(isize(subtrack) > ghosts_to_save && ghosts_to_save > 0)
|
||||||
subtrack.resize(ghosts_to_save);
|
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<display_data*> c(current_display, &player_displays[p]);
|
|
||||||
what();
|
|
||||||
}
|
|
||||||
in_subscreen = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
12
shmup.cpp
12
shmup.cpp
@ -1582,7 +1582,7 @@ void movePlayer(monster *m, int delta) {
|
|||||||
cpid = m->pid;
|
cpid = m->pid;
|
||||||
|
|
||||||
#if CAP_RACING
|
#if CAP_RACING
|
||||||
if(racing::on && cpid != racing::current_player) return;
|
if(racing::on && cpid != subscreens::current_player) return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
double mturn = 0, mgo = 0, mdx = 0, mdy = 0;
|
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;
|
playerturn[cpid] = mgo * SCALE * delta / 200;
|
||||||
playerturny[cpid] = mturn * SCALE * delta / 200;
|
playerturny[cpid] = mturn * SCALE * delta / 200;
|
||||||
|
|
||||||
if(!lctrlclick) {
|
if(!lctrlclick && cpid == 0) {
|
||||||
playerturn[cpid] += mouseaim_x;
|
playerturn[cpid] += mouseaim_x;
|
||||||
playerturny[cpid] += mouseaim_y;
|
playerturny[cpid] += mouseaim_y;
|
||||||
mouseaim_x = mouseaim_y = 0;
|
mouseaim_x = mouseaim_y = 0;
|
||||||
@ -3112,7 +3112,7 @@ hookset<bool(int)> *hooks_turn;
|
|||||||
|
|
||||||
void turn(int delta) {
|
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(callhandlers(false, hooks_turn, delta)) return;
|
||||||
if(!shmup::on) return;
|
if(!shmup::on) return;
|
||||||
@ -3463,16 +3463,16 @@ bool drawMonster(const transmatrix& V, cell *c, const transmatrix*& Vboat, trans
|
|||||||
switch(m->type) {
|
switch(m->type) {
|
||||||
case moPlayer:
|
case moPlayer:
|
||||||
playerfound = true;
|
playerfound = true;
|
||||||
cpid = m->pid;
|
|
||||||
|
|
||||||
if(!hide_player()) {
|
if(!hide_player() || !subscreens::is_current_player(m->pid)) {
|
||||||
|
dynamicval<int> d(cpid, m->pid);
|
||||||
if(DIM == 3) view = view * spin(-M_PI/2);
|
if(DIM == 3) view = view * spin(-M_PI/2);
|
||||||
drawPlayerEffects(view, c, true);
|
drawPlayerEffects(view, c, true);
|
||||||
if(m->inBoat) m->footphase = 0;
|
if(m->inBoat) m->footphase = 0;
|
||||||
if(mapeditor::drawplayer) drawMonsterType(moPlayer, c, view, 0xFFFFFFC0, m->footphase);
|
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);
|
hyperpoint h = keytarget(cpid);
|
||||||
if(DIM == 2)
|
if(DIM == 2)
|
||||||
queuechr(h, vid.fsize, '+', iinf[keyresult[cpid]].color);
|
queuechr(h, vid.fsize, '+', iinf[keyresult[cpid]].color);
|
||||||
|
@ -1366,9 +1366,7 @@ void start_game() {
|
|||||||
#if CAP_TEXTURE
|
#if CAP_TEXTURE
|
||||||
texture::config.remap();
|
texture::config.remap();
|
||||||
#endif
|
#endif
|
||||||
#if CAP_RACING
|
subscreens::prepare();
|
||||||
racing::prepare_subscreens();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void restart_game(char switchWhat) {
|
void restart_game(char switchWhat) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user