1

I am trying to make a game where your supposed to land the player on a surface. I have named this surface as 'lander'. Here is my player class:

class player:
    def __init__(self, x, y, height, width):
        self.ufo = pygame.image.load(r"C:\Users\rahul\OneDrive\Documents\A level python codes\lander\ufo.png")
        self.ufo = pygame.transform.scale(self.ufo, (height, width))
        self.height = height
        self.width = width
        self.x = x
        self.y = y
        self.speed = 0
        self.score = 0

    def draw(self):
        g.screen.blit(self.ufo, (self.x, self.y))

    def fly_up(self):
        self.speed = 5
        p.y = p.y -4
        self.y -= self.speed

    def fly_right(self):
        self.speed = 5
        p.y = p.y -4
        self.x += self.speed

    def fly_left(self):
        self.speed = 5
        p.y = p.y -4
        self.x -= self.speed

Here is my lander class:

class lander:
        def __init__(self, x, y, height, width):
            self.x = x
            self.y = y
            self.height = height
            self.width = width
            self.color = (192, 192, 192)

        def draw(self):
            self.lander = pygame.draw.rect(g.screen, self.color, (self.x, self.y, self.width, self.height))


        def move(self):
            self.speed = 4
            self.x -= self.speed

        def lander_off_screen(self):
            if self.x == 0 - p.height - 50:
                self.x = 1200 + p.height + 50
                self.y = random.randint(230, 590)

I want to detect if they are colliding using masks. However I am having a couple of problems. Firstly I dont know how to convert self.lander to alpha. It gave me an error when I tried. Even when I used an actual image instead of a rectange as lander, it didnt work like I I wanted it to. Thanks

My code so far for reference is here:

import pygame
import os
import random
import time

os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()

start = time.time()

def main():
    class game:
        def __init__(self, *args):
            self.win = pygame.display
            self.SH = 600
            self.SW = 1200
            self.screen = self.win.set_mode((self.SW, self.SH))
            self.win.set_caption("UFO Lander")
            self.white = (255, 255, 255)
            self.red = (255, 0, 0)
            self.green = (0, 255, 0)
            self.transparent =  (0, 0, 0, 0)
            self.background = pygame.image.load(r"C:\Users\rahul\OneDrive\Documents\A level python codes\lander\background.png")
            self.background = pygame.transform.scale(self.background, (self.SW, self.SH))
            self.transparent =  (0, 0, 0, 0)
            clock = pygame.time.Clock()
            self.FPS = 30
            self.FPS = clock.tick(self.FPS)
            self.gravity = 4
            self.time_passed = pygame.time.get_ticks()/1000

        def write(self, text, color, x , y, size):
            font = pygame.font.SysFont("Aerial", size)
            text = font.render(text, True, color)
            textRect = text.get_rect()
            self.screen.blit(text,(x , y))

        def player_off_screen(self):
            if p.x < 0:
                p.x = 0
                g.write("YOU CRASHED!!", self.red, 50, 250, 200)
                g.win.update()
                pygame.time.delay(1000)
                main()

            if p.x + p.height > 1200:
                p.x = 1200 - p.height
                g.write("YOU CRASHED!!", self.red, 50, 250, 200)
                g.win.update()
                pygame.time.delay(1000)
                main()

            if p.y < 0:
                p.y = 0
                g.write("YOU CRASHED!!", self.red, 50, 250, 200)
                g.win.update()
                pygame.time.delay(1000)
                main()

            if p.y + p.width > 600:
                p.y = 600 - p.width
                g.write("YOU CRASHED!!", self.red, 50, 250, 200)
                g.win.update()
                pygame.time.delay(1000)
                main()

    class thrust:
        def __init__(self, x, y):
            self.thrust = pygame.image.load(r"C:\Users\rahul\OneDrive\Documents\A level python codes\lander\thrust.png")
            self.thrust = pygame.transform.scale(self.thrust, (100, 150))
            self.x = x
            self.y = y

        def draw(self):
            g.screen.blit(self.thrust, (self.x, self.y))

        def update_x(self, variable):
            self.x = p.x + variable

        def update_y(self, variable):
            self.y = p.y + variable

    class player:
        def __init__(self, x, y, height, width):
            self.ufo = pygame.image.load(r"C:\Users\rahul\OneDrive\Documents\A level python codes\lander\ufo.png")
            self.ufo = pygame.transform.scale(self.ufo, (height, width))
            self.height = height
            self.width = width
            self.x = x
            self.y = y
            self.speed = 0
            self.score = 0

        def draw(self):
            g.screen.blit(self.ufo, (self.x, self.y))

        def fly_up(self):
            self.speed = 5
            p.y = p.y -4
            self.y -= self.speed

        def fly_right(self):
            self.speed = 5
            p.y = p.y -4
            self.x += self.speed

        def fly_left(self):
            self.speed = 5
            p.y = p.y -4
            self.x -= self.speed

    p = player(100, 100, 350, 150)
    t = thrust(p.x, p.y)
    t2 = thrust(p.x, p.y)

    class obstacles:pass

    class lander:
        def __init__(self, x, y, height, width):
            self.x = x
            self.y = y
            self.height = height
            self.width = width
            self.color = (192, 192, 192)

        def draw(self):
            self.lander = pygame.draw.rect(g.screen, self.color, (self.x, self.y, self.width, self.height))


        def move(self):
            self.speed = 4
            self.x -= self.speed

        def lander_off_screen(self):
            if self.x == 0 - p.height - 50:
                self.x = 1200 + p.height + 50
                self.y = random.randint(230, 590)

    class fuel:
        def __init__(self):
            self.x = 100
            self.y = 60
            self.height = 30
            self.width = 300

        def draw(self):
            pygame.draw.rect(g.screen, g.white, (self.x, self.y, self.width, self.height))

        def less_fuel(self):
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT or (pygame.K_UP) or (pygame.K_LEFT):
                    self.change = 0.7
                    self.width -= self.change

        def run_out(self):
            if self.width < 0:
                g.write("FUEL EMPTY!!", g.red, 50, 250, 200)
                g.win.update()
                pygame.time.delay(1000)
                main()

    f = fuel()


    class menu: pass

    g = game()


    run = True
    t = thrust(p.x, p.y)
    l = lander(1200 - p.height - 50, random.randint(230, 590), 20, p.height+ 50)
    while run:
        g.screen.blit(g.background, (0, 0))

        l.draw()
        l.move()

        g.write("s", g.white, 350, 10, 50)
        g.write("Fuel: ", g.white ,10, 60, 50)
        g.write("Score: %d" %(p.score), g.white, 1000, 10, 50)

        p.draw()
        p.y += g.gravity

        g.player_off_screen()
        l.lander_off_screen()

        t.update_x(50)
        t.update_y(110)
        t2.update_x(200)
        t2.update_y(110)

        f.draw()
        f.run_out()

        try:

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    quit()

            f.less_fuel()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT:
                    p.fly_right()
                if event.key == pygame.K_LEFT:
                    p.fly_left()
                if event.key == pygame.K_UP:
                    t.draw()
                    t2.draw()
                    p.fly_up()

            end = time.time()
            duration = end - start
            g.write("Total game time: %d" %(duration), g.white ,10, 10, 50)

        except NameError:
            pass

        pygame.display.flip()        


