face target

BlitzMax Forums/MiniB3D Module/face target

redmoth(Posted 2013) [#1]
Hi

I'm trying to learn minib3d (inside Monkey) by trying to make a very basic on rails shooter. As you see in the photo below, I have a target (it will become the cross-hair, to where the player aims and shoots) and a ship:



The ship and the target move forward at a steady rate and I can move the target.
'move ship mesh entity (mShip) and target entity (mTarget)
mShip.z+=Speed
mTarget.z+=Speed

'move the target left or right, but keep it in the window view
If KeyDown(KEY_LEFT) Or DirectionInput = 1 Then 
	If targetX>= -40 Then targetX -=1
	
	
Else If KeyDown(KEY_RIGHT)Or DirectionInput = 2 Then
	If targetX<= 40 Then targetX +=1

End


But what I'm having problems with, is making the ship face the target. I've had a look in the blitz3D docs, but don't understand correctly what I should be doing.

dx = targetX - x
dy = targetY - y
dz = targetZ - z
AlignToVector( mShip, dx, dy, dz, 3, 0.5)
mShip.TurnEntity(0,dy,dz)



Any help would be appreciated.


redmoth(Posted 2013) [#2]
Ok, I've been looking through the blitz3D forums and I've tried this:
mShip.TurnEntity(0,(DeltaYaw(mShip,mTarget)*2),0)

but, the ship is facing backwards. :-(


Midimaster(Posted 2013) [#3]
1.
better you move the objects by using

objectxxx.MoveEntity x,y,z
or 
objectxxx.TurnEntity x,y,z


instead of direct acces to the coordinates.


2.
all object hav a "inner" coordinate system, where z is the always the "ahead" direction, so ...
mShip.mMoveEntity 0,0,1

...always moves the ship "forward".

If in such a condition your ship does look like not moving forward, your 3D modell has a wrong orientation. You should turn it in the 3D construction tool.


redmoth(Posted 2013) [#4]
Thank you.

I've updated my code to use MoveEntity instead of the coordinates.

And with a little tinkering with DeltaYaw and DeltaPitch, the ship doesn't look to bad how it moves to look at the target box.


redmoth(Posted 2013) [#5]
The code works.
but I have the problem that if I mode the target to the side,s the ship goes too far. This means that the ship is closer to the side of the screen than the target, so it's always pointing inwards, so I can't shoot towards the sides.
So I'm trying to get the ship to look at the target without moving it, so I can move it independently and that the ship to always be closer to the center of the screen than the target.
mTarget1.MoveEntity(0,0,moveSpeed)
mTarget1.MoveEntity(0,0,moveSpeed)
PointEntity(mShip,mTarget2)

If KeyDown(KEY_LEFT) '
		If EntityX(mTarget1)>= -30 Then  'keep the target in window
		mTarget1.MoveEntity(-3,0,0)
Else If KeyDown(KEY_LEFT)
...


I've tried limiting the ships movement in the KeyDown functions, but to no avail.

The problem is shown in the screen below, where I've moved the target to the left, but now the ship is futher left than the target.


Any help greatly appreciated


ima747(Posted 2013) [#6]
Are you sure the ship is actually further left than the target? I'm not sure exactly what you're trying to accomplish but those 3 points (2 targets and ship nose) are quite possibly in line, perspective is hard to gauge and the targets appear to be billboard sprites which makes it even harder to tell... Again, not sure exactly what you're trying to accomplish, it seems like you might want to adjust your camera's field of view to be wider, OR pull your camera further back...


Midimaster(Posted 2013) [#7]
I think, what you try to reach is, that the camera shall be connected to the ship. Shall the camera be always behind the ship?

In this case it would look like the ship is exactly on the line from camera to target.

A.)
Try to create the ship as a child of the camera:
Ship=LoadMesh("blabla.b3d",camera)
MoveEntity Ship 0,0,5

Now you have to turn or move the camera towards the target. The ship will always be between camera and target.



B.)
Or the camera as a child of the ship:
Ship=LoadMesh("blabla.b3d")
Camera=CreateCamera(Ship)
MoveEntity Camera 0,0,-5

Here you can still move and turn the ship. The camera will always be behind the ship


C.)
Or with a pivot:
Mother=CreatePivot()
Camera=CreateCamera(Mother)
Ship=LoadMesh("blabla.b3d",Mother)
MoveEntity Ship 0,0,2
MoveEntity Camera 0,0,-2

Turn the ship, but move the Mother. This will look like target can get away to the sides of the screen.


redmoth(Posted 2013) [#8]
Thanks for your suggestions and your time!

Well, I'm trying to create is a basic 'on rails' shooter (like star fox) so

1.the camera never moves along the x or y axis, and just goes forward in a straight line down the z axis. (works fine)

2. The target and ship can only move in the confines of the screen, which is this part ( the buttons control the screen, and the ship moves as it's always pointing in the direction of the taget):

If KeyDown(KEY_LEFT) '
	If EntityX(mTarget1)>= -30 Then  'keep the target in window
	mTarget1.MoveEntity(-3,0,0)


@ima747
yes they are in line perfectly, but that's the problem, If I move the target to one of the sides, the ship goes off screen and so it lines itself up to the target and the lasers go towards the center of the screen.
I think Midimaster's 'c' suggestion will give me something to play around with, and I'll post my results for anyone else to see.


Kryzon(Posted 2013) [#9]
Hi. What a cool subject. Star Fox 64 uses a complex navigation system, with a lot of smooth corrections.

First, let's see some reference (put it on 3:00):



There are two navigation modes in the game. On-rail (navigating through a fixed path) and all-range (you fly wherever you want). Since you want to reproduce the on-rail, we'll deal with that.

Before writing this, I played the game. From my interpretation there are four elements responsible for the on-rail navigation, with the following order of importance:
1) An invisible 3D path.
2) A pivot moving along the path.
3) A camera.
4) The player ship.

How do these elements relate?
- The player ship roams "freely" in a 3D rectangular zone. If you keep moving your ship in a certain direction, it will eventually reach one of the sides of this rectangular zone and not move further.
This rectangular area and its orientation are derived from the main pivot traveling the path. You can use TFormPoint to check if the ship's location in relation to the main pivot has crossed the borders of this rectangular area that you define.
The ship's pivot-point (or mesh center) is located at its rear. When you move the ship, it tilts and starts going in the direction you want. If you let go, the ship smoothly returns to alignment with the path. This means, if you let go of the control, the ship will slowly turn parallel to the current path direction.
The target sights displayed on screen are derived from the ship's position and orientation based on a TForm and CameraProject. They're calculated after the ship moves, not the other way around.

- The camera does the exact same movement and orientation behavior as the ship described above, but in a partial manner.
This means if the ship moves sideways the distance 10, the camera will move someting like 5.
If the ship turns right 30 degrees, the camera turns right 15.
The camera does not point to the ship, otherwise the ship would always be centered on the screen. When the ship reaches the rectangular limit area described previously, the camera also stops moving (it doesn't "reach" to the ship, even from the ship being unable to move further from the limit).
The fact that the camera turns in the same direction as the ship is turning drives the view toward the obstacles the ship will encounter. This is an intuitive way to let the player see not only his ship but also the obstacles and enemies coming ahead.

- Both the camera and ship are parented to the main pivot. This means the ship or camera don't move forward, only sideways and vertically - what drives them forward is the main pivot.
The main pivot keeps traveling and pointing along the path. If the path changes direction, the ship and camera will simply be smoothly displaced from the pivot turning to this new direction (they'll be dragged along because they're parented to the pivot).

This is all very complex because it's all very well designed (Nintendo!).
If you need help with code I can write some; It handles some pesky TForm commands to put it all in order.


redmoth(Posted 2013) [#10]
Thanks, I hadn't thought about it like that. I've started from scratch trying to think about your advice. A good excuse to play Star Fox 64, I have also played it, and have noticed how it slowly resets.

I think I can ignore '1' as I just want 1 path, and will obviously not attempt to make something as complex as Star Fox.

I've been looking at TForm in the docs, but am finding it difficult getting my head around it, as before I was using a number such as 30 on each side to limit the movement, but obviously using TForm sounds much better. I've pasted my restarted Ship class below, but would appreciate help or even an explanation on how to implement the TForm.

Class Ship
	Field originX:Float = 0
	Field originY:Float = 70 'a decent amount above the ground
	Field originZ:Float =0
	Field mTarget1:TMesh  'the target sights
	
	Field mShip:TMesh	
	Field mainPivot:TPivot 'the main pivot as described
	
	Method New()
		mainPivot = CreatePivot()
		mainPivot.MoveEntity(0,originY,0)
		
		mTarget1 = LoadSprite("target.png",2,mainPivot)
		mTarget1.MoveEntity(0,0,+40)
		
		mShip=LoadMesh("ship1.b3d",mainPivot)
		mShip.MoveEntity(0,0,+10)
	End
	
	Method Update()
		mainPivot.MoveEntity(0,0,moveSpeed) 'move the main pivot along
	End
	
	Method Control(clicked:Bool,mX:Float,mY:Float)
		If KeyDown(KEY_LEFT) 
			mShip.MoveEntity(-1,0,0)
			mShip.TurnEntity(0,2,0)
		Else If KeyDown(KEY_RIGHT)
			mShip.MoveEntity(1,0,0)
			mShip.TurnEntity(0,-2,0)
		Else
		  'Here will be the reset code to move the ship
		  'slowly back to the center	
		End
	End

End





redmoth(Posted 2013) [#11]
I think I missed adding a ship Pivot there, anyway I'll keep on trying. I've been reading and searching these forums all day. But worth it. Even, though the game will probably turn out to be very basic, it will be a good learning experience.


ima747(Posted 2013) [#12]
Haven't played star fox in years but from memory the camera did move along X and Y, just not as far as the ship (as noted above). I think I recall that the camera also rotated to face roughly (but not exactly) towards the ship, allowing for yet more X/Y movement of the ship, while keeping the camera motion minimal. The ship (and by extension the camera since it was following the ships motions) was confined to an invisible "tunnel" along the rail flight path.

While the term on rails is appropriate for star fox like motion, it typically refers to game play where the player's character is total out of their control, with the exception of aiming (which is usually limited). Think any light gun game (anything in an arcade with a gun controller), that's a super limited rail shooter. Any game where you're in a turret and can't control your craft is also a rail shooter sequence... Just throwing that out there as it can give the wrong impression of what you're trying to accomplish.

A thought that might give you near what you want with relative ease: Player controls position of the ship, but the camera is actually fixed to point at the actual target reticle, rather than the ship itself. You may need to point at the mid reticle rather than the end reticle to keep the ship in view, or maybe even an invisible pivot along the line between the ship and the target, but fixing the camera to the flight path, and just pivoting it to look at an arbitrary point like that would be very easy (see PointEntity http://www.blitzbasic.com/b3ddocs/command.php?name=PointEntity&ref=3d_cat) and probably give you a good enough experience to keep moving forward. Important to not get bogged down with getting something perfect when the game is super rough since if you ever finish it you *will* change literally everything anyway :)


redmoth(Posted 2013) [#13]
Thanks, I do agree that I'm starting to get bogged down in this, but I really want to have something basic that works first.

As shown in my code above (Post #5) I was using PointEntity, and that's where I was having the problems, such as the ship moving too far to the left.

The following code sort of works, although, I'm not sure about the best way to implement the 'tunnel', ie to limit the movement of the target and the ship, using the TForm commands.

And also I have another problem in that with every left/right/up/down movement, the ship starts to move forwards and get away from the camera, I've made a video of it to explain it. I know that it's to do with the ships pivot, but am having problems working out the best solution, I've tried to limit the targets z movement, but that didn't work too well.




'in the main class code,
playerShip = New Ship()
Camera = CreateCamera(playerShip.mainPivot)

Class Ship
	Field originX:Float = 0
	Field originY:Float = 70 'a decent amount above the ground
	Field originZ:Float =0
	Field mTarget1:TMesh
	Field mTarget2:TMesh
	
	Field mShip:TMesh	
	Field mainPivot:TPivot 'the pivot which moves the camera and everything along the z axis
	
	Method New()
		originY = 70
		
		mainPivot = CreatePivot()
		mainPivot.MoveEntity(0,originY,0)
		
		'create the target cross hair
		mTarget1 = LoadSprite("target.png",2,mainPivot)
		mTarget1.MoveEntity(0,0,+40)
		
		mShip=LoadMesh("ship1_b3d_base64.txt",mainPivot)
		mShip.MoveEntity(0,0,+10)
		
	
	End
	
	Method Update()
	
		mainPivot.MoveEntity(0,0,moveSpeed)
		'mTarget1.TFormPoint(0,0,-20,mTarget1,mShip)
		'mShip.PositionEntity(TFormedX(),TFormedY(),TFormedZ())
		PointEntity(mShip,mTarget1)
		
	End
	
	Method Control(clicked:Bool,mX:Float,mY:Float)
		If KeyDown(KEY_LEFT) 
			mTarget1.MoveEntity(-4,0,0)
			mShip.MoveEntity(-1,0,0)
			'mShip.
		Else If KeyDown(KEY_RIGHT)
			mTarget1.MoveEntity(4,0,0)
			mShip.MoveEntity(1,0,0)
		Else
		End
		
		If KeyDown(KEY_UP) 
			mTarget1.MoveEntity(0,4,0)
			mShip.MoveEntity(0,1,0)
			'mShip.
		Else If KeyDown(KEY_DOWN)
			mTarget1.MoveEntity(0,-4,0)
			mShip.MoveEntity(0,-1,0)
		Else
			
		End
	End
End



PS @ima747
Thanks for your suggestions.
I do admit that maybe I should of added the fact that the camera in my game only moves down the z axis and doesn't turn or move along the x or y axis. I do know what 'on rails' games are. Star fox is considered a 'rail shooter' and since what I'm trying to achieve here is even more restricted I think it's fine. We could continue to be pedantic about this, however it really doesn't matter.


Kryzon(Posted 2013) [#14]
Hi, I did some code. I used Blitz3D though.

1) If you don't have Blitz3D, download the demo from here.

2) Open this youtube video and let it running in the background for some tunes.

3) Paste and run the B3D code below.
You can also download the compiled executable from here (MediaFire). This way you don't need Blitz3D to run it.





If any part is not clear, feel free to ask. It seems you have difficulty with TForm, so I'll explain how it works later on.
See ya.


redmoth(Posted 2013) [#15]
thanks, I've been converting the code to fit in with minib3d, which has helped me understand it more. I've also been playing around with it.

Just a question, If I move all the enemies and world objects instead of just the player, won't that slow things down?


Kryzon(Posted 2013) [#16]
It would add just a little to the cost. It shouldn't be something you have to worry about.
Most of the time you'd be moving things such as enemy ships etc. so they're performing coreography (getting in formation, flying towards the player etc.) so you'd be calling transformation methods on them anyway - so you can sneak in the -Z offset in these calls.
The actual slow down will come from world objects that are "static" and wouldn't have needed these calls upon them if the player was moving.

To keep things as economical as possible you should do it like the code above: handle positions and rotation angles only by absolute numerical values. Then, before doing an UpdateWorld() or RenderWorld(), you can update each object with the following:

Ship.PositionEntity( Ship.X, Ship.Y, Ship.Z, False )
Ship.RotateEntity( Ship.Pitch, Ship.Yaw, Ship.Roll, False )

I just checked the mB3D source, and the 'False' arguments at the end of these functions ensures the quickest code is run.

- - - - -
The benefits of moving the universe instead of the player in a game like StarFox 64 are far greater than their cost, in my opinion.
A game like this should be more easily handled if you're using this origin-centric architecture because you get the following:
- No problems with floating point precision.
- If an enemy or object passes through the origin (plus its mesh size), you can delete it.
- If you need an object to "syncronize" with the player (that is, travel at the same speed as), all you have to do is not move it. Since the player isn't moving and neither is the object, they'll appear to be moving together, at the same speed.