2016-03-22 02:35:30

Hi, I have been slowly working on building an audio game in python 3.4. I am currently using accessible_output2 and pygame. I have been working on trying to create a map, but I wanted to see what the best way to build the map is. I set the project down a while ago, but I have the time now, so I am working on it.


I am just working on building a basic grid based game first.
I created the map using ones and zeros in a two dimensional list.  Zeros were paths and ones were walls. I then was able to move through the map using the errows, but this didn't seem very good because I felt that I neded a character. I did manage to get this to work at one point, but I haven't looked at it for a long time and it is not working any more, or else I would post what I had built. This way of building a map seemed very tedious and not very flexible. I couldn't figure out how to add objects to the map either.

What are some other ways I could design a game map, or improve what I have started?

2016-03-22 05:40:25

One way as you've discovered is explicitly storing the 2d (or 3d) grid. You could have say, arrays of arrays of cell objects, and these cell objects could in turn be filled with whatever you wanted to occupy that square. Another approach which is more suitable for sparse environments is to represent the contents of the game world in some sort of list; this is much better if the map itself is large but the number of objects is small.

2016-03-30 06:39:50

Can you give an example of both of these? I understand creating a two dementional array, which would create a 2d map, how would you create a 3d map this way? Also can you explain a little more what you mean by a list?

2016-03-30 08:45:37

A number of my own games including my Audio RTS Demo use similar 2D array's for registering tile types, objects, and collision detection. For adding additional objects just add a symbolic number, so if 0 is open ground and 1 are walls, then 2 could be a power up, 3 could be a door, etc. Alternatively if working with classes you can add those instead of numbers to do lookups for more specific data.

A 3D array is basically a 2D array, but instead of putting a number or variable in each x/y position of the array, you put another array. So for example:

#2D array
box = [[0,0,0],[0,0,0],[0,0,0]]
print box[0][0]

#3D array
box = [[[0,0,0],[0,0,0],[0,0,0]],
       [[0,0,0],[0,0,0],[0,0,0]],
       [[0,0,0],[0,0,0],[0,0,0]]]
print box[0][0][0]

The list he mentioned I think refers to having a 1D array that contains coordinates or classes with x and y data. So for example lets say I have a space ship game and a 1D array with a space ship class and 3 asteroid classes, they would each locally store their own X and Y positions without the need for a map.

-BrushTone v1.3.3: Accessible Paint Tool
-AudiMesh3D v1.0.0: Accessible 3D Model Viewer

2016-03-31 07:14:31

Thank you so much. this was very helpful. 3d arrays are a little confusing, but I am not going to deal with them right now.

2016-03-31 22:38:06

So I have built a map, but I can't get it to work the way I want it to. the currentPosition variable is keeping track of where the player is, and I use conditionals to try and make sure that the currentPosition does not stray ouside the index range for the 2d array I am using for the map.
However, my conditionals are not halting the player at the boarder of the map, and I can't figure out why. It is halting the player in one direction, but once you move around enough the program throws an error (index out of range).

Can someone help? Is there a better way of writing this?

Here is the map text file I am pulling into my 2d array. It just makes it easier for me to do it this way so that I can create maps that make more sense to me than in an array.
I just added a few walls here and there to test out my map.py file.

map1.txt
p p p p w p p p p p
p w p p w p p p p p
p w p w w p p p p p
p w p p p p p p p p
p p p p p p p p p p
p p p p p p p p p p
p p p p p p p p p p
p p p p p p p p p p
p p p p p p p p p p
p p p p p p p p p w

# map.py

from accessible_output2.outputs.auto import Auto as s
import pygame

