@Python编程从入门到实践 Python项目练习

四、创建Ship类

建立ship.py,创建Ship类,管理飞船行为。

# ship.py
import pygame class Ship(): def __init__(self, ai_settings, screen):
"""初始化飞船并设置其初始位置"""
self.screen = screen
self.ai_settings = ai_settings # 加载飞船图像
self.image = pygame.image.load('images/ship.bmp')
self.image = pygame.transform.scale(self.image, (37*2, 34*2)) # 获取其外接矩形(rect为surface矩形属性)
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect() # 将每艘新飞船放在屏幕底部中央
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom # 在飞船的属性center中存储小数值
self.center_x = float(self.rect.centerx)
self.center_y = float(self.rect.centery) # 移动标志
self.moving_right = False
self.moving_left = False
self.moving_up = False
self.moving_down = False def update(self):
"""根据移动标志调整飞船到位置"""
# 更新飞船的center值, 而不是rect
if self.moving_right and self.rect.right < self.screen_rect.right:
self.center_x += self.ai_settings.ship_speed_factor
if self.moving_left and self.rect.left > 0:
self.center_x -= self.ai_settings.ship_speed_factor if self.moving_down and self.rect.bottom < self.screen_rect.bottom:
self.center_y += self.ai_settings.ship_speed_factor
if self.moving_up and self.rect.top > self.screen_rect.top:
self.center_y -= self.ai_settings.ship_speed_factor # 根据self.center更新rect对象
self.rect.centerx = self.center_x
self.rect.centery = self.center_y def blitme(self):
"""在指定位置绘制飞船"""
self.screen.blit(self.image, self.rect) def center_ship(self):
"""让飞船在屏幕上居中"""
self.center_x = self.screen_rect.centerx
ship_half_width = self.rect.bottom - self.center_y
self.center_y = self.screen_rect.bottom - ship_half_width

五、创建Bullet类

建立bullet.py,创建Bullet类,继承pygame.sprite中的Sprite类,作为游戏中的子弹元素。

# settings.py
import pygame from pygame.sprite import Sprite class Bullet(Sprite):
"""一个对子弹发射进行管理的类""" def __init__(self, ai_settings, screen, ship):
super(Bullet, self).__init__()
self.screen = screen # 在(0, 0)处创建一个表示子弹的矩形,将初始位置放在(0,0)
self.rect = pygame.Rect(0, 0, ai_settings.bullet_width,
ai_settings.bullet_height)
# 重设子弹位置
self.rect.centerx = ship.rect.centerx
# self.rect.centery = ship.rect.centery
self.rect.top = ship.rect.top # 存储用小数表示的子弹位置 self.y = float(self.rect.y) self.color = ai_settings.bullet_color
self.speed_factor = ai_settings.bullet_speed_factor def update(self):
"""向上移动子弹""" # 更新表示子弹的小数值
self.y -= self.speed_factor
# 更新表示子弹的rect的位置
self.rect.y = self.y def draw_bullet(self):
"""在屏幕上绘制子弹"""
pygame.draw.rect(self.screen, self.color, self.rect)

六、创建game_functions模块

创建game_functions.py 模块,存储函数,让alien_invasion中主代码更易懂。

