mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 14:02:59 +00:00 
			
		
		
		
	device orientation-based scrolling on mobiles
This commit is contained in:
		| @@ -629,7 +629,7 @@ void achievement_final(bool really_final) { | |||||||
|   specific_improved = 0; |   specific_improved = 0; | ||||||
|   specific_what = 0; |   specific_what = 0; | ||||||
|    |    | ||||||
|   if(specials == 0) improveItemScores();  |   if(specialcode == 0) improveItemScores();  | ||||||
|    |    | ||||||
|   int tg = gold(); |   int tg = gold(); | ||||||
|   if(tg && haveLeaderboard(sid)) { |   if(tg && haveLeaderboard(sid)) { | ||||||
|   | |||||||
| @@ -829,6 +829,8 @@ void showBasicConfig() { | |||||||
|  |  | ||||||
|   dialog::addBoolItem(XLAT("forget faraway cells"), memory_saving_mode, 'y'); |   dialog::addBoolItem(XLAT("forget faraway cells"), memory_saving_mode, 'y'); | ||||||
|  |  | ||||||
|  |   dialog::addSelItem(XLAT("scrolling by device rotation"), ors::choices[ors::mode], '1');   | ||||||
|  |  | ||||||
|   if(CAP_SHMUP && !ISMOBILE) |   if(CAP_SHMUP && !ISMOBILE) | ||||||
|     dialog::addSelItem(XLAT("configure keys/joysticks"), "", 'p'); |     dialog::addSelItem(XLAT("configure keys/joysticks"), "", 'p'); | ||||||
|  |  | ||||||
| @@ -846,6 +848,8 @@ void showBasicConfig() { | |||||||
|      |      | ||||||
|     if(uni >= 32 && uni < 64) xuni = uni; |     if(uni >= 32 && uni < 64) xuni = uni; | ||||||
|      |      | ||||||
|  |     if(xuni == '1') pushScreen(ors::show); | ||||||
|  |  | ||||||
|     if(uni == 'M') vid.quickmouse = !vid.quickmouse; |     if(uni == 'M') vid.quickmouse = !vid.quickmouse; | ||||||
|     else if(xuni == 'm') vid.skipstart = !vid.skipstart; |     else if(xuni == 'm') vid.skipstart = !vid.skipstart; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										141
									
								
								control.cpp
									
									
									
									
									
								
							
							
						
						
									
										141
									
								
								control.cpp
									
									
									
									
									
								
							| @@ -517,6 +517,7 @@ void mainloopiter() { | |||||||
|   if(timetowait > 0) |   if(timetowait > 0) | ||||||
|     SDL_Delay(timetowait); |     SDL_Delay(timetowait); | ||||||
|   else { |   else { | ||||||
|  |     ors::check_orientation(); | ||||||
|     if(cmode & sm::CENTER) { |     if(cmode & sm::CENTER) { | ||||||
|       if(playermoved && vid.sspeed > -4.99 && !outoffocus) |       if(playermoved && vid.sspeed > -4.99 && !outoffocus) | ||||||
|         centerpc((ticks - lastt) / 1000.0 * exp(vid.sspeed)); |         centerpc((ticks - lastt) / 1000.0 * exp(vid.sspeed)); | ||||||
| @@ -908,4 +909,144 @@ bool handleCompass() { | |||||||
|   return false; |   return false; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | // orientation sensitivity | ||||||
|  | namespace ors { | ||||||
|  |  | ||||||
|  | int mode; | ||||||
|  | double sensitivity = 1; | ||||||
|  |  | ||||||
|  | int when_enabled; | ||||||
|  | transmatrix last_orientation; | ||||||
|  | transmatrix relative_matrix = Id; | ||||||
|  |  | ||||||
|  | string choices[3] = {"OFF", "relative", "absolute"}; | ||||||
|  |  | ||||||
|  | #if CAP_ORIENTATION | ||||||
|  | transmatrix getOrientation() { | ||||||
|  |   return MirrorX * MirrorZ * hr::getOrientation() * MirrorX * MirrorZ; | ||||||
|  |   } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | void reset() { | ||||||
|  | #if CAP_ORIENTATION | ||||||
|  |   if(mode) last_orientation = getOrientation(); | ||||||
|  |   relative_matrix = Id; | ||||||
|  | #endif | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | void delayed_reset() { | ||||||
|  | #if CAP_ORIENTATION | ||||||
|  |   relative_matrix = Id; when_enabled = ticks; | ||||||
|  | #endif | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | void show() { | ||||||
|  | #if CAP_ORIENTATION | ||||||
|  |   cmode = sm::SIDE; | ||||||
|  |   gamescreen(0); | ||||||
|  |  | ||||||
|  |   dialog::init(XLAT("scrolling by device rotation")); | ||||||
|  |    | ||||||
|  |   dialog::addHelp(XLAT( | ||||||
|  |     "This lets you scroll the map by rotating your device. It can be e.g. used to " | ||||||
|  |     "play the spherical mode of HyperRogue in mobile VR goggles -- the \"spherical VR\" " | ||||||
|  |     "button configures this; this VR mode can be disabled by touching the screen for 1 second.")); | ||||||
|  |    | ||||||
|  |   dialog::addSelItem(XLAT("mode"), choices[mode], 'm'); | ||||||
|  |   dialog::add_action([] () { int m = (mode + 1) % 3; mode = 0; fullcenter(); mode = m; delayed_reset(); }); | ||||||
|  |   dialog::addSelItem(XLAT("sensitivity"), fts(sensitivity), 's'); | ||||||
|  |   dialog::add_action([] () {  | ||||||
|  |     dialog::editNumber(sensitivity, -10, 10, 1, 1, XLAT("sensitivity"),  | ||||||
|  |         XLAT("1 means that rotating the device by 1 radian corresponds to scrolling by 1 unit. In spherical geometry, 1 unit = 1 radian.")); | ||||||
|  |     }); | ||||||
|  |    | ||||||
|  |   dialog::addBreak(100); | ||||||
|  |  | ||||||
|  |   dialog::addItem(XLAT("stereo vision config"), 'e'); | ||||||
|  |   dialog::add_action([] () { pushScreen(showStereo); }); | ||||||
|  |  | ||||||
|  |   dialog::addItem(XLAT("experiment with geometry"), 'g'); | ||||||
|  |   dialog::add_action([] () { runGeometryExperiments(); }); | ||||||
|  |  | ||||||
|  |   dialog::addSelItem(XLAT("projection"), fts(vid.alpha), 'p'); | ||||||
|  |   dialog::add_action([] () { projectionDialog(); }); | ||||||
|  |  | ||||||
|  |   dialog::addSelItem(XLAT("scale factor"), fts(vid.scale), 'z'); | ||||||
|  |   dialog::add_action([] () { editScale(); }); | ||||||
|  |  | ||||||
|  |   dialog::addItem(XLAT("spherical VR"), 'v'); | ||||||
|  |   dialog::add_action([] () {  | ||||||
|  |     if(!sphere) { targetgeometry = gSphere; restart_game(rg::geometry); } | ||||||
|  |     mode = 0; fullcenter(); | ||||||
|  |     mode = 2; sensitivity = 1; | ||||||
|  |     stereo::mode = sLR; stereo::ipd = 0.2; | ||||||
|  |     vid.alpha = 0; vid.scale = 1; | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |   dialog::addBreak(100); | ||||||
|  |  | ||||||
|  |   dialog::addBack(); | ||||||
|  |  | ||||||
|  |   dialog::display(); | ||||||
|  | #endif | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | void relative_apply() { | ||||||
|  |   if(ors::mode == 1) View = relative_matrix * View; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | void relative_unapply() { | ||||||
|  |   if(ors::mode == 1) View = inverse(relative_matrix) * View; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | transmatrix change_geometry(const transmatrix& T) { | ||||||
|  |   if(sphere && sensitivity == 1) return T; | ||||||
|  |   ld alpha, beta, push; | ||||||
|  |    | ||||||
|  |   { | ||||||
|  |   dynamicval<eGeometry> g(geometry, gSphere); | ||||||
|  |   hyperpoint h = T * C0; | ||||||
|  |   push = hdist0(h); | ||||||
|  |   alpha = atan2(h[1], h[0]); | ||||||
|  |   if(push == 0) alpha = 0; | ||||||
|  |   hyperpoint spinpoint = gpushxto0(h) * T * xpush(1) * C0; | ||||||
|  |   beta = atan2(spinpoint[1], spinpoint[0]); | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   // gpushxto0(h) * T * xpush(1) * C0 == spin(beta) * xpush(1) * C0 | ||||||
|  |   // gpushxto0(h) * T == spin(beta) | ||||||
|  |   // T = rgpushxto0(h) * spin(beta) | ||||||
|  |  | ||||||
|  |    | ||||||
|  |   transmatrix U = spin(-alpha) * xpush(push * sensitivity) * spin(-beta+alpha); | ||||||
|  |  | ||||||
|  |   return U; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | void unrotate(transmatrix& T) { | ||||||
|  |   if(mode == 1) T = inverse(relative_matrix) * T; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | void rerotate(transmatrix& T) { | ||||||
|  |   if(mode == 1) T = (relative_matrix) * T; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | void check_orientation() { | ||||||
|  | #if CAP_ORIENTATION | ||||||
|  |   if(!mode) return; | ||||||
|  |   if(ticks < when_enabled + 500) { | ||||||
|  |     last_orientation = getOrientation(); | ||||||
|  |     return; | ||||||
|  |     } | ||||||
|  |   transmatrix next_orientation = MirrorX * getOrientation(); | ||||||
|  |   transmatrix T = inverse(next_orientation) * last_orientation; | ||||||
|  |   if(mode == 1) unrotate(View), unrotate(cwtV); | ||||||
|  |   relative_matrix = change_geometry(T); | ||||||
|  |   if(mode == 1) rerotate(View), rerotate(cwtV); | ||||||
|  |   if(mode == 2) View = relative_matrix * View, last_orientation = next_orientation; | ||||||
|  | #endif | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								hyper.h
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								hyper.h
									
									
									
									
									
								
							| @@ -3727,4 +3727,16 @@ extern void switchHardcore(); | |||||||
| extern bool using_perspective; | extern bool using_perspective; | ||||||
|  |  | ||||||
| void generateAlts(heptagon *h, int levs = irr::on ? 1 : S3-3, bool link_cdata = true); | void generateAlts(heptagon *h, int levs = irr::on ? 1 : S3-3, bool link_cdata = true); | ||||||
|  |  | ||||||
|  | namespace ors { | ||||||
|  |   extern int mode; | ||||||
|  |   extern string choices[]; | ||||||
|  |   void show(); | ||||||
|  |   void apply(); | ||||||
|  |   void check_orientation(); | ||||||
|  |   void unrotate(transmatrix& T); | ||||||
|  |   void rerotate(transmatrix& T); | ||||||
|  |   void reset(); | ||||||
|  |   } | ||||||
|  |    | ||||||
| } | } | ||||||
|   | |||||||
| @@ -242,6 +242,9 @@ const transmatrix Mirror = {{{1,0,0}, {0,-1,0}, {0,0,1}}}; | |||||||
| // mirror image | // mirror image | ||||||
| const transmatrix MirrorX = {{{-1,0,0}, {0,1,0}, {0,0,1}}}; | const transmatrix MirrorX = {{{-1,0,0}, {0,1,0}, {0,0,1}}}; | ||||||
|  |  | ||||||
|  | // mirror image | ||||||
|  | const transmatrix MirrorZ = {{{1,0,0}, {0,1,0}, {0,0,-1}}}; | ||||||
|  |  | ||||||
| // rotate by PI | // rotate by PI | ||||||
| const transmatrix pispin = {{{-1,0,0}, {0,-1,0}, {0,0,1}}}; | const transmatrix pispin = {{{-1,0,0}, {0,-1,0}, {0,0,1}}}; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -730,8 +730,12 @@ void spinEdge(ld aspd) { | |||||||
|   } |   } | ||||||
|  |  | ||||||
| void centerpc(ld aspd) {  | void centerpc(ld aspd) {  | ||||||
|  |   if(ors::mode == 2 && vid.sspeed < 5) return; | ||||||
|   if(vid.sspeed >= 4.99) aspd = 1000; |   if(vid.sspeed >= 4.99) aspd = 1000; | ||||||
|   DEBB(DF_GRAPH, (debugfile,"center pc\n")); |   DEBB(DF_GRAPH, (debugfile,"center pc\n")); | ||||||
|  |    | ||||||
|  |   ors::unrotate(cwtV); ors::unrotate(View); | ||||||
|  |    | ||||||
|   hyperpoint H = ypush(-vid.yshift) * sphereflip * tC0(cwtV); |   hyperpoint H = ypush(-vid.yshift) * sphereflip * tC0(cwtV); | ||||||
|   ld R = H[0] == 0 && H[1] == 0 ? 0 : hdist0(H); // = sqrt(H[0] * H[0] + H[1] * H[1]); |   ld R = H[0] == 0 && H[1] == 0 ? 0 : hdist0(H); // = sqrt(H[0] * H[0] + H[1] * H[1]); | ||||||
|   if(R < 1e-9) { |   if(R < 1e-9) { | ||||||
| @@ -741,6 +745,7 @@ void centerpc(ld aspd) { | |||||||
|       } */ |       } */ | ||||||
|     spinEdge(aspd); |     spinEdge(aspd); | ||||||
|     fixmatrix(View); |     fixmatrix(View); | ||||||
|  |     ors::rerotate(cwtV); ors::rerotate(View); | ||||||
|     return; |     return; | ||||||
|     } |     } | ||||||
|    |    | ||||||
| @@ -766,6 +771,8 @@ void centerpc(ld aspd) { | |||||||
|     fixmatrix(View); |     fixmatrix(View); | ||||||
|     spinEdge(aspd); |     spinEdge(aspd); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |   ors::rerotate(cwtV); ors::rerotate(View); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| void optimizeview() { | void optimizeview() { | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								init.cpp
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								init.cpp
									
									
									
									
									
								
							| @@ -168,6 +168,7 @@ void handleclick(MOBPAR_FORMAL) { | |||||||
|             if(andmode == 0 && shmup::on) ; // just fire, do not change modes |             if(andmode == 0 && shmup::on) ; // just fire, do not change modes | ||||||
|             else { |             else { | ||||||
|               if(andmode == 1) { |               if(andmode == 1) { | ||||||
|  |                 ors::reset(); | ||||||
|                 centerpc(INF); |                 centerpc(INF); | ||||||
|                 View = Id; |                 View = Id; | ||||||
|                 viewctr.h = cwt.c->master; |                 viewctr.h = cwt.c->master; | ||||||
| @@ -235,6 +236,8 @@ void mobile_draw(MOBPAR_FORMAL) { | |||||||
|   if(lastt > ticks) lastt = ticks; |   if(lastt > ticks) lastt = ticks; | ||||||
|   int tdiff = ticks - lastt; |   int tdiff = ticks - lastt; | ||||||
|  |  | ||||||
|  |   ors::check_orientation(); | ||||||
|  |  | ||||||
|   if(playermoved && vid.sspeed > -4.99) |   if(playermoved && vid.sspeed > -4.99) | ||||||
|     centerpc(tdiff / 1000.0 * exp(vid.sspeed)); |     centerpc(tdiff / 1000.0 * exp(vid.sspeed)); | ||||||
|  |  | ||||||
| @@ -287,6 +290,11 @@ void mobile_draw(MOBPAR_FORMAL) { | |||||||
|   #endif |   #endif | ||||||
|     mouseh = gethyper(mousex, mousey); |     mouseh = gethyper(mousex, mousey); | ||||||
|  |  | ||||||
|  |   inmenu = isize(screens) > 1; | ||||||
|  |  | ||||||
|  |   if(!inmenu && stereo::mode == stereo::sLR && ors::mode) | ||||||
|  |     mousex = vid.xres/2, mousey = vid.yres/2, mouseh = sphereflip * C0; | ||||||
|  |  | ||||||
| //  if(debfile) fprintf(debfile, "d1\n"), fflush(debfile); | //  if(debfile) fprintf(debfile, "d1\n"), fflush(debfile); | ||||||
|   frames++; |   frames++; | ||||||
|   if(conformal::on) conformal::apply(); |   if(conformal::on) conformal::apply(); | ||||||
| @@ -303,8 +311,6 @@ void mobile_draw(MOBPAR_FORMAL) { | |||||||
|   shiftmul = getcshift; |   shiftmul = getcshift; | ||||||
|   calcMousedest(); |   calcMousedest(); | ||||||
|  |  | ||||||
|   inmenu = isize(screens) > 1; |  | ||||||
|  |  | ||||||
|   if(lclicked && !clicked && !inmenu) handleclick(MOBPAR_ACTUAL); |   if(lclicked && !clicked && !inmenu) handleclick(MOBPAR_ACTUAL); | ||||||
|  |  | ||||||
|   if(inmenu && !clicked && !lclicked) inmenu = false; |   if(inmenu && !clicked && !lclicked) inmenu = false; | ||||||
| @@ -336,6 +342,8 @@ void mobile_draw(MOBPAR_FORMAL) { | |||||||
|     if(lclicked && !clicked) { |     if(lclicked && !clicked) { | ||||||
|       if(rug::rugged) |       if(rug::rugged) | ||||||
|         rug::select(); |         rug::select(); | ||||||
|  |       else if(ors::mode && !longclick) | ||||||
|  |         normal_reaction = true; | ||||||
|       else |       else | ||||||
|         pushScreen(showStereo); |         pushScreen(showStereo); | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -1176,6 +1176,7 @@ void switch_game_mode(char switchWhat) { | |||||||
|       break; |       break; | ||||||
|  |  | ||||||
|     case rg::geometry: |     case rg::geometry: | ||||||
|  |       ors::reset(); | ||||||
|       if(geometry == targetgeometry) geometry = gNormal; |       if(geometry == targetgeometry) geometry = gNormal; | ||||||
|       else geometry = targetgeometry; |       else geometry = targetgeometry; | ||||||
|       if(chaosmode && (euclid || sphere || quotient)) chaosmode = false; |       if(chaosmode && (euclid || sphere || quotient)) chaosmode = false; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Zeno Rogue
					Zeno Rogue