python - 在 pygame 中实现 Rect 对象和球之间的碰撞检测功能

标签 python pygame

import pygame, random, time
# main function where we call all other functions, start the game loop, quit pygame and clean up the window. Inside we create a game object, display surface, and start the game loop by calling the play method on the game object. There is also a set caption with the title of the game.
def main():
    pygame.init()
    size =(500,400)
    surface=pygame.display.set_mode(size)
    pygame.display.set_caption('Pong v2')
    game = Game(surface)
    game.play()
    pygame.quit()
# This is where we define the class game    
class Game():
    # an object in this class represents a complete game

    # here we initialize a game. self is the game that is initialized surface is the display window surface object we also set default values for continuing the game and closing the window. we also define what fps we are running the game at, and define the velocity color position and radius of the ball
    def __init__(self,surface):

        # defining surface, fps, background color
        self.surface=surface
        self.FPS=120
        self.bg_color=pygame.Color('black')
        screen_width = surface.get_width()
        screen_height = surface.get_height()

        # defining ball attributes
        ball_radius=10
        ball_pos = [random.randint(ball_radius, screen_width-ball_radius), 
                    random.randint(ball_radius, screen_height-ball_radius)]
        ball_color=pygame.Color('white')
        ball_velocity=[2,1]
        self.ball=Ball(ball_pos,ball_radius,ball_color,ball_velocity,surface)

        # defining paddle attributes

        rect_left=[50,450]
        rect_top=225
        rect_height=60
        rect_width=10
        self.Paddle1=Rect(rect_left[0],rect_top,rect_width,rect_height,surface)
        self.Paddle2=Rect(rect_left[1],rect_top,rect_width,rect_height,surface)


        self.game_Clock=pygame.time.Clock()
        self.close_clicked=False
        self.continue_game=True
        self.score1=0
        self.score2=0
        self.frame_counter=0

    def play(self):
        # game is played until player clicks close
        while not self.close_clicked:  

            self.handle_events()

            self.draw()


            # if nothing sets this to false the game will continue to update
            if self.continue_game:
                self.update()

            self.game_Clock.tick(self.FPS)
    # score is drawn onto the screen (unimportant this is just playing with a feature for the next version), we define color font background etc of the score message and update score upon points being scored
    def draw_score(self):
        font_color = pygame.Color("white")
        font_bg    = pygame.Color("black")
        font       = pygame.font.SysFont("arial", 18)
        text_img   = font.render("Score for Player 1: " + str(self.score1) + ' Score for Player 2: ' + str(self.score2), True, font_color, font_bg)     
        text_pos   = (0,0)
        self.surface.blit(text_img, text_pos)

    # ball, surface, score, and two paddles are drawn, pygame also updates this drawing once per frame    
    def draw(self):
        self.surface.fill(self.bg_color)

        self.draw_score()
        #pygame.draw.rect(self.surface,pygame.Color('blue'),(50,225,10,50))
        #pygame.draw.rect(self.surface,pygame.Color('red'),(450,225,10,50))
        self.Paddle1.draw()
        self.Paddle2.draw()

        self.ball.draw()


        pygame.display.update()
    # score value set to default of 0 we tell ball to move and add 1 to frame counter upon each update. update game object for the next frame 
    def update(self):
        self.ball.move()
        self.score=0
        self.frame_counter+=self.frame_counter+1











    # here we setup an event loop and figure out if the action to end the game has been done
    def handle_events(self):
        events=pygame.event.get()
        for event in events:
            if event.type== pygame.QUIT:
                self.close_clicked=True
# user defined class ball            
class Ball:
    # self is the ball to intialize. color/center/radius are defined for the ball that is initialized
    def __init__(self,center,radius,color,velocity,surface):
        self.center=center
        self.radius=radius
        self.color=color
        self.velocity=velocity
        self.surface=surface
    # screen size is determined and edge of ball is checked that it is not touching the edge. if it is touching the edge it bounces and reverses velocity   
    def move(self):
        screen_width=self.surface.get_width()
        screen_height=self.surface.get_height()
        screen_size=(screen_width,screen_height)
        for i in range(0,len(self.center)):
            self.center[i]+=self.velocity[i]
            if (self.center[i]<=0 + self.radius or self.center[i]>=screen_size[i] - self.radius):
                self.velocity[i]=-self.velocity[i]
    # ball is drawn            
    def draw(self):
        pygame.draw.circle(self.surface,self.color,self.center,self.radius)


