Stencyl 3.4.0 is now out. Get it now!

3D Flight Simulator - Musical Trade Route

ceosol

  • *
  • Posts: 2104
There's a dolby contest and it has inspired me to work more on Musical Trade Route. Short history of the game - it was my LD30 something entry for Connected Worlds. I had it on android for a while, but a bug caused the screen to blank out. GPlay doesn't allow reverting back to a previous version if the newer one covers more devices. I started picking up collaborations/contracts and never got back to working on it.

So I am thinking about incorporating my 3D tests and making the game into a flight simulator. merrak could probably do this instantly :)

Here's what I am thinking. The vector magnitude is calculated as:
P = sqrt ( Px^2 + Py^2 + Pz^2 )

I know my magnitude will be 1 because I would like the player to move 1 step in any direction. Now the difficult part is back calculating x, y and z.

I know what phi1 would be because the angle1 is determined by the player - say using the left and right arrow keys to subtract or add 1 degree. If we tilt the 3D space by 90 degrees, having the y axis pointing up, phi2 would then be the angle2 also determined by the player - for example using the up and down arrow keys. Finally, the theta/gamma angle would be  90 - phi2 since the distance from the z axis is opposite angle from the rise off of the x, y plane.

Just remember, the left-right angle is angle1 (phi1).
The up-down angle is angle2 (phi2).

cos phi1 = Px / sqrt ( Px^2 + Py^2 ) = cos angle1
cos phi2 = Pz / sqrt ( Pz^2 + Px^2 ) = cos angle2
cos theta = Pz / P
since P = 1, we can write this as:
Pz = cos ( 90 - angle2 )

Hurray, we found the z-axis coordinates. Let's plug it back in:

cos angle2 = cos ( 90 - angle2 ) / sqrt ( ( cos ( 90 - angle2 ) ) ^2 + Px^2 )
sqrt ( ( cos ( 90 - angle2 ) ) ^2 + Px^2 ) = ( cos ( 90 - angle2 ) ) / ( cos angle2 )
cos ( 90 - angle2 ) ) ^2 + Px^2 = ( cos ( 90 - angle2 ) ) / ( cos angle2 ) ^2
Px^2 = ( ( cos ( 90 - angle2 ) ) / ( cos angle2 ) ^2 ) - ( cos ( 90 - angle2 ) ) ^2 )
Px = sqrt ( ( ( cos ( 90 - angle2 ) ) / ( cos angle2 ) ^2 ) - ( cos ( 90 - angle2 ) ) ^2 ) )

Hurray???!??!?!? we found Px. Let's simplify it and put Pz back into it - since we already have it calculated.

Px = sqrt ( ( Pz / ( cos angle2 ) ^2 ) - Pz^2 )

Now let's calculate Py since we have Px.

cos angle1 = Px / sqrt ( Px^2 + Py^2 )
sqrt ( Px^2 + Py^2 ) = Px / cos angle1
Px^2 + Py^2 = ( Px / cos angle1 ) ^2
Py^2 = ( Px / cos angle1 ) ^2 - Px^2
Py = sqrt ( ( Px / cos angle1 ) ^2 - Px^2 )

Phew, ok so now we can determine movement in the 3D space. Next post, I will go into the pitch and yaw calculations, which are quite a bit easier.

Anybody who thinks that Stencyl should automatically have 3D needs to think about these calculations :D

« Last Edit: March 13, 2016, 09:52:55 am by ceosol »

ceosol

  • *
  • Posts: 2104
duh, I'm dumb. All of the "cos ( 90 - angle2 )" can be written as "sin angle2"

ceosol

  • *
  • Posts: 2104
I just tried to implement those equations and something was off. Pz works fine. And that was the only part of the equations that I was comfortable with, so that's good. I need to revisit the other equations. Maybe this time, I will just plug in the Pz during the calculations

ceosol

  • *
  • Posts: 2104
I think I had labeled the x-axis and z-axis incorrectly when I did my flip to have the y-axis pointing up. The new theta would be 90 - the original phi1 (angle1).

cos  theta2 = Py / P
cos ( 90 - angle1 ) = Py
Py = sin angle1
Pz = sin angle2

My original problem with Px is that it NEEDS to incorporate both the angle 1 and angle 2. So let's backtrack to the original equation.

P = sqrt ( Px^2 + Py^2 + Pz^2 )
1 = sqrt ( Px^2 + Py^2 + Pz^2 )
1 = Px^2 + Py^2 + Pz^2
Px^2 = 1 - Py^2 - Pz^2
Px = sqrt ( 1 - Py^2 - Pz^2 )

But now that cancels out Px. Hmm...

ceosol

  • *
  • Posts: 2104
So here is one place that I am incorrect, the Py and Pz cannot be a simple sin function. Take 45 degrees for both the angle1 and angle2. All 3 of the player's location values should then result in the same number. That means 1 = sqrt ( 3 * value^2 ). The value would equal the square root of 1/3, or 0.5777. Using the straight sin 45, the values are 0.7071.


