在 pygame 中使用 vector2.与窗框碰撞,将球限制在矩形区域内 [英] Use vector2 in pygame. Collide with the window frame and restrict the ball to the rectangular area

查看:14
本文介绍了在 pygame 中使用 vector2.与窗框碰撞,将球限制在矩形区域内的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嘿,我正在尝试使用 pygame 创建一个突破性克隆,我使用了

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

为了弹起桨的球,但是我正在研究矢量 2 类,但我不知道如何使用它来转换我的 Ball 类.如果有人能指导我朝着正确的方向前进.

这是我想使用 vector2 转换的代码.

导入pygame导入数学类球(pygame.sprite.Sprite):课程 = 130def __init__(self):# 调用父类(Sprite)pygame.sprite.Sprite.__init__(self)# 创建球并加载球图像self.image = pygame.image.load("ball.png").convert()self.rect = self.image.get_rect()self.rect.x = 0self.rect.y = 270# 创建一个弹跳函数,使球在表面上弹跳.def反弹(自我,差异):self.course = (180 - self.course) % 360self.course -= 差异# 创建将更新球的函数.定义更新(自我):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.xself.rect.y = self.rect.y# 检查球是否越过顶部如果 self.rect.y <= 0:self.bounce(0)self.rect.y = 1# 检查球是否越过左侧如果 self.rect.x <= 0:self.course = (360 - self.course) % 360self.rect.x = 1# 检查球是否经过右侧如果 self.rect.x >= 800:self.course = (360 - self.course) % 360self.rect.x = 800 - 1如果 self.rect.y >600:返回真别的:返回错误

解决方案

一个向量定义了一个方向和一个数量.您必须将向量添加到球的位置.遗憾的是,pygame.Rect 仅存储整数,因此对象的位置必须存储在

导入pygame随机导入类球(pygame.sprite.Sprite):def __init__(self、startpos、velocity、startdir):super().__init__()self.pos = pygame.math.Vector2(startpos)self.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)))定义反射(自我,NV):self.dir = self.dir.reflect(pygame.math.Vector2(NV))定义更新(自我):self.pos += self.dir * self.velocityself.rect.center = round(self.pos.x), round(self.pos.y)pygame.init()窗口 = pygame.display.set_mode((500, 500))时钟 = pygame.time.Clock()all_groups = pygame.sprite.Group()开始,速度,方向 = (250, 250), 5, (random.random(), random.random())球=球(开始,速度,方向)all_groups.add(球)运行 = 真运行时:时钟滴答(60)对于 pygame.event.get() 中的事件:如果 event.type == pygame.QUIT:运行 = 错误all_groups.update()如果 ball.rect.left <= 100:ball.reflect((1, 0))如果 ball.rect.right >= 400:ball.reflect((-1, 0))如果 ball.rect.top <= 100:ball.reflect((0, 1))如果 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(窗口)pygame.display.flip()


假设您有一组块:

block_group = pygame.sprite.Group()

检测ballblock_group 的碰撞.一旦发生碰撞(pygame.sprite.spritecollide()) 被检测到,反射块上的球:

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

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

解决方案

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:

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)

这篇关于在 pygame 中使用 vector2.与窗框碰撞,将球限制在矩形区域内的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