Python Forum
Problem with Tiles and Mobs
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Problem with Tiles and Mobs
#1
Hello.

I am programming a tile based game with pygame.
I am loading different objects, like trees, walls, houses etc. on the surface.
For that, I am using different files.
In the first file, I have my images defined:

WALL_IMG = 'stone_wall2.png'
TREE_IMG = 'tree.png'
HOUSE_IMG = 'houseSmallAlt1.png'
WATER_IMG = 'water.png'
In the second, I am loading them and loading them onto the map:

class Game:
    def __init__(self):
        pg.init()
        self.screen = pg.display.set_mode((WIDTH, HEIGHT))
        pg.display.set_caption(TITLE)
        self.clock = pg.time.Clock()
        self.load_data()

    def load_data(self):
        #Folders
        game_folder = path.dirname(__file__)
        img_folder = path.join(game_folder, 'img')
        mob_folder = path.join(game_folder, 'mobimg')
        player_folder = path.join(game_folder, 'playerimg')
        tile_folder = path.join(game_folder, 'tileimg')

        # Map
        self.map = Map(path.join(game_folder, 'map.txt'))
        #Player IMG
        self.player_img = pg.image.load(path.join(player_folder, PLAYER_IMG)).convert_alpha()
        # Zombie IMGs
        self.zombie_img = pg.image.load(path.join(mob_folder, ZOMBIE_IMG)).convert_alpha()
        # TILE IMG
        self.wall_img = pg.image.load(path.join(tile_folder, WALL_IMG)).convert_alpha()
        self.wall_img = pg.transform.scale(self.wall_img, (TILESIZE, TILESIZE))
        self.tree_img = pg.image.load(path.join(tile_folder, TREE_IMG))
        self.tree_img = pg.transform.scale(self.tree_img, (TILESIZE, TILESIZE))

    def new(self):
        # initialize all variables and do all the setup for a new game
        self.all_sprites = pg.sprite.Group()
        self.walls = pg.sprite.Group()
        self.trees = pg.sprite.Group()
        self.zombies = pg.sprite.Group()
        self.flubbers = pg.sprite.Group()
        self.water = pg.sprite.Group()
        self.blowpipes = pg.sprite.Group()
        for row, tiles in enumerate(self.map.data):
            for col, tile in enumerate(tiles):
                if tile == '1':
                    Wall(self, col, row)
                if tile == '2':
                    Water(self, col, row)
                if tile == '3':
                    Tree(self, col, row)
                if tile == '4':
                    House(self, col, row)
                if tile == 'Z':
                    Zombie(self, col, row)
                if tile == 'P':
                    self.player = Player(self, col, row)
                self.camera = Camera(self.map.width, self.map.height)

    def update(self):
        # update portion of the game loop
        self.all_sprites.update()
        self.camera.update(self.player)
        # And here follows stuff, you don't need to solve the problem
That above is just a part of the whole code. And there is also another file, called tile map. My problem is explained below.

class Map:
    def __init__(self, filename):
        self.data = []
        with open(filename, 'rt') as f:
            for line in f:
                self.data.append(line.strip())

        self.tilewidth = len(self.data[0])
        self.tileheight = len(self.data)
        self.width = self.tilewidth * TILESIZE
        self.height = self.tileheight * TILESIZE

class Camera:
    def __init__(self, width, height):
        self.camera = pg.Rect(0, 0, width, height)
        self.width = width
        self.height = height

    def apply(self, entity):
        return entity.rect.move(self.camera.topleft)

    def update(self, target):
        x = -target.rect.centerx + int(WIDTH / 2)
        y = -target.rect.centery + int(HEIGHT / 2)

        # limit scrolling to map size
        x = min(0, x)  # left
        y = min(0, y)  # top
        x = max(-(self.width - WIDTH), x)  # right
        y = max(-(self.height - HEIGHT), y)  # bottom
        self.camera = pg.Rect(x, y, self.width, self.height)
NOW MY PROBLEM:
I can move my player around the screen (not shown in the code above). And if I walk through trees, that are above my y spawning position, I am on top of them, but if there are trees below that y position I spawned at, I am under them. This is pretty annoying, e.g. I am not seeing myself when I am in water, that is below my y position I spawned at. Because I don't wanna spawn at the edge of the map.
Do you have any idea, how I could fix this problem? I have the same problem with mobs.
I just want to be able to tell python, if I am supposed to be below or upon the object.
Thank you so much for your help (sorry for posting so much code, was necessary).

Piethon
Reply
#2
I use Tiled to draw and layout my maps. This includes hidden barriers for mobs, starting locations, movement sequences, etc.

I use PyTMX to load the maps created by Tiled.

I use pygame to do the rest.

Here is a really basic example of all that combined.

If the player is under another image, then the player is being drawn before that image. Put your code up on Github so we can run the entire thing for example.
Recommended Tutorials:
Reply
#3
So I use a text file to make my map.
So e.g. , represents the background, P is the player and 1 is a tree.
I think it draws it from the bottom to the ground, that's why.
I think I'm gonna try out that "Tiled" app, in about a week or so. Thanks for the tip.
How is it drawing the map, when you are doing it with Tiled? Does it also draw the map, from the top to the bottom?
Reply
#4
Tiled just creates a tmx file which is really an xml file. Tiled does not draw the map. It does not even define in what order to draw it. You can group objects together and then draw the group on a group by group basis. Tiled just makes it easier to create the map and see what it would look like in game as you create it. As well as creating collision points and path positions.

Pygame controls where you draw each object (in layer terms). The location is determined by the xml file Tiled output. Pygame draws it in the order you put the draw commands. For example the last one is top outermost layer that will overlap other objects. So if group A is draw, then group B. all of group B would overlap group A whenever they come to the same location.

If you dont want this you would have to redefine the groups into more groups to reorder them further. At worst case you dont put it in a group and draw it directly last if you want it over other objects. Like a player character most likely would be above objects on the group such as trees. So trees would be drawn first. Then the player. At that point the player would always be on top of the trees.

If you made a github repo without your images included i could probably take a look at your code and run it to determine what is wrong. Otherwise i have to define all the files, create bogus images, etc. and frankly I dont want to do that. Specifically i would need to see the blit method to all your images, and the order they are in (Which you do not have shown here).
Recommended Tutorials:
Reply
#5
I found a good tutorial on how to load tiled maps with pytmx.

One question: Is it also possible to load isometric maps with pytmx. I know, that you would need a very different camera movement and stuff for it, but just loading an isometric map? Is that also possible with pytmx? Thanks for your great explanations.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020