class mapParser(object):
    """Import the data from map.txt and add it to a list to be parced."""
    def __init__(self):
        self.mapList = []
        self.exitGame = False
        self.currentPosition = [0, 0]  # y value, x value  

    def readMap(self):
        with open("resources/map1.txt", "r") as mapFile:
            # loop through the map file and add each row as a sublist
            for line in mapFile:
                row = line.split()
                self.mapList.append(row)

    def mapKeys(self):
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    s().output("closing game")
                    self.exitGame = True
                # Moving north
                if event.key == pygame.K_UP:
                    if (self.mapList[self.currentPosition[0]-1][self.currentPosition[1]] == "w" or
                            self.currentPosition[0]-1 < 0):
                        s().output("Wall, can't go that way", interrupt=True)
                    elif self.mapList[self.currentPosition[0]-1][self.currentPosition[1]] == "p":
                        self.currentPosition[0] -= 1
                        s().output("path", interrupt=True)
                # Moving east
                if event.key == pygame.K_RIGHT:
                    if (self.mapList[self.currentPosition[0]][self.currentPosition[1]+1] == "w" or
                            self.currentPosition[1]+1 > len(self.mapList[0])-1):
                        s().output("Wall, can't go that way", interrupt=True)
                    elif self.mapList[self.currentPosition[0]][self.currentPosition[1]+1] == "p":
                        self.currentPosition[1] += 1
                        s().output("path", interrupt=True)
                # Moving south
                if event.key == pygame.K_DOWN:
                    if (self.mapList[self.currentPosition[0]+1][self.currentPosition[1]] == "w" or
                            self.currentPosition[0]+1 > len(self.mapList)-1):
                        s().output("Wall, can't go that way", interrupt=True)
                    elif self.mapList[self.currentPosition[0]+1][self.currentPosition[1]] == "p":
                        self.currentPosition[0] += 1
                        s().output("path", interrupt=True)
                # Moving west
                if event.key == pygame.K_LEFT:
                    if (self.mapList[self.currentPosition[0]][self.currentPosition[1]-1] == "w" or
                            self.currentPosition[1]-1 < 0):
                        s().output("Wall, can't go that way", interrupt=True)
                    elif self.mapList[self.currentPosition[0]][self.currentPosition[1]-1] == "p":
                        self.currentPosition[0] -= 1
                        s().output("path", interrupt=True)
        print(self.currentPosition)

    def run(self):
        self.readMap()
        while self.exitGame == False:
            self.mapKeys()

pygame.init()
screen = pygame.display.set_mode((400, 300))
clock = pygame.time.Clock()
clock.tick(30)

mapParser().run()
pygame.display.flip()

2016-04-01 02:09:03 (edited by magurp244 2016-04-01 02:30:42)

The problem may be the order in which your doing your checks, for example if you try and check if the current position in maplist + 1 is "w" without first checking if thats in bounds of the map, it will throw a list index out of range exception. Try putting your out of bounds checks ahead of your type checks. Another thing is that when using negative numbers on a list it can loop over to the end of the list, so going "list[-1]" will give you the last item in the list, where as using a positive number greater than the list length will throw an exception. Try this:


                # Moving east
                if event.key == pygame.K_RIGHT:
                    if self.currentPosition[1]+1 <= len(self.mapList[0])-1:
                        if self.mapList[self.currentPosition[0]][self.currentPosition[1]+1] == "w":
                            s().output("Wall, can't go that way", interrupt=True)
                        elif self.mapList[self.currentPosition[0]][self.currentPosition[1]+1] == "p":
                            self.currentPosition[1] += 1
                            s().output("path", interrupt=True)
                    else:
                        s().output("Wall, can't go that way", interrupt=True)

                # Moving west
                if event.key == pygame.K_LEFT:
                    if self.currentPosition[1]-1 >= 0:
                        if self.mapList[self.currentPosition[0]][self.currentPosition[1]-1] == "w":
                            s().output("Wall, can't go that way", interrupt=True)
                        elif self.mapList[self.currentPosition[0]][self.currentPosition[1]-1] == "p":
                            self.currentPosition[0] -= 1
                            s().output("path", interrupt=True)
                    else:
                        s().output("Wall, can't go that way", interrupt=True)
-BrushTone v1.3.3: Accessible Paint Tool
-AudiMesh3D v1.0.0: Accessible 3D Model Viewer

2016-04-01 04:18:33

So, that makes sense to me. I changed all of my directions to that format, but it is still not working correctly. The counter currentPosition is just not staying in the bounds of the map.
perhaps I made a mistake when editing my code? I am not sure. It looks like it should work to me.

