Pygame Mask не работает при создании объекта? - PullRequest
1 голос
/ 10 апреля 2020

Следующая программа представляет собой простую игру, в которой вы можете ударить по мячу. Теперь я собирался реализовать класс («Gameobject») для мяча, чтобы сделать вещи объектно-ориентированными.

Пока все хорошо. Но как только я добавлю mask.from_surface () в качестве атрибута к классу, шар больше не будет двигаться. Что я делаю не так?

Рабочий код (маска расположена в строке 61):

import pygame
from pygame.math import Vector2
import math

width = 1150
height = 800

# Colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREY = (210, 210, 210)
RED = (255, 0, 0)
GREEN = (20, 255, 140)
BLUE = (0, 0, 255)
GOLD = (255, 215, 0)
SILVER = (192, 192, 192)

drag = 0.399  # Between 0 and 1
elasticity = 0.75  # Between 0 and 1
gravity = (math.pi, 0.000)

pygame.init()
screen = pygame.display.set_mode((width, height))
clock = pygame.time.Clock()


# Define game object class
class Gameobject:
    """
    Interactive objects with the game
    """
    def __init__(self, coordinates, velocity, angle, radius, objectColor):
        self.x = coordinates[0]
        self.y = coordinates[1]
        self.velocity = velocity
        self.angle = angle
        self.radius = radius
        self.objectColor = objectColor
        self.surface = pygame.Surface((self.radius*2, self.radius*2), pygame.SRCALPHA)
        self.rectangle = self.surface.get_rect(center=[self.x, self.y])

    def draw(self):
        """
        Rendering game object
        :param screen: pygame screen
        """
        pygame.draw.circle(self.surface, self.objectColor, [self.radius, self.radius], self.radius)

# Images.
BG_IMG = pygame.Surface((1150, 800))
BG_IMG.fill((30, 120, 30))

REDCAR_ORIGINAL = pygame.Surface((50, 30), pygame.SRCALPHA)
pygame.draw.polygon(
    REDCAR_ORIGINAL, (255, 0, 0), [(0, 0), (50, 10), (50, 20), (0, 30)])
redcar = REDCAR_ORIGINAL

myBall = Gameobject(Vector2(575, 400), Vector2(0, 0), 0, 60, GOLD)
myBall.draw()
mask_ball = pygame.mask.from_surface(myBall.surface)

# Car variables.
pos_red = Vector2(470, 370)
vel_red = Vector2(3, 0)
redrect = redcar.get_rect(center=pos_red)
redangle = 0

# Masks.
mask_red = pygame.mask.from_surface(redcar)

run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    keys = pygame.key.get_pressed()

    if keys[pygame.K_LEFT]:
        redangle += 5
        vel_red.rotate_ip(-5)
        redcar = pygame.transform.rotate(REDCAR_ORIGINAL, redangle)
        redrect = redcar.get_rect(center=redrect.center)
        # We need a new mask after the rotation.
        mask_red = pygame.mask.from_surface(redcar)
    elif keys[pygame.K_RIGHT]:
        redangle -= 5
        vel_red.rotate_ip(5)
        redcar = pygame.transform.rotate(REDCAR_ORIGINAL, redangle)
        redrect = redcar.get_rect(center=redrect.center)
        mask_red = pygame.mask.from_surface(redcar)

    # Move the cars.
    pos_red += vel_red
    redrect.center = pos_red

    # Move the ball.
    myBall.velocity *= .99  # Friction.
    myBall.x += myBall.velocity[0]
    myBall.y += myBall.velocity[1]
    myBall.rectangle.center = [myBall.x, myBall.y]

    # Red car collision.
    # We need the offset between the redrect and the ballrect.
    offset_red = redrect[0] - myBall.rectangle[0], redrect[1] - myBall.rectangle[1]
    # Pass the offset to the `overlap` method. If the masks collide,
    # overlap will return a single point, otherwise `None`.
    overlap_red = mask_ball.overlap(mask_red, offset_red)
    # Blue car collision.

    if overlap_red:  # Red collides with the ball.
        myBall.velocity = Vector2(vel_red) * 1.4

    # Drawing.
    screen.blit(BG_IMG, (0, 0))
    screen.blit(myBall.surface, myBall.rectangle)
    screen.blit(redcar, redrect)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Моя попытка реализовать маску внутри класса Gameobject:

import pygame
from pygame.math import Vector2
import math

width = 1150
height = 800

# Colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREY = (210, 210, 210)
RED = (255, 0, 0)
GREEN = (20, 255, 140)
BLUE = (0, 0, 255)
GOLD = (255, 215, 0)
SILVER = (192, 192, 192)

