相关文章推荐
腼腆的柠檬  ·  python ...·  2 周前    · 
有情有义的大白菜  ·  python ...·  2 周前    · 
完美的馒头  ·  python QTreeWidget ...·  2 周前    · 
失眠的烤红薯  ·  python qt textBrowser ...·  1 周前    · 
谈吐大方的跑步鞋  ·  python mysql ...·  1 年前    · 
唠叨的松树  ·  protobuf之string ...·  1 年前    · 
直爽的跑步机  ·  embedded - How do I ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Use vector2 in pygame. Collide with the window frame and restrict the ball to the rectangular area

Ask Question

Hey i am trying to create a breakout clone with pygame, and i used

self.course(180 - self.course) % 360

To bounce the ball of the paddle, however i was looking into the vector 2 class, but i got no idea how to convert my Ball class using this. If anyone could guide me in the right direction.

here is my code that i want to convert using vector2.

import pygame
import math
class Ball(pygame.sprite.Sprite):
    course = 130
    def __init__(self):
        # Calling the parent class (Sprite)
        pygame.sprite.Sprite.__init__(self)
        # Creating the ball and load the ball image
        self.image = pygame.image.load("ball.png").convert()
        self.rect = self.image.get_rect()
        self.rect.x = 0
        self.rect.y = 270
    # Creating a bounce function to make the ball bounce of surfaces.
    def bounce(self, diff):
        self.course = (180 - self.course) % 360
        self.course -= diff
    # Create the function that will update the ball.
    def update(self):
        course_radianse = math.radians(self.course)
        self.rect.x += 10 * math.sin(course_radianse)
        self.rect.y -= 10 * math.cos(course_radianse)
        self.rect.x = self.rect.x
        self.rect.y = self.rect.y
        # Check if ball goes past top
        if self.rect.y <= 0:
            self.bounce(0)
            self.rect.y = 1
        # Check if ball goes past left side
        if self.rect.x <= 0:
            self.course = (360 - self.course) % 360
            self.rect.x = 1
        # Check if ball goes past right side
        if self.rect.x >= 800:
            self.course = (360 - self.course) % 360
            self.rect.x = 800 - 1
        if self.rect.y > 600:
            return True
        else:
            return False
                I want to avoid using cos and sin, to get familiar using vector2 in pygame. I belive i need to declare all my objects in using vector2 but i am not familiar with the procedure. Hope this answered your question
– MerrinX
                Feb 13, 2020 at 17:30

A vector defines a direction and an amount. You have to add the vector to the location of the ball. Sadly pygame.Rect stores integral numbers only, so the location of the object has to be stored in a pygame.math.Vector2, too. You need 1 vector for the location of the object and a 2nd one for the direction. Every time when the location changes, then the .rect attribute has to be set by the rounded location. If the object hits a surface then the Ball is reflected (.reflect()) by the Normal vector to the surface.

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

import pygame
import random
class Ball(pygame.sprite.Sprite):
    def __init__(self, startpos, velocity, startdir):
        super().__init__()
        self.pos = pygame.math.Vector2(startpos)
        self.velocity = velocity
        self.dir = pygame.math.Vector2(startdir).normalize()
        self.image = pygame.image.load("ball.png").convert_alpha()
        self.rect = self.image.get_rect(center = (round(self.pos.x), round(self.pos.y)))
    def reflect(self, NV):
        self.dir = self.dir.reflect(pygame.math.Vector2(NV))
    def update(self):
        self.pos += self.dir * self.velocity
        self.rect.center = round(self.pos.x), round(self.pos.y)
pygame.init()
window = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
all_groups = pygame.sprite.Group()
start, velocity, direction = (250, 250), 5, (random.random(), random.random())
ball = Ball(start, velocity, direction)
all_groups.add(ball)
run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
    all_groups.update()
    if ball.rect.left <= 100:
        ball.reflect((1, 0))
    if ball.rect.right >= 400:
        ball.reflect((-1, 0))
    if ball.rect.top <= 100:
        ball.reflect((0, 1))
    if ball.rect.bottom >= 400:
        ball.reflect((0, -1))
    window.fill(0)
    pygame.draw.rect(window, (255, 0, 0), (100, 100, 300, 300), 1)
    all_groups.draw(window)
    pygame.display.flip()

Lets assume you have a group of blocks:

block_group = pygame.sprite.Group()

Detect the collision of the ball and the block_group. Once a collision (pygame.sprite.spritecollide()) is detected, reflect the ball on the block:

block_hit = pygame.sprite.spritecollide(ball, block_group, False)
if block_hit:
    bl = block_hit[0].rect.left  - ball.rect.width/4
    br = block_hit[0].rect.right + ball.rect.width/4
    nv = (0, 1) if bl < ball.rect.centerx < br else (1, 0)
    ball.reflect(nv)
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.