Crossin的编程教室

标题: 【Pygame 第10课】 命中目标 [打印本页]

作者: crossin先生    时间: 2013-9-3 20:37
标题: 【Pygame 第10课】 命中目标

现在,我们的“打飞机”游戏已经到了万事俱备只欠东风的阶段:有了子弹也有了敌机,但它们之间还没有办法擦出火花。这节课的内容就是让玩家可以真正的“打”飞机。


我们判断子弹命中飞机的依据很简单:就是子弹的位置在飞机图片的内部。这不需要很精确,因为在快速的游戏过程中,人眼也无法分辨细微的差别。来看下面这张示意图:

10show.jpg

按照我们的设定(为了简化,假设子弹的长宽忽略不计),当子弹的坐标(b.x, b.y)在飞机的图片范围,也就是(e.x, e.y)到(e.x+e.width, e.y+e.height)所围成的矩形当中时,就可以认定是命中了。也就是满足:

e.x < b.x < e.x+e.width

e.y < b.y < e.y+e.height


当命中后,要做两件事:把敌机重置;把子弹重置。(之后还可以加上得分)


在代码中的实现:

  1. def checkHit(enemy, bullet):
  2.         if (bullet.x > enemy.x and bullet.x < enemy.x + enemy.image.get_width()) and (bullet.y > enemy.y and bullet.y < enemy.y + enemy.image.get_height()):
  3.             enemy.restart()
  4.             bullet.active = False</font></font>
复制代码

我们把这段是否命中的检测代码写成一个函数checkHit(enemy, bullet),在主循环中,检测每一颗active的子弹是否命中任何一个enemy:

  1. for b in bullets:
  2.     if b.active:
  3.         for e in enemies:
  4.             checkHit(e, b)</font></font>
复制代码

运行代码,你就可以痛击敌机了,虽然效果还很突兀。


在游戏中,我们把这种判断两样物体是否有重合关系的处理称为“碰撞检测”。其实在pygame中,已经为我们实现好了更方便更高效的碰撞检测方法。这里自己手动实现一个简单的碰撞检测,可以对其原理有更好的认识。


10-1.jpg

10-2.jpg

#==== Crossin的编程教室 ====#
微信ID:crossincode
论坛:http://crossin.me
QQ群:156630350

面向零基础初学者的编程课
每天5分钟,轻松学编程

pcqr.jpg

10.py

2.37 KB, 下载次数: 383

第10课源码


作者: 匠逍之岿    时间: 2013-9-3 23:48
终于可以打飞机了!
作者: viking    时间: 2013-9-4 10:25
····打起来了
作者: Victor    时间: 2013-9-4 15:54
看看效果咋样
作者: liqing215    时间: 2013-9-4 20:59
<font color="rgb(62, 62, 62)"><font face="Helvetica,">  这个是干嘛吖? 设置哪儿的字体?
作者: crossin先生    时间: 2013-9-5 19:51
liqing215 发表于 2013-9-4 20:59
这个是干嘛吖? 设置哪儿的字体?

。。。
这个是发到论坛上时候,不知道怎么被混到代码格式里的。
之前没注意,现在已经改掉了
作者: liqing215    时间: 2013-9-5 21:08
crossin先生 发表于 2013-9-5 19:51
。。。
这个是发到论坛上时候,不知道怎么被混到代码格式里的。
之前没注意,现在已经改掉了 ...

嘿嘿~
作者: liu-pengfei    时间: 2014-9-20 21:56
终于打起来了。哈哈哈哈。
作者: 百分之三十    时间: 2016-1-13 15:36
请问:为什么把这里的checkHit函数放在class Bullet中,然后主循环里写b.checkHit时,编译报错:TypeError: checkHit() takes exactly 2 arguments (3 given)  ?
作者: crossin先生    时间: 2016-1-13 17:53
百分之三十 发表于 2016-1-13 15:36
请问:为什么把这里的checkHit函数放在class Bullet中,然后主循环里写b.checkHit时,编译报错:TypeError: ...

