0 votes

Hello. I am making a top down shooter game. The character should rotate towards the mouse global position. Something like this:
Character rotating

As you can see, the character changes their sprite and the gun changes its rotation according to where the mouse is pointing at. Also, if the mouse is pointing down, the gun shows in front of the player. As you can see in the GIF below:
Character with gun in front

As I have seen. The character uses 4 different sprites (one looking at the front, at the front right, the right, back right and back), and then it flips the sprite according to the mouse.
The gun could be a separate sprite that does rotate looking to the mouse.
I have tried all of this, however, it looks pretty weird, and the direction detection tends to fail sometimes and the code is too messy. What would you recommend me to achieve this in the best way? Thanks.

PS: The game in the gifs above is "Enter the Gungeon"

asked Jun 16 in Engine by SebSharper (63 points)

1 Answer

0 votes

idle is the idle animation of a sprite
runf is the run forward animation of a sprite
runb is the run backward animation of a sprite
sprMinipistol is the gun sprite.

var MAX_SPEED = 100
var ACCELERATION = 2000
var motion = Vector2.ZERO
var target = Vector2()

func control(delta):
    target = get_global_mouse_position()
    $sprMinipistol.look_at(target)
    if target.x > self.position.x :
        get_node("sprMinipistol").set_flip_v(false)
    elif target.x < self.position.x :
        get_node("sprMinipistol").set_flip_v(true)
    if target.y > self.position.y :
        get_node("sprMinipistol").z_index = 0
    else :
        get_node("sprMinipistol").z_index = -1
    if Input.is_action_just_pressed("click"):
        shoot()

onready var sprite = get_node("sprPlayer")
var anim = "idle"

func _physics_process(delta):
    target = get_global_mouse_position()
    if motion.x == 0:
        anim = "idle"
    else:
        anim = "runf"
    if target.x > self.position.x :
        sprite.set_flip_h(false)
        if Input.is_action_pressed("ui_left") == true or Input.is_action_pressed("ui_down") == true:
            anim = "runb"
        elif Input.is_action_pressed("ui_right") == true or Input.is_action_pressed("ui_up") == true:
            anim = "runf" 
    elif target.x < self.position.x :
        sprite.set_flip_h(true)
        if Input.is_action_pressed("ui_left") == true or Input.is_action_pressed("ui_up") == true:
            anim = "runf" 
        elif Input.is_action_pressed("ui_right") == true or Input.is_action_pressed("ui_down") == true:
            anim = "runb"
    sprite.play(anim)
    var axis = get_input_axis()
    if axis == Vector2.ZERO:
        apply_friction(ACCELERATION * delta)
    else:
        apply_movement(axis * ACCELERATION * delta)
    motion = move_and_slide(motion)


func get_input_axis():
    var axis = Vector2.ZERO
    axis.x = int(Input.is_action_pressed("ui_right")) - int(Input.is_action_pressed("ui_left"))
    axis.y = int(Input.is_action_pressed("ui_down")) - int(Input.is_action_pressed("ui_up"))
    return axis.normalized()


func apply_friction(amount):
    if motion.length() > amount:
        motion -= motion.normalized() * amount
    else:
        motion = Vector2.ZERO

func apply_movement(acceleration):
    motion += acceleration
    motion = motion.clamped(MAX_SPEED)
answered Jun 16 by 2Dfanatic (39 points)

Use Animated sprites node to add Animated sprites

Is control(delta) called in _process?

You can call it under fucn _physics_process(delta) aswell

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.