【问题标题】:How to delete a single pygame drawing from the screen?如何从屏幕上删除单个 pygame 绘图?
【发布时间】:2020-09-21 03:35:43
【问题描述】:

当大圆圈接触小圆圈时,我希望它接触的小圆圈从屏幕上消失。但是,我无法弄清楚你是如何在 pygame 中删除单个绘图的。我该如何解决这个问题? pygame 有内置这个功能吗?

from pygame import *
import random as rd
import math as m

init()
screen = display.set_mode((800, 600))

p_1_x = 200
p_1_y = 200
p_1_change_x = 0
p_1_change_y = 0

def p_1(x, y):
    player_1 = draw.circle(screen, (0, 0, 0), (x, y), 15)

def pick_up(x, y, xx, yy):
    distance = m.sqrt(m.pow(xx - x, 2) + m.pow(yy - y, 2))
    if distance < 19:
        # I think the code to delete should go here
        pass

dots = []
locations = []

for i in range(5):
    x = rd.randint(100, 700)
    y = rd.randint(100, 500)
    locations.append((x, y))

while True:
    screen.fill((255, 255, 255))
    for events in event.get():
        if events.type == QUIT:
            quit()
        if events.type == KEYDOWN:
            if events.key == K_RIGHT:
                p_1_change_x = 1
            if events.key == K_LEFT:
                p_1_change_x = -1
            if events.key == K_UP:
                p_1_change_y += 1
            if events.key == K_DOWN:
                p_1_change_y -= 1

        if events.type == KEYUP:
            if events.key == K_RIGHT or K_LEFT or K_UP or K_DOWN:
                p_1_change_x = 0
                p_1_change_y = 0

    p_1_x += p_1_change_x
    p_1_y -= p_1_change_y
    for i, locate in enumerate(locations):
        dot = draw.circle(screen, (0, 0, 0), locate, 5)
        dots.append(dot)
        for l in enumerate(locate):
            pick_up(p_1_x, p_1_y, locate[0], locate[1])

    p_1(p_1_x, p_1_y)
    display.update()

【问题讨论】:

    标签: python pygame draw


    【解决方案1】:

    您的代码非常混乱且难以维护,首先我为 Balls & Dots 创建了 2 个类。 我通过pygame.Rect.colliderect 检测到碰撞,首先我制作了 2 个矩形,然后我像这样检查碰撞:

    def pick_up(ball, dot):
        ball_rect = Rect( ball.x - ball.SIZE , ball.y - ball.SIZE , ball.SIZE*2, ball.SIZE*2)
        dot_rect = Rect( dot.x - dot.SIZE , dot.y - dot.SIZE , dot.SIZE*2, dot.SIZE*2)
        if ball_rect.colliderect(dot_rect): 
            return True
        return False
    

    如果检测到碰撞,我将其从 while 循环中的点数组中删除:

    for dot in dots:
        if pick_up(ball, dot): # if dot in range ball
                dots.remove(dot)
        dot.draw()
    

    这是完整的来源:

    from pygame import *
    import random as rd
    
    SCREEN_WIDTH = 800
    SCREEN_HEIGHT = 600
    NUMBER_OF_DOTS = 5
    
    class Ball():
        SIZE = 15
        def __init__(self, x, y):
            self.x = x
            self.y = y
            
        def draw(self):
            draw.circle(screen, (0, 0, 0), (self.x, self.y), Ball.SIZE)
        def move(self, vx, vy):
            self.x += vx
            self.y += vy
    
    class Dot():
        SIZE = 5    
        def __init__(self, x, y):
            self.x = x
            self.y = y
            
        def draw(self):
            draw.circle(screen, (0, 0, 0), (self.x, self.y), Dot.SIZE)
    
    
    def pick_up(ball, dot):
        ball_rect = Rect( ball.x - ball.SIZE , ball.y - ball.SIZE , ball.SIZE*2, ball.SIZE*2)
        dot_rect = Rect( dot.x - dot.SIZE , dot.y - dot.SIZE , dot.SIZE*2, dot.SIZE*2)
        if ball_rect.colliderect(dot_rect): 
            return True
        return False
    
    
    
    init()
    screen = display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    
    dots = []
    ball = Ball(200,200)
    
    # generate dots
    for i in range(NUMBER_OF_DOTS):
        x = rd.randint(100, 700)
        y = rd.randint(100, 500)
        dots.append(Dot(x,y))
    
    # the main game loop
    while True:
        screen.fill((255, 255, 255))
        keys=key.get_pressed()
    
        for events in event.get():
            keys=key.get_pressed()
            if events.type == QUIT:
                quit()
    
        if keys[K_RIGHT]:
            ball.move(+1,0)
        if keys[K_LEFT]:
            ball.move(-1,0)
        if keys[K_UP]:
            ball.move(0,-1)
        if keys[K_DOWN]:
            ball.move(0,+1)
    
        for dot in dots:
            dot.draw()
            
            if pick_up(ball, dot):
                    dots.remove(dot)
    
        ball.draw()
        display.update()
        time.delay(1) # Speed down
    

    更新1:

    PyGame 矩形碰撞 http://www.pygame.org/docs/ref/rect.html#pygame.Rect.colliderect

    更新2:

    我在 github 上做了一个 repo 并做了一些更改,
    点是彩色的,新点的颜色随机,每次吃点球都会变大。

    https://github.com/peymanmajidi/Ball-And-Dots-Game__Pygame

    【讨论】:

      【解决方案2】:

      代码应该将它从locations 列表中删除,这样以后就不会重新绘制它。您每帧清除屏幕,因此清除+不重绘是“删除”。

      假设您修改了pick_up() 以简单地返回 True 或 False:

      def pick_up(x, y, xx, yy):
          result = False
          distance = m.sqrt(m.pow(xx - x, 2) + m.pow(yy - y, 2))
          if distance < 19:
              result = True              # It was picked
          return result
      

      然后,当您遍历 locations 列表绘图并检查是否被选中时,保存选中圆圈的索引,然后在第二步中将它们从 locations 中删除。使用两步表单意味着您不必担心在迭代时从列表中删除项目时意外跳过项目。

      p_1_x += p_1_change_x
      p_1_y -= p_1_change_y
      picked_up = []                           # empty list to hold "picked" items
      for i, locate in enumerate(locations):
          dot = draw.circle(screen, (0, 0, 0), locate, 5)
          dots.append(dot)
          for l in enumerate(locate):
              if ( pick_up(p_1_x, p_1_y, locate[0], locate[1]) ):
                  picked_up.append( i )        # save the index of anything "picked"
      
      # remove any picked-up circles from the list
      for index in sorted( picked_up, reverse=True ):   # start with the highest index first
          print( "Removing circle from location[%d]" % ( index ) )  # DEBUG
          del( locations[ index ] )
      

      【讨论】:

      • 为什么有时会说索引超出范围?
      • @mr.bug - 啊,也许sorted() 没有像我想象的那样工作?它应该首先删除最大的元素,因此它们会从列表的“远端”中删除。啊,或者它可能在列表末尾出现多次碰撞?您可以添加 print() 以查看被删除内容的索引。
      猜你喜欢
      • 1970-01-01
      • 2021-12-12
      • 2012-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多