这个报错应该是你函数定义参数的时候没有加上self
作者: BDHELLO    时间: 2016-11-24 11:42
为什么我的程序运行起来出现鼠标不动画面不动的现象?
作者: crossin先生    时间: 2016-11-24 13:27
BDHELLO 发表于 2016-11-24 11:42
为什么我的程序运行起来出现鼠标不动画面不动的现象?

是不是你代码里的循环写的有问题。
对照例子代码看看,缩进什么的有没有搞错了
作者: BDHELLO    时间: 2016-11-25 14:35
crossin先生 发表于 2016-11-24 13:27
是不是你代码里的循环写的有问题。
对照例子代码看看,缩进什么的有没有搞错了 ...

检查出来了,是缩进的原因,谢谢!
作者: wwb951108    时间: 2017-3-10 17:18
老师为什么我屏幕里总是有一个飞机命中不了
作者: crossin先生    时间: 2017-3-11 15:24
wwb951108 发表于 2017-3-10 17:18
老师为什么我屏幕里总是有一个飞机命中不了

不知道……
查一查你碰撞检测那里的循环,是不是有个飞机不在循环列表里
作者: wwb951108    时间: 2017-3-15 19:07


  1. import pygame
  2. from sys import exit
  3. import random
  4. def hit(enemy,bullet):
  5.     if (bullet.x>enemy.x and bullet.x<enemy.x+enemy.image.get_width())and(bullet.y>enemy.y and bullet.y<enemy.y+enemy.image.get_height()):
  6.         enemy.restart()
  7.         bullet.active=False
  8. class Plane(object):
  9.     def __init__(self):
  10.         self.image = pygame.image.load('plane.png').convert_alpha()
  11.         self.width = self.image.get_width()
  12.         self.height = self.image.get_height()
  13.         self.x = 225 - self.width / 2
  14.         self.y = 700 - self.height / 2

  15.     def move(self):
  16.         mouseX, mouseY = pygame.mouse.get_pos()
  17.         self.x = mouseX - self.width / 2
  18.         self.y = mouseY - self.height / 2

  19. class Enemy:
  20.     def restart(self):
  21.         self.x = random.randint(50, 400)
  22.         self.y = random.randint(-200, -50)
  23.         self.speed = 0.3
  24.     def __init__(self):
  25.                 self.restart()
  26.                 self.image = pygame.image.load('diji.png').convert_alpha()

  27.     def move(self):
  28.                 if self.y < 800:
  29.                         self.y += self.speed
  30.                 else:
  31.                         self.restart()
  32. class Bullet:
  33.     def __init__(self):
  34.         self.x=0
  35.         self.y=-5
  36.         self.image=pygame.image.load('1.png').convert_alpha()
  37.         self.active = False

  38.     def move(self):
  39.         if self.active:
  40.             self.y -= 3
  41.       
  42.         if self.y < 0:
  43.             self.active = False
  44.     def restart(self):
  45.         
  46.         mousex,mousey=pygame.mouse.get_pos()
  47.         self.x=mousex-self.image.get_width()/2
  48.         self.y=mousey-self.image.get_height()/2
  49.         self.active=True
  50.             


  51. pygame.init()

  52. screen=pygame.display.set_mode((450,800),0,32)
  53. pygame.display.set_caption('hello,world')
  54. background1=pygame.image.load('back.jpg').convert()
  55. pygame.mouse.set_visible(False)
  56. filename='yinyue.mp3'
  57. pygame.mixer.init()
  58. pygame.mixer.music.load(filename)
  59. pygame.mixer.music.play(1)
  60. enemy=Enemy()
  61. plane=Plane()

  62. bullets = []

  63. for i in range(5):
  64.     bullets.append(Bullet())

  65. count_b = len(bullets)

  66. index_b = 0

  67. interval_b = 0
  68. enemies = []
  69. #向list中添加5架敌机
  70. for i in range(5):
  71.     enemies.append(Enemy())
  72. while True:
  73.     for event in pygame.event.get():
  74.         if event.type==pygame.QUIT:
  75.             pygame.quit()
  76.             exit()      
  77.     screen.blit(background1,(0,0))
  78.     interval_b -= 1
  79.     #当间隔小于0时,激活一发子弹
  80.     if interval_b < 0:
  81.         bullets[index_b].restart()
  82.         #重置间隔时间
  83.         interval_b = 100
  84.         #子弹序号周期性递增
  85.         index_b = (index_b + 1) % count_b
  86.     #判断每个子弹的状态
  87.     for b in bullets:
  88.         #处于激活状态的子弹,移动位置并绘制
  89.         if b.active:
  90.             b.move()
  91.             screen.blit(b.image, (b.x, b.y))
  92.     for b in bullets:
  93.         if b.active:
  94.             for e in enemies:
  95.                 hit(e, b)
  96.             b.move()
  97.             screen.blit(b.image, (b.x, b.y))

  98.         plane.move()
  99.     for e in enemies:
  100.         e.move()
  101.         screen.blit(e.image, (e.x, e.y))



  102.    
  103.     enemy.move()
  104.     screen.blit(enemy.image,(enemy.x,enemy.y))
  105.    
  106.     screen.blit(plane.image, (plane.x, plane.y))

  107.     pygame.display.update()
  108.    
