0 votes

So, I'm working on a top down shooter/survival game, and am just getting started. I'm working on player movement.

my player is a kinematic body 2D object. This is a truly top down game (meaning the graphics dont show the character from the back, but from the top), and I want the character to rotate towards the mouse.

This is the code I have. most of it is copied from the 2d movement godot docs tutorial.

extends KinematicBody2D



export (int) var speed = 200

var velocity = Vector2()

func get_input():

look_at(get_global_mouse_position())

velocity = Vector2()
if Input.is_action_pressed('ui_right'):
    velocity.x += 1
if Input.is_action_pressed('ui_left'):
    velocity.x -= 1
if Input.is_action_pressed('ui_down'):
    velocity.y += 1
if Input.is_action_pressed('ui_up'):
    velocity.y -= 1
velocity = velocity.normalized() * speed

 func _physics_process(delta):
    get_input()
    velocity = move_and_slide(velocity)

I have two problems with this. first, the player is rotating towards the mouse, but the instead of facing it from the front it's facing it from his side. I hope that makes sense.

secondly, when i move up or down, It moves in the global up and down direction. I want it to move up and down in relation to the mouse position.

please comment if this doesn't make sense, and thanks in advance for any help.

:)

in Engine by (370 points)

1 Answer

+1 vote
Best answer

Here is a simple way to do it

extends KinematicBody2D

const SPEED = 120


func _physics_process(delta):
    var mouse_pos = get_global_mouse_position()
    look_at(mouse_pos)

    var angle = position.angle_to_point(mouse_pos)

    var direction = Vector2(cos(angle), sin(angle))

    if Input.is_action_pressed("ui_up"):
        direction *= -SPEED

    if Input.is_action_pressed("ui_down"):
        direction *= SPEED

    move_and_slide(direction, Vector2.UP)

To move your player you need a vector that is pointing in the direction you want to move it. That's what direction is, it is a vector of length 1 pointed towards where the mouse is. Then by multiplying that vector by the speed value, you end up with how much the player needs to move along x and y to get to where the mouse is.

This is a very simple implementation, but it gets the idea across. You will probably want acceleration and friction and all that good stuff to make the movement more smooth and natural.

Here is a tiny Godot project with the above code in it:
https://github.com/city41/GodotMoveTowardsMouse

Also, I took the player sprite and rotated it 90 degrees. That way the look_at(mouse_pos) does what you expect. That is a pretty quick and dirty way to fix that problem, but it works.

by (84 points)
selected by

thank you, this is working! Could you explain in further detail these to code lines?

var angle = position.angle_to_point(mouse_pos)

var direction = Vector2(cos(angle), sin(angle))

I'm not sure what cos, sine, or position.angletopoint do, and I think that it's important that i understand how its working so I can do further implementation. Thanks for your answer. :)

also, I'm having trouble implementing left and right movement.

This is all using trigonometry to accomplish the movement. I'm not sure how well equipped I am to explain trig :)

Your player's position is a vector, which Godot calls a Vector2. It looks just like a point with an x and a y coordinate, but vectors are more than that. They are basically a way to describe in what direction something is pointing.

Angles also describe how something is pointing, they are kind of the opposite of vectors. So if the mouse cursor is in the upper right of the screen, and the player is down in the lower left, then the mouse cursor is about 45 degrees from the player.

var angle = position.angle_to_point(mouse_pos) is taking two vectors (the player's position and the mouse cursor's position), and figuring out what the angle is between them. Like in the above example, it'd figure out 45 degrees.

Once you have an angle, you can convert it into a vector. cos and sin are trig functions that help with that.

var direction = Vector2(cos(angle), sin(angle)) took the angle (45 degrees) and converted that into a vector.

Once you have the proper vector, you can give it to Godot and it will use it to move your character. Godot uses vectors for a lot of things, in this case it is using it for movement.

If you want to learn more, doing a Google search for "trigonometry for game developers" turns up a lot of stuff. Here is a tutorial I just found that looks like it might be good:

https://www.raywenderlich.com/2736-trigonometry-for-game-programming-part-1-2

If nothing else, that tutorial explains sin and cos

For left and right movement, I assume you want to "strafe"? This would take more trigonometry to pull off.

The angle we calculated above is the angle from the player to the mouse. If you want to player to move left, then you basically take that angle and subtract 90 degrees from it, convert it to a vector, magnify the vector by multiplying it with SPEED, then passing it to move_and_slide.

Unfortunately there is another wrinkle, Godot uses radians, not degrees. They are just another unit for measuring angles. So you'd need to take angle, and subtract pi/2 from it to get the proper angle value.

Having a grasp of some basic trig will help with game programming and help with understanding how Godot works.

Also, it looks like Godot transforms can help you accomplish what you want and possibly avoid trig in the process

https://kidscancode.org/godot_recipes/math/transforms/

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.