Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Pygame教程-带碰撞检测的坦克_Python_Pygame - Fatal编程技术网

Python Pygame教程-带碰撞检测的坦克

Python Pygame教程-带碰撞检测的坦克,python,pygame,Python,Pygame,我是Pygame的新手,正在努力学习精灵和碰撞检测。我找到了一些代码,并尝试向其中添加一些功能 基本的想法是,我有一个多边形,可以旋转到位。当用户按下空格键时,多边形会发射一个可以围绕帧反弹的投射物。如果弹丸再次击中多边形,我想修改程序 首先,这里是代码 import pygame class Player(pygame.sprite.Sprite): def __init__(self): super().__init__() self.image =

我是Pygame的新手,正在努力学习精灵和碰撞检测。我找到了一些代码,并尝试向其中添加一些功能

基本的想法是,我有一个多边形,可以旋转到位。当用户按下空格键时,多边形会发射一个可以围绕帧反弹的投射物。如果弹丸再次击中多边形,我想修改程序

首先,这里是代码

import pygame

class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((32, 32))
        self.image.fill((0, 0, 0))
        self.image.set_colorkey((0, 0, 0))
        self.fire_from = (36, 20)
        pygame.draw.polygon(self.image, pygame.Color('dodgerblue'), ((0, 0), (32, 16), (0, 32)))
        self.org_image = self.image.copy()
        self.angle = 0
        self.direction = pygame.Vector2(1, 0)
        self.rect = self.image.get_rect(center=(200, 200))
        self.pos = pygame.Vector2(self.rect.center)

    def update(self, events, dt):

        for e in events:
            if e.type == pygame.KEYDOWN:
                if e.key == pygame.K_SPACE:
                    bullet = Projectile(self.fire_from, self.direction.normalize())
                    self.groups()[0].add(bullet)
        pressed = pygame.key.get_pressed()

        if pressed[pygame.K_LEFT]:
            self.angle += 3
        if pressed[pygame.K_RIGHT]:
            self.angle -= 3

        self.direction = pygame.Vector2(1, 0).rotate(-self.angle)
        self.image = pygame.transform.rotate(self.org_image, self.angle)
        self.rect = self.image.get_rect(center=self.rect.center)

class Projectile(pygame.sprite.Sprite):
    def __init__(self, pos, direction):
        super().__init__()
        self.image = pygame.Surface((8, 8))
        self.image.fill((0, 0, 0))
        self.image.set_colorkey((0, 0, 0))
        pygame.draw.circle(self.image, pygame.Color('orange'), (4, 4), 4)
        self.rect = self.image.get_rect(center=pos)
        self.direction = direction
        self.pos = pygame.Vector2(self.rect.center)
        self.max_bounce = 10

    def update(self, events, dt):

        #print(self.pos)
        # Bounding box of the screen
        screen_r = pygame.display.get_surface().get_rect()

        # where we would move next
        next_pos = self.pos + self.direction * dt

        # we hit a wall
        if not screen_r.contains(self.rect):

            # after 10 hits, destroy self
            self.max_bounce -= 1
            if self.max_bounce == 0:
                return self.kill()

            # horizontal reflection
            if next_pos.x > screen_r.right or next_pos.x < screen_r.left:
                self.direction.x *= -1

            # vertical reflection
            if next_pos.y > screen_r.bottom or next_pos.y < screen_r.top:
                self.direction.y *= -1

            # move after applying reflection
            next_pos = self.pos + self.direction * dt

        # set the new position
        self.pos = next_pos
        self.rect.center = self.pos

def main():
    pygame.init()
    screen = pygame.display.set_mode((500, 500))
    tank = Player()
    sprites = pygame.sprite.Group()
    sprites.add(tank)
    #print(tank.groups()[0])
    clock = pygame.time.Clock()
    dt = 0
    running = True
    while running:
        #print(tank.groups()[0])
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return
        sprites.update(events, dt)
        screen.fill((30, 30, 30))
        sprites.draw(screen)
        pygame.display.update()

        ## ALWAYS DETECTS A COLLISION, WHY?
        if len(tank.groups()[0])>1:
            if pygame.sprite.spritecollideany(tank, tank.groups()[0]):
                running = False

        dt = clock.tick(60)

if __name__ == '__main__':
    main()