复制代码

作者: wwb951108    时间: 2017-3-15 19:07
老师我感觉没出错啊
作者: crossin先生    时间: 2017-3-16 17:56
wwb951108 发表于 2017-3-15 19:07
老师我感觉没出错啊

我也没看出问题。这个不大能直接这么看出来,得具体调试了,先想办法重新问题,然后多加输出,看看哪里出了问题
作者: mihchaelli    时间: 2017-8-6 00:07
老师 一直说 NameError: global name 'enemey' is not defined

但是这个只是一个parameter啊 为什么会有这个问题。
作者: mihchaelli    时间: 2017-8-6 00:09
mihchaelli 发表于 2017-8-6 00:07
老师 一直说 NameError: global name 'enemey' is not defined

但是这个只是一个parameter啊 为什么会有这 ...

总是发过贴之后才发现。。 有一个typo
作者: gysgo2    时间: 2017-9-17 02:13
请问老师,如果在命中目标后再加个爆炸效果该怎么实现?
作者: crossin先生    时间: 2017-9-17 11:57
gysgo2 发表于 2017-9-17 02:13
请问老师,如果在命中目标后再加个爆炸效果该怎么实现?

增加一种爆炸的 sprite,用帧动画实现爆炸效果(这个网上可以搜到)
然后击中了之后,就在击中的位置放这个sprite,放完就移除
作者: lsp84ch83    时间: 2017-9-18 19:18
本帖最后由 lsp84ch83 于 2017-9-18 19:22 编辑