ceosol

  • *
  • Posts: 2104
I gave up on those equations. I was able to solve for Py and Pz in terms of Px. But then I couldn't solve for Px. If you are curious, here is what those equations look like:
Py = sqrt((Px/cos angle1)^2-Px^2)
Pz = sin angle2 * sqrt((1- (Px^2/cos angle1^2))+Px^2)

Anyway, I decided to cheat by abandoning my P = 1. Now my Px is about 20% off from where it should be, but I don't think it will be noticeable moving in 3D space.

Here's a prototype. Left and right to angle 1 and up and down to change angle 2. Use Z and X to change your speed (going from 0 to 50).

« Last Edit: March 15, 2016, 12:46:52 pm by ceosol »

merrak

  • *
  • Posts: 1488
Interesting demo... actually reminds me of some of the first QBASIC games I wrote :D (They all had purely numerical output). But what is P? Is this the player's position?

In graphics hardware, these types of calculations are often represented using vector and matrix operations, which would make them much easier to follow. If you're really interested in extending Stencyl to 3D ("true" 3D--not isometric or "2.5D"), then Edward Angel's primer on OpenGL may be a useful reference, albeit long. You can probably find a cheap copy somewhere. You wouldn't need most of it, which is specific to OpenGL. But the math is the same and optimizing the math is the key to getting good 3D performance.

ceosol

  • *
  • Posts: 2104
Interesting demo... actually reminds me of some of the first QBASIC games I wrote :D (They all had purely numerical output). But what is P? Is this the player's position?

In graphics hardware, these types of calculations are often represented using vector and matrix operations, which would make them much easier to follow. If you're really interested in extending Stencyl to 3D ("true" 3D--not isometric or "2.5D"), then Edward Angel's primer on OpenGL may be a useful reference, albeit long. You can probably find a cheap copy somewhere. You wouldn't need most of it, which is specific to OpenGL. But the math is the same and optimizing the math is the key to getting good 3D performance.

Thanks merrak. I do not understand anything that coders say, so I am not sure whether or not the book would be helpful. I need to see how things react on the screen to learn and understand the mechanics.

Let's get into pitch and yaw.

To answer merrak's other question, P is the player's position after one step in whichever direction. If it makes more sense, think of the origin as Porigin and the end of the vector as Pfinal.

We have our player starting at 50, 50, 0. I'll place an object (V) at 100, 50, 0. In order to orient yourself, the y-axis is going from left to right. The z-axis is going from bottom to top. And the x-axis is going into the screen. So the object is starting direction in front of us.

X = Px - Vx
Y = Py - Vy
Z = Pz - Vz
Pitch = - atan^2 ( Y, sqrt ( Z^2 + X^2 ) )
Yaw = ( atan^2 ( Z, X ) ) + 180
Distance (magnitude of the vector) = sqrt ( X^2 + Y^2 + Z^2 )

Using our starting points, the pitch will be 0 degrees and the yaw will be 0 degrees because the object is directly in front of us on the x-axis. If you fly past the object, it would be a yaw of 180 because it would be directly behind us.

However, it is not as simple as "in front" or "behind". Remember, the objects would be in 3D space and the pitch/yaw are only taking vector locations into consideration. So a yaw of 180 is in relation to the player's position and independent of the player's view. In order to "see" the object again, the players can spin their ship around.

Here's the update. Left and right to angle 1 and up and down to change angle 2. Use Z and X to change your speed (going from 0 to 50).

« Last Edit: March 16, 2016, 08:13:07 am by ceosol »

ceosol

  • *
  • Posts: 2104
So now I am working on visualizing the object. Let's say the screen size has a view of 120 degree by 90 degrees. As far as I can imagine, there are eight scenarios where visualization is possible:

1. The ABS(angle-pitch) < 60 and ABS(angle2-yaw) < 45
2. The ABS((angle-360)-pitch) < 60 and ABS((angle2-360)-yaw) < 45
3. The ABS((angle-360)-pitch) < 60 and ABS(angle2-yaw) < 45
4. The ABS(angle-pitch) < 60 and ABS((angle2-360)-yaw) < 45
5. The ABS((angle-180)-pitch) < 60 and ABS((angle2-180)-yaw) < 45
6. The ABS((angle-180)-pitch) < 60 and ABS((angle2+180)-yaw) < 45
7. The ABS((angle+180)-pitch) < 60 and ABS((angle2-180)-yaw) < 45
8. The ABS((angle+180)-pitch) < 60 and ABS((angle2+180)-yaw) < 45

For now, I have the object appearing and vanishing from the screen. It seems to be working correctly for all eight scenarios. The next step is having it moving.

ceosol

  • *
  • Posts: 2104
