如何使用“ Colliderect”删除Pygame中的矩形.只有当矩形被“命中”时X次



我正在制作突破性的版本,尽管基本游戏正常,但我想确定级别等。因此,我想做的就是做到这一点,以便在球击中X时才拆除砖。

我尝试添加一个计数器:

 for brick in self.bricks:
        if self.ball.colliderect(brick):
            self.brick_counter += 1
            self.score += 3
            self.ball_vel[1] = -self.ball_vel[1]
            if self.brick_counter == 2:
            self.bricks.remove(brick)
            break

,但结果是球只是通过砖矩形。

我还考虑过创建两层(或更多(砖,但我不确定如何实施。

这是完整的代码:

import sys
import pygame
# Global variables is usually in the top of the document
SCREEN_SIZE = 750, 550
#OBJECT ATTRIBUTES
#PADDLE ATTRIBUTES
PADDLE_WIDTH = 54
PADDLE_HEIGHT = 10
MAX_PADDLE_X = SCREEN_SIZE[0] - PADDLE_WIDTH
PADDLE_Y = SCREEN_SIZE[1] - PADDLE_HEIGHT - 10
#BRICK ATTRIBUTES
BRICK_WIDTH = 75
BRICK_HEIGHT = 15
#BALL ATTRIBUTES
BALL_DIAMETER = 16
BALL_RADIUS = BALL_DIAMETER // 2
MAX_BALL_X = SCREEN_SIZE[0] - BALL_DIAMETER
MAX_BALL_Y = SCREEN_SIZE[1] - BALL_DIAMETER
#COLORS
BLACK       = (0,   0,     0)
WHITE       = (255, 255, 255)
BLUE        = (0,   0,   255)
CYAN        = (0,   255, 255)
PINK        = (255, 102, 255)
WHITE       = (255, 255, 255)
NAVYBLUE    = ( 60,  60, 100)
RED         = (200,   0,   0)
DARKRED     = (100,   0,   0)
ORANGE      = (200, 100,   0)
DARKORANGE  = (100,  50,   0)
YELLOW      = (200, 200,   0)
DARKYELLOW  = (100, 100,   0)
GREEN       = (  0, 200,   0)
DARKGREEN   = (  0, 100,   0)
BLUE        = (  0,   0, 200)
DARKBLUE    = (  0,   0, 100)
PURPLE      = (200,   0, 200)
DARKPURPLE  = (100,   0, 100)
RAINBOW = [(RED, DARKRED),(ORANGE,DARKORANGE),(YELLOW,DARKYELLOW),
           (GREEN,DARKGREEN),(BLUE,DARKBLUE),(PURPLE,DARKPURPLE)]
BRICK_COLOR =(0,   255, 255)
# State constants
STATE_BALL_IN_PADDLE = 0
STATE_PLAYING = 1
STATE_GAME_WON = 2
STATE_GAME_OVER = 3
STATE_LEVEL_ONE = 4
STATE_LEVEL_TWO = 5
STATE_LEVEL_THREE = 6
STATE_LEVEL_ONE_WON = 7
STATE_LEVEL_TWO_WON = 8
STATE_LEVEL_THREE_WON = 9
# Initialising pygame
class Breakout:
    def __init__(self):
        pygame.init()
        self.screen = pygame.display.set_mode(SCREEN_SIZE)
        pygame.display.set_caption("Breakout")
        self.clock = pygame.time.Clock()
        if pygame.font:
            self.font = pygame.font.SysFont("impact", 20)
        else:
            self.font = None
        self.init_game()
    def init_game(self):
        self.lives = 3
        self.score = 0
        self.state = STATE_BALL_IN_PADDLE
        self.level_state = STATE_LEVEL_ONE
        self.paddle   = pygame.Rect(300,PADDLE_Y,PADDLE_WIDTH,PADDLE_HEIGHT)
        self.ball     = pygame.Rect(300,PADDLE_Y - BALL_DIAMETER,BALL_DIAMETER,BALL_DIAMETER)
        self.ball_vel = [5,-5]
        self.create_bricks()

    def draw_level_one(self):
        self.lives = 3
        self.score = 0
        self.level_state = STATE_LEVEL_ONE
        self.state = STATE_BALL_IN_PADDLE
        self.paddle = pygame.Rect(300, PADDLE_Y,PADDLE_WIDTH,PADDLE_HEIGHT)
        self.ball   = pygame.Rect(300,PADDLE_Y - BALL_DIAMETER,BALL_DIAMETER,BALL_DIAMETER)
        self.ball_vel = [5,-5]
        self.create_bricks()
    def draw_level_two(self):
        self.lives = 3
        self.score = 0
        self.level_state = STATE_LEVEL_TWO
        self.state = STATE_BALL_IN_PADDLE
        self.paddle   = pygame.Rect(300,PADDLE_Y,PADDLE_WIDTH,PADDLE_HEIGHT)
        self.ball     = pygame.Rect(300,PADDLE_Y - BALL_DIAMETER,BALL_DIAMETER,BALL_DIAMETER)
        self.ball_vel = [5,-5]
        self.create_bricks()
    def draw_level_three(self):
        self.lives = 3
        self.score = 0
        self.level_state = STATE_LEVEL_THREE
        self.state = STATE_BALL_IN_PADDLE
        self.paddle   = pygame.Rect(300,PADDLE_Y,PADDLE_WIDTH,PADDLE_HEIGHT)
        self.ball     = pygame.Rect(300,PADDLE_Y - BALL_DIAMETER,BALL_DIAMETER,BALL_DIAMETER)
        self.ball_vel = [5,-5]
        self.create_bricks()
    def create_bricks(self):
        y_ofs = 50
        self.bricks = []
        for i in range(7):
            x_ofs = 50
            for j in range(8):
                self.bricks.append(pygame.Rect(x_ofs,y_ofs,BRICK_WIDTH,BRICK_HEIGHT))
                x_ofs += BRICK_WIDTH + 10
            y_ofs += BRICK_HEIGHT + 5
    def draw_bricks(self):
        if self.level_state == STATE_LEVEL_ONE:
            for brick in self.bricks:
                pygame.draw.rect(self.screen, CYAN, brick)
        elif self.level_state == STATE_LEVEL_TWO:
            for brick in self.bricks:
                pygame.draw.rect(self.screen, GREEN, brick)
        elif self.level_state == STATE_LEVEL_THREE:
            for brick in self.bricks:
                pygame.draw.rect(self.screen, DARKRED, brick)
    def check_input(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            self.paddle.left -= 7
            if self.paddle.left < 0:
                self.paddle.left = 0
        if keys[pygame.K_RIGHT]:
            self.paddle.left += 7
            if self.paddle.left > MAX_PADDLE_X:
                self.paddle.left = MAX_PADDLE_X
        if keys[pygame.K_SPACE] and self.state == STATE_BALL_IN_PADDLE:
            self.ball_vel = [5,-5]
            self.state = STATE_PLAYING
        elif keys[pygame.K_RETURN] and (self.state == STATE_GAME_OVER
                                            or self.state == STATE_GAME_WON):
                                            self.draw_level_one()
        if keys[pygame.K_w]:
            self.state = STATE_GAME_WON
            self.ball.left = self.paddle.left + self.paddle.width / 2
            self.ball.top  = self.paddle.top - self.ball.height
        if keys[pygame.K_l]:
            self.state = STATE_GAME_OVER
            self.ball.left = self.paddle.left + self.paddle.width / 2
            self.ball.top  = self.paddle.top - self.ball.height
        if keys[pygame.K_1]:
            self.draw_level_one()
            self.ball.left = self.paddle.left + self.paddle.width / 2
            self.ball.top  = self.paddle.top - self.ball.height
        if keys[pygame.K_2]:
            self.draw_level_two()
            self.ball.left = self.paddle.left + self.paddle.width / 2
            self.ball.top  = self.paddle.top - self.ball.height
        if keys[pygame.K_3]:
            self.draw_level_three()
            self.ball.left = self.paddle.left + self.paddle.width / 2
            self.ball.top  = self.paddle.top - self.ball.height
        if self.level_state == STATE_LEVEL_ONE_WON:
            if keys[pygame.K_KP_ENTER]:
                self.draw_level_two()
                self.ball.left = self.paddle.left + self.paddle.width / 2
                self.ball.top  = self.paddle.top - self.ball.height
        if self.level_state == STATE_LEVEL_TWO_WON:
            if keys[pygame.K_KP_ENTER]:
                self.draw_level_three()
                self.ball.left = self.paddle.left + self.paddle.width / 2
                self.ball.top  = self.paddle.top - self.ball.height
        if self.level_state == STATE_LEVEL_THREE_WON:
            if keys[pygame.K_KP_ENTER]:
                self.draw_level_one()
                self.ball.left = self.paddle.left + self.paddle.width / 2
                self.ball.top  = self.paddle.top - self.ball.height
        if keys[pygame.K_ESCAPE]:
            sys.exit()
    def move_ball (self):
        self.ball.left += self.ball_vel[0]
        self.ball.top += self.ball_vel[1]
        #bounds check
        if self.ball.left <= 0:
            self.ball.left = 0
            self.ball_vel[0] = -self.ball_vel[0]
        elif self.ball.left >= MAX_BALL_X:
            self.ball.left = MAX_BALL_X
            self.ball_vel[0] = -self.ball_vel[0]
        if self.ball.top < 0:
            self.ball.top = 0
            self.ball_vel[1] = -self.ball_vel[1]
        elif self.ball.top >= MAX_BALL_Y:
            self.ball.top = MAX_BALL_Y
            self.ball_vel[1] = -self.ball_vel[1]

    def handle_collisions(self):
        self.brick_counter = 0
        for brick in self.bricks:
            if self.ball.colliderect(brick):
                #self.brick_counter += 1
                self.score += 3
                self.ball_vel[1] = -self.ball_vel[1]
                #if self.brick_counter == 2:
                self.bricks.remove(brick)
                break
        if len(self.bricks) == 0 or self.state == STATE_GAME_WON:
            if self.level_state == STATE_LEVEL_ONE:
                self.level_state == STATE_LEVEL_ONE_WON
            elif self.level_state == STATE_LEVEL_TWO:
                self.level_state == STATE_LEVEL_TWO_WON
            elif self.level_state == STATE_LEVEL_THREE:
                self.level_state == STATE_LEVEL_THREE_WON
        if self.ball.colliderect(self.paddle):
            self.ball.top = PADDLE_Y - BALL_DIAMETER
            self.ball_vel[1] = -self.ball_vel[1]
        elif self.ball.top > self.paddle.top:
            self.lives -= 1
            if self.lives > 0:
                self.state = STATE_BALL_IN_PADDLE
            else:
                self.state = STATE_GAME_OVER
    def show_stats(self):
        if self.font:
            font_surface = self.font.render("SCORE: " + str(self.score)
                                             + " LIVES: " + str(self.lives), False, WHITE)
            self.screen.blit(font_surface, (205, 5))
    def show_message(self, message):
        if self.font:
            size = self.font.size(message)
            font_surface = self.font.render(message, False, WHITE)
            x = (SCREEN_SIZE[0] - size[0]) /2
            y = (SCREEN_SIZE[1] - size[1]) /2
            self.screen.blit(font_surface, (x,y))
    def run(self):
        while 1:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    sys.exit()
            self.clock.tick(60)
            self.screen.fill(BLACK)
            self.check_input()
            self.handle_collisions()
            if self.state == STATE_PLAYING:
                self.move_ball()
                self.handle_collisions()
            elif self.state == STATE_BALL_IN_PADDLE:
                self.ball.left = self.paddle.left + self.paddle.width / 2
                self.ball.top = self.paddle.top - self.ball.height
                self.show_message("PRESS SPACE TO LAUNCH THE BALL")
            elif self.state == STATE_GAME_OVER:
                self.show_message("GAME OVER. PRESS ENTER TO PLAY AGAIN")
            elif self.state == STATE_GAME_WON:
                self.show_message("YOU WON! PRESS ENTER TO GO TO THE NEXT LEVEL")
            self.draw_bricks()
            #Draw paddle
            pygame.draw.rect(self.screen, PINK, self.paddle)
            #DraW ball
            pygame.draw.circle(self.screen, WHITE, (self.ball.left + BALL_RADIUS,
                               self.ball.top + BALL_RADIUS), BALL_RADIUS)
            self.show_stats()
            pygame.display.flip()
if __name__ == "__main__":
    Breakout().run()

看起来您正在使用pygame。一旦任何砖被撞到两次,柜台就不再适当地达到其目的。您真正应该做的是创建一个既有矩形又有柜台的砖管,然后更新砖块的计数器。

class Brick:
  def __init__(self, rect):
    self.rect = rect
    self.hit_counter = 2

,然后self.bricks将是这些对象的列表。

另外,看起来您假设砖会从底部或顶部碰撞,并导致速度的Y组分反转。如果它从侧面发生碰撞,弹跳看起来会很奇怪,并且可能会导致球"只是通过"。在碰撞时,您必须查看球相对于砖块的位置,并决定将速度或Y组分的X分量翻转。

这样的东西(对不起,我可能不完全匹配您的领域,但是您明白了(:

dx = brick.centerx - ball.centerx
dy = brick.centery - ball.centery
if abs(dx) > abs(dy):
  self.ball_vel[0] *= -1
else:
  self.ball_vel[1] *= -1

相关内容

  • 没有找到相关文章

最新更新