导入pygame
职业玩家(pygame.sprite.sprite):
定义初始化(自):
super()。\uuuu init\uuuuu()
self.image=pygame.Surface((32,32))
self.image.fill((0,0,0))
self.image.set_colorkey((0,0,0))
self.fire_from=(36,20)
pygame.draw.polygon(self.image,pygame.Color('dodgerblue'),((0,0)、(32,16)、(0,32)))
self.org_image=self.image.copy()
自转角=0
self.direction=pygame.Vector2(1,0)
self.rect=self.image.get_rect(中心=(200200))
self.pos=pygame.Vector2(self.rect.center)
def更新(自身、事件、dt):
对于事件中的e:
如果e.type==pygame.KEYDOWN:
如果e.key==pygame.K_空间:
子弹=射弹(self.fire\u from,self.direction.normalize())
self.groups()[0]。添加(项目符号)
pressed=pygame.key.get_pressed()
如果按下[pygame.K_LEFT]:
自转角+=3
如果按下[pygame.K_RIGHT]:
自转角-=3
self.direction=pygame.Vector2(1,0)。旋转(-self.angle)
self.image=pygame.transform.rotate(self.org\u image,self.angle)
self.rect=self.image.get_rect(中心=self.rect.center)
类射弹(pygame.sprite.sprite):
定义初始(自身、位置、方向):
super()。\uuuu init\uuuuu()
self.image=pygame.Surface((8,8))
self.image.fill((0,0,0))
self.image.set_colorkey((0,0,0))
pygame.draw.circle(self.image,pygame.Color('orange'),(4,4),4)
self.rect=self.image.get_rect(中心=pos)
方向
self.pos=pygame.Vector2(self.rect.center)
self.max_反弹=10
def更新(自身、事件、dt):
#打印(self.pos)
#屏幕边框
screen_r=pygame.display.get_surface().get_rect()
#我们下一步要去哪里
下一个位置=self.pos+self.direction*dt
#我们碰壁了
如果屏幕不包含(self.rect):
#10次命中后,摧毁自我
self.max_反弹-=1
如果self.max_bounce==0:
返回self.kill()
#水平反射
如果下一个位置x>右屏幕或下一个位置x<左屏幕:
self.direction.x*=-1
#垂直反射
如果下一个位置y>屏幕底部或下一个位置y<屏幕顶部:
自我方向y*=-1
#应用反射后移动
下一个位置=self.pos+self.direction*dt
#设置新位置
self.pos=下一个位置
self.rect.center=self.pos
def main():
pygame.init()
screen=pygame.display.set_模式((500500))
坦克=玩家()
sprites=pygame.sprite.Group()
雪碧。添加(水箱)
#打印(储罐组()[0])
clock=pygame.time.clock()
dt=0
运行=真
运行时:
#打印(储罐组()[0])
events=pygame.event.get()
对于事件中的e:
如果e.type==pygame.QUIT:
返回
sprites.update(事件,dt)
屏幕填充((30,30,30))
精灵。绘制(屏幕)
pygame.display.update()
##总是检测到碰撞,为什么?
如果len(储罐组()[0])>1:
如果pygame.sprite.spriteany(tank,tank.groups()[0]):
运行=错误
dt=时钟滴答声(60)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
main()
我在这里收集到,玩家类(即我的坦克)本身有一个精灵组,它将每一个发射物作为发射物添加到该组中。此外,投射物起源于多边形的矩形内(因此最初总是碰撞)

我只想将投射物添加到精灵组,如果它至少有1次反弹,这是可能的吗?或有更好的方法吗

有什么帮助或指点吗

谢谢
Null

由于是
tank.groups()[0]
的成员,
tank
与其自身发生冲突:

如果pygame.sprite.spritecany(坦克,坦克.groups()[0]):
添加仅包含项目符号的组:

职业玩家(pygame.sprite.sprite):
定义初始化(自):
# [...]
self.bullets=pygame.sprite.Group()
def更新(自身、事件、dt):
对于事件中的e:
如果e.type==pygame.KEYDOWN:
如果e.key==pygame.K_空间:
子弹=射弹(self.fire\u from,self.direction.normalize())
self.groups()[0]。添加(项目符号)
self.bullets.add(bullet)
# [...]
将此组用于碰撞测试:

def main():
# [...]
运行时:
# [...]
pygame.display.update()
如果pygame.sprite.spriteany(坦克、坦克、子弹):
运行=错误
dt=时钟滴答声(60)

非常感谢您,我之前一直在尝试这样做,但始终混淆了不同的精灵组!但这是有道理的,玩家类拥有自己的一组精灵(即发射的子弹)。但问题是,为什么我们在玩家类中需要两个精灵组?@NullPointer你不需要它们。但是你想用一次调用来绘制所有精灵(
sprites.draw(screen)
)。好的,很有意义,谢谢拉比,我想我已经掌握了这个窍门,非常感谢!