2424import org .destinationsol .assets .Assets ;
2525import org .destinationsol .common .SolMath ;
2626import org .destinationsol .game .Hero ;
27+ import org .destinationsol .game .SolCam ;
2728import org .destinationsol .game .SolGame ;
2829import org .destinationsol .game .input .Mover ;
2930import org .destinationsol .game .input .Shooter ;
@@ -38,15 +39,15 @@ public class ShipMixedControl implements ShipUiControl {
3839 public final SolUiControl shoot2Ctrl ;
3940 public final SolUiControl abilityCtrl ;
4041 private final SolUiControl myDownCtrl ;
41- private final Vector2 myMouseWorldPos ;
42+ private final Vector2 myMouseScreenPos ;
4243 private final TextureAtlas .AtlasRegion myCursor ;
4344 private boolean myRight ;
4445 private boolean myLeft ;
4546
4647 ShipMixedControl (SolApplication solApplication , List <SolUiControl > controls ) {
4748 GameOptions gameOptions = solApplication .getOptions ();
4849 myCursor = Assets .getAtlasRegion ("engine:uiCursorTarget" );
49- myMouseWorldPos = new Vector2 ();
50+ myMouseScreenPos = new Vector2 ();
5051 upCtrl = new SolUiControl (null , false , gameOptions .getKeyUpMouse ());
5152 controls .add (upCtrl );
5253 myDownCtrl = new SolUiControl (null , false , gameOptions .getKeyDownMouse ());
@@ -63,16 +64,19 @@ public class ShipMixedControl implements ShipUiControl {
6364 public void update (SolApplication solApplication , boolean enabled ) {
6465 GameOptions gameOptions = solApplication .getOptions ();
6566 blur ();
66- if (!enabled ) {
67+ SolGame game = solApplication .getGame ();
68+ if (!enabled || problemWithProjections (game .getCam ())) {
6769 return ;
6870 }
6971 SolInputManager im = solApplication .getInputManager ();
70- SolGame game = solApplication .getGame ();
7172 Hero hero = game .getHero ();
7273 if (hero .isNonTranscendent ()) {
73- myMouseWorldPos .set (Gdx .input .getX (), Gdx .input .getY ());
74- game .getCam ().screenToWorld (myMouseWorldPos );
75- float desiredAngle = SolMath .angle (hero .getPosition (), myMouseWorldPos );
74+ myMouseScreenPos .set (Gdx .input .getX (), Gdx .input .getY ());
75+ // project mouse coordinates [0;width] and [0;height] to screen coordinates [0,1], [0,1] by scaling down
76+ myMouseScreenPos .scl (1.0f / Gdx .graphics .getWidth (), 1.0f / Gdx .graphics .getHeight ());
77+ Vector2 shipOnScreen = game .getCam ().worldToScreen (hero .getShip ()); // unproject hero to screen coordinates
78+ assertHeroAndMouseCoords (myMouseScreenPos , shipOnScreen );
79+ float desiredAngle = SolMath .angle (shipOnScreen , myMouseScreenPos );
7680 Boolean ntt = Mover .needsToTurn (hero .getAngle (), desiredAngle , hero .getRotationSpeed (), hero .getRotationAcceleration (), Shooter .MIN_SHOOT_AAD );
7781 if (ntt != null ) {
7882 if (ntt ) {
@@ -95,6 +99,33 @@ public void update(SolApplication solApplication, boolean enabled) {
9599 }
96100 }
97101
102+ /**
103+ * When alt+tabbing in full screen mode, the client area can become 0 with/height, and when alt+tabbing back,
104+ * the camera matrix can contain NaN values for the first frame
105+ * @return true if projections should not be done this update
106+ */
107+ private boolean problemWithProjections (SolCam camera ) {
108+ return Gdx .graphics .getWidth () == 0 || Gdx .graphics .getHeight () == 0 ||
109+ camera .getViewWidth () <= 0.f || camera .getViewHeight () <= 0.f || !camera .isMatrixValid ();
110+ }
111+
112+ /**
113+ * Assert that the following vectors do not contain NaN or infinite values
114+ * @param mouseCoords mouse coordinates in [0;1] screen space
115+ * @param heroCoords hero coordinates projected to [0;1] screen space
116+ */
117+ private void assertHeroAndMouseCoords (Vector2 mouseCoords , Vector2 heroCoords ) {
118+ if (Double .isNaN (mouseCoords .x ) || Double .isNaN (mouseCoords .y )) {
119+ System .err .println ("Screen size: " + Gdx .graphics .getWidth () + " " + Gdx .graphics .getHeight ());
120+ throw new RuntimeException ("Mouse coordinates are not valid: " + mouseCoords .x + " " + mouseCoords .y );
121+ }
122+
123+ if (Double .isNaN (heroCoords .x ) || Double .isNaN (heroCoords .y )) {
124+ System .err .println ("Screen size: " + Gdx .graphics .getWidth () + " " + Gdx .graphics .getHeight ());
125+ throw new RuntimeException ("Hero coordinates are not valid: " + heroCoords .x + " " + heroCoords .y );
126+ }
127+ }
128+
98129 @ Override
99130 public boolean isLeft () {
100131 return myLeft ;
0 commit comments