4 回答
TA贡献1803条经验 获得超3个赞
回答
每次球弹过边缘时,分数就会瞬间增加,每次球重生时分数都会回到 0。
分数在主循环中不断初始化。您必须在循环之前初始化分数:
def main():
# [...]
score_A = 0 # <--- INSERT
score_B = 0
while run:
# score_A = 0 <--- DELETE
# score_B = 0
TA贡献1934条经验 获得超2个赞
回答问题1:是的。肯定有很多更有效的方法来做事。没有必要为方向制造那么多变数。简单地说direction = [True, False],其中direction[0]代表not direction[0]x 轴的左,代表右。同样,direction[1]代表 y 轴。这也解决了您在开始时随机化方向的问题。您只需 direction = [random.randint(0, 1), random.randint(0, 1)]在 init 方法中执行即可随机化方向。同样的方式,也列出速度清单。self.speed = [0.5, random.uniform(0.1, 1)]。这样,左右方向的速度将始终相同,但 y 将根据所选的随机数而变化,因此存在适当的随机性,并且您也不必硬编码随机方向。这样,移动变得非常简单。
class Ball:
def __init__(self, x, y, color, size):
self.x = x
self.y = y
self.color = color
self.size = size
self.direction = [random.randint(0, 1), random.randint(0, 1)]
self.speed = [0.5, random.uniform(0.1, 1)]
def draw(self, display):
pygame.draw.rect(display, self.color, (self.x, self.y, self.size, self.size))
def move(self):
if self.direction[0]:
self.x += self.speed[0]
else:
self.x -= self.speed[0]
if self.direction[1]:
self.y += self.speed[0]
else:
self.y -= self.speed[0]
因为我们定义的方向方向是布尔值,所以改变状态也变得非常容易。如果球击中球拍,您可以简单地切换direction[0] = not direction[0]x 中的布尔值并为 y 选择一个新的随机数,而不是手动分配布尔值。
def switchDirection(self):
self.direction = not self.direction
self.speed[1] = random.uniform(0.1, 1)
move通过为 Paddle 类提供一个函数而不是在主循环中移动,Paddle 也可以稍微改进。这只是意味着您必须编写更少的代码。
def move(self, vel, up=pygame.K_UP, down=pygame.K_DOWN):
keys = pygame.key.get_perssed()
if keys[up]:
self.y -= vel
if keys[down]:
self.y += vel
对于碰撞,我建议使用pygame.Rect()andcolliderect因为它更强大并且可能也更有效。
例子:
import random
import pygame
WIN = pygame.display
D = WIN.set_mode((800, 500))
class Paddle:
def __init__(self, x, y, width, height, vel, color):
self.x = x
self.y = y
self.width = width
self.height = height
self.vel = vel
self.color = color
def move(self, vel, up=pygame.K_UP, down=pygame.K_DOWN):
keys = pygame.key.get_pressed()
if keys[up]:
self.y -= vel
if keys[down]:
self.y += vel
def draw(self, window):
pygame.draw.rect(window, self.color, (self.x, self.y, self.width, self.height), 0)
def getRect(self):
return pygame.Rect(self.x, self.y, self.width, self.height)
left_paddle = Paddle(20, 100, 10, 50, 5, (0, 0, 0))
right_paddle = Paddle(770, 350, 10, 50, 5, (0, 0, 0))
class Ball:
def __init__(self, x, y, color, size):
self.x = x
self.y = y
self.color = color
self.size = size
self.direction = [random.randint(0, 1), random.randint(0, 1)]
self.speed = [0.3, random.uniform(0.2, 0.2)]
def draw(self, window):
pygame.draw.rect(window, self.color, (self.x, self.y, self.size, self.size))
def switchDirection(self):
self.direction[0] = not self.direction[0]
self.direction[1] = not self.direction[1]
self.speed = [0.2, random.uniform(0.1, 0.5)]
def bounce(self):
self.direction[1] = not self.direction[1]
self.speed = [0.2, random.uniform(0.01, 0.2)]
def move(self):
if self.direction[0]:
self.x += self.speed[0]
else:
self.x -= self.speed[0]
if self.direction[1]:
self.y += self.speed[1]
else:
self.y -= self.speed[1]
def getRect(self):
return pygame.Rect(self.x, self.y, self.size, self.size)
def boundaries(self):
if ball.x <= 10:
self.switchDirection()
if ball.x + self.size >= 800:
self.switchDirection()
if ball.y + self.size >= 490:
self.bounce()
if ball.y <= 0:
self.bounce()
ball = Ball(400, 250, (255, 0, 0), 20)
while True:
pygame.event.get()
D.fill((255, 255, 255))
ball.draw(D)
ball.boundaries()
ball.move()
#print(ball.x, ball.y)
left_paddle.draw(D)
right_paddle.draw(D)
right_paddle.move(0.4)
left_paddle.move(0.4, down=pygame.K_s, up=pygame.K_w)
if left_paddle.getRect().colliderect(ball.getRect()):
ball.switchDirection()
if right_paddle.getRect().colliderect(ball.getRect()):
ball.switchDirection()
WIN.flip()
TA贡献1804条经验 获得超8个赞
我基本上对球在边缘弹跳时的每一种可能的运动进行了编码。我花了几个小时的时间来研究它,并且让它工作起来,我只是想知道是否有一种更有效的方法可以用我的代码产生类似的输出(因为我知道这应该是一个初学者项目)?
和
如何使球在随机方向上产生?在每轮开始(和重新开始)时?
您可以使用浮动坐标,而不是实现球的“每个”方向。这些变量通常称为 dx 和 dy。通过这种方式获得球的随机或反向方向很简单,只需使用 dx 和 dy 的随机或反向值即可。
你的球的更新应该如下所示:
def update(self. dt): self.x += self.dx * self.speed * time_elapsed self.y += self.dy * self.speed * time_elapsed # Time elasped is often called dt.
每次球弹过边缘时,分数就会瞬间增加,每次球重生时分数都会回到 0。
理想情况下,您应该有一个 GameState 对象,其中包含分数、生命和其他内容作为属性。
TA贡献1796条经验 获得超4个赞
关于如何减少所有球运动/碰撞代码并提高可重用性的一些值得思考的地方:
import pygame
class Ball:
def __init__(self, bounds, color):
from random import randint, choice
self.bounds = bounds
self.position = pygame.math.Vector2(
randint(self.bounds.left, self.bounds.left+self.bounds.width),
randint(self.bounds.top, self.bounds.top+self.bounds.height)
)
self.velocity = pygame.math.Vector2(choice((-1, 1)), choice((-1, 1)))
self.color = color
self.size = 8
def draw(self, window):
pygame.draw.rect(
window,
self.color,
(
self.position.x-self.size,
self.position.y-self.size,
self.size*2,
self.size*2
),
0
)
def update(self):
self.position.x += self.velocity.x
self.position.y += self.velocity.y
if not self.bounds.left+self.size < self.position.x < self.bounds.left+self.bounds.width-self.size:
self.velocity.x *= -1
if not self.bounds.top+self.size < self.position.y < self.bounds.top+self.bounds.height-self.size:
self.velocity.y *= -1
def main():
from random import randint
window_width, window_height = 800, 500
window = pygame.display.set_mode((window_width, window_height))
pygame.display.set_caption("Pong")
clock = pygame.time.Clock()
black = (0, 0, 0)
white = (255, 255, 255)
padding = 20
bounds = pygame.Rect(padding, padding, window_width-(padding*2), window_height-(padding*2))
ball = Ball(bounds, white)
def redraw_window():
window.fill(black)
pygame.draw.rect(
window,
white,
(
padding,
padding,
window_width-(padding*2),
window_height-(padding*2)
),
1
)
ball.draw(window)
pygame.display.update()
while True:
clock.tick(60)
ball.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
break
else:
redraw_window()
continue
break
pygame.quit()
return 0
if __name__ == "__main__":
import sys
sys.exit(main())
这不是一个完整的替代品,我只是重新实现了该类Ball。没有桨。本质上,在实例化一个球时,您传递一个pygame.Rect,它描述了允许球弹跳的边界。您还传递一个颜色元组。然后,球在边界内选择一个随机位置(该位置是 a pygame.math.Vector2,而不是存储x和y作为单独的实例变量)。球也有速度,它也是pygame.math.Vector2,因此您可以拥有独立的速度分量 - 一个用于x(水平速度),一个用于y(垂直速度)。球size的 简单地描述了球的尺寸。例如,如果size设置为8,则球将为 16x16 像素。
该类Ball还有一个update方法,每个游戏循环迭代都会调用该方法。它将球移动到速度决定的下一个位置,并检查球是否与边界碰撞。如果是,则反转相应的速度分量。
添加回答
举报