问题遇到的现象和发生背景
运行程序时,有时飞机与敌机子弹碰撞会爆炸,有时不会,我无法理解这种问题可能的发生原因
问题相关代码,请勿粘贴截图
import time
import random
import pygame
from pygame.constants import *
#飞机类
class HeroPlane(pygame.sprite.Sprite):
#存放所有子弹的组
bullets=pygame.sprite.Group()
def init(self,screen):
#精灵初始化
pygame.sprite.Sprite.init(self)
#2创建一个图片,玩家飞机
self.player=pygame.image.load("C:\Users\L\source\repos\PythonApplication5\PythonApplication5\feijidazhan\feiji\hero1.png")
#根据图片image获取矩形对象
self.rect=self.player.get_rect()
self.rect.topleft=[0,350]#调用左上角坐标
#飞机速度
self.speed=8
self.screen=screen
#装子弹的列表
self.bullets=pygame.sprite.Group()
#控制按键监听
def key_control(self):
key_pressed=pygame.key.get_pressed()
if self.rect.top>0:
if key_pressed[K_w] or key_pressed[K_UP]:
self.rect.top-=self.speed
if self.rect.bottom<731:
if key_pressed[K_s] or key_pressed[K_DOWN]:
self.rect.bottom+=self.speed
if self.rect.left>0:
if key_pressed[K_a] or key_pressed[K_LEFT]:
self.rect.left-=self.speed
if self.rect.right<1300:
if key_pressed[K_d] or key_pressed[K_RIGHT]:
self.rect.right+=self.speed
if Manager.attackspeed==3 and Manager.bulletnumber!=0:
if key_pressed[K_SPACE]:
#按下空格发射子弹
bullet=Bullet(self.screen,self.rect.right,self.rect.top)
#把子弹放到列表里
self.bullets.add(bullet)
#存放所有飞机子弹的组
HeroPlane.bullets.add(bullet)
Manager.bulletnumber-=1
def update(self):
self.key_control()
self.display()
def display(self):
#将飞机图片贴到窗口中
self.screen.blit(self.player,self.rect)
#更新子弹坐标
self.bullets.update()
#把所有子弹添加到屏幕
self.bullets.draw(self.screen)
#敌机类
class EnemyPlane(pygame.sprite.Sprite):
#敌方子弹
enemy_bullets=pygame.sprite.Group()
def init(self,screen):
#精灵初始化
pygame.sprite.Sprite.init(self)
#2创建一个图片,玩家飞机
self.player=pygame.image.load("C:\Users\L\source\repos\PythonApplication5\PythonApplication5\feijidazhan\feiji\enemy0.png")
#根据图片image获取矩形对象
self.rect=self.player.get_rect()
y=random.randrange(1,Manager.bg_size[1],50)
self.rect.topleft=[1200,y]#调用左上角坐标
#飞机速度
self.speed=4
self.screen=screen
#装子弹的列表
self.bullets=pygame.sprite.Group()
#敌机移动方向
self.direction='bottom'
def display(self):
#3将飞机贴到窗口中
self.screen.blit(self.player,self.rect)
#更新子弹坐标
self.bullets.update()
#把所有子弹添加到屏幕
self.bullets.draw(self.screen)
def update(self):
self.auto_move()
self.auto_fire()
self.display()
def auto_move(self):
if self.direction=='bottom':
self.rect.bottom+=self.speed
elif self.direction=='top':
self.rect.bottom-=self.speed
if self.rect.bottom>730:
self.direction='top'
elif self.rect.top<0:
self.direction='bottom'
self.rect.left-=self.speed-3
def auto_fire(self):
#自动开火 创建列表对象 添加进列表
random_num=random.randint(1,15)
if random_num==8:
bullet=EnemyBullet(self.screen,self.rect.left,self.rect.top)
self.bullets.add(bullet)
#把子弹添加到类属性的子弹组里
EnemyPlane.enemy_bullets.add(bullet)
#子弹类
#属性
class Bullet(pygame.sprite.Sprite):
def init(self,screen,x,y):
#精灵类初始化
pygame.sprite.Sprite.init(self)
#创建图片
self.image=pygame.image.load("C:\Users\L\source\repos\PythonApplication5\PythonApplication5\feijidazhan\feiji\bullet.png")
#获取矩形对象
self.rect=self.image.get_rect()
self.rect.topleft=[x,y-15]
#窗口
self.screen=screen
#速度
self.speed=10
def update(self):
#修改子弹坐标
self.rect.left+=self.speed
#如果子弹已出屏幕上方,销毁子弹
if self.rect.left>1300:
self.kill()
#敌人子弹类
#属性
class EnemyBullet(pygame.sprite.Sprite):
def __init__(self,screen,x,y):
#精灵类初始化
pygame.sprite.Sprite.__init__(self)
#创建图片
self.image=pygame.image.load("C:\\Users\\L\\source\\repos\\PythonApplication5\\PythonApplication5\\feijidazhan\\feiji\\bullet1.png")
#获取矩形对象
self.rect=self.image.get_rect()
self.rect.topleft=[x+30-8,y+89-10]
#窗口
self.screen=screen
#速度
self.speed=5
def update(self):
#修改子弹坐标
self.rect.left-=self.speed
#如果子弹已出屏幕上方,销毁子弹
if self.rect.right<0:
self.kill()
class GameSound(object):
def init(self):
pygame.mixer.init()
pygame.mixer.music.load("C:\Users\L\source\repos\PythonApplication5\PythonApplication5\feijidazhan\feiji\HOYO-MiX - The Fool.flac")
pygame.mixer.music.set_volume(0.5)
def playBackgroundMusic(self):
pygame.mixer.music.play(-1)
class Bomb(object):
#初始化碰撞
def init(self,screen,type):#type只有我方和敌人
self.screen=screen
if type=="enemy":
#加载爆炸资源
self.mImages=[pygame.image.load("C:\Users\L\source\repos\PythonApplication5\PythonApplication5\feijidazhan\feiji\enemy"+str(v)+".png")for v in range(0,4)]
else:
self.mImages=[pygame.image.load("C:\Users\L\source\repos\PythonApplication5\PythonApplication5\feijidazhan\feiji\hero"+str(v)+".png")for v in range(1,3)]
#设置爆炸播放索引
self.mIndex=0#作为下标,上面导入的图片命名都是从0开始的
#爆炸位置
self.mPos=[0,0]
#爆炸开关
self.mVisible=False
def action(self,rect):
#触发爆炸方法
#爆炸的坐标
self.mPos[0]=rect.left#精灵的位置
self.mPos[1]=rect.top
#打开爆炸的开关
self.mVisible=True
def draw(self):
if not self.mVisible:
return
self.screen.blit(self.mImages[self.mIndex],(self.mPos[0],self.mPos[1]))#贴入名称和位置
self.mIndex += 1#输入下一张图片直到达到range
if self.mIndex >=len(self.mImages):#判断是否达到了range设定的最大值,如果达到,传递false
self.mIndex=0
self.mVisible=False
class GameBackground(object):
#初始化地图
def init(self,screen):
self.mImage1=pygame.image.load("C:\Users\L\source\repos\PythonApplication5\PythonApplication5\feijidazhan\feiji\background.png")
self.mImage2=pygame.image.load("C:\Users\L\source\repos\PythonApplication5\PythonApplication5\feijidazhan\feiji\background.png")
#窗口
self.screen=screen
#辅助移动地图
self.x1=0
self.x2=Manager.bg_size[0]
#绘制地图
def draw(self):
self.screen.blit(self.mImage1,(self.x1,0))
self.screen.blit(self.mImage2,(self.x2,0))
#移动地图
def move(self):
self.x1-=1
self.x2-=1
if self.x1<=-Manager.bg_size[0]:
self.x1=0
if self.x2<=0:
self.x2=Manager.bg_size[0]
class Manager(object):
bg_size=(1300,731)
#创建敌机定时器的id
create_enemy_id=10
#游戏结束,倒计时的id
game_over_id=11
#游戏是否结束
is_game_over=False
#倒计时时间
over_time=3
#距离月球初始距离
distance=363000
#计算距离月球的id
fly_tomoon_id=39
#攻击速度
attackspeed=8
#攻击速度id
attack_id=15
#弹药
bulletnumber=30
#弹药id
bullet_id=30
#缓时
i=1
def init(self):
pygame.init()
#创建窗口
self.screen=pygame.display.set_mode([1300,731])
#创建背景图片
#self.background=pygame.image.load("C:\Users\L\source\repos\PythonApplication5\PythonApplication5\feijidazhan\feiji\background.png")
self.map=GameBackground(self.screen)
#初始化一个装玩家精灵的group
self.players=pygame.sprite.Group()
#初始化一个装敌机精灵的group
self.enemys=pygame.sprite.Group()
#初始化一个玩家爆炸的对象
self.player_bomb=Bomb(self.screen,'player')
#初始化一个敌机爆炸的对象
self.enemy_bomb=Bomb(self.screen,'enemy')
#初始化一个声音播放的对象
self.sound=GameSound()
def exit(self):
pygame.quit()
exit()
def show_over_text(self):
#游戏结束,显示重新开始倒计时
self.drawText('gameover %d' % Manager.over_time,220,Manager.bg_size[1]/2-50,textHeight=50,fontColor=[255,0,0])
def show_Distance(self):
#在屏幕左上角显示距离月球的距离
self.drawText('DISTANCE TO THE MOON : %d' % Manager.distance,0,0)
def show_bulletnumber(self):
self.drawText('bullet number : %d' % Manager.bulletnumber,1100,700)
def attack_timer(self):
Manager.attackspeed-=1
if Manager.attackspeed==0:
Manager.attackspeed=8
def bullet_timer(self):
if Manager.bulletnumber==0:
if Manager.i!=80:
Manager.i+=1
elif Manager.i==80:
Manager.bulletnumber+=30
Manager.i=1
def distance_timer(self):
Manager.distance-=59
def game_over_timer(self):
self.show_over_text()
Manager.over_time-=1
if Manager.over_time==0:
pygame.time.set_timer(Manager.game_over_id,0)
Manager.over_time=3
Manager.is_game_over=False
self.start_game()
def start_game(self):
Manager.distance=363000
Manager.bulletnumber=30
EnemyPlane.enemy_bullets.remove(EnemyPlane.enemy_bullets)
manager=Manager()
manager.main()
def new_player(self):
player=HeroPlane(self.screen)
self.players.add(player)
def new_enemy(self):
enemy=EnemyPlane(self.screen)
self.enemys.add(enemy)
def drawText(self,text,x,y,textHeight=20,fontColor=(0,255,0),backgroundColor=None):
#通过字体文件获取字体对象
font_obj=pygame.font.Font("C:\\Users\\L\\source\\repos\\PythonApplication5\\PythonApplication5\\feijidazhan\\feiji\\VINERITC.TTF",textHeight)
#配置要显示的文字
text_obj=font_obj.render(text,True,fontColor,backgroundColor)
#获取要显示的对象的rect
text_rect=text_obj.get_rect()
#设置显示对象的坐标
text_rect.topleft=(x,y)
#绘制字到指定区域
self.screen.blit(text_obj,text_rect)
def main(self):
self.sound.playBackgroundMusic()
#创建一个玩家
self.new_player()
#开启创建敌机的定时器
pygame.time.set_timer(Manager.create_enemy_id,1000)
self.new_enemy()
while True:
pygame.time.set_timer(Manager.fly_tomoon_id,1000)
self.distance_timer()
pygame.time.set_timer(Manager.attack_id,1000)
self.attack_timer()
pygame.time.set_timer(Manager.bullet_id,10000)
self.bullet_timer()
#移动地图
self.map.move()
#把地图贴在窗口上
self.map.draw()
#绘制文字
self.show_Distance()
self.show_bulletnumber()
#self.drawText('DISTANCE TO THE MOON',0,0)#200
if Manager.is_game_over:
self.show_over_text()
#遍历所有的事件
for event in pygame.event.get():
if event.type==QUIT:
self.exit()
elif event.type==Manager.create_enemy_id:
#创建新的敌机
self.new_enemy()
elif event.type==Manager.game_over_id:
self.game_over_timer()
#调用爆炸的对象
self.player_bomb.draw()
self.enemy_bomb.draw()
#玩家飞机和敌机子弹的判断
if self.players.sprites():
isover=pygame.sprite.spritecollide(self.players.sprites()[0],EnemyPlane.enemy_bullets,True)
if isover:
Manager.is_game_over=True#标志着游戏结束了
pygame.time.set_timer(Manager.game_over_id,1000)#开始游戏倒计时
self.player_bomb.action(self.players.sprites()[0].rect)
#把玩家飞机从精灵组移除
self.players.remove(self.players.sprites()[0])
HeroPlane.bullets.remove(HeroPlane.bullets)
#判断碰撞
iscollide=pygame.sprite.groupcollide(self.players,self.enemys,True,True)#调用group什么玩意判断是否碰撞
if iscollide:
Manager.is_game_over=True
pygame.time.set_timer(Manager.game_over_id,1000)
items=list(iscollide.items())[0]#转化为列表
print(items)
x=items[0]#提取列表
y=items[1][0]
#玩家爆炸图片
self.player_bomb.action(x.rect)#调用bomb输出图片
#敌机爆炸图片
self.enemy_bomb.action(y.rect)
#判断子弹和飞机的碰撞
is_enemy=pygame.sprite.groupcollide(HeroPlane.bullets,self.enemys,True,True)
if is_enemy:
items=list(is_enemy.items())[0]
y=items[1][0]
#敌机爆炸图片
self.enemy_bomb.action(y.rect)
EnemyPlane.enemy_bullets.remove(EnemyPlane.enemy_bullets)
#玩家飞机和子弹的显示
self.players.update()
#敌机和子弹的显示
self.enemys.update()
#刷新窗口的内容
pygame.display.update()
time.sleep(0.01)
if name=='main':
manager=Manager()
manager.main()