Cannot inherit from KinematicBody2D

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By phil1234

Hi,

I created a class that inherits from KinematicBody2D
…so far so good

then I want other objects to inherit from my class
and it does not work

what am I missing ?
thanks for your help

:bust_in_silhouette: Reply From: timothybrentwood

Multiple inheritance is not allow in Godot. Since CharacterClass already inherits from KinematicBody2D, CharacterClass cannot be inherited from again.

You should generally favor composition over inheritance when programming in Godot.

and I thought Godot was so easy going to make a 2D game, I knew there was a catch

what do you mean by composition ?

phil1234 | 2021-05-20 18:17

It is easy. It’s difficult if you’re not accustomed to programming with an observer pattern (which most game engines use) or not accustomed to creating your objects via composition rather than inheritance (which is just a preference thing). Neither of these styles are focused very heavily on in computer science programs.

Inheritance is an “is a” relationship, while composition is a “has a” relationship. If you think about it in an inheritance way: a Tank is a Vehicle so it makes sense that a Tank would inherit from a Vehicle class. Tank.move() would likely just call Vehicle.move().

If you think about it in a composition way: a Vehicle really is just an object that moves so a Tank and a Vehicle could just have a Mover class that they act on when they want to move. Tank.move() or Vehicle.move() could just call Mover.move().

Tanks in both situations will likely have a Turret to shoot out of. So in the inheritance case: a Tank is a Vehicle that has a Turret OR a Tank inherits from the Vehicle class and is composed of a Turret. In the composition case: a Tank has a Mover and a Turret OR a Tank is an object that is composed of a Mover and a Turret.

There are many ways to skin a cat while programming. It is initially difficult moving from what you learn in a computer science based curriculum, which generally favors inheritance and using the command or chain of responsibility patterns to a system that limits inheritance and uses an observer pattern. I assure you that you can solve any problem that you want to solve in Godot, you’ll probably just have to go at it a different way than you’re used to.

Composition over inheritance - Wikipedia

Object composition - Wikipedia

timothybrentwood | 2021-05-20 19:08

most game engine use controllers and inheritance

I want to be able to control different characters/vehicles during the game

like a player picking up a bike and then controlling the bike with the keyboard

my issue is to understand how to create the equivalent of a CharacterController that all my other characters will be inheriting

so I need to do inheritance around classes AND scenes

without using bad design practices like

if instance == player
..
else if instance == bike 
...
else ..

or worst

if instance.has(feet)
...
else if instance.has(wheels)
...
then

so far I am investigating scenes re usability and interfaces

phil1234 | 2021-05-20 19:16

That guy seems to use abstract “interfaces” and inherited scenes

https://www.youtube.com/watch?v=AM9bQVgzw3M

phil1234 | 2021-05-20 20:10

If you’re creating a single player game make a controller autoload singleton that processes all your inputs. Then register which object that the player is currently controlling when you swap vehicles/moving on foot.

class_name Controller
extends Node

var current_object 

func register_object_as_current(obj):
    current_object = obj

func query_inputs():
    var input_vector = Vector2.ZERO
    input_vector.x = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
    input_vector.y = Input.get_action_strength("move_down") - Input.get_action_strength("move_up")

    current_object.input_vector = input_vector.normalized()

Then when you enter a vehicle:

vehicle.gd
func on_vehicle_entry():
    Controller.register_object_as_current(self)

If you’re worried about code reuse make a Mover class that handles any logic related to movement then:

var my_mover = get_node("Mover")

func _physics_process(delta):
    Controller.query_inputs()
    my_mover.handle_movement(delta)

mover.gd
func handle_movement(delta):
    direction = get_parent().input_vector
    speed = get_parent().speed # alternatively use a setup() function to set this
    ...
    get_parent().move_and_slide(direction * speed)

This way you create different Movers for your objects that can function differently without needing to inherit from some master base class.

timothybrentwood | 2021-05-20 20:18

thanks, I’ll implement something like this indeed

phil1234 | 2021-05-20 20:39

:bust_in_silhouette: Reply From: phil1234

That guy seems to use abstract “interfaces” and inherited scenes

which deals with scenes AND script inheritance