Adding the player
Now that we have a world, the next step to making a functional game is to add a player. We begin by making a
Player scene that represents a player in the world, once again using an asset from Humble Bundle for the player sprite.
Adding the player to the world, we now have a player!
However, at the moment, there are several problems with playing the game. First of all, because the player is added to the scene before the tiles are, the player is placed behind the tiles. We can fix this by setting the
Z Index property of the
Player node to 1, which places it above the default 0.
Next of all, the player is not in the correct location. To resolve this issue, we add the following code to the
_process function of the
$Player.position = get_tile_position(0, 0)
This code uses the
get_tile_position function previously defined to place the tiles in the correct place, to place the player accordingly in the same way, on top of the tile
(0, 0). Now we get the player in the correct place, on top of the grass tile at
One of the primary mechanisms for the player interacting with the world is player movement. Pressing one of the directional movement keys should move the player one tile in the direction of the movement key, provided that the movement should be permitted. Since we already use the arrow keys for moving the camera, I decided to use the
WASD keys for controlling player movement instead. To do so, I set up entries in the input map in the project settings corresponding to
Adding this code to the player and changing the player location updating in the
World script to refer to
y will enable movement:
var x var y func _process(delta): # ... if Input.is_action_just_pressed("player_left"): x -= 1 if Input.is_action_just_pressed("player_right"): x += 1 if Input.is_action_just_pressed("player_up"): y -= 1 if Input.is_action_just_pressed("player_down"): y += 1
However, this doesn’t stop the player from moving somewhere where they shouldn’t go:
Therefore, there needs to be a check in the
World script as to whether the destination for the player is a valid block:
func can_move(character, x, y): if x < 0 || y < 0: return false if y >= len(map): return false var row = map[y] if x >= len(row): return false var tile = row[x] return can_move_to_tile(character, tile) func can_move_to_tile(character, tile): # Prevent movement to water tiles if tile == "w2": return false return true
With this change, we should move the input processing code also to the
# World.gd func _process(delta): # ... if Input.is_action_just_pressed("player_left"): $Player.move(self, -1, 0) if Input.is_action_just_pressed("player_right"): $Player.move(self, 1, 0) if Input.is_action_just_pressed("player_up"): $Player.move(self, 0, -1) if Input.is_action_just_pressed("player_down"): $Player.move(self, 0, 1) # Player.gd func move(world, dx, dy): if world.can_move(self, x + dx, y + dy): x += dx y += dy
There, no more players moving off the rails.
One central mechanic of Gridworld Plus is the Action mechanic. Essentially, every single action the player can perform - move, use a skill, etc. - costs a certain amount of Action. Each player starts at 0 action, and usage of skills increase this Action. Players can only interact when Action is zero, so this essentially acts as a cooldown on everything the player can do. Action depletes at 1 per second, so eventually the player will be able to act again.
For now, I implemented Action for movement so that movement costs action, making the following modifications to the existing functions:
# Player.gd var action = 0 func _process(delta): if action > 0: action -= 1.0 * delta if action < 0: action = 0 func move(world, dx, dy): if can_make_move(world, x + dx, y + dy): # Moving costs 0.5 seconds of action action = 0.5 x += dx y += dy func can_make_move(world, x, y): if action > 0: return false if not world.can_move(self, x, y): return false return true
Now, there is a 0.5 second delay before the player can move again.
The next step in developing this game is to add enemies and skills to make a playable game. But before that, I’ll make some usability changes, specifically focused on creating a basic player UI for displaying Action and animating the player movement. Stay tuned for more!