drag = 0.399  # Between 0 and 1
elasticity = 0.75  # Between 0 and 1
gravity = (math.pi, 0.000)

pygame.init()
screen = pygame.display.set_mode((width, height))
clock = pygame.time.Clock()


# Define game object class
class Gameobject:
    """
    Interactive objects with the game
    """
    def __init__(self, coordinates, velocity, angle, radius, objectColor):
        self.x = coordinates[0]
        self.y = coordinates[1]
        self.velocity = velocity
        self.angle = angle
        self.radius = radius
        self.objectColor = objectColor
        self.surface = pygame.Surface((self.radius*2, self.radius*2), pygame.SRCALPHA)
        self.rectangle = self.surface.get_rect(center=[self.x, self.y])
        self.mask = pygame.mask.from_surface(self.surface)

    def draw(self):
        """
        Rendering game object
        :param screen: pygame screen
        """
        pygame.draw.circle(self.surface, self.objectColor, [self.radius, self.radius], self.radius)

# Images.
BG_IMG = pygame.Surface((1150, 800))
BG_IMG.fill((30, 120, 30))

REDCAR_ORIGINAL = pygame.Surface((50, 30), pygame.SRCALPHA)
pygame.draw.polygon(
    REDCAR_ORIGINAL, (255, 0, 0), [(0, 0), (50, 10), (50, 20), (0, 30)])
redcar = REDCAR_ORIGINAL

myBall = Gameobject(Vector2(575, 400), Vector2(0, 0), 0, 60, GOLD)
myBall.draw()

# Car variables.
pos_red = Vector2(470, 370)
vel_red = Vector2(3, 0)
redrect = redcar.get_rect(center=pos_red)
redangle = 0

# Masks.
mask_red = pygame.mask.from_surface(redcar)

run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    keys = pygame.key.get_pressed()

    if keys[pygame.K_LEFT]:
        redangle += 5
        vel_red.rotate_ip(-5)
        redcar = pygame.transform.rotate(REDCAR_ORIGINAL, redangle)
        redrect = redcar.get_rect(center=redrect.center)
        # We need a new mask after the rotation.
        mask_red = pygame.mask.from_surface(redcar)
    elif keys[pygame.K_RIGHT]:
        redangle -= 5
        vel_red.rotate_ip(5)
        redcar = pygame.transform.rotate(REDCAR_ORIGINAL, redangle)
        redrect = redcar.get_rect(center=redrect.center)
        mask_red = pygame.mask.from_surface(redcar)

    # Move the cars.
    pos_red += vel_red
    redrect.center = pos_red

    # Move the ball.
    myBall.velocity *= .99  # Friction.
    myBall.x += myBall.velocity[0]
    myBall.y += myBall.velocity[1]
    myBall.rectangle.center = [myBall.x, myBall.y]

    # Red car collision.
    # We need the offset between the redrect and the ballrect.
    offset_red = redrect[0] - myBall.rectangle[0], redrect[1] - myBall.rectangle[1]
    # Pass the offset to the `overlap` method. If the masks collide,
    # overlap will return a single point, otherwise `None`.
    overlap_red = myBall.mask.overlap(mask_red, offset_red)
    # Blue car collision.

    if overlap_red:  # Red collides with the ball.
        myBall.velocity = Vector2(vel_red) * 1.4

    # Drawing.
    screen.blit(BG_IMG, (0, 0))
    screen.blit(myBall.surface, myBall.rectangle)
    screen.blit(redcar, redrect)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

1 Ответ

1 голос
/ 11 апреля 2020

Когда вы создаете маску из поверхности, то поверхность пуста, потому что круг нарисован на поверхности в draw:

class Gameobject:
   """
   Interactive objects with the game
   """
   def __init__(self, coordinates, velocity, angle, radius, objectColor):
       # [...]

       self.surface = pygame.Surface((self.radius*2, self.radius*2), pygame.SRCALPHA)
       self.rectangle = self.surface.get_rect(center=[self.x, self.y])
       self.mask = pygame.mask.from_surface(self.surface)

   def draw(self):
       pygame.draw.circle(self.surface, self.objectColor, [self.radius, self.radius], self.radius)

Вы должны создать маска после круга нарисована на .surface из Gameobject:

class Gameobject:
    # [...]    

    def draw(self):

        # draw circle on surface 
        pygame.draw.circle(self.surface, self.objectColor, [self.radius, self.radius], self.radius)

        # create mask from surface with circle
        self.mask = pygame.mask.from_surface(self.surface)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...