d

Issue with room

dofudengames

for room it says trying to asign type of 'testRoom' to variable of type 'BaseRoom'.

  • Nathan Lovato replied

    Did you change the first line of code in the BaseRoom.gd script by any chance?

    The first line should be:

    class_name BaseRoom

    If you changed the class name to testRoom, that could be the issue.

    Another possibility would be that you added the provided test room scene, TestRoom.tscn, to your level generator, as opposed to the BaseRoom scene and other derived rooms created in the previous step. If that's the case, then that could be the cause of your issue.

    1 love
  • d
    dofudengames replied

    I did that,But It did not work.

  • Anthony SOLER(AnthonyS) replied

    Hello ddofudengames,

    Game Engines are complex pieces of technology and sometimes, they are several ways to get the same error.

    Based on what you said "trying to asign type of 'testRoom' to variable of type 'BaseRoom'.", and the related course, I believe your error came from the following lines:

    var RoomScene: PackedScene = rooms[randi() % rooms.size()]
    var room: BaseRoom = RoomScene.instance()

    In the code snippet, a variable "room" is created and a type hint is added to tell the engine that this variable will hold a "BaseRoom" instance.

    In the error, the engine tells you that the value returned by

    RoomScene.instance()
    is not a BaseRoom.

    You may want to have a look at rooms you put in the rooms array (in the inspector) and verify the script associated to the root node of each room.
    The script must be BaseRoom (see screenshot below)

    ipt verification.png

    If the issue is not this one, I believe you will have to share your code, using github for example (I do not know what is the recommended way to share an entire project.).


    Have a good day,

    1 love
  • d
    dofudengames replied

    I Tried doing that but it didn't Work

    because Nonexistent Function get_Children() in type Nil .I Dont UnderSTand.

  • Anthony SOLER(AnthonyS) replied

    Hello ddofudengames,

    I am sorry but I will not be able to help (not enough information / no code, ...).

    I hope in the meantime you found what was wrong.

    Have a good day,

    1 love
  • Nathan Lovato replied

    Thanks once again for the great help message Anthony!

    We will indeed need a lot more information and context to be able to help you. At this point, it would be great if you could share your full code.

    2 loves
  • d
    dofudengames replied

    Main: extends YSort

    export(Array,PackedScene) var rooms := []

    export var grid_width := 2

    export var grid_height := 2

    export var room_size := Vector2(13,13)*128

    onready var pause_screen := $CanvasLayer/PauseScreen

    onready var music_player := $MusicPlayer

    func _ready():

     randomize()

     pause_screen.hide()

     music_player.play()

     generate_level()

    func generate_level():

     var last_room_index := (grid_width*grid_height) -1

     var current_room_index := 0

     for x in grid_width:

      for y in grid_height:

       var room_position := Vector2(x,y)

       current_room_index += 1

       var RoomScene: PackedScene = rooms[randi() % rooms.size()]

       var room :BaseRoom = RoomScene.instance()

       room.global_position = room_size * room_position

       if current_room_index == 0:

        room.spawn_robot()

        room.spawn_items()

       elif current_room_index == last_room_index:

        room.spawn_teleporter()

        room.spawn_mobs()

       else:

        room.spawn_mobs()

        room.spawn_items()

       add_child(room)

       if x == 0:

        room.hide_left_bridge()

       elif x == -1:

        room.hide_right_bridge()

       if y == 0:

        room.hide_top_bridge()

       elif y == -1:

        room.hide_bottom_bridge()


    BaseRoom:# This is the base script each room should use or extend.

    #

    # It takes care of spawing enemies and items, but can also optionally spawn a

    # player and a teleporter.

    #

    # It also handles hiding and showing bridges.

    #

    # Note: we would rather call this class "Room", but there is already a node

    # named Room in Godot, so we cannot use that name.

    class_name BaseRoom

    extends Node2D

    # Default size of the rectangle encompassing bridges drawn in the tilemap, to

    # erase the ones that don't lead to a room.

    const BRIDGES_DEFAULT_SIZE := Vector2(2, 2)

    # The tiles indices in the "invisible wall" tileset

    const INVISIBLE_WALL_TILE_INDEX := 1

    const INVISIBLE_LEDGE_TILE_INDEX := 0

    # We use Rect2 values to represents the regions of the tile map where we drew

    # bridges. This allows us to erase bridges that are outside of the game grid

    # (the ones that don't lead to a room).

    export var top_bridge := Rect2(Vector2(5, -2), BRIDGES_DEFAULT_SIZE)

    export var right_bridge := Rect2(Vector2(11, 4), BRIDGES_DEFAULT_SIZE)

    export var left_bridge := Rect2(Vector2(-2, 4), BRIDGES_DEFAULT_SIZE)

    export var bottom_bridge := Rect2(Vector2(5, 11), BRIDGES_DEFAULT_SIZE)

    onready var _bridges := $bridges

    onready var _limits := $Limits

    onready var _mobs_spawners := $Mobs

    onready var _items_spawners := $Items

    onready var _spawner_robot := $SpawnerRobot

    onready var _spawner_teleporter := $SpawnerTeleporter

    func _ready() -> void:

     # If we instantiate this room in another scene, we want the other scene to

     # manage the robot and the teleporter.

     #

     # But if we run the room scene directly with F6, we want to spawn the player

     # and teleporter to test the room.

     var is_main_scene = get_tree().current_scene == self

     if is_main_scene:

      spawn_robot()

      spawn_teleporter()

      spawn_mobs()

      spawn_items()

      hide_top_bridge()

      hide_right_bridge()

      hide_left_bridge()

      hide_bottom_bridge()

     else:

      # hide invisible walls

      _limits.hide()

    # Spawns all the mobs

    func spawn_mobs() -> void:

     for child in _mobs_spawners.get_children():

      if child is Spawner:

       child.spawn()

    # Spawns all the items

    func spawn_items() -> void:

     for child in _items_spawners.get_children():

      if child is Spawner:

       child.spawn()

    # Spawns the player character. This should be called by the parent scene, but

    # will be called by the room itself if it's run with F6.

    func spawn_robot() -> void:

     _spawner_robot.spawn()

    # Spawns the teleporter. This should be called by the parent scene, but will be

    # called by the room itself if it's run with F6.

    func spawn_teleporter() -> void:

     _spawner_teleporter.spawn()

    # Hides a set of bridge cells within a 2D rectangle and replaces them with

    # invisible walls to prevent the player from leaving the room and walking over

    # the sky.

    func _hide_bridge(bridge_region: Rect2) -> void:

     var start := bridge_region.position

     var end := start + bridge_region.size

     var x_range := range(start.x, end.x)

     var y_range := range(start.y, end.y)

     # We loop over all cells between

     for x in x_range:

      for y in y_range:

       var cell_coordinates := Vector2(x, y)

       # We remove the tile from the bridge tilemap. Passing -1 to the

       # set_cellv() function erases the tile at cell_coordinates.

       _bridges.set_cellv(cell_coordinates, -1)

       # In the limits tilemap, we draw an invisible wall to block the

       # player.

       _limits.set_cellv(cell_coordinates, INVISIBLE_WALL_TILE_INDEX)

     # There's a ledge at the bottom of islands, we need to add extra half-size

     # invisible walls in this case.

     if bridge_region == bottom_bridge:

      for x in range(start.x, end.x):

       var ledge_cell_coordinates := Vector2(x, bottom_bridge.position.y - 1)

       _limits.set_cellv(ledge_cell_coordinates, INVISIBLE_LEDGE_TILE_INDEX)

    func hide_top_bridge() -> void:

     _hide_bridge(top_bridge)

    func hide_left_bridge() -> void:

     _hide_bridge(left_bridge)

    func hide_right_bridge() -> void:

     _hide_bridge(right_bridge)

    func hide_bottom_bridge() -> void:

     _hide_bridge(bottom_bridge)

    # This is the base script each room should use or extend.

    #

    # It takes care of spawing enemies and items, but can also optionally spawn a

    # player and a teleporter.

    #

    # It also handles hiding and showing bridges.

    #

    # Note: we would rather call this class "Room", but there is already a node

    # named Room in Godot, so we cannot use that name.

    class_name BaseRoom

    extends Node2D

    # Default size of the rectangle encompassing bridges drawn in the tilemap, to

    # erase the ones that don't lead to a room.

    const BRIDGES_DEFAULT_SIZE := Vector2(2, 2)

    # The tiles indices in the "invisible wall" tileset

    const INVISIBLE_WALL_TILE_INDEX := 1

    const INVISIBLE_LEDGE_TILE_INDEX := 0

    # We use Rect2 values to represents the regions of the tile map where we drew

    # bridges. This allows us to erase bridges that are outside of the game grid

    # (the ones that don't lead to a room).

    export var top_bridge := Rect2(Vector2(5, -2), BRIDGES_DEFAULT_SIZE)

    export var right_bridge := Rect2(Vector2(11, 4), BRIDGES_DEFAULT_SIZE)

    export var left_bridge := Rect2(Vector2(-2, 4), BRIDGES_DEFAULT_SIZE)

    export var bottom_bridge := Rect2(Vector2(5, 11), BRIDGES_DEFAULT_SIZE)

    onready var _bridges := $bridges

    onready var _limits := $Limits

    onready var _mobs_spawners := $Mobs

    onready var _items_spawners := $Items

    onready var _spawner_robot := $SpawnerRobot

    onready var _spawner_teleporter := $SpawnerTeleporter

    func _ready() -> void:

     # If we instantiate this room in another scene, we want the other scene to

     # manage the robot and the teleporter.

     #

     # But if we run the room scene directly with F6, we want to spawn the player

     # and teleporter to test the room.

     var is_main_scene = get_tree().current_scene == self

     if is_main_scene:

      spawn_robot()

      spawn_teleporter()

      spawn_mobs()

      spawn_items()

      hide_top_bridge()

      hide_right_bridge()

      hide_left_bridge()

      hide_bottom_bridge()

     else:

      # hide invisible walls

      _limits.hide()

    # Spawns all the mobs

    func spawn_mobs() -> void:

     for child in _mobs_spawners.get_children():

      if child is Spawner:

       child.spawn()

    # Spawns all the items

    func spawn_items() -> void:

     for child in _items_spawners.get_children():

      if child is Spawner:

       child.spawn()

    # Spawns the player character. This should be called by the parent scene, but

    # will be called by the room itself if it's run with F6.

    func spawn_robot() -> void:

     _spawner_robot.spawn()

    # Spawns the teleporter. This should be called by the parent scene, but will be

    # called by the room itself if it's run with F6.

    func spawn_teleporter() -> void:

     _spawner_teleporter.spawn()

    # Hides a set of bridge cells within a 2D rectangle and replaces them with

    # invisible walls to prevent the player from leaving the room and walking over

    # the sky.

    func _hide_bridge(bridge_region: Rect2) -> void:

     var start := bridge_region.position

     var end := start + bridge_region.size

     var x_range := range(start.x, end.x)

     var y_range := range(start.y, end.y)

     # We loop over all cells between

     for x in x_range:

      for y in y_range:

       var cell_coordinates := Vector2(x, y)

       # We remove the tile from the bridge tilemap. Passing -1 to the

       # set_cellv() function erases the tile at cell_coordinates.

       _bridges.set_cellv(cell_coordinates, -1)

       # In the limits tilemap, we draw an invisible wall to block the

       # player.

       _limits.set_cellv(cell_coordinates, INVISIBLE_WALL_TILE_INDEX)

     # There's a ledge at the bottom of islands, we need to add extra half-size

     # invisible walls in this case.

     if bridge_region == bottom_bridge:

      for x in range(start.x, end.x):

       var ledge_cell_coordinates := Vector2(x, bottom_bridge.position.y - 1)

       _limits.set_cellv(ledge_cell_coordinates, INVISIBLE_LEDGE_TILE_INDEX)

    func hide_top_bridge() -> void:

     _hide_bridge(top_bridge)

    func hide_left_bridge() -> void:

     _hide_bridge(left_bridge)

    func hide_right_bridge() -> void:

     _hide_bridge(right_bridge)

    func hide_bottom_bridge() -> void:

     _hide_bridge(bottom_bridge)


    Also,How do you make your own sprite?

    1 love
  • d
    dofudengames replied

    Also, look at this picture for RoomC:


    Also, look at this picture for RoomF:



    1 love
  • Nathan Lovato replied

    Sorry, I should've been more precise.

    Could you please compress your Godot project as a ZIP archive, and upload it to a platform like Google Drive (or dropbox, or wetransfer, or mega, whichever you prefer). That way, I could download your files, open in Godot, fix the bug, and explain the solution with screenshots.

    Otherwise, it's difficult to debug your code pasted like this on the forum, and I still lack access to a bunch of context from your project, unfortunately.

    1 love
  • d
    dofudengames replied

    Okay

  • d
    dofudengames replied

    I uploaded the archived file to a google drive, here is the link: 

    https://drive.google.com/file/d/19iQIdJPAQj_SUOiapf3zK9XuuWOWQxKR/view?usp=sharing


    Thanks very much for your help!

    2 loves
  • Nathan Lovato replied
    Solution

    I just went through your code, and the issue is that in MAIN.gd, you call add_child(room) after trying to spawn the mobs. But if you do that, because the rooms haven't been added to the scene tree first, their onready variables (like _mob_spawner etc.) are all null: the nodes we're trying to get aren't available yet.

    This is why you're getting errors.

    If you move the call to add_child(room) before trying to spawn mobs and items, it will work OK. Like this:


    1 love
  • d
    dofudengames replied

    Thanks very much.I found this helpful.  IT WAS A GREAT ANSWER!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  • Nathan Lovato replied

    Glad this helped :)

    1 love
  • d
    dofudengames replied

    Would you give me the full code for Main (with tabs)

    and the code for every spawner(with tabs)?

    Thank you very much.

  • Nathan Lovato replied

    Sure, you can find these completed scripts and all other scripts completed for the project in the course downloads: check out file godot-final-game-completed-1.2.1.zip.

    It's a copy of this project that's fully functional.

    1 love
  • d
    dofudengames replied
    Nonexistint function  get children in base nil (error) please help
  • d
    dofudengames replied
    HELP FAST!!!!!!!!!!!!
  • Nathan Lovato replied

    I will need a lot more information to help you in detail. Could you please explain where and when this error is happening exactly? Where in your code, and when in terms of after what action in the game. Is it when running a specific scene, or when the player does a specific action?

    With what you said, what I can explain now you is the general cause of this error.

    The error message tells you that you are trying to call the function get_children() on something, but that thing has a value of null.

    Instead, you probably expect that thing to be a node. If the value is null, it means that the node has not been referenced properly or that it does not exist at the time you're trying to access it.

    Once I have more information I'll do my best to give you a more contextual answer.

    1 love
  • d
    dofudengames replied

    This is happening as soon as I play the game and is happening in BaseRoom.gd



    Thanks! Also,would you please always keep an eye on this thread?