以下是我对照论坛写的飞机代码,但是我的子弹距离很短,附件图片为运行效果
  1. # -*- coding:utf-8 -*-
  2. import pygame
  3. import random
  4. from sys import exit


  5. # 定义子弹的速度、运动方向
  6. class Bullet:
  7.     def __init__(self):
  8.         # 初始化成员变量:x,y,image
  9.         self.x = 0
  10.         self.y = -1
  11.         self.image = pygame.image.load('bullet.png').convert_alpha()
  12.         # 默认不激活
  13.         self.active = False

  14.     def move(self):
  15.         # 激活状态下,向上移动
  16.         if self.active:
  17.             self.y -= 0.8
  18.         # 当飞出屏幕,就设为不激活
  19.         if self.y < 0:
  20.             self.active = False

  21.     def restart(self):
  22.         # 重置子弹位置
  23.         mouseX, mouseY = pygame.mouse.get_pos()
  24.         self.x = mouseX - self.image.get_width() / 2
  25.         self.y = mouseY - self.image.get_height() / 2
  26.         # 激活子弹
  27.         self.active = True

  28. # 定义敌机的速度、出现位置
  29. class Enemy:
  30.     def restart(self):
  31.         # 重置敌机位置和速度
  32.         self.x = random.randint(50,400)
  33.         self.y = random.randint(-200,-50)
  34.         self.speed = random.random() + 0.1

  35.     def __init__(self):
  36.         # 初始化
  37.         self.restart()
  38.         self.image = pygame.image.load('enemy.png').convert_alpha()

  39.     def move(self):
  40.         if self.y < 800:
  41.             # 向下移动
  42.             self.y += self.speed
  43.         else:
  44.             # 重置
  45.             self.restart()


  46. # 检测子弹是否命中        
  47. def checkHit(enemy,bullet):
  48.     if (bullet.x > enemy.x and bullet.x < enemy.x + enemy.image.get_width()) and (
  49.                     bullet.y > enemy.y and bullet.y < enemy.y + enemy.image.get_height()):
  50.         enemy.restart()
  51.         bullet.active = False

  52. # 初始化
  53. pygame.init()
  54. screen = pygame.display.set_mode((450,800), 0, 32)
  55. pygame.display.set_caption('飞机')
  56. background = pygame.image.load('back.jpg').convert()
  57. plane = pygame.image.load('plane.png').convert_alpha()
  58. # 创建子弹的list
  59. bullets = []
  60. # 向list中添加 5 发子弹
  61. for i in range(5):
  62.     bullets.append(Bullet())
  63. # 子弹总数
  64. count_b = len(bullets)
  65. # 即将激活的子弹序号
  66. index_b = 0
  67. # 发射子弹的间隔
  68. interval_b = 0
  69. # 创建敌机的list
  70. enemies = []
  71. # 向list总添加 5 架敌机
  72. for i in range(5):
  73.     enemies.append(Enemy())

  74. # 游戏主体
  75. while True:
  76.     # 判断退出条件
  77.     for event in pygame.event.get():
  78.         if event.type == pygame.QUIT:
  79.             pygame.quit()
  80.             exit()
  81.     screen.blit(background,(0,0))
  82.     # 发射间隔递减
  83.     interval_b -= 1
  84.     # 当间隔小于0时,激活一发子弹
  85.     if interval_b < 0:
  86.         bullets[interval_b].restart()
  87.         # 重置间隔时间
  88.         interval_b = 200
  89.         # 子弹序号周期性递增
  90.         index_b = (index_b + 1) % count_b
  91.     # 判断每个子弹的状态
  92.     for b in bullets:
  93.         # 处于激活状态的子弹,移动位置并绘制
  94.         if b.active:
  95.             for e in enemies:
  96.                 checkHit(e,b)
  97.             b.move()
  98.             screen.blit(b.image, (b.x, b.y))
  99.     # 更新敌机位置,处理每架敌机的运动
  100.     for e in enemies:
  101.         e.move()
  102.         screen.blit(e.image,(e.x,e.y))
  103.     # 绘制子弹,数据来自其成员变量
  104.     x,y = pygame.mouse.get_pos()
  105.     x -= plane.get_width() / 2
  106.     y -= plane.get_height() / 2
  107.     screen.blit(plane,(x,y))
  108.     pygame.display.update()
复制代码

新建位图图像.jpg (48.94 KB, 下载次数: 268)

新建位图图像.jpg


作者: crossin先生    时间: 2017-9-18 22:54
lsp84ch83 发表于 2017-9-18 19:18
以下是我对照论坛写的飞机代码,但是我的子弹距离很短,附件图片为运行效果 ...

那你可以通过调节 speed 或者 interval_b 来修改。
作者: lsp84ch83    时间: 2017-9-19 16:40
本帖最后由 lsp84ch83 于 2017-9-19 16:59 编辑
crossin先生 发表于 2017-9-18 22:54
那你可以通过调节 speed 或者 interval_b 来修改。

