Godot Version
Godot 4.2.1
Question
Sorry for my bad english
Hi, i’m very new in Godot and I need help. I try to do a little 2d game following to tutorial(I think you don’t need link 'cause tutorial not on english).
In my code I add global.gd for health, but tutorial dude don’t used it, so now I should move healthbar and add stamina bar and I’m kinda confused how I can move healthbar.
Now for stats I create a new scene, add healthbar at player, create script for stats
global.gd:
extends Node
var playerMaxHealth = 100
var playerHealth
# Called when the node enters the scene tree for the first time.
func _ready():
playerHealth = playerMaxHealth
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass
Player.gd:
enum {
MOVE,
ROLL,
SLIDE,
ATTACK,
ATTACK2,
DAMAGE,
DEATH
}
const SPEED = 180.0
const JUMP_VELOCITY = -270.0
# For Flip
@onready var playerAnim = $PlayerSprite
# For Signals
@onready var playerFullAnimation = $AnimationPlayer
@onready var playerCollisionShape = $CollisionShape2D
@onready var playerCollisionShapeAfter = $CollisionShape2D
@onready var playerAttackDirection = $AttackDirectionPlayer
@onready var playerStats = $stats
# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
var playerHealth = playerStats.playerHealth
var state = MOVE
# Move It Later #
var playerCurrentDamage
var playerAttackDamage = 10
var playerAttack2Damage = 20
var attackfreez = false
var slidefreez = false
var playerPos
# ---- Player Statement ---- #
# MOVE STATE #
func playerMoveState():
# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
var direction = Input.get_axis("left", "right")
# RUN ANIMATION
if direction:
# If Player run add animation and movement
velocity.x = direction * SPEED
# If Player Doesnt's jumping:
if velocity.y == 0:
playerAnim.play("Run")
if direction == -1:
# If Player go back (left): reverse playerSprite to left
playerAnim.flip_h = true
playerAttackDirection.rotation_degrees = 180
# Revers Player Collision, for get her a center of Player #
playerCollisionShape.position.x = 8
else:
# If Player go front (right): reverse playerSprite to right
playerAnim.flip_h = false
playerAttackDirection.rotation_degrees = 0
playerCollisionShape.position.x = 0
# IDLE ANIMATION
else:
# If Player AFK add animation
velocity.x = move_toward(velocity.x, 0, SPEED)
# If Player Doesnt's jumping:
if velocity.y == 0:
playerAnim.play("Idle")
# --- Swap to Statements --- #
# Swap to ROLL aimation
if direction and Input.is_action_pressed("roll"):
state = ROLL
# Swap to SLIDE animation
if direction and Input.is_action_just_pressed("slide") and slidefreez == false:
if velocity.y == 0:
state = SLIDE
# Swap to ATTACK animation
if Input.is_action_just_pressed("attack") and attackfreez == false:
if velocity.y == 0:
state = ATTACK
# Swap to ATTACK2 animation
if Input.is_action_just_pressed("attack2") and attackfreez == false:
if velocity.y == 0:
state = ATTACK2
# ROLL STATE
func playerRollState():
if Input.is_action_pressed("roll"):
if velocity.y == 0:
playerFullAnimation .play("Roll")
await playerFullAnimation .animation_finished
state = MOVE
else:
state = MOVE
# SLIDE STATE #
func playerSlideState():
if Input.is_action_pressed("slide"):
if velocity.y == 0:
playerFullAnimation .play("Slide")
await playerFullAnimation .animation_finished
slideCoolDown()
state = MOVE
else:
state = MOVE
# ATTACK STATE #
func playerAttackState():
playerCurrentDamage = playerAttackDamage
velocity.x = 0
if velocity.y == 0:
playerFullAnimation.play("Attack")
await playerFullAnimation .animation_finished
attackCoolDown()
state = MOVE
else:
state = MOVE
# ATTACK2 STATE #
func playerAttack2State():
playerCurrentDamage = playerAttack2Damage
velocity.x = 0
if velocity.y == 0:
playerFullAnimation.play("Attack2")
await playerFullAnimation .animation_finished
attack2CoolDown()
state = MOVE
else:
state = MOVE
# DAMAGE STATE #
func playerDamageState():
velocity.x = 0
playerAnim.play("Damage")
await playerAnim.animation_finished
state = MOVE
# DEATH STATE #
func playerDeathState():
# If Player Died (health <= 0)
velocity.x = 0
playerAnim.play("Death")
await playerAnim.animation_finished
queue_free()
get_tree().change_scene_to_file.bind("res://scn/menu/menu.tscn").call_deferred()
# Attack CoolDown Function #
func attackCoolDown():
attackfreez = true
await get_tree().create_timer(0.3).timeout
attackfreez = false
func attack2CoolDown():
attackfreez = true
await get_tree().create_timer(1).timeout
attackfreez = false
func slideCoolDown():
slidefreez = true
await get_tree().create_timer(0.5).timeout
slidefreez = false
# --- Get Damage from Enemy --- #
func _on_damage_received(enemyDamage):
if state == ROLL:
enemyDamage = 0
elif state ==SLIDE:
enemyDamage /= 2
else:
state = DAMAGE
playerHealth -= enemyDamage
# Death #
if playerHealth <= 0:
playerHealth = 0
state = DEATH
func _physics_process(delta):
# Add the gravity.
if not is_on_floor():
velocity.y += gravity * delta
# Handle JUMP.
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = JUMP_VELOCITY
playerAnim.play("Jump")
# FALL
if velocity.y > 0:
playerAnim.play("Fall")
playerCurrentDamage = playerAttackDamage
match state:
MOVE:
playerMoveState()
ROLL:
playerRollState()
SLIDE:
playerSlideState()
ATTACK:
playerAttackState()
ATTACK2:
playerAttack2State()
DAMAGE:
playerDamageState()
DEATH:
playerDeathState()
# Sending Signal about Player's position #
playerPos = self.position
Signals.emit_signal("playerPositionUpdate", playerPos)
move_and_slide()
func _ready():
Signals.connect("enemyAttack", Callable(self, "_on_damage_received"))
func _on_hit_box_area_entered(area):
Signals.emit_signal("playerAttack", playerCurrentDamage)
stats.gd:
extends CanvasLayer
@onready var playerHealthBar = $HealthBar
var playerMaxHealth = Global.playerMaxHealth
var playerHealth = Global.playerHealth:
set(value):
playerHealth = value
playerHealthBar.value = playerHealth
# Called when the node enters the scene tree for the first time.
func _ready():
playerHealth = playerMaxHealth
playerHealthBar.max_value = playerHealth
playerHealthBar.value = playerHealth
When I’m starting game (click on “play button” than scen changing on level) I have error: Invalid get index ‘playerHealth’ (on base: ‘Nil’).
I think it’s easy to fix, but nothing comes to mind.
Please tell me what I need to move/change/add to make the code work. Thank You