Non-programmer here attempting to make my first game. This is going to be a simplified Brotato clone while I get accustomed to the application.
I am trying to use the docs primarily but I am stuck on something. I have my player controller and I am attempting to implement a iFrame system. Here is the scene tree and script that I have thus far:
extends Node2D
@onready var idle_anim = $AnimatedSprite2D
@onready var run_anim = $AnimatedSprite2D
@onready var i_frames_timer = $iFrames
@onready var hurtbox = $Hurtbox
var health: float
var speed: float = 100.0
var invulnerable :bool
# Called when the node enters the scene tree for the first time.
func _ready():
idle_anim.play("Idle")
health = 10
invulnerable = true
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
_movement(delta)
if invulnerable == false:
_player_health()
print(health)
print (invulnerable)
# print ("iFrames ", i_frames_timer.time_left)
func _movement(delta):
var direction = Vector2.ZERO
if Input.is_action_pressed("down"):
direction.y += 1
if Input.is_action_pressed("up"):
direction.y -= 1
if Input.is_action_pressed("right"):
direction.x += 1
if Input.is_action_pressed("left"):
direction.x -= 1
position += direction.normalized() * speed * delta
# Animation
if direction != Vector2.ZERO:
run_anim.play("Run")
if direction.x < 0:
run_anim.flip_h = true
if direction.x > 0:
run_anim.flip_h = false
else:
idle_anim.play("Idle")
func _on_i_frames_timeout():
invulnerable = false
func _player_health():
for area in hurtbox.get_overlapping_areas():
if area.is_in_group("Enemy"):
health -= 1
invulnerable = true
i_frames_timer.start()
if health <= 0:
queue_free()
I am able to see invulnerable change from true to false:
I would add print statements to see what happens. Examples below.
You could also remove the “group” check, if you set only nodes belonging to a certain group to every layer. E.g. player is layer 1, enemies 2. If player is only looking for 2, you don’t need an extra check in the code. The function would not be called if the area was not an enemy.
You have a few problems here. First, you are trying to re-invent the wheel. Second, you are not doing collision checking correctly with an Area2D node.
It might help to take a step back and describe what you’re trying to accomplish. For example:
You said you are a non-programmer. So where did you come up with the idea to adopt a web programming paradigm to making a game? Can you define what an iFrame system is to you? What you’re trying to do with it? How and why did you decide it was the appropriate choice for whatever you’re trying to do? Your initial post reads like sci-fi gibberish, like when Doctor Who talks about “reversing the polarity” of something.
Please use a screen shot of your scene tree. There is a lot of hidden information in a picture of a scene tree that we can use to figure out what’s going wrong. This gets lost when you give us a text version.
Don’t Reinvent the Wheel
Your player is a Node2D instead of a CharacterBody2D. This not only complicates the code you need to create to move the player around, it also then requires you to add another CollisionObject2D to it to enable collisions. I recommend you do this:
Change your Node2D to a CharacterBody2D.
Delete your _player_health() function.
Add a damage() function.
@onready var i_frames_timer = $iFrames
func damage(amount: float) -> void:
if not i_frames_timer.is_stopped()
return
health -= amount
i_frames_timer.start()
if health <= 0:
queue_free()
“Iframe” in game context tends to mean “invincibility frame”, aka a short period of invulnerability after taking damage. I’m honestly surprised I have to tell you of all people.
I can’t know everything. I’ve never heard the term. But that’s how I learn new things. I even googled it to see if it meant something else and couldn’t find it. I looked it up, and this is how I would implement that:
@onready var i_frames_timer = $iFrames
func damage(amount: float) -> void:
if not i_frames_timer.is_stopped()
return
health -= amount
i_frames_timer.start()
if health <= 0:
queue_free()
No need for a bool named invulnerable. I will update my previous post.