我通过工具对比了下,代码里有个变量应用错了。
作者: Youngkuso    时间: 2018-1-12 10:24
老师,我的两排子弹其中一排打到敌机为什么会出现不同步的情况呀?是因为延迟的关系吗?
  1. #-*- coding: utf-8 -*-
  2. import pygame  #导入pygame库
  3. import random
  4. from itertools import product

  5. from sys import exit  #向sys模块借一个exit函数用来退出程序

  6. class Bullet:
  7.     def __init__(self):
  8.         self.x = 0
  9.         self.y = -1
  10.         self.image = pygame.image.load('C:/Python27/test/pic/bullet.png').convert_alpha()
  11.         self.active = False #默认不激活
  12.         
  13.     def move(self):#处理子弹运动
  14.         #激活状态下,向上移动
  15.         if self.active:
  16.             self.y -= 0.1
  17.         #当飞出屏幕,就设为不激活
  18.         if self.y < 0:
  19.             self.active = False

  20.     def restart(self):   
  21.         #重置子弹位置
  22.         mouseX,mouseY = pygame.mouse.get_pos()
  23.         self.x = mouseX - self.image.get_width() / 2
  24.         self.y = mouseY - self.image.get_height() / 2
  25.         #激活子弹
  26.         self.active = True

  27. class Enemy:
  28.     def restart(self):#重置敌机位置和速度
  29.         self.x = random.randint(50,400)
  30.         self.y = random.randint(-200,-50)
  31.         self.speed = random.random() + 0.1

  32.     def __init__(self):
  33.         self.restart()
  34.         self.image = pygame.image.load('c:/Python27/test/pic/enemy.png').convert_alpha()

  35.     def move(self):
  36.         if self.y < 800:#向下运动
  37.             self.y += self.speed
  38.         else:
  39.             self.restart() #重置
  40.             
  41. def checkHit(enemy,bullet1,bullet2): #如果子弹在敌机图片的范围之内
  42.     if((bullet1.x + 24  > enemy.x or bullet2.x - 23 > enemy.x )and (
  43.         bullet1.x +24< enemy.x + enemy.image.get_width() or bullet2.x - 23
  44.         < enemy.x + enemy.image.get_width())and( bullet1.y > enemy.y or bullet2.y> enemy.y)
  45.        and( bullet1.y < enemy.y + enemy.image.get_height() or bullet2.y < enemy.y + enemy.image.get_height())):

  46.         enemy.restart() #重置敌机
  47.         bullet1.active = bullet2.active = False #重置子弹
  48.       
  49.         #print bullet2.y ,bullet1.y   


  50. pygame.init() #初始化pygame,为使用硬件做准备
  51. screen = pygame.display.set_mode((450,800), 0, 32) #创建了一个窗口,窗口大小和背景图片大小一样
  52. pygame.display.set_caption("ONE PIECE")
  53. background = pygame.image.load('C:/Python27/test/pic/back.jpg').convert_alpha()#加载并转换图像
  54. plane = pygame.image.load('C:/Python27/test/pic/plane.png').convert_alpha()
  55. pygame.mouse.set_visible(False)

  56. bullets1 = [] #创建子弹的list
  57. bullets2 = []
  58. for i in range(5): #向list中添加5发子弹
  59.     bullets1.append(Bullet())
  60.     bullets2.append(Bullet())
  61.    
  62. count_b = len(bullets1) #子弹总数
  63. index_b = 0 #即将激活的子弹序号
  64. interval_b = 0 #发射子弹的间隔

  65. enemies = []
  66. for i in range(5):
  67.     enemies.append(Enemy()) #创建敌机

  68. while True: #游戏主循环
  69.     for event in pygame.event.get():
  70.         if event.type == pygame.QUIT: #接收到退出事件后退出程序
  71.             pygame.quit()
  72.             exit()
  73.                
  74.     screen.blit(background, (0,0))

  75.     interval_b -= 1 #发射间隔递减
  76.     #print interval_b
  77.     if interval_b < 0: #当间隔小于0时,激活一发子弹
  78.         bullets1[index_b].restart()
  79.         bullets2[index_b].restart()
  80.         interval_b = 900 #重置间隔时间
  81.         index_b = (index_b + 1) % count_b #子弹序号周期性递增

  82.     for b,c in product(bullets1,bullets2): #判断每个子弹的状态
  83.         if b.active and c.active: #处于激活状态的子弹,移动位置并绘制
  84.             for e in enemies:
  85.                 checkHit(e,b,c)
  86.             b.move()
  87.             c.move()
  88.             screen.blit(b.image,(b.x + 24,b.y))
  89.             screen.blit(c.image,(c.x - 23,c.y))        
  90.     #print '第一颗子弹:',bullets1[0].x , bullets1[0].y,'第二颗子弹:',bullets1[1].x , bullets1[1].y ,'第三颗子弹:',bullets1[2].x , bullets1[2].y , '第四颗子弹:',bullets1[3].x , bullets1[3].y , '第五颗子弹:',bullets1[4].x , bullets1[4].y      

  91.     for e in enemies:
  92.         e.move()
  93.         screen.blit(e.image,(e.x,e.y))
  94.         #print '第一架:',enemies[0].x,enemies[0].y,'第二架:',enemies[1].x,enemies[2].y

  95.    
  96.     x,y = pygame.mouse.get_pos()
  97.     x-= plane.get_width()/2
  98.     y-= plane.get_height()/2#计算飞机的左上角位置
  99.     screen.blit(plane,(x,y))#把飞机画到屏幕上
  100.     pygame.display.update() #刷新一下画面
