前言

  在上一节我们完成了对玩家飞机的基本操作,这一节我们就来创造出敌人了(°∀°)ノ~目标有三个,第一个是在屏幕上绘制出敌机,第二个是判断子弹是否击中了敌人,第三个是对被击中的敌人作后续的处理。明白方向后就可以开始了!

正片开始~

  1. 绘制敌机

  随机是游戏中一个很重要的元素,不可预测的机制为游戏带来了更丰富的体验。这次我们要在程序中加入随机数,两行代码:

# 导入random库中的randint函数
from random import randint
# 返回一个整数N, a<=N<=b
N = randint(a, b)

这样我们就可以使得敌机每次出现的位置变得不可预测了~(。・ω・。)

  跟之前的风格类似,我们把敌机封装成类,主要是为了能够更方便地使用碰撞检测的功能。

# 敌人类
class Enemy(pygame.sprite.Sprite):def __init__(self, enemy_surface, enemy_init_pos):pygame.sprite.Sprite.__init__(self)            self.image = enemy_surfaceself.rect = self.image.get_rect()self.rect.topleft = enemy_init_posself.speed = 2def update(self):self.rect.top += self.speedif self.rect.top > SCREEN_HEIGHT:self.kill()

依然是超出屏幕区域自动销毁对象,最后就是创建敌人对象并在屏幕上绘制出来:

...
# enemy1图片 **********************************************************
enemy1_surface = shoot_img.subsurface(pygame.Rect(534, 612, 57, 43))
# ********************************************************************
...# 事件循环(main loop)
while True:...# 产生敌机 *****************************************************if ticks % 30 == 0:enemy = Enemy(enemy1_surface, [randint(0, SCREEN_WIDTH - enemy1_surface.get_width()), -enemy1_surface.get_height()])enemy_group.add(enemy)# 控制敌机enemy_group.update()# 绘制敌机enemy_group.draw(screen)# ************************************************************...

导入图片资源当然是必不可少的啦;我们使用ticks控制敌人产生的频率,每30ticks产生一架新敌机,然后将敌机对象加入一个group,统一操作,每一tick更新一次全体enemy的位置。现在绘制的任务就完成啦~看一下效果:

  虽然enemy绘制出来了,但是现在出现了两个问题;第一,子弹无法击中敌人;第二,敌人无法击毁玩家飞机。下面我们先来解决第一个问题。

2. 我们的子弹击穿了敌人的铠甲!

  说了那么久,终于说到了“碰撞检测”,游戏中的碰撞检测应用范围很广,不过在pygame中,碰撞检测(collide)的机制其实很简单,就是判断sprite1.rect与sprite2.rect是否重叠。那么在pygame.sprite中,我们可以看到一些函数名中包含collide的函数,这些函数一般是用于检测碰撞的,我们可以大体分为sprite与sprite的碰撞检测,sprite与group的碰撞检测,group与group的碰撞检测。回归问题,子弹是一个group,敌人是一个group,那我们在游戏中检测子弹是否击中了敌人很明显需要用group与group的碰撞检测了~

  pygame.sprite.groupcollide()——检测两个group之间所有sprite的碰撞

  groupcollide(group1, group2, dokill1, dokill2, collided = None) -> Sprite_dict

  group1——精灵组1

  group2——精灵组2

  dokill1——是否杀死发生碰撞时group1中的精灵对象

  dokill2——是否杀死发生碰撞时group2中的精灵对象

  collided——可选参数,可自定义一个回调函数,参数为两个精灵对象,用于自定义两个精灵是否发生碰撞,返回bool值;若忽略此参数,则默认碰撞条件为两个精灵的rect发生重叠

  返回一个包含所有group1中与group2发生碰撞的精灵字典(dict)

  

  现在,我们只需要在程序中加入两行代码:

...# 创建击毁敌人组
enemy1_down_group = pygame.sprite.Group()# 事件循环(main loop)
while True:...# 检测敌机与子弹的碰撞 *******************************************enemy1_down_group.add(pygame.sprite.groupcollide(enemy1_group, hero.bullets1, True, True))...

