Godot Version
Godot 4.6 Stable
Question
I created a custom class called Arrow
class_name Arrow extends CharacterBody2D
@onready var sprite = $Sprite2D
var SPEED : int = 300
var SHOTS : int = 0
var PRESET : PackedScene
func _init(_speed : int, _shots : int, _preset : PackedScene) -> void:
SPEED = _speed
SHOTS = _shots
PRESET = _preset
func _physics_process(delta: float) -> void:
var collision: KinematicCollision2D = get_last_slide_collision()
if collision :
var collider := collision.get_collider()
#if arrows collide w/ each other
if collider is Arrow:
queue_free()
print("arrow collision!")
if collider is StaticBody2D:
velocity = Vector2.ZERO
move_and_slide()
func spawn(start_pos: Vector2, direction : Vector2) -> void:
sprite.scale.x *= sign(direction.x)
global_position = start_pos
velocity = direction * SPEED
I then have a child class of it called Normal Arrow
extends Arrow
class_name Funny_Arrow
func _init(_shots : int) -> void:
super(100, _shots, preload("res://Scenes/funny_arrow.tscn"))
In my Bow script, I create an inventory of Normal Arrow and a Funny Arrow (which has the same structure as Normal Arrow but a couple of tweaks)
extends Node2D
var amount_of_arrows : int
var arrow_inventory : Arrow_Inventory
var arrow_inventory_index : int = 0
var selected_arrow : Arrow
func _ready() -> void:
arrow_inventory = Arrow_Inventory.new([Normal_Arrow.new(5), Funny_Arrow.new(5)])
SignalManager.change_arrow_count.emit(amount_of_arrows)
selected_arrow = arrow_inventory.select_arrow(arrow_inventory_index)
#print(selected_arrow is Arrow)
func _process(_delta: float) -> void:
if Input.is_action_just_pressed("Switch_Arrows"):
arrow_inventory_index = (arrow_inventory_index + 1) % arrow_inventory.get_size()
selected_arrow = arrow_inventory.select_arrow(arrow_inventory_index)
pass
func shoot(arrow_spawn_pos, direction) -> void:
if $Timer.is_stopped():
var arrow = selected_arrow.PRESET.instantiate()
print(arrow is Arrow)
get_tree().current_scene.add_child(arrow)
arrow.position = arrow_spawn_pos
arrow.spawn(arrow.position, Vector2(direction,0))
SignalManager.change_arrow_count.emit(amount_of_arrows)
$Timer.start(.5)
Here is my Arrow Inventory script; it’s just essentially an array.
extends Node
class_name Arrow_Inventory
var ARROW_INVENTORY : Array
func _init(_arrow_inventory : Array) -> void:
ARROW_INVENTORY = _arrow_inventory
pass
func decrease_shot(index : int) -> void:
ARROW_INVENTORY[index].SHOTS -= 1
func select_arrow(index : int) -> Arrow:
return ARROW_INVENTORY[index]
func get_size() -> int:
return len(ARROW_INVENTORY)
Whenever I run the game and try to shoot, I get this error: Invalid call. Nonexistent function ‘spawn’ in base ‘CharacterBody2D’.
For this line in Bow: arrow.spawn(arrow.position, Vector2(direction,0))
I read somewhere that instantiating a scene calls _init() with zero parameters and therefore, the custom class is moot. When I put lines to check the class of the Arrow made it returns “CharacterBody2D.”
So, how do I instantiate a node stemming from a custom class that keeps all its parameters and can call functions of its custom superclass?