复制代码
11.png


作者: Youngkuso    时间: 2018-1-12 13:14
本帖最后由 Youngkuso 于 2018-1-12 15:10 编辑

不仅延迟,还能感觉到打到敌机的子弹会明显变慢
作者: crossin先生    时间: 2018-1-12 16:32
Youngkuso 发表于 2018-1-12 13:14
不仅延迟,还能感觉到打到敌机的子弹会明显变慢

你的代码里不是击中敌机就 actice False ,然后不移动了吗
你这个要自己调试代码来看的
作者: skybeak    时间: 2018-3-14 16:18
请问判断飞机是否被打中的那段代码
            for e in enemies:
                checkHit(e, b)
是不是也可以放在别的位置,比如单独出去,或者是处理每个飞机运动的for循环里,比如
    for e in enemies:
        checkHit(e, b)
        e.move()
        screen.blit(e.image, (e.x, e.y))
两处有什么不同么?只是响应时间会有所不同,还是会有很多其他的不一样,谢谢老师

作者: crossin先生    时间: 2018-3-15 17:15
skybeak 发表于 2018-3-14 16:18
请问判断飞机是否被打中的那段代码
            for e in enemies:
                checkHit(e, b)

可以,一个功能可以有不同的实现
作者: 花花啊    时间: 2018-4-16 11:13
我的飞机打中之后没有被重置是为什么?
# -*- coding: utf-8 -*-
import pygame, random
from sys import exit





class Bullet:
    def __init__(self):
        self.x = 0
        self.y = -1
        self.image = pygame.image.load('bullet.png').convert_alpha()
        self.active = False

    def move(self):
        if self.active:
            self.y -= 3
        if self.y < 0:
            self.active = False

    def restart(self):
        mouseX, mouseY = pygame.mouse.get_pos()
        self.x = mouseX - self.image.get_width() / 2
        self.y = mouseY - self.image.get_height() / 2
        self.active = True


class Enemy:
    def restart(self):
        self.x = random.randint(50, 800)
        self.y = random.randint(-200, -50)
        self.speed = random.random() + 0.1

    def __init__(self):
        self.restart()
        self.image = pygame.image.load('enemy.png').convert_alpha()

    def move(self):
        if self.y < 800:
            self.y += self.speed
        else:
            self.restart()

def checkHit(enemy, bullet):
    if (bullet.x > enemy.x and bullet.x < enemy.x + enemy.image.get_width()) and (
            bullet.y > enemy.y and bullet.y < enemy.y + enemy.image.get_height()):
        enemy.restart()
        bullet.active = False


pygame.init()
screen = pygame.display.set_mode((450, 800), 0, 32)
pygame.display.set_caption("Hello, World!")
background = pygame.image.load('back.jpg').convert()
plane = pygame.image.load('plane.png').convert_alpha()
# 创建子弹的list
bullets = []
# 向list添加5发子弹
for i in range(5):
    bullets.append(Bullet())
# 子弹总个数
count_b = len(bullets)
# 即将激发的子弹序号
index_b = 0
# 发射子弹的间隔
interval_b = 0
# 创建敌机的list
enemies = []
# 向list中添加5架敌机
for i in range(5):
    enemies.append(Enemy())
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
    screen.blit(background, (0, 0))
    interval_b -= 1
    if interval_b < 0:
        bullets[index_b].restart()
        interval_b = 100
        index_b = (index_b + 1) % count_b
    for b in bullets:
        #处于激活状态的子弹,移动位置并绘制
        if b.active:
            b.move()
            screen.blit(b.image, (b.x, b.y))
    for b in bullets:
        if b.active:
            for e in enemies:
                checkHit(e, b)
    # 处理每架敌机的运动
    for e in enemies:
        e.move()
        screen.blit(e.image, (e.x, e.y))
    x, y = pygame.mouse.get_pos()
    x -= plane.get_width() / 2
    y -= plane.get_height() / 2
    screen.blit(plane, (x, y))
    pygame.display.update()
作者: crossin先生    时间: 2018-4-16 23:03
在你的checkHit里面加上print输出调试,
看看是函数没掉用到,还是判断出错,还是重置没成功。
作者: koalaoycx    时间: 2018-6-6 15:53
#定义命中函数
def checkHit(enemy,bullet):
    if (bullet.x > enemy.x and bullet.x < enemy.x+enemy.image.get_width()) and (bullet.y > enemy.y
    and bullet.y < enemy.y +enemy.image.get_height()):
        screen.blit(boom,(enemy.x,enemy.y))
        enemy.restart()
        bullet.active=False


先生您好,我想给被击中的敌机加一个boom的特效,但不知为什么boom图片好像是随机出现的,请问应该怎么修改呢?

捕获.PNG (10.15 KB, 下载次数: 271)

捕获.PNG


作者: crossin先生    时间: 2018-6-6 17:15
koalaoycx 发表于 2018-6-6 15:53
#定义命中函数
def checkHit(enemy,bullet):
    if (bullet.x > enemy.x and bullet.x < enemy.x+enemy.im ...

代码没看出问题
再调试下吧,输出看看那句blit有没有被执行到,传给blit的参数是多少,还有把你的图片换下试试
作者: 皮一下    时间: 2018-6-24 11:16
我加了命中目标这段代码后,比如说我有5颗子弹,这五颗子弹会5颗一条5颗一条的射出来,和之前的不一样了。是不是电脑处理不行了
作者: crossin先生    时间: 2018-6-24 13:30
皮一下 发表于 2018-6-24 11:16
我加了命中目标这段代码后,比如说我有5颗子弹,这五颗子弹会5颗一条5颗一条的射出来,和之前的不一样了。 ...

你需要有个间隔时间,不要让子弹那么快出来,不然你一共就5颗,后面就出不来了
代码里是有 interval_b 这个参数的,调大一点试试
这不是你电脑不行,可能正相反,是计算太快了
作者: 皮一下    时间: 2018-6-24 22:55
crossin先生 发表于 2018-6-24 13:30
你需要有个间隔时间,不要让子弹那么快出来,不然你一共就5颗,后面就出不来了
代码里是有 interval_b 这 ...

Interval_b我试过200, 我之前是30, 就是加了碰撞代码后,就出现异常了。我一共确实也就5颗,但是后面也会出来,5颗一组5颗一组的射出来。这是我的代码:
import pygame
from sys import exit
import random


class Bullet:
    def __init__(self):
        self.x=0
        self.y=-1
        self.image= pygame.image.load('bullet.png').convert_alpha()
        self.active=False

    def move(self):
        if self.active:
            self.y-=5
        if self.y<0:
            self.active=False
            
    def restart(self):
        mousex,mousey=pygame.mouse.get_pos()
        self.x=mousex-self.image.get_width()/2
        self.y=mousey-self.image.get_height()/2
        self.active=True
        
        
class Air:
    def __init__(self):
        self.x=0
        self.y=0
        self.image=pygame.image.load('air.png').convert_alpha()

    def Move(self):
        mousex,mousey=pygame.mouse.get_pos()
        self.x=mousex-self.image.get_width()/2
        self.y=mousey-self.image.get_height()/2


class Enemy:
    def restart(self):
        self.x=random.uniform(30,420)
        self.y=random.uniform(-200,-50)
        
    def __init__(self):
        self.restart()
        self.image=pygame.image.load('enemy.png')
        self.speed=0.08

    def move(self):
        if self.y>608:
            self.speed+=0.01
            self.restart()
            
        else:
            self.y=self.y+self.speed
            
            

pygame.init()
screen=pygame.display.set_mode((450,608))
pygame.display.set_caption('Star War')
background=pygame.image.load('background.png').convert()
interval_b=0
index_b=0
bullets=[]

for i in range(10):
    bullets.append(Bullet())

air=Air()
enemies=[]
for i in range(6):
    enemies.append(Enemy())

#def checkHit(enemy, bullet):
#   if (bullet.x > enemy.x and bullet.x < enemy.x + enemy.image.get_width()) and (bullet.y > enemy.y and bullet.y < enemy.y + enemy.image.get_height()):
  #      enemy.restart()
   #     bullet.active = False

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
    screen.blit(background,(0,0))
    interval_b-=1
    if interval_b<0:
        bullets[index_b].restart()
        interval_b=30
        index_b=(1+index_b)%10
    for e in enemies:
        e.move()
        screen.blit(e.image,(e.x,e.y))
    for b in bullets:
        if b.active:
            #for e in enemies:
             #   checkHit(e,b)
            b.move()
            screen.blit(b.image,(b.x,b.y))
    air.Move()
    screen.blit(air.image,(air.x,air.y))
    pygame.display.update()
作者: crossin先生    时间: 2018-6-25 23:12
皮一下 发表于 2018-6-24 22:55
Interval_b我试过200, 我之前是30, 就是加了碰撞代码后,就出现异常了。我一共确实也就5颗,但是后面也 ...

你5颗子弹,为什么这里改成了
index_b=(1+index_b)%10

对照之前代码再看看
作者: 皮一下    时间: 2018-6-26 03:01
crossin先生 发表于 2018-6-25 23:12
你5颗子弹,为什么这里改成了
index_b=(1+index_b)%10

haha这里我乱改子弹就是测试下。。我找到问题所在了。。b.move()那一块的代码缩进我搞错了。现在正常了。谢谢
作者: 皮一下    时间: 2018-6-26 03:03
crossin先生 发表于 2018-6-25 23:12
你5颗子弹,为什么这里改成了
index_b=(1+index_b)%10

我用的python3.7 现在都没有适配3.7转换成exe的文件。该咋办,找了好多教程最多也只有3.6
作者: crossin先生    时间: 2018-6-26 15:30
皮一下 发表于 2018-6-26 03:03
我用的python3.7 现在都没有适配3.7转换成exe的文件。该咋办,找了好多教程最多也只有3.6 ...

这个我也没办法,exe支持没那么快,你试试3.6的行不行。
不行的话,如果一定要打包,你可以建一个3.6的虚拟环境,或者重装个3.6的python
作者: 皮一下    时间: 2018-6-26 22:48
crossin先生 发表于 2018-6-26 15:30
这个我也没办法,exe支持没那么快,你试试3.6的行不行。
不行的话,如果一定要打包,你可以建一个3.6的虚 ...

我用了pyinstaller,3.5,3.6都试过没用。
作者: crossin先生    时间: 2018-6-26 23:03
皮一下 发表于 2018-6-26 22:48
我用了pyinstaller,3.5,3.6都试过没用。

我以前是用 cxfreeze ,不过也没打过 3.7 的包
作者: swing    时间: 2020-6-8 15:46
wwb951108 发表于 2017-3-10 17:18
老师为什么我屏幕里总是有一个飞机命中不了

请问问题解决了吗?我现在也遇到同样的问题了。。。。
作者: crossin先生    时间: 2020-6-8 22:55
swing 发表于 2020-6-8 15:46
请问问题解决了吗?我现在也遇到同样的问题了。。。。

他的代码里,一开始创建了一个
enemy=Enemy()

但这个 enemy 并没有加到 enemies 列表里




欢迎光临 Crossin的编程教室 (https://bbs.crossincode.com/) Powered by Discuz! X2.5