-
Notifications
You must be signed in to change notification settings - Fork 16
At the end of this chapter, your dungeon will be filled with floors, walls and actors.
First of all, add a font and a tilemap to resource
folder. The GUI font, Fira Code, is created by Nikita Prokopov. The tileset, curses_vector, is created by DragonDePlatino for Dwarf Fortress. Create a new folder sprite
which will be used to store sprite scenes.
Remove icon
node from previous chapter. Add a Sprite
node and name it as PC
. Follow these steps to cut a sprite off the tilemap. (1) Select PC
node. (2) In the Inspector
tab, click Sprite -> Texture -> [empty]
. In the dropdown menu, select New AtlasTexture
. (3) Click Sprite -> Texture -> AtlasTexture
. Click Atlas -> [empty]
. In the dropdown menu, select Load
. (4) Load res://resource/curses_vector_24x36.png
.
(5) Click TextureRegion
on the Bottom Panel. (6) Click the up arrows on the lower right corner or press Shift+F12 to expand the panel. (7) Set Snap Mode
to Grid Snap
. The offsets and steps are 24x36
, which corrsepond to the size of each tile (24px wide and 36px high). (8) Drag and drop a rectangular to select @
symbol.
There are two more post-processing steps. Change PC
's color to ABB2BF
. Save the node as a scene (PC.tscn
) in sprite
folder. Repeat these steps until your demo looks like the image below. Note that Floor
sprite has a greyish color: 495162
.
Remove all nodes except the root. Add a new Node2D
node to MainScene
and name it as InitWorld
. Attach a script (InitWorld.gd
) to it. Before writing the first line of code, here is a reminder. I use static typing and stick to the style guide as much as possible. However, when my mind fails me and my fingers betray me, you shall not pass the wide gate. <('o')=|~~~B
It is faily simple to instance a PC
sprite (actually it is a packed scene), place it at (100, 100)
and add it to group pc
.
# InitWorld.gd
func _ready() -> void:
var new_sprite := preload("res://sprite/PC.tscn").instance() as Sprite
new_sprite.position = Vector2(100, 100)
new_sprite.add_to_group("pc")
add_child(new_sprite)
In order to create many more sprites, put them at different positions and add them to various groups, we need to satisify three requirements.
- Add a private function to
InitWorld.gd
for creating sprites. - Find a way to convert
0, 0
(a pair of integers that represent the top left grid in the dungeon) toVector2(100, 100)
(the Vector position used by sprites). - Find a way to avoid typing or copying the string
pc
.
Start from the last requirement. Since GDScripts can be loaded as resources just as you load an image or a packed scene, a possible solution is to store the string pc
as a constant in a script and load the script inside InitWorld.gd
.
Make a new folder library
to store helper scripts. Add a GDScript resource GroupName.gd
to the folder.
# GroupName.gd
const PC: String = "pc"
# InitWorld.gd
const Player := preload("res://sprite/PC.tscn")
var _new_GroupName := preload("res://library/GroupName.gd").new()
func _ready() -> void:
var new_sprite := Player.instance() as Sprite
new_sprite.position = Vector2(100, 100)
new_sprite.add_to_group(_new_GroupName.PC)
add_child(new_sprite)
As for the second requirement, add another GDScript resource ConvertCoord.gd
to library
.
# ConvertCoord.gd
const START_X: int = 50
const START_Y: int = 54
const STEP_X: int = 26
const STEP_Y: int = 34
func vector_to_array(vector_coord: Vector2) -> Array:
pass
func index_to_vector(x: int, y: int,
x_offset: int = 0, y_offset: int = 0) -> Vector2:
pass
Try to implement these functions yourself. The constants define the top left grid in the dungeon and the width and height of each grid. You might have noticed that in the first image, two arrows appear outside the dungeon. That's why we need x_offset
and y_offset
.
The helper script enables us to generate pc
in the corner of the dungeon like this.
# InitWorld.gd
new_sprite.position = _new_ConvertCoord.index_to_vector(0, 0)
The first requirement should be easy to meet. Implement _create_sprite()
yourself.
# InitWorld.gd
const Player := preload("res://sprite/PC.tscn")
var _new_GroupName := preload("res://library/GroupName.gd").new()
var _new_ConvertCoord := preload("res://library/ConvertCoord.gd").new()
func _ready() -> void:
_create_sprite(Player, _new_GroupName.PC, 0, 0)
func _create_sprite(prefab: PackedScene, group: String, x: int, y: int,
x_offset: int = 0, y_offset: int = 0) -> void:
pass
Now that you know how to instance one sprite, with the help of res://library/DungeonSize.gd
, you should be able to expand InitWorld.gd
to generate the full dungeon as shown in the first image.
# DungeonSize.gd
const MAX_X: int = 21
const MAX_Y: int = 15
const CENTER_X: int = 10
const CENTER_Y: int = 7
const ARROW_MARGIN: int = 32
One more thing. If you happen to create wall
sprites before floor
, the grey dot appears in front of the wall sign #
. To solve this problem, simply set the Z Index
of wall
, dwarf
and pc
to 1
. Let floor
's Z Index
remain to be 0
.