Реализация функции обнаружения столкновений между объектом Rect и шаром в Pygame - PullRequest
1 голос
/ 05 ноября 2019
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()

Выше моя работа, в основном это должен быть ретро-аркадный понг, где мяч отскакивает от краев лопастей, а если нет, противоположная сторона забивает точку, ударяясь о край. окна. Так что именно эта часть проекта требует от меня отскока мяча от передней части лопаток, и я не понимаю, как это сделать. Первоначально моя идея заключалась в том, чтобы использовать метод collidepoint внутри класса Rect, который, если он возвращает true, изменил бы скорость шаров. Тем не менее, у меня нет доступа к координатам центра шара внутри класса или внутри метода игры в игре класса, где я намеревался сделать эту работу на конкретных экземплярах ball и paddle1, paddle2, поэтому я нене знаю, как это сделать.

1 Ответ

1 голос
/ 06 ноября 2019

Оцените, попадет ли мяч в левый фланг справа, соответственно в правый фланг слева в Game.update.
Если мяч попал в паддл, счет может быть увеличен:

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 / ВНИЗ :

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)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...