How to get a Spatial to look at mouse position

danjodanjo Posts: 81Member
edited August 2016 in Programming
Hi,<br /><br />I'm working on a player controller similar to the one used in the game "Alien Shooter".<br />I got the movement working quite well but I can't figure out how to get the rotation right, so that the character is facing towards the mouse.<br />This is the closest I could get so far:<br />
<br />onready var body = get_node(&quot;body&quot;)<br /><br />func _ready():<br />	set_process_input(true)<br /><br />func _input(ie):<br />	if ie.type == InputEvent.MOUSE_MOTION:<br />		if last_position == null:<br />			last_position = ie.pos<br />		var delta = ie.pos - last_position<br />		last_position = ie.pos<br />		body.rotate_y(-delta.x * 0.01)<br />
<br /><br />My node tree looks like:<br />
<br />- KinematicBody<br />&nbsp; - Camera<br />&nbsp; - Body<br />
<br />The script is attached to KinematicBody.<br /><br />I read a lot about vectors and trigonometry and tried to adapt a third-person-controller-demo, but I just don't get it right. <br /><br />Hope someone can give me a nudge in the right direction!?
Tagged:

Tags :

Comments

  • deldel Posts: 20Member
    You could use the [tt]look_at()[/tt] function. It takes a target vector, where you can put in the mouse position (from [tt]get_viewport().get_mouse_pos()[/tt]) and a vector which defines the up direction.<br />edit: I just tested that. the object moves with the mouse, but not very accurate. :-X I should test this before posting next time.
  • danjodanjo Posts: 81Member
    I just tested that. the object moves with the mouse, but not very accurate. :-X I should test this before posting next time.
    How did you turn the Vector2 from get_mouse_pos() into a Vector3 that can be passed to look_at?<br />I tried to do something like
    var mouse_pos = Camera.get_viewport().get_mouse_pos()<br />body.look_at(Vector3(mouse_pos.x, 1, mouse_pos.y), Vector3(0,1,0))
    
    and got pretty weired results.<br />I think that is because a mouse position of (0,0) is the top left corner of the screen, but (0,1,0) is the center of the local space of the Spatial that I want to rotate. Maybe there is a way to transform the "point on screen" to "point in local space"!?<br />
  • deldel Posts: 20Member
    I did the same thing except I used a 0 for y. I think you're right with the mouse position on the screen. That is probably useless, unless you can get the zero position of the screen to the player object.<br />To be honest, I don't know much about mouse interaction in 3d, but there should be an easy way to do something with look_at, i think. <br /><br />You should take a look at the gui-in-3d demo. I think there is the answer for this problem. The 3d space of the area node is converted to 2d space.
  • danjodanjo Posts: 81Member
    It' works but I'm not sure if I did it the you had in mind:<br /><br />I added a Area to the KinematicBody and made the CollisionShape (added to Area), slightly bigger than the size of the viewport.<br /><br />My node tree now looks like<br />
    <br />- KinematicBody (script attached)<br />&nbsp; - Camera<br />&nbsp; - Body<br />&nbsp; - Area<br />
    
    <br /><br />The script:<br />
    <br />extends KinematicBody<br /><br />onready var body = get_node(&quot;body&quot;)<br /><br />func _on_area_input_event(camera, event, click_pos, click_normal, shape_idx):<br />&nbsp; &nbsp; if event.type == InputEvent.MOUSE_MOTION:<br />	click_pos.y = 1<br />	body.look_at(click_pos, Vector3(0,1,0))<br />
    
  • deldel Posts: 20Member
    Nice, if it works!  :D I couldn't really get your code to work for me, but I've played a little with the navigation mesh demo and found an easy solution. I'll try to reconstruct that and upload it.
  • danjodanjo Posts: 81Member
    on 1461353025:
    <br />Nice, if it works!  :D I couldn't really get your code to work for me
    <br />I put together a minimal project, it should just work out of the box:<br />http://pub.atze.libra.uberspace.de/mouse_pos_in_3d.zip<br /><br />
    but I've played a little with the navigation mesh demo and found an easy solution. I'll try to reconstruct that and upload it.<br />
    I would really like to see that.<br /><br />Thank you very much for your help.
  • deldel Posts: 20Member
    Nice work! It works really good!<br />I've had some trouble with making a the nav mesh, but i think I've got it now. will try to make a demo on the weekend.
  • deldel Posts: 20Member
    So here is my demo.<br />Basically I parented a Navigation node (with a navmesh) to the Camera (which follows the player) and the player looks at the position, where a ray (cast by the mouse motion) hits the navmesh (the code for this is in the navi.gd).<br />But it seems that somehow the navmesh doesn't follow the player yet. It works only if you stay on the ground plane.<br />With this method it should also be possible to aim at points that are on a higher or lower position then the player.
  • danjodanjo Posts: 81Member
    Thanks for putting this together. I'm not sure if I'll make use of it somehow. It seems way too much code and nodes for a simple task like this.<br />Also I didn't notice any issues with the "put-the-player-in-a-large-Area-that-covers-whole-screen-solution" so far so I'll stick with it for now and try to get some useful results with GridMap but that's another topic.
  • RandomNumber4RandomNumber4 Posts: 1Member

    func _fixed_process(delta):
        var body = get_node("body")
        var m = get_viewport().get_mouse_pos()
        var s = get_viewport().get_rect().size
        var body_y = body.get_global_transform().origin.y
        var center = (m-s/2)
        body.look_at(Vector3(center.x,body_y,center.y),Vector3(0,1,0))

    This is the easiest way i could think of. In total, over the code I spent five hours. Programming is painful.
    And here I created an example.
Sign In or Register to comment.