The shortest distance between two points is a straight line. But if there's an obstacle in the way, how can AI determine if it's faster to go under or over?
def __init__(self, tile):
self.tile = tile #Tile size
self.walls = []
def draw_grid(self, win, width, height):
for x in range (0, width, self.tile):
pygame.draw.line(win, (20,20,20), (x, 0), (x, height))
for y in range (0, height, self.tile):
pygame.draw.line(win, (20,20,20), (0,y), (width,y))
From videos I've watched, there are several different models for finding the shortest distance between two locations with obstacles in the way. The first step to implement pathfinding is to establish a tile grid, and assign weights to each movement direction. Single movements have a weight of 1, while diagonal has a weight of 1.21. The tiles are important because it sorts the game window into segments for the directional vectors. Each tile can also be assigned unique properties, such as an impassable terrain or a slowing terrain.
From the starting tile (or "node"), the function tracks to the neighboring tile in every direction. From this tile, it moves to the next neighboring tile in every direction until it reaches the end tile. This is known as a "flood-fill" method since the assessed tiles expand exponentially from the start. Once the end tile is reached, there a complete directional vector is created.
Grid Creation
So first I'll create the "Tiles" class, which takes the inputs of the tile size. I'll create a simple function to draw the grids and visualize the boundaries.
class Tiles:def __init__(self, tile):
self.tile = tile #Tile size
self.walls = []
def draw_grid(self, win, width, height):
for x in range (0, width, self.tile):
pygame.draw.line(win, (20,20,20), (x, 0), (x, height))
for y in range (0, height, self.tile):
pygame.draw.line(win, (20,20,20), (0,y), (width,y))
The tiles are assignable coordinates; tile (0,0) is top left, tile (16, 0) is top right, tile (0, 12) is bottom left, etc. Based on the visuals, I need to assign the wall tiles to a list that prevents them from being moved it. This will be done manually for now in the "self.walls" list.
Next is to update the previous "Move_Object" function to input the wall list created. I need another condition to convert the player object's coordinates into the nearest tile, and use the boundary collision boundaries to limit movement. Since the object won't always be squarely inside a tile, there has to be some rounding to determine the object's tile position.
Within the "Move_Object" function, a "For" loop checks if the object is moving into a tile position that will be equal to a wall in the list. If it is, the movement direction vector will be set to "0", thus preventing further movement and causing "collision".
The tile collision is still static as defined in the "wall" list. Different lists of "walls" are needed for different types of screens. The easy, but laborious approach would be define the "wall" tiles for every type of screen. The "Level_Walls" dictionary takes the (x, y) screen value as the key to return the specified collision list.
This only generates open spaces with entrances between screens, but dungeon explorers need obstacles within their levels to keep gameplay interesting. I can add a "rock"; a 2 x 2 series of tiles into the "walls" list, starting at the (3, 3) tile. The "draw_collision" function displays the tiles within the "wall" list in red.
Python's "randint" function can be used to randomly assign a location for this 2 x 2 "rock", as well as other types of collisions. This concept will be fundamental in the next section.
Infinite Levels
Typically, maps are randomly generated based on tilesets. A semi-randomized set of "wall" coordinates are used to create the level. The visual tilesets are then stitched together to visually represent the level. The "semi-randomized" levels need to follow certain rules:
- Levels are connected by entrances
- Entrances are spaced consistently
- Walls are continuous and filled
- All areas are accessible
In addition to the functional wall rules, the visual tilesets also have to correspond accurately:
- Tile orientations match position on screen
- Different visuals between floor and wall tile types
- Random variety within floor tiles
Comments
Post a Comment