2

I make a tile game in python using the library PyGame. The essence of the game: there is a square that we control and enemies that will appear on all sides. I have a problem with the appearance of enemies, I can not make the enemies along the X coordinate appear exactly on the tile. Now they appear at a random point along the X coordinate, but they need to be on the tiles.
Here is the code:

import sys
import pygame as pg
import random

WHITE = (255, 255, 255,)
BLACK = (0, 0, 0)
DARKGREY = (40, 40, 40)
LIGHTGREY = (100, 100, 100)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)

WIDTH = 1008  # 16 * 64 или 32 * 32 или 64 * 16
HEIGHT = 768  # 16 * 48 или 32 * 24 или 64 * 12
FPS = 60
TITLE = "TITLE GAME"
BGCOLOR = DARKGREY

TILESIZE = 48
GRIDWIDTH = WIDTH / TILESIZE
GRIDHEIGHT = HEIGHT / TILESIZE


class Player(pg.sprite.Sprite):
    def __init__(self, game, x, y):
        self.groups = game.all_sprites
        pg.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        self.image = pg.Surface((TILESIZE, TILESIZE))
        self.image.fill(YELLOW)
        self.rect = self.image.get_rect()
        self.x = x
        self.y = y

    def move(self, dx=0, dy=0):
        if not self.colide_with_walls(dx, dy):
            self.x += dx
            self.y += dy

    def colide_with_walls(self, dx=0, dy=0):
        for wall in self.game.walls:
            if wall.x == self.x + dx and wall.y == self.y + dy:
                return True
        return False

    def update(self):
        self.rect.x = self.x * TILESIZE
        self.rect.y = self.y * TILESIZE


class Wall(pg.sprite.Sprite):
    def __init__(self, game, x, y):
        self.groups = game.all_sprites, game.walls
        pg.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        self.image = pg.Surface((TILESIZE, TILESIZE))
        self.image.fill(GREEN)
        self.rect = self.image.get_rect()
        self.x, self.y = x, y
        self.rect.x = x * TILESIZE
        self.rect.y = y * TILESIZE


class Mob(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((TILESIZE, TILESIZE))
        self.image.fill(RED)
        self.rect = self.image.get_rect()
        self.rect.x = random.randrange(WIDTH - self.rect.width)
        self.rect.y = random.randrange(-100, -40)
        self.speedy = random.randrange(6, 9)

    def update(self):
        self.rect.y += self.speedy
        if self.rect.top > HEIGHT + TILESIZE:
            self.rect.x = random.randrange(WIDTH - self.rect.width)
            self.rect.y = random.randrange(-100, -40)
            self.speedy = random.randrange(6, 9)


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()
        pg.key.set_repeat(1, 15)

    def new(self):
        self.all_sprites = pg.sprite.Group()
        self.walls = pg.sprite.Group()
        self.mobs = pg.sprite.Group()
        self.player = Player(self, 10, 10)
        for i in range(10):
            m = Mob()
            self.all_sprites.add(m)
            self.mobs.add(m)
        for x in range(-1, 22):
            Wall(self, x, -1)
        for x in range(-1, 22):
            Wall(self, x, 16)
        for x in range(-1, 17):
            Wall(self, -1, x)
        for x in range(-1, 17):
            Wall(self, 21, x)

    def run(self):
        self.playing = True
        while self.playing:
            self.dt = self.clock.tick(FPS) / 1000
            self.events()
            self.update()
            self.draw()

    def quit(self):
        pg.quit()
        sys.exit()

    def update(self):
        self.all_sprites.update()

    def draw_grid(self):
        for x in range(0, WIDTH, TILESIZE):
            pg.draw.line(self.screen, LIGHTGREY, (x, 0), (x, HEIGHT))
        for y in range(0, HEIGHT, TILESIZE):
            pg.draw.line(self.screen, LIGHTGREY, (0, y), (WIDTH, y))

    def draw(self):
        self.screen.fill(BGCOLOR)
        self.draw_grid()
        self.all_sprites.draw(self.screen)
        pg.display.flip()

    def events(self):
        for event in pg.event.get():
            if event.type == pg.QUIT:
                self.quit()
            if event.type == pg.KEYDOWN:
                if event.key == pg.K_ESCAPE:
                    self.quit()
                if event.key == pg.K_LEFT:
                    self.player.move(dx=-1)
                if event.key == pg.K_RIGHT:
                    self.player.move(dx=1)
                if event.key == pg.K_UP:
                    self.player.move(dy=-1)
                if event.key == pg.K_DOWN:
                    self.player.move(dy=1)

g = Game()
while True:
    g.new()
    g.run()

2 Answers 2

2

You can use third argument of randrange which is step. In the Mob class, set x value of rect object like this:

self.rect.x = random.randrange(0, WIDTH, TILESIZE) 

And they will be perfectly aligned with the tiles.

Sign up to request clarification or add additional context in comments.

3 Comments

Not fair! I posted that answer earlier XD.
@AnnZen Sorry, but you are wrong. Asocia was first, I was the second and you were the third.
@Rabbid76 Now I see.
2

Add the step TILE_SIZE to the self.rect.x() Here:

class Mob(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((TILESIZE, TILESIZE))
        self.image.fill(RED)
        self.rect = self.image.get_rect()
        self.rect.x = random.randrange(0,WIDTH-self.rect.width,48)
        self.rect.y = random.randrange(-100, -40)
        self.speedy = random.randrange(6, 9)

    def update(self):
        self.rect.y += self.speedy
        if self.rect.top > HEIGHT + TILESIZE:
            self.rect.x = random.randrange(0,WIDTH-self.rect.width,48)
            self.rect.y = random.randrange(-100, -40)
            self.speedy = random.randrange(6, 9)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.