创建一个包含被击毁的敌人的group,然后在每一tick中检测一次是否发生碰撞,再将被击毁的敌人加入这个group,方便后续对坠毁敌机的动画渲染;这样第二部分也完成啦~

  3. 华丽的坠毁(`・ω・´)

  现在我们已经实现子弹与敌机的碰撞检测了,但凭空消失是在不咋的,我们来一个华丽一点的爆炸!(°∀°)ノ

  首先导入enemy1爆炸的资源图片

 enemy1_down_surface = []enemy1_down_surface.append(shoot_img.subsurface(pygame.Rect(267, 347, 57, 43)))enemy1_down_surface.append(shoot_img.subsurface(pygame.Rect(873, 697, 57, 43)))enemy1_down_surface.append(shoot_img.subsurface(pygame.Rect(267, 296, 57, 43)))enemy1_down_surface.append(shoot_img.subsurface(pygame.Rect(930, 697, 57, 43)))

然后就是控制爆炸图片切换的速度了,在主循环中加入:

for enemy1_down in enemy1_down_group:screen.blit(enemy1_down_surface[enemy1_down.down_index], enemy1_down.rect)if ticks % (ANIMATE_CYCLE//2) == 0:if enemy1_down.down_index < 3:enemy1_down.down_index += 1else:enemy1_down_group.remove(enemy1_down)

当index超出图片下标,判断为爆炸效果演示完毕,销毁坠毁的enemy1精灵。

  这样爆炸效果就出来啦~~

  这一节任务完成!~附上完整代码:

# -*- coding = utf-8 -*-
"""
@author: Will Wu
"""import pygame                   # 导入pygame库
from pygame.locals import *     # 导入pygame库中的一些常量
from sys import exit            # 导入sys库中的exit函数
from random import randint# 定义窗口的分辨率
SCREEN_WIDTH = 480
SCREEN_HEIGHT = 640# 子弹类
class Bullet(pygame.sprite.Sprite):def __init__(self, bullet_surface, bullet_init_pos):pygame.sprite.Sprite.__init__(self)            self.image = bullet_surfaceself.rect = self.image.get_rect()self.rect.topleft = bullet_init_posself.speed = 8# 控制子弹移动def update(self):self.rect.top -= self.speedif self.rect.bottom < 0:self.kill()# 玩家类
class Hero(pygame.sprite.Sprite):def __init__(self, hero_surface, hero_init_pos):pygame.sprite.Sprite.__init__(self)            self.image = hero_surfaceself.rect = self.image.get_rect()self.rect.topleft = hero_init_posself.speed = 6# 子弹1的Groupself.bullets1 = pygame.sprite.Group()# 控制射击行为def single_shoot(self, bullet1_surface):bullet1 = Bullet(bullet1_surface, self.rect.midtop)self.bullets1.add(bullet1)# 控制飞机移动def move(self, offset):x = self.rect.left + offset[pygame.K_RIGHT] - offset[pygame.K_LEFT]y = self.rect.top + offset[pygame.K_DOWN] - offset[pygame.K_UP]if x < 0:self.rect.left = 0elif x > SCREEN_WIDTH - self.rect.width:self.rect.left = SCREEN_WIDTH - self.rect.widthelse:self.rect.left = xif y < 0:self.rect.top = 0elif y > SCREEN_HEIGHT - self.rect.height:self.rect.top = SCREEN_HEIGHT - self.rect.heightelse:self.rect.top = y# 敌人类
class Enemy(pygame.sprite.Sprite):def __init__(self, enemy_surface, enemy_init_pos):pygame.sprite.Sprite.__init__(self)            self.image = enemy_surfaceself.rect = self.image.get_rect()self.rect.topleft = enemy_init_posself.speed = 2# 爆炸动画画面索引self.down_index = 0def update(self):self.rect.top += self.speedif self.rect.top > SCREEN_HEIGHT:self.kill()############################################################################ 定义画面帧率
FRAME_RATE = 60# 定义动画周期(帧数)
ANIMATE_CYCLE = 30ticks = 0
clock = pygame.time.Clock()
offset = {pygame.K_LEFT:0, pygame.K_RIGHT:0, pygame.K_UP:0, pygame.K_DOWN:0}# 初始化游戏
pygame.init()                   # 初始化pygame
screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])     # 初始化窗口
pygame.display.set_caption('This is my first pygame-program')       # 设置窗口标题# 载入背景图
background = pygame.image.load('resources/image/background.png')# 载入资源图片
shoot_img = pygame.image.load('resources/image/shoot.png')# 用subsurface剪切读入的图片
# Hero图片
hero_surface = []
hero_surface.append(shoot_img.subsurface(pygame.Rect(0, 99, 102, 126)))
hero_surface.append(shoot_img.subsurface(pygame.Rect(165, 360, 102, 126)))
#hero_surface.append(shoot_img.subsurface(pygame.Rect(165, 234, 102, 126)))
#hero_surface.append(shoot_img.subsurface(pygame.Rect(330, 624, 102, 126)))
#hero_surface.append(shoot_img.subsurface(pygame.Rect(330, 498, 102, 126)))
#hero_surface.append(shoot_img.subsurface(pygame.Rect(432, 624, 102, 126)))
hero_pos = [200, 500]# bullet1图片
bullet1_surface = shoot_img.subsurface(pygame.Rect(1004, 987, 9, 21))# enemy1图片 **********************************************************
enemy1_surface = shoot_img.subsurface(pygame.Rect(534, 612, 57, 43))
enemy1_down_surface = []
enemy1_down_surface.append(shoot_img.subsurface(pygame.Rect(267, 347, 57, 43)))
enemy1_down_surface.append(shoot_img.subsurface(pygame.Rect(873, 697, 57, 43)))
enemy1_down_surface.append(shoot_img.subsurface(pygame.Rect(267, 296, 57, 43)))
enemy1_down_surface.append(shoot_img.subsurface(pygame.Rect(930, 697, 57, 43)))
# ********************************************************************# 创建玩家
hero = Hero(hero_surface[0], hero_pos)# 创建敌人组
enemy1_group = pygame.sprite.Group()# 创建击毁敌人组
enemy1_down_group = pygame.sprite.Group()# 事件循环(main loop)
while True:# 控制游戏最大帧率clock.tick(FRAME_RATE)# 绘制背景screen.blit(background, (0, 0))# 改变飞机图片制造动画if ticks >= ANIMATE_CYCLE:ticks = 0hero.image = hero_surface[ticks//(ANIMATE_CYCLE//2)]# 射击if ticks % 10 == 0:hero.single_shoot(bullet1_surface)# 控制子弹hero.bullets1.update()# 绘制子弹hero.bullets1.draw(screen)# 产生敌机 *****************************************************if ticks % 30 == 0:enemy = Enemy(enemy1_surface, [randint(0, SCREEN_WIDTH - enemy1_surface.get_width()), -enemy1_surface.get_height()])enemy1_group.add(enemy)# 控制敌机enemy1_group.update()# 绘制敌机enemy1_group.draw(screen)# ************************************************************# 检测敌机与子弹的碰撞 *******************************************enemy1_down_group.add(pygame.sprite.groupcollide(enemy1_group, hero.bullets1, True, True))for enemy1_down in enemy1_down_group:screen.blit(enemy1_down_surface[enemy1_down.down_index], enemy1_down.rect)if ticks % (ANIMATE_CYCLE//2) == 0:if enemy1_down.down_index < 3:enemy1_down.down_index += 1else:enemy1_down_group.remove(enemy1_down)# ************************************************************# 绘制飞机screen.blit(hero.image, hero.rect)ticks += 1 # python已略去自增运算符# 更新屏幕pygame.display.update()                                         # 处理游戏退出# 从消息队列中循环取for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()exit()# ※ Python中没有switch-case 多用字典类型替代# 控制方向       if event.type == pygame.KEYDOWN:if event.key in offset:offset[event.key] = hero.speedelif event.type == pygame.KEYUP:if event.key in offset:offset[event.key] = 0# 移动飞机hero.move(offset)

Pygame - Python游戏编程入门(3)相关推荐

  1. Pygame - Python游戏编程入门(1)

    前言 在上一篇中,我们初步熟悉了pygame的控制流程,但这对于一个游戏而言是远远不够的.所以在这一篇中,我们的任务是添加一架飞机(玩家),并且能够控制它进行移动,这样我们就又离目标进了一步了~ε=ε ...

  2. pygame 学习笔记(4)推荐一本python入门游戏书籍《PYTHON游戏编程入门》

    简介 <PYTHON游戏编程入门>(More Python Programming for the Absolute Beginner)是 S.Harbour写的一本入门书籍,基于pyga ...

  3. python游戏编程入门-python游戏编程入门

    <Python游戏编程入门> 这些文章负责整理在这本书中的知识点.注意事项和课后习题的尝试实现. 并且对每一个章节给出的最终实例进行分析和注释. 初识pygame:pie游戏 pygame ...

  4. python游戏编程入门 免费-python游戏编程入门 python游戏编程入门课

    python游戏编程入门 python游戏编程入门课 什么是python游戏编程入门?首先我们需要认识什么是Python Python既是一个软件工具包,也是一种语言.Python软件包包含了一个名为 ...

  5. 《Python游戏编程入门》——1.2 初识Python

    本节书摘来自异步社区<Python游戏编程入门>一书中的第1章,第1.2节,作者[美]Jonathan S. Harbour ,李强 译,更多章节内容可以访问云栖社区"异步社区& ...

  6. 青少年Python游戏编程入门(Beginning Game Programming for Teens with Python译文)

    青少年Python游戏编程入门 Beginning Game Programming for Teens with Python   Julian Meyer on January 22, 2013 ...

  7. python游戏编程入门免费_python游戏编程入门 python游戏编程入门课

    python游戏编程入门 python游戏编程入门课 什么是python游戏编程入门?首先我们需要认识什么是Python Python既是一个软件工具包,也是一种语言.Python软件包包含了一个名为 ...

  8. python游戏编程入门p_Python游戏编程入门 PDF高清完整版

    Python游戏编程入门 PDF高清完整版 作者: 哈伯 (Jonathan S.Harbour) 译者: 李强 出版年: 2015-1-1 页数: 292 装帧: 平装 ISBN: 97871153 ...

  9. python游戏编程入门源代码_python游戏编程入门源代码

    [实例简介] <Python游戏编程入门>的源代码,作者Jonathan S.Harbour 很好的资源,希望对学习python的同学有帮助,代码都可以运行 [实例截图] [核心代码] p ...

最新文章

  1. 以太坊搭建,不能使用puppeth 创建初始块,报错Fatal: Failed to write genesis block: unsupported fork ordering: eip15
  2. 读《JavaScript dom编程艺术(第2版)》笔记 1-2
  3. Spring Boot中配置文件application.properties使用
  4. R pdf大小_「福昕PDF助手」12个常用的Word快捷键,一看就会,你值得拥有!
  5. spring官方网站
  6. 需求简报_代码简报:我如何通过做自己喜欢的事情来获得顶级技术实习
  7. c语言程序设计平时作业代刷,C语言程序设计——小学生口算刷题系统
  8. linux 常见命令整理记录
  9. 【词向量】从Word2Vec到Bert,聊聊词向量的前世今生(一)
  10. java servlet 开发_Java之基于Servlet的Web开发简介
  11. 字符编码乱码问题(servlet底层 编码大揭秘)
  12. Python--day21--包
  13. 算法“视”界杯上演十强争锋,大赛终极一战圆满落幕
  14. 2.任务包多线程并行计算
  15. asp.net 页面ajax访问被阻塞
  16. 物流软件之Microcity介绍
  17. anki 神级插件 fastWQ 提取本地朗文音频
  18. 商城购物系统设计与实现(Java毕业设计-SSM项目)
  19. windows 系统快捷键小技巧
  20. css实现背景图片透明内容不透明

热门文章

  1. win11VMware打开虚拟机就蓝屏重启以及启动不了的解决方案(最全方案)
  2. 系统——Linux服务器
  3. 3090人工神经网络工作站配置
  4. 4412开发板UT-Exynos4412三星A9四核4412开发平台调试android4.0GPS功能信号超强
  5. 4412 fimc to hdmi
  6. python国内下载地址_python下载链接
  7. 大海捞针 Skia(C++) 第 1 期:Skia 环境搭建
  8. 调焦后焦实现不同距离成像_一次性学全佳能尼康的对焦模式、对焦区域模式等对焦知识!(上)...
  9. android uri图片压缩,详解android 通过uri获取bitmap图片并压缩
  10. 【2018-11-09】中证500指数的估值详情