Here is my code now:

# map parcer

from accessible_output2.outputs.auto import Auto as s
import pygame

class mapParser(object):
    """Import the data from map.txt and add it to a list to be parced."""
    def __init__(self):
        self.mapList = []
        self.exitGame = False
        self.currentPosition = [0, 0]  # y value, x value  

    def readMap(self):
        with open("resources/map1.txt", "r") as mapFile:
            # loop through the map file and add each row as a sublist
            for line in mapFile:
                row = line.split()
                self.mapList.append(row)

    def mapKeys(self):
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    s().output("closing game")
                    self.exitGame = True
                # Moving north
                if event.key == pygame.K_UP:
                    if self.currentPosition[0]-1 >= 0:
                        if self.mapList[self.currentPosition[0]-1][self.currentPosition[1]] == "w":
                            s().output("Wall, can't go that way", interrupt=True)
                        elif self.mapList[self.currentPosition[0]-1][self.currentPosition[1]] == "p":
                            self.currentPosition[0] -= 1
                            s().output("path", interrupt=True)
                    else:
                        s().output("path", interrupt=True)
                # Moving east
                if event.key == pygame.K_RIGHT:
                    if self.currentPosition[1]+1 <= len(self.mapList[0])-1:
                        if self.mapList[self.currentPosition[0]][self.currentPosition[1]+1] == "w":
                            s().output("Wall, can't go that way", interrupt=True)
                        elif self.mapList[self.currentPosition[0]][self.currentPosition[1]+1] == "p":
                            self.currentPosition[1] += 1
                            s().output("path", interrupt=True)
                    else:
                        s().output("Wall, can't go that way", interrupt=True)
                # Moving south
                if event.key == pygame.K_DOWN:
                    if self.currentPosition[0]+1 <= len(self.mapList)-1:
                        if self.mapList[self.currentPosition[0]+1][self.currentPosition[1]] == "w":
                            s().output("Wall, can't go that way", interrupt=True)
                        elif self.mapList[self.currentPosition[0]+1][self.currentPosition[1]] == "p":
                            self.currentPosition[0] += 1
                            s().output("path", interrupt=True)
                    else:
                        s().output("Wall, can't go that way", interrupt=True)
                # Moving west
                if event.key == pygame.K_LEFT:
                    if self.currentPosition[1]-1 >= 0:
                        if self.mapList[self.currentPosition[0]][self.currentPosition[1]-1] == "w":
                            s().output("Wall, can't go that way", interrupt=True)
                        elif self.mapList[self.currentPosition[0]][self.currentPosition[1]-1] == "p":
                            self.currentPosition[0] -= 1
                            s().output("path", interrupt=True)
                    else:
                        s().output("Wall, can't go that way", interrupt=True)
        print(self.currentPosition)

    def run(self):
        self.readMap()
        while self.exitGame == False:
            self.mapKeys()

pygame.init()
screen = pygame.display.set_mode((400, 300))
clock = pygame.time.Clock()
clock.tick(30)

mapParser().run()
pygame.display.flip()

2016-04-01 06:40:56 (edited by magurp244 2016-04-01 07:21:20)

Hm, there's seems to be a typo in the "Moving West" code segment, instead of subtracting currentPosition[1] your subtracting currentPosition[0], so:

                # Moving west
                if event.key == pygame.K_LEFT:
                    if self.currentPosition[1]-1 >= 0:
                        if self.mapList[self.currentPosition[0]][self.currentPosition[1]-1] == "w":
                            s().output("Wall, can't go that way", interrupt=True)
                        elif self.mapList[self.currentPosition[0]][self.currentPosition[1]-1] == "p":
                            self.currentPosition[1] -= 1
                            s().output("path", interrupt=True)
                    else:
                        s().output("Wall, can't go that way", interrupt=True)
-BrushTone v1.3.3: Accessible Paint Tool
-AudiMesh3D v1.0.0: Accessible 3D Model Viewer

2016-04-01 08:01:37

This did it. Thank you magurp244. I also found an error in my north section. I have path to be spoken under the else statement rather than wall. It is working perfectly now.
Thanks again.