#game_functions.py
import sys import pygame from bullet import Bullet
from passenger import Passenger
from time import sleep def check_keydown_events(event, ai_settings, screen, ship, bullet_group):
"""响应按键"""
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True
elif event.key == pygame.K_UP:
ship.moving_up = True
elif event.key == pygame.K_DOWN:
ship.moving_down = True
elif event.key == pygame.K_SPACE:
fire_bullet(ai_settings, screen, ship, bullet_group)
elif event.key == pygame.K_ESCAPE:
sys.exit() def fire_bullet(ai_settings, screen, ship, bullet_group):
"""如果没有到达限制,就发射一颗子弹"""
# 创建一颗子弹,并将其加入到编组bullets中
if len(bullet_group) < ai_settings.bullet_group_allowed:
new_bullet = Bullet(ai_settings, screen, ship)
bullet_group.add(new_bullet) def check_keyup_events(event, ship):
"""松开按键"""
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False
elif event.key == pygame.K_UP:
ship.moving_up = False
elif event.key == pygame.K_DOWN:
ship.moving_down = False def check_events(ai_settings, screen, ship, bullet_group):
"""响应按键和鼠标事件"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# 按下
elif event.type == pygame.KEYDOWN:
check_keydown_events(event, ai_settings, screen, ship, bullet_group)
# 松开
elif event.type == pygame.KEYUP:
check_keyup_events(event, ship) def update_screen(ai_settings, screen, ship, passenger_group, bullet_group):
"""更新屏幕上的图像,并切换到新屏幕""" # 每次循环时(即打开游戏运行)重绘屏幕
screen.fill(ai_settings.bg_color)
# 绘制子弹
for bullet in bullet_group:
bullet.draw_bullet()
ship.blitme()
for i in passenger_group:
i.blitme()
#passenger_group.draw(screen) # 更新屏幕(隐藏旧屏,更新新屏)
pygame.display.flip() def update_bullet_group(ai_settings, screen, ship, passenger_group, bullet_group ):
"""更新子弹的位置,并删除已消失的子弹"""
# 更新子弹的位置
bullet_group.update() # 删除已消失的子弹
for bullet in bullet_group.copy():
if bullet.rect.top <= 0:
bullet_group.remove(bullet) check_bullet_passenger_collisions(ai_settings, screen, ship, passenger_group,
bullet_group) def check_bullet_passenger_collisions(ai_settings,screen, ship, passenger_group,
bullet_group):
# 检查是否有子弹击中了乘客
# 如果是这样,就删除相应的子弹和乘客
# groupcollide()返回字典,实参为True即删除发生碰撞的子弹或外星人
collisions = pygame.sprite.groupcollide(bullet_group, passenger_group, False, True) if len(passenger_group) == 0:
# 删除现有子弹并新建一波新的乘客
bullet_group.empty()
create_fleet(ai_settings, screen, ship, passenger_group) def get_number_passenger_x(ai_settings, passenger_width):
"""计算每行可以容纳多少个乘客"""
available_space_x = ai_settings.screen_width - 2 * passenger_width
number_passenger_x = int(available_space_x / (2 * passenger_width))
return number_passenger_x def get_number_rows(ai_settings, ship_height, passenger_height):
"""计算屏幕可以容纳多少行的乘客"""
available_space_y = (ai_settings.screen_height - passenger_height - ship_height)
number_rows = int(available_space_y / (1.5 * passenger_height))
return number_rows def create_passenger(ai_settings, screen, passenger_group, passenger_number, row_number):
"""创建一个乘客并将其放在当前行"""
passenger = Passenger(ai_settings, screen)
passenger_width = passenger.rect.width passenger.x = passenger_width + 2 * passenger_width * passenger_number
passenger.rect.x = passenger.x
passenger.rect.y = 0.5 * passenger.rect.height + 1.5 * passenger.rect.height * row_number
passenger_group.add(passenger) def create_fleet(ai_settings, screen, ship, passgener_group):
"""创建乘客群"""
# 创建一个乘客,并计算一行可以容纳多少人
passenger = Passenger(ai_settings, screen)
number_passenger_x = get_number_passenger_x(ai_settings, passenger.rect.width)
number_rows = get_number_rows(ai_settings, ship.rect.height, passenger.rect.height) # 创建乘客群
for row_number in range(number_rows):
for passenger_number in range(number_passenger_x):
create_passenger(ai_settings, screen, passgener_group, passenger_number,
row_number) def change_fleet_direction(ai_settings, passenger_group):
"""将整群乘客下移,并改变它们的方向"""
for passenger in passenger_group.sprites():
passenger.rect.y += ai_settings.fleet_drop_speed
ai_settings.fleet_direction *= -1 def check_fleet_edges(ai_settings, passenger_group):
"""有外星人到达边缘时采取相应的措施"""
for passenger in passenger_group.sprites():
if passenger.check_edges():
change_fleet_direction(ai_settings, passenger_group)
break def ship_hit(ai_settings, stats, screen, ship, passenger_group, bullet_group):
"""响应被乘客撞到的飞船"""
if stats.ships_left > 0:
# 讲ship_left减一
stats.ships_left -= 1
# 清空乘客列表和子弹列表
passenger_group.empty()
bullet_group.empty() # 创建一群新的外星人,并讲飞船放在屏幕底部中央
create_fleet(ai_settings, screen, ship, passenger_group)
ship.center_ship()
# 暂停
sleep(0.5)
else:
stats.game_active = False def check_passenger_group_bottom(ai_settings, stats, screen, ship, passenger_group, bullet_group):
"""检查是否有外星人到达屏幕底端"""
screen_rect = screen.get_rect()
for passenger in passenger_group.sprites():
if passenger.rect.bottom >= screen_rect.bottom:
# 像飞船被撞到一样进行处理
ship_hit(ai_settings, stats, screen, ship, passenger_group, bullet_group)
break def update_passenger_group(ai_settings, stats, screen, ship, passenger_group, bullet_group):
"""检查是否有乘客在边缘,并更新乘客群中所有乘客的位置"""
check_fleet_edges(ai_settings, passenger_group)
passenger_group.update() # 检测外星人和飞船之间的碰撞
if pygame.sprite.spritecollideany(ship, passenger_group):
ship_hit(ai_settings, stats, screen, ship, passenger_group, bullet_group)
# 检查是否有外星让到达屏幕底端
check_passenger_group_bottom(ai_settings, stats, screen, ship, passenger_group, bullet_group)

Pygame小游戏练习二的更多相关文章

  1. pygame小游戏之坦克大战

    以前在学校的时候无聊的学了会pygame.看了大概一周的教学视频,做出来个坦克大战的小游戏 Python3.5  pycharm import pygame,sys,time from random ...

  2. Pygame小游戏练习五

    @Python编程从入门到实践 Python项目练习 十一.显示游戏得分及最高分 创建新类Scoreboard,用以显示得分和最高分. # scoreboard.py import pygame.fo ...

  3. Pygame小游戏练习四

    @Python编程从入门到实践 Python项目练习 九.添加Play按钮 一.创建Button类 先让游戏一开始为非活动状态 # game_stats.py # --snip-- self.game ...

  4. Pygame小游戏练习一

    @Python编程从入门到实践 Python项目练习 一.安装Python包Pygame 通过pip安装包工具安装 python3 -m pip --version #查看是否安装pip 确定安装pi ...

  5. web版扫雷小游戏(二)

    接上篇~~第一次写这种技术博客,发现把自己做的东西介绍出来还是一件脑力活,不是那么轻松啊,好吧,想到哪写到哪,流水记录之,待完成之后再根据大家的意见进行修改吧. 游戏实现 根据对扫雷游戏的体验和分析, ...

  6. Pygame小游戏练习三

    @Python编程从入门到实践 Python项目练习 七.创建Passenger类 创建passenger.py文件,创建Passenger类,控制乘客属性和行为 # passenger.py imp ...

  7. 软件设计之基于Java的连连看小游戏(二)——游戏基础界面的制作及事件的添加

    上次完成到游戏首页的制作,今天完成了游戏基础界面的制作以及事件的简单添加.由于功能尚未完全实现,因此游戏界面的菜单列表只是简单地添加了一下,其余菜单列表以及倒计时等在后续的制作中逐一完善. 1.首先在 ...

  8. python小游戏-pygame模块

    一.tkinter模块的GUI 基本上使用tkinter来开发GUI应用需要以下5个步骤: 导入tkinter模块中我们需要的东西. 创建一个顶层窗口对象并用它来承载整个GUI应用. 在顶层窗口对象上 ...

  9. Python小游戏——外星人入侵(保姆级教程)第一章 01创建Pygame窗口 02创建设置类Setting()

    系列文章目录 第一章:武装飞船 01:创建Pygame窗口以及响应用户输入 02:创建设置类Setting() 一.前期准备 1.语言版本 Python3.9.0 2.编译器 Pycharm2022 ...

随机推荐

  1. ZR#955 折纸

    ZR#955 折纸 解法: 可以发现折纸之后被折到上面的部分实际上是没有用的,因为他和下面对应位置一定是一样的,而影响答案的只有每个位置的颜色和最底层的坐标范围.因此,我们只需要考虑最底层即可,即我们 ...

  2. 小程序开发:用原生还是选框架(wepy/mpvue/uni-app/taro)?

    小程序开发:用原生还是选框架(wepy/mpvue/uni-app/taro)? 自 2017-1-9微信小程序诞生以来,历经2年多的迭代升级,已有数百万小程序上线,成为继Web.iOS.Androi ...

  3. 电路IO驱动能力

    驱动能力 电源驱动能力 -> 输出电流能力 -> 输出电阻 指输出电流的能力,比如芯片的IO在高电平时的最大输出电流是4mA -> 该IO口的驱动驱动能力为4mA 负载过大(小电阻) ...

  4. js中那些方法不改变原来的数组对象

    一.map方法 function fuzzyPlural(single) { var result = single.replace(/o/g, 'e'); //replace也不会修改原来数组的值, ...

  5. postgresql interval 字段拼接

    无拼接时: SELECT scan_time + '5 day' FROM tbl_temp_record SELECT scan_time + '-5 day' FROM tbl_temp_reco ...

  6. java 设计模式 之 装饰器模式

    装饰器模式的作用 在不修改原先对象核心的功能的情况下,对功能进行增强. 增强对象的功能的途径 通过类继承的方式,对父对象进行增强操作,例如造车是父类,改装跑车,跑车加大灯,改装房车,房车加私人电影院. ...

  7. vue单页面项目架构方案

    这里的架构方案是基于vue-cli2生成的项目应用程序产生的,是对项目应用程序或者项目模板的一些方便开发和维护的封装.针对单页面的解决方案. 主要有四个方面: 一,不同环境下的分别打包 主要是测试环境 ...

  8. 微信自定义分享 IOS端分享失败

    1.在IOS微信浏览器中自定义分享link 链接中的中文需要encodeURIComponent() 编码(安卓会自动编码) 2.另外在IOS微信浏览器中自定义分享 imgUrl  不能大于34KB ...

  9. Qt编写安防视频监控系统4-删除视频

    一.前言 一般会有两种处理方式来删除视频,一种是鼠标右键菜单,删除当前视频或者删除所有视频,一种是直接按住当前视频,移到视频通道界面以外就表示删除当前视频,这也是个比较人性化的设置,每个人的喜好不一样 ...

  10. Spring Boot连接DB2查询结果时报错“java.lang.AbstractMethodError: com.ibm.db2.jcc.t4.b.isValid(I)Z”的解决办法

    关于在maven项目中如何添加DB2的坐标的详细,见:https://www.cnblogs.com/zifeiy/p/7918554.html Spring Boot项目中的application. ...