I just figured out that there are even more calculations to consider:

1. Upside down and backwards. The Py and Pz equations did not account for upside down or backwards orientations. To compensate, I have added in -sin angle functions if the other angle is between 90 and 270.

2. Pitch could go negative. I added in +180 like the yaw equation has. This changes the 8 scenarios for on-screen determination. I will post new scenarios as I discover them :)

3D calculations are so much fun!

« Last Edit: March 15, 2016, 03:26:12 pm by ceosol »

ceosol

  • *
  • Posts: 2104
I found another special case. If the yaw is ~90 or ~270 and the angle2 is ~90 or ~270, respectively, all angle 1 values should make the object visible.

merrak

  • *
  • Posts: 1488
Thanks merrak. I do not understand anything that coders say, so I am not sure whether or not the book would be helpful. I need to see how things react on the screen to learn and understand the mechanics.

It's definitely programming heavy--so based on what you said it may not be a great book after all. This is looking pretty neat so far, though. I'm interested in seeing how you implement the rest of the 3D world (planets, etc.). Your first 3D demo seemed to work pretty well.

ceosol

  • *
  • Posts: 2104
It's definitely programming heavy--so based on what you said it may not be a great book after all. This is looking pretty neat so far, though. I'm interested in seeing how you implement the rest of the 3D world (planets, etc.). Your first 3D demo seemed to work pretty well.

My brother is the coder, so he would understand it. But then, he is also a horrible teacher so it wouldn't do me any good :)

The planets are an interesting topic. Along the lines of stars in the background. You need them to move, you not necessarily be able to reach them. So maybe they could have a separate "zoom" feature where they are placed at x of 999999999, but will always be a consistent scale. I was also wondering about having a background that moves with your angles. Let's say I change the viewport to 128 width, then I could have a repeating background 5x the screen width and just nudge the scroll factor every time the player is turning. Unless I want the player to reach the planet, I could have it as part of the background.

The object zoom in general is just a function of the magnitude vector. We already have that being calculated:
Magnitude of the player-object vector = sqrt ( X^2 + Y^2 + Z^2 )
The actual zoom would be based on how big you want the object to be. So I am going to say that the object is 64x64. At a distance of 1, it should be 240x240 (half of the screen height). Let's make it easy and say 400% zoom at a distance of 1. At a distance of 25, I would like it to be normal size (100% zoom). If we made this a linear relationship, the object would vanish at a distance of 33. Let's try a logarithmic curve instead. Adding in another data point, the object should be 25% at a distance of 50. Doing this gives us the equation:

%Zoom = -95.032 * ln ( distance ) + 400.89
Instead of having decimals, let's just go:
%Zoom =  -100 * ln ( distance ) + 400

Here's the updated prototype. I only have the x, y (on screen) of the object for the first four visualizing conditions that I listed above. Keep in mind, it will not work correctly for all positions in the 3D space. Left and right to angle 1 and up and down to change angle 2. Use Z and X to change your speed (going from 0 to 50).




« Last Edit: March 27, 2016, 08:10:07 am by ceosol »

ceosol

  • *
  • Posts: 2104
I felt like toying with some rail shooter mechanics. For anybody who does not know what a rail shooter it, you follow a set path through the environment and shoot at things appearing on the screen. Here are some of the equations I used for this version:

The circle starts at 100, 50, 0. It travels to 100, 100, 0 (to the right) over 4 seconds, then 200, 40, 10 over 6 seconds and finally behind you to 50, 20, -10 over 6 seconds. The reason it is behind you is because you are moving forward on the x-axis. This puts you past x=50 by the end of the circle's motion.

I disabled left/right and up/down for now. It might be neat to add those back in, giving spherical targeting while moving on the rail. Rail motion is much easier for starting out with 3D calculations. Everything is controlled instead  of possibly having bugs appearing from calculations you did not account for.

For shooting, hold down the mouse. The bullets fire at a rate of 0.2 seconds. The hit equation I based off of the magnitude and on-screen circle coordinates... although a better method would be calculating trajectory in 3D space. Simplified, I made the target hitbox as 2000/distance. If the distance is 10, you have a hitbox of 200x200 pixels. If the distance is 100, you have a hitbox of 20x20 pixels. To make this a little bit easier to conceptualize while playing, I had to adjust the zoom%. The new zoom is:

zoom% = 500 - ( 115 x ln ( distance ) )

New version, use the mouse to fire. If you can still move up/down/left/right, it is the previous version. This game has been taking a long time to update on the stencyl arcade :)



« Last Edit: March 31, 2016, 01:33:02 pm by ceosol »

merrak

  • *
  • Posts: 1488
28 damage inflicted! Did you ever play Rebel Assault? This reminds me a bit of that game. The only thing I'm not sure of is how close the ball is relative to the vanishing point for the shots. It seems like holding the mouse pointer over the ball doesn't always register a hit.