class Rect:
    def __init__(self,left,top,width,height,surface):
        #self.left=left
        #self.top=top
        #self.width=width
        #self.height=height
        self.surface=surface
        self.rect=pygame.Rect(left,top,width,height)

    def draw(self):
        pygame.draw.rect(self.surface,pygame.Color('red'),self.rect)

    def collide(self):
        if pygame.Rect.collide(x,y) == True:
            return True
        else:
            return False
















main()

上面是我到目前为止的工作,基本上它应该是复古街机游戏乒乓球,球从桨的边缘反弹,如果没有反弹,对面在击中 window 边缘时得分。因此,具体来说,项目的这一部分要求我让球从 Racket 的前部弹起,而我对如何做到这一点感到困惑。我最初的想法是使用 Rect 类内部的 collidepoint 方法,如果它返回 true 将反转球的速度。但是,我无法访问类内部或类游戏中的方法 play 内部的球的中心坐标,我打算在球和 paddle1、paddle2 的特定实例上进行这项工作,所以我不这样做不知道该怎么做。

最佳答案

Game.update 中评估球是否击中右侧的左桨,以及左侧的右桨。
如果球击中 Racket ,得分就会增加:

class Game():

    # [...]

    def update(self):
        self.ball.move()

        # evaluate if Ball hits the left paddle (Paddle1) at the right
        if self.ball.velocity[0] < 0 and self.Paddle1.rect.top <= self.ball.center[1] <= self.Paddle1.rect.bottom:
           if self.Paddle1.rect.right <= self.ball.center[0] <= self.Paddle1.rect.right + self.ball.radius:
                self.ball.velocity[0] = -self.ball.velocity[0]
                self.ball.center[0] = self.Paddle1.rect.right + self.ball.radius
                self.score1 += 1

        # evaluate if Ball hits the right paddle (Paddle2) at the left
        if self.ball.velocity[0] > 0 and self.Paddle2.rect.top <= self.ball.center[1] <= self.Paddle2.rect.bottom:
           if self.Paddle2.rect.left >= self.ball.center[0] >= self.Paddle2.rect.left - self.ball.radius:
                self.ball.velocity[0] = -self.ball.velocity[0]
                self.ball.center[0] = self.Paddle2.rect.left - self.ball.radius
                self.score2 += 1 

通过 pygame.key.get_pressed() 获取按键状态并更改桨的位置是 Game.handle_events 。

例如将左桨移动 w/s,将右桨移动 UP/DOWN:

class Game():

    # [...]

    def handle_events(self):
        events=pygame.event.get()
        for event in events:
            if event.type== pygame.QUIT:
                self.close_clicked=True
        keys = pygame.key.get_pressed()
        if keys[pygame.K_w]:
            self.Paddle1.rect.top = max(0, self.Paddle1.rect.top - 3)
        if keys[pygame.K_s]:
            self.Paddle1.rect.bottom = min(self.surface.get_height(), self.Paddle1.rect.bottom + 3)
        if keys[pygame.K_UP]:
            self.Paddle2.rect.top = max(0, self.Paddle2.rect.top - 3)
        if keys[pygame.K_DOWN]:
            self.Paddle2.rect.bottom = min(self.surface.get_height(), self.Paddle2.rect.bottom + 3)

关于python - 在 pygame 中实现 Rect 对象和球之间的碰撞检测功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58716774/

相关文章:

python - python导入全局变量的两种方式

python - Python 中的快速逆矩阵和转置矩阵

python - Pygame 无限循环与 keydown

Python,pygame鼠标位置和按下哪个按钮

PYTHON & PYGAME 如何向鼠标位置移动和旋转多边形?

python - 使用单个查询从多个表中提取

python - 使用 amqp 后端和数据库后端获取 Celery 结果有什么区别?

python - 为什么我的生成器阻止 Flask 发送 SSE 响应?

python - 电影加载但在 pygame 中却没有电影声音

python - 在python 3.8.3上的IDE中导入pygame失败