if __name__ == "__main__":
    main()
  • 1
    in most situations using normal `pygame.Rect` to check collision can be enough. BTW: If you will keep position and size in `pygame.Rect` then you can use `p.rect.right == 600` instead of `p.x == 600 - p.widht`. And then you can use standard method `lander.rect.colliderect(player.rect)` – furas Dec 22 '19 at 14:12
  • 1
    BTW: there is good rule to use `CamelCaseNames` for classes - i.e `class Player` similar to `pygame.Rect`, `pygame.surface.Surface`, `pygame.time.Clock` - it helps to recognize class in code - ie. `player = Player()`. More: [PEP 8 -- Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/) – furas Dec 22 '19 at 14:14

1 Answers1

0

Create a pygame.Surface with the size of the rectangle rather than drawing a rectangle:

class lander:
    def __init__(self, x, y, height, width):
        # [...]

        self.image = pygame.Surface((width, height))
        self.image.fill((192, 192, 192))

        def draw(self):
            self.lander = self.image.get_rect(topleft = (self.x, self.y))
            g.screen.blit(self.image, self.lander)

Use pygame.mask.from_surface() to create a pygame.mask.Mask object from a Surface:

class player:
    def __init__(self, x, y, height, width):
        # [...]

        self.mask = pygame.mask.from_surface(self.ufo)
class lander:
    def __init__(self, x, y, height, width):
        # [...]

        self.mask = pygame.mask.from_surface(self.image)

Use overlap() to detect the collision of masks. The offset parameter of the method overlap() is the relative position of the othermask in relation to the pygame.mask.Mask object.
In the following p is an instance of player and l is an instance of lander. So the offset is calculated by subtracting the coordinates of p from the coordinates of l:

offset = (l.x - p.x), (l.y - p.y)
if p.mask.overlap(l.mask, offset):
    print("hit")

Minimal example: repl.it/@Rabbid76/PyGame-SurfaceMaskIntersect

See also: Mask and Pygame collision with masks is not working

Rabbid76
  • 202,892
  • 27
  • 131
  • 174