You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

11 KiB

Generating maps

Amazeing maps with game assets

Our journey begins here...

https://www.kenney.nl/assets/cartography-pack

In [ ]:
!wget "https://www.kenney.nl/content/3-assets/26-cartography-pack/cartographypack.zip"
!mkdir cartographypack
!unzip cartographypack.zip -d cartographypack
In [ ]:
!ls cartographypack/PNG/Default/path*
In [ ]:
from glob import glob
import os
from IPython.display import display, HTML

html = ""

for img_path in glob("cartographypack/PNG/Default/path*"):

    html += f'<img src="{ img_path }" style="float:left;">'

display(HTML(html))
In [ ]:
from random import choice

pieces = glob("cartographypack/PNG/Default/path*")
html = ""

for i in range(100):
    piece = choice(pieces)
    html += f'<img src="{ piece }" style="float:left;">'
    
display(HTML(html))

Stepping away from random.choice(): writing an algorithm to generate patterns

In order to generate patterns in a non-random way, we might want to move around through our canvas in a non-linear way, to make the patterns a bit more complex.

moving through the canvas

Each character on our "canvas" has a specific position and thus is connected to a x and y coordinate.

How can we do that?

We will use a list-of-lists... or in other words:

we make one big list, that contains a # of rows (the y axis, or height of the canvas), with a # of characters (the x axis, or width of the canvas).

To make this list-of-lists, we will use a loop-in-a-loop:

In [ ]:
width = 10
height = 10

canvas = []

for y in range(height):
    
    row = []

    for x in range(width):
        row.append(x)
        
    canvas.append(row)
    
print(canvas)

Let's print the canvas row for row, to make it easier to see it as a x-y canvas:

In [ ]:
for row in canvas:
    print(row)

And let's bring it back into an plain text pattern: turn this list-of-lists into a multiline string:

In [ ]:
# canvas is our list-of-lists
# canvas_string is the plain text version that we want to create

canvas_string = ''

for row in canvas:
    row_string = ''
    for character in row:
        row_string += str(character)
    canvas_string += row_string + "\n"

print(canvas_string)

Let's save this as a function that we can reuse later!

In [ ]:
def plain(canvas):
    canvas_string = ''
    for row in canvas:
        row_string = "".join(row)
        canvas_string += row_string + "\n"

    return canvas_string

Now, we can work with the x and y axes of the canvas, by slicing the canvas:

In [ ]:
canvas[0][0]
In [ ]:
canvas[1][9]

My first algorithm

Now let's write a short algorithm, to generate a map.

We will start by writing the rules of our algorithm.

Let's first think of these rules without writing them in code.

How would you like to generate a pattern?

For example:

Characters

  • . is used as background
  • as light shade
  • as darker shade

Rules

  • always appears in horizontal ánd vertical blocks of 3
.....
..░..
.░░░.
..░..
.....
  • surrounds the blobs of light shade on the left side of each light shadow
.....
.▒░..
▒░░░.
.▒░..
.....

Let's try this!

First we create a new canvas and fill it with .'s.

In [ ]:
width = 100
height = 25

canvas = []
for y in range(height):
    row = []
    for x in range(width):
        row.append('.')
    canvas.append(row)

print(plain(canvas))

Now let's add the light shade...

In [ ]:
from random import randrange

light_shade = '░'

for y in range(height):
    for x in range(width):
        
        # To work with a degree of chance, 
        # we "roll the dice" and only add a ░
        # when the number is lower then 5
        random_number = randrange(0, 100, 1)
        if random_number < 3: 
            
            # If so, then we add a ░
            canvas[y][x] = light_shade
            
            # Check is there is a character on the left, right, 
            # top and bottom AT ALL, before adding them...
            if x - 1 >= 0:
                canvas[y][x - 1] = light_shade
            if x + 1 < width:
                canvas[y][x + 1] = light_shade
            if y - 1 >= 0:
                canvas[y - 1][x] = light_shade
            if y + 1 < height:
                canvas[y + 1][x] = light_shade
                   
        else:
            continue
    
print(plain(canvas))

Now let's add the darker shade...

In [ ]:
from random import randrange

light_shade = '░'
darker_shade = '▒'

for y in range(height):
    for x in range(width):
        
        # First we check if the current character is a light shade
        if canvas[y][x] == light_shade:
            
            # If that is the case, we need to look around, to see if we need to place a shade on the left, right, top or bottom
    
            # Check is there is a left character AT ALL
            if x - 1 >= 0:
                # If so, then we check if the left character is a '.'
                if canvas[y][x - 1] == '.':
                    # If so, then we replace it with a dark shade
                    canvas[y][x - 1] = '▒'
                    
        else:
            continue
    
print(plain(canvas))
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 

Could we make a maze generator with the cartographypack now?

:---)

In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]: