设为首页收藏本站

Crossin的编程教室

 找回密码
 立即加入
查看: 45039|回复: 44
打印 上一主题 下一主题

【Pygame 第10课】 命中目标

[复制链接]

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

跳转到指定楼层
楼主
发表于 2013-9-3 20:37:27 |只看该作者 |正序浏览

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


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

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课源码

#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

45#
发表于 2020-6-8 22:55:37 |只看该作者
swing 发表于 2020-6-8 15:46
请问问题解决了吗?我现在也遇到同样的问题了。。。。

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

但这个 enemy 并没有加到 enemies 列表里
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

0

主题

0

好友

4

积分

新手上路

Rank: 1

44#
发表于 2020-6-8 15:46:46 |只看该作者
wwb951108 发表于 2017-3-10 17:18
老师为什么我屏幕里总是有一个飞机命中不了

请问问题解决了吗?我现在也遇到同样的问题了。。。。
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

43#
发表于 2018-6-26 23:03:18 |只看该作者
皮一下 发表于 2018-6-26 22:48
我用了pyinstaller,3.5,3.6都试过没用。

我以前是用 cxfreeze ,不过也没打过 3.7 的包
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

5

主题

1

好友

87

积分

注册会员

Rank: 2

42#
发表于 2018-6-26 22:48:12 |只看该作者
crossin先生 发表于 2018-6-26 15:30
这个我也没办法,exe支持没那么快,你试试3.6的行不行。
不行的话,如果一定要打包,你可以建一个3.6的虚 ...

我用了pyinstaller,3.5,3.6都试过没用。
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

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

这个我也没办法,exe支持没那么快,你试试3.6的行不行。
不行的话,如果一定要打包,你可以建一个3.6的虚拟环境,或者重装个3.6的python
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

5

主题

1

好友

87

积分

注册会员

Rank: 2

40#
发表于 2018-6-26 03:03:21 |只看该作者
crossin先生 发表于 2018-6-25 23:12
你5颗子弹,为什么这里改成了
index_b=(1+index_b)%10

我用的python3.7 现在都没有适配3.7转换成exe的文件。该咋办,找了好多教程最多也只有3.6
回复

使用道具 举报

5

主题

1

好友

87

积分

注册会员

Rank: 2

39#
发表于 2018-6-26 03:01:33 |只看该作者
crossin先生 发表于 2018-6-25 23:12
你5颗子弹,为什么这里改成了
index_b=(1+index_b)%10

haha这里我乱改子弹就是测试下。。我找到问题所在了。。b.move()那一块的代码缩进我搞错了。现在正常了。谢谢
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

38#
发表于 2018-6-25 23:12:35 |只看该作者
皮一下 发表于 2018-6-24 22:55
Interval_b我试过200, 我之前是30, 就是加了碰撞代码后,就出现异常了。我一共确实也就5颗,但是后面也 ...

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

对照之前代码再看看
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

5

主题

1

好友

87

积分

注册会员

Rank: 2

37#
发表于 2018-6-24 22:55:47 |只看该作者
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()
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即加入

QQ|手机版|Archiver|Crossin的编程教室 ( 苏ICP备15063769号  

GMT+8, 2024-5-3 01:00 , Processed in 0.032624 second(s), 25 queries .

Powered by Discuz! X2.5

© 2001-2012 Comsenz Inc.

回顶部