Aiming

Blitz3D Forums/Blitz3D Beginners Area/Aiming

Happy Llama(Posted 2012) [#1]
I have some simple controls set up so that W and S use the MoveEntity command and A and D use TranslateEntity command. How would I make it so that the character always faces the mouse. Is it possible to point a 3d object at a 2d one?


Yasha(Posted 2012) [#2]
Is it possible to point a 3d object at a 2d one?


No. There is no way for that to work, or even make sense; 3D and 2D objects exist in entirely separate coordinate systems and conceptual models.

What you can do is get the 3D position directly "underneath" a pixel of the camera viewport in question (that's nearly the same thing, only translated through the camera's projection matrix onto the 3D scene so that it makes sense). Take a look at the CameraPick command. You can use this to get the 3D position the mouse is hovering over (having set appropriate collision types), and then have a couple of options for how to point your entity at that.


Matty(Posted 2012) [#3]
I think I understand what you want from memory you were doing a top down shooter and so you want the character to always face the mouse position on the screen.

First of all there is no need to mix move entity/translate entity when moving with WASD....use on or the other..the mathematics is slightly different for each but better to use one or the other, most likely moveentity is your better option moving locally with respect to the orientation of your 'character'.

To point the character at the mouse use the aligntovector command, and use a vector that has a direction based on the vector from a camerapick from the centre of the screen to the world and a camerapick from the mouse position to the world.

Hope that makes sense.


Happy Llama(Posted 2012) [#4]
I read the example and tried it out. I don't know if this is the right approach to what i'm trying to achieve.

player = CreateCube()
EntityColor player,255,0,255


camera = CreateCamera(player)
RotateEntity camera,90,0,0
PositionEntity camera,0,10,0

playerlook = CreatePivot() 


ground = CreatePlane()
PositionEntity ground,0,0,0
EntityPickMode ground,2



PositionEntity player,playerx,0,playerz

PositionEntity playerlook,PickedX(),0,PickedY()

PointEntity player,playerlook



When I move the mouse I notice the ground move but I don't really know
what's happening.


Stevie G(Posted 2012) [#5]
I think this is what you're after:

[bbcode]
Graphics3D 1024,768,32,1
SetBuffer BackBuffer()

Global Camera = CreateCamera() : RotateEntity Camera, 90,0,0 : PositionEntity Camera, 0, 50, 0
Global Light = CreateLight()
Global Player = CreateCone() : RotateMesh Player, 90,0,0 : ScaleMesh Player, 1,1,3 : EntityColor Player, 50,100,50
Global Plane= CreatePlane() : EntityPickMode Plane, 2 : EntityColor Plane, 50,50,100
Global Cursor = CreateSphere() : EntityColor Cursor, 255,255,255

Global Dx#, Dz#
Global MoveSpeed# = .5
Global TurnSpeed# = .25
MoveMouse GraphicsWidth()*.5, GraphicsHeight()*.5

While Not KeyHit(1)

;player movement
Dx# = ( KeyDown(32) - KeyDown(30) ) * MoveSpeed
Dz# = ( KeyDown(17) - KeyDown(31) ) * MoveSpeed
TranslateEntity Player,Dx, 0,Dz

;player orientation
CameraPick ( Camera, MouseX(), MouseY() )
PositionEntity Cursor, PickedX(), 0, PickedZ()
TurnEntity Player, 0, DeltaYaw( Player, Cursor ) * TurnSpeed, 0

RenderWorld()

Flip

Wend
[/bbcode]

Last edited 2012


Happy Llama(Posted 2012) [#6]
Dx# = ( KeyDown(32) - KeyDown(30) ) * MoveSpeed
Dz# = ( KeyDown(17) - KeyDown(31) ) * MoveSpeed

What exactly does this do. I know it moves the player but I've never seen it done this way. And also, how would you make it so that the up arrow makes the player go towards the aimer and the down arrow goes away?


Yasha(Posted 2012) [#7]
Since the KeyDown function returns a 1 or a 0, this gives a 1 or a -1 for the move speed (if you put the "backward" key second, you get Forward:0 - Backward:1 = Move: -1).

It's just a more efficient, and more accurate, way to convert keystrokes to movement than the old "If KeyDown(BACKWARD) Then Dx = -1 * MoveSpeed".


_PJ_(Posted 2012) [#8]
What exactly does this do. I know it moves the player but I've never seen it done this way.



As Yasha explains, the use of
n_sgn=KeyDown(scancode_a)-KeyDown(scancode_b)
is a more efficient way of writing
n_sgn=0
If (KeyDown(scancode_a))
 n_sgn=n_sgn+1
End If
If (KeyDown(scancode_a))
 n_sgn=n_sgn-1
End If


And also, how would you make it so that the up arrow makes the player go towards the aimer and the down arrow goes away?


To answer this question, I am making a few basic assumptions. Such as by "player" you are referring to an Entity in the 3D world.

When you mention "aimer", I am assuming this is perhaps the Mouse cursor again, or some other entity?

If it's an entity, then all that's required is that the Player Entity (or a parent pivot for the player to preserve the player entity's rotation) is set to face the aimer Entity with PointEntity() and then moved with the arrow keys like so:
PointEntity player,aimer
MoveEntity player,0,0,KeyDown(200)-KeyDown(208)
[/code
The localisation of the MoveEntity command means that the z vector will always refer to the entity's "forward/backwards" direction regardless of its actual global facing.

If, however, the Aimer is NOT an entity in the 3D world, then there's a more complicated issue. There's no default means to Move Towards A Point, even if you have the global X,Y,Z coordinates of the point. If, as in Stevie G's code, you are using the PickedX() Y or Z() etc. to identify 3D coordinates then these can be used to at least determine the 3D target location.
With these coordinates, you can eiither place (or move) a 3D entity such as a Pivot to this location, then use that entity as the target entity for PointEntity with the above - OR - use this function (which I haven't actually tested fully) so you don't need to use another entity:

[code]
;Moves Entity by amount Distance# towards a point specified by XYZ coordinates.
Function MoveToPoint(Entity,X#,Y#,Z#,Distance#=0.0,bGlobal=True)
	Local EX#=X#-EntityX#(Entity,bGlobal)
	Local EY#=Y#-EntityY#(Entity,bGlobal)
	Local EZ#=Z#-EntityZ#(Entity,bGlobal)
	
	Local ActualDistance#=Sqr((EX*EX)+(EY*EY)+(EZ*EZ))
	
	If (ActualDistance<Distance)
		Distance=ActualDistance
	End If
	
	TranslateEntity Entity,Sgn(EX#)*Distance,Sgn(EY#)*Distance,Sgn(EZ#)*Distance,bGlobal
End Function[/Code]

To use this function and move towards/away form the target X Y Z position with the up & down arrow keys (Assuming you have already identified the X Y Z coordinates with CameraPick() and MouseX() / MouseY() etc.):
[code]
MoveToPoint(player,X,Y,Z,KeyDown(200)-KeyDown(208))