python - 如何在pygame中检查我的类的所有实例之间的冲突?
问题描述
我目前正在尝试在发生碰撞时在屏幕上打印,但不知道如何仅针对 1 个班级进行打印。我知道如何让 2 个对象从不同的类中碰撞,但我不知道如何为一个有 1000 个不同对象的类做到这一点
我尝试在游戏中使用一些 pygame 函数,例如 pygame.rect.contain,但我不知道从那里去哪里。谢谢你们帮助我。
代码如下:
import pygame
import random
import sys
import time
Height = 800
Width = 800
Steps = 0
running = True
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
pygame.init()
display = pygame.display.set_mode((Height, Width))
clock = pygame.time.Clock()
pygame.display.set_caption("Game")
class Ball(object):
def __init__(self, x, y, delta_x, delta_y):
self.x = x
self.y = y
self.delta_x = delta_x
self.delta_y = delta_y
def draw(self):
pygame.draw.rect(display, WHITE, (self.x, self.y, 1, 1))
def update(self):
self.x += self.delta_x
self.y += self.delta_y
if self.x < 0:
self.delta_x = self.delta_x * -1
if self.x > Width - 5:
self.delta_x = self.delta_x * -1
if self.y < 0:
self.delta_y = self.delta_y * -1
if self.y > Height - 5:
self.delta_y = self.delta_y * -1
list = []
for i in range(1000):
ball = Ball(random.randrange(0, Width - 5), random.randrange(0, Height - 5),
random.randint(-10, 10), random.randint(-10, 10))
list.append(ball)
while running:
display.fill(BLACK)
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
# Update
# Draw
for ball in list:
ball.draw()
ball.update()
pygame.display.update()
pygame.display.update()
print(clock.tick(60))
解决方案
如果要找到相等的点,则必须比较点的 x 和 y 坐标。
例如
for i in range(len(list)):
eq_list = [j for j in range(len(list)) if i != j and list[i].x == list[j].x and list[i].y == list[j].y]
例如,您可以为这种方法在 read 中绘制碰撞点:
class Ball(object):
# [...]
def draw(self, color):
pygame.draw.rect(display, color, (self.x, self.y, 1, 1))
for i in range(len(list)):
ball = list[i]
collide = any([j for j in range(len(list)) if i != j and list[i].x == list[j].x and list[i].y == list[j].y])
ball.draw(RED if collide else WHITE)
ball.update()
请注意,这种方法对于 1000 点和 1000*1000 碰撞测试会很慢。
更好的解决方案是使用 1000x1000 字段并在字段中设置状态(如果对象在其上)。如果设置了字段中的状态,这会将碰撞测试减少到一些测试。
创建一个具有布尔状态的字段:
obj_grid = [[False for i in range(Height)] for j in range(Width)]
获取对象的位置列表并在字段中设置相应的状态。将字段传递给Ball.update
方法。更新和绘制后,必须清除该字段,因为位置已更改。为此使用位置列表,因为这比“清除”整个字段要快得多。我添加了一些绑定检查,因为您的某些对象似乎超出了范围(可能这个错误也必须修复)。
# collect the postions of the items
poslist = [(ball.x, ball.y) for ball in list]
# set the positions in the field
for pos in poslist:
if pos[0] < Width and pos[1] < Height:
obj_grid[pos[0]][pos[1]] = True
# update and draw
for ball in list:
ball.update(obj_grid)
ball.draw()
# set the positions in the field
for pos in poslist:
if pos[0] < Width and pos[1] < Height:
obj_grid[pos[0]][pos[1]] = False
在该Ball.update
方法中,必须测试路径的未决路径上的位置。如果声明了任何字段,则对象会发生碰撞。我将状态存储在一个属性self.collide
中。如果设置了状态,则对象被放大并涂成红色,以可视化碰撞。当然你也可以做一些别的事情,比如改变方向:
class Ball(object):
def __init__(self, x, y, delta_x, delta_y):
self.x = x
self.y = y
self.delta_x = delta_x
self.delta_y = delta_y
self.collide = False
def draw(self):
color, size = (RED, 5) if self.collide else (WHITE, 1)
pygame.draw.rect(display, color, (self.x, self.y, size, size))
def update(self, obj_grid):
# check if the object is colliding on his way
pos = [self.x, self.y]
new_pos = [self.x + self.delta_x, self.y + self.delta_y]
self.collide = False
while not self.collide and pos != new_pos:
if abs(pos[0]-new_pos[0]) > abs(pos[1]-new_pos[1]):
pos[0] += 1 if self.delta_x > 0 else -1
else:
pos[1] += 1 if self.delta_y > 0 else -1
self.collide = pos[0] < Width and pos[1] < Height and obj_grid[pos[0]][pos[1]]
self.x += self.delta_x
self.y += self.delta_y
if self.x < 0:
self.delta_x = self.delta_x * -1
if self.x > Width - 5:
self.delta_x = self.delta_x * -1
if self.y < 0:
self.delta_y = self.delta_y * -1
if self.y > Height - 5:
self.delta_y = self.delta_y * -1
推荐阅读
- javascript - 选中/取消选中基于返回 Y(true/checked) 反应 js 的数据(钩子)的材料 ui 复选框的值
- python - Word processing text with python or macro word
- postgresql - 在 Excel/PowerQuery 中使用 psqlodbc 的性能问题
- r - 检查点坐标是否在多边形内
- laravel - Laravel 或 Nova 在更新事件和更新事件时具有相同的模型属性
- asp.net-core - 在 .NET Core 运行时创建和使用数据库
- sql-server - 将 SQL Server 中的日期与可能的空值进行比较的优雅方法
- javascript - 使用 Jquery 显示数组对象
- sql - Oracle 组和数据透视 - Oracle 中的动态数据透视
- javascript - 为什么 Youtube 和许多其他视频页面会在页面加载时播放?