Godot Version
4.2.1
I have made the weapon node rotate around the weapon_pivot node based on the mouse location, however I am not sure how to make the sword rotate to essentially be mirrored.
Here is the player script, please let me know if any other information is needed.
extends CharacterBody2D
class_name Player
signal healthChanged
@export var speed: int = 100
@export var knockbackPower: int = 1000
@export var maxHealth: int = 3
@onready var animations: AnimationPlayer = $playerAnimations
@onready var effects: AnimationPlayer = $Effects
@onready var arrowAnimations: AnimationPlayer = $arrowAnimations
@onready var weapon: Node2D = $weapon_pivot/weapon
@onready var hurtTimer: Timer = $hurtTimer
@onready var currentHealth: int = maxHealth
@onready var bow: Area2D = $bow_pivot/bow
@onready var bow_pivot: Node2D = $bow_pivot
@onready var arrow = preload("res://actors/player/weapons/arrow.tscn")
@onready var arrowNode2D: Node2D = $arrowNode2D
@onready var weapon_pivot: Node2D = $weapon_pivot
@onready var weaponAnimation: AnimationPlayer = $weaponAnimationPlayer
@onready var swordSprite: Area2D = $weapon_pivot/weapon/sword
var lastAnimDirection: String = "Right"
var isAttacking: bool = false
var isHurt: bool = false
var isArrowCharging: bool = false
var isArrowCharged: bool = false
var isArrowFired: bool = false
var enemyCollisions = []
var bow_equipped: bool = false
var bow_cooldown: bool = true
var mouseLocFromPlayer = null
var bowCharge = 0.0
var maxBowCharge = 1.0
var bowChargeSpeed = 1.0
func _ready():
effects.play("RESET")
arrowAnimations.play("RESET")
bow.visible = false
func handleInput():
var moveDirection = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
velocity = moveDirection * speed
if Input.is_action_just_pressed("attack"):
attack()
func attack():
if bow_equipped: return
#ATTACK ANIMATION HERE
isAttacking = true
await animations.animation_finished
isAttacking = false
func updateAnimation():
if isAttacking: return
mouseLocFromPlayer = get_global_mouse_position() - self.position
var mouse_pos = get_global_mouse_position()
$Marker2D.look_at(mouse_pos)
var direction = "Right"
if mouseLocFromPlayer.x > 0:
# Mouse is to the right of the player
direction = "Right"
elif mouseLocFromPlayer.x < 0:
# Mouse is to the left of the player
direction = "Left"
if velocity.length() == 0:
animations.play("idle" + direction)
else:
animations.play("walk" + direction)
lastAnimDirection = direction
func knockback(enemyPosition: Vector2):
var knockbackDirection = (enemyPosition - position).normalized() * knockbackPower
velocity = knockbackDirection
move_and_slide()
func handleCollision():
for i in get_slide_collision_count():
var collision = get_slide_collision(i)
var collider = collision.get_collider()
print_debug(collider.name)
func player():
pass
func _physics_process(delta):
handleInput()
move_and_slide()
updateAnimation()
handleCollision()
bowAttack(delta)
if !isHurt:
for enemyArea in enemyCollisions:
hurtByEnemy(enemyArea)
mouseLocFromPlayer = get_global_mouse_position() - self.position
var mouse_pos = get_global_mouse_position()
$Marker2D.look_at(mouse_pos)
if !bow_equipped:
var angle = atan2(mouseLocFromPlayer.y, mouseLocFromPlayer.x)
# Add or subtract an offset to adjust the rotation
weapon_pivot.rotation_degrees = rad_to_deg(angle) + 45
if mouseLocFromPlayer.x < 0:
swordSprite.flip_h = true
elif mouseLocFromPlayer.x >= 0:
swordSprite.flip_h = false
# Rotate the bow pivot based on the angle between the player and the mouse
if bow_equipped:
var angle = atan2(mouseLocFromPlayer.y, mouseLocFromPlayer.x)
# Add or subtract an offset to adjust the rotation
bow_pivot.rotation_degrees = rad_to_deg(angle) - 90
func bowAttack(delta):
if Input.is_action_just_pressed("bowEquip"):
if bow_equipped:
bow_equipped = false
bow.visible = false
else:
bow_equipped = true
bow.visible = true
if Input.is_action_pressed("bowAttack") and bow_equipped and bowCharge <= maxBowCharge:
isArrowCharging = true
bowCharge += delta * bowChargeSpeed
else:
if bowCharge < maxBowCharge:
if Input.is_action_just_released("bowAttack"): return
elif bowCharge >= maxBowCharge:
isArrowCharging = false
isArrowCharged = true
if Input.is_action_just_released("bowAttack"):
isArrowCharged = false
isArrowFired = true
bowFire()
if isArrowCharging:
# Customize behavior when the arrow is charged
effects.play("chargeFlash")
if isArrowCharged:
# Customize behavior when the arrow is charged
effects.play("correctTiming")
if isArrowFired:
# Customize behavior when the arrow is fired
effects.play("")
func bowFire():
var arrow_instance = arrow.instantiate()
arrow_instance.rotation = $Marker2D.rotation
arrow_instance.global_position = $Marker2D.global_position
add_child(arrow_instance)
bowCharge = 0.0
isArrowFired = false
func hurtByEnemy(area):
currentHealth -= 1
if currentHealth == 0:
animations.play("death")
await animations.animation_finished
queue_free()
# Activate the Game Over screen here
else:
healthChanged.emit(currentHealth)
isHurt = true
knockback(area.get_parent().velocity)