一、该源码的出处
以下所有的内容都来自于Python编程:从入门到实践(此书有电子版,若需要电子版,可在我的下载中查看到相关信息),该编码的源码也可以在我的下载中查看
二、为什么写?
因为书上的很多内容可能会忘记,所以直接在敲源码的途中将一些需要记住的点还有一些需要理解的点以注释的方式呈现了出来
三、项目讲解
(1)讲一下项目
这个项目是外星人入侵游戏三章中的其中一章,最后实现的结果是在屏幕上有一辆飞船可以左右移动(在移动的时候不能移出屏幕而且要可以连续移动),并可以发射子弹(限制发射的子弹数)
(2)从项目中学习到的点
游戏开发计划的指定
使用Pygame编写的游戏的基本机构
设置背景色,以及如何设置存储在可供游戏的各个部分访问的独立类中
在屏幕上绘制图像,以及如何让玩家控制游戏元素的移动
如何创建自动移动的元素(子弹)
如何定期重构项目的代码
(3)自己的总结
从该项目中学到了很多东西,真正实践到做一个完整的项目应该注意的点。比如定义(可以设置一些经常设置的变量在一个类中,这样容易修改,设置其他的变量的时候如果在函数中需要注意self的使用,变量需要能够看懂,设置类的存储的时候也要注意之后的使用,用一些方法创建的图像的时候最好将其赋给一个变量)、函数(函数的调用真的是非常重要,但是要注意函数中的self以及函数间彼此的调用)、传参(传参数不需要一次性传完,需要慢慢传,因为要添加东西,所以可以根据你的需要再添加参数)、类与类(重构中最重要的就是类与类之间的联系,尽量将主程序文件中的内容缩短)
四、说明
输出源码前,我想先说明以下几点
(1)我使用的语言是python
(2)我使用的IDE是Pycharm
(3)该项目一共包含5个py文件,以及一张图片,如下图
五、源码
(1)alien_invasion.py
#该主文件创建一系列整个游戏都要用到的对象:存储在ai_settings中的设置、存储在screen中的主显示surface以及一个飞船实例
#还包含游戏的主循环,这是一个调用check_events()、ship.update()和update_screen()的while循环
#整个游戏只需要运行该文件,其他文件包含的代码被间接或直接的导入到这个文件中
#创建Pygame窗口以及响应用户输入
import sys
import pygame
from ship import Ship
from settings import Settings
import game_functioins as gf
from pygame.sprite import Group
def run_game():
#初始化游戏并创建一个屏幕对象
pygame.init() #初始化背景设置,让Pygame能够正确工作
#我们导入了Settings类,这里创建了一个Settings实例,并将其存储在ai_settings中
ai_settings = Settings()
screen = pygame.display.set_mode(
(ai_settings.screen_width,ai_settings.screen_height))
# (ai_settings.screen_width,ai_settings.screen_height))
pygame.display.set_caption("Alien Invasion")
#创建一艘飞船
#这里之所以要将形参添加到这里,原因是因为在ship中的Ship函数中添加了形参
ship = Ship(ai_settings,screen)
#创建一个用于存储子弹的编组
#创建了一个Group实例,并将其命名为bullets
# 这个编组是在while循环外面创建的,这样就无需每次运行该循环时都创建一个新的子弹编组
#我们将bullets传递给了check_events()和update_screen()
#在check_events()中,需要玩家按空格键时处理bullets
#在update_screen()中,需要更新要绘制到屏幕上的bullets
#当编组调用update()时,编组将自动对其中的每个精灵调用update()
# 因此代码行bullets.update()将为编组bullets中的每颗子弹调用bullets.update()
bullets = Group()
"""
#个人理解:设置屏幕的高低以及左上角名称
# 实参(1200,800)是一个元组,指定了游戏窗口的尺寸
#对象screen是一个surface,surface是屏幕的一部分,用于显示游戏元素
#在这个游戏中,每个元素都是一个surface
# display.set_mode()返回的surface表示整个游戏窗口
#激活游戏的动画循环后,每经过一次循环都将自动重绘这个surface
screen = pygame.display.set_mode((1200,800))
pygame.display.set_caption("Alien Invasion")
"""
"""
#个人理解:设置整个游戏的背景颜色
#设置背景色
#该颜色只需指定一次,因此在主while循环前定义它
#在Pygame中,颜色是以RGB值指定的
#(255,0,0)红色,(0,255,0)绿色,(0,0,255)蓝色,(230,230,230)灰色
bg_color = (230,230,230)
"""
#开始游戏的主循环
#如果在循环内部创建编组,游戏运行时将创建数千个子弹编组,导致游戏慢的像蜗牛
#如果游戏停滞不前,很有可能是主while循环中发生的情况
while True:
#调用鼠标点击
#游戏中发生的情况:检查玩家的输入
gf.check_events(ai_settings,screen,ship,bullets )
#飞机的位置将在检测到键盘事件后(但在更新屏幕前)更新
#这样,玩家输入时,飞船的位置将更新,从而确保使用更新后的位置将飞船绘制到屏幕上
#游戏中发生的情况:更新飞船的位置
ship.update()
#游戏中发生的情况:所有未消失的子弹的位置
gf.update_bullets(bullets)
"""将子弹管理代码移到game_functions中,让主程序文件尽可能简单
bullets.update()
#子弹抵达屏幕顶端后消失,这仅仅是因为Pygame无法在屏幕外面绘制它们
#它们的y坐标为负数,且越来越小,这是个问题,因为它们将继续消耗内存和处理能力
# 删除已消失的子弹
#在for循环中,不应从列表或编组中删除条目,因此必须遍历编组的副本,使用方法copy()
for bullet in bullets.copy():
#判断其是否到达了顶端,并在bullets中将其删除
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
#验证上述三行代码是否有效,可以print一下,应该是最终都会归于0
#验证完之后就要将其print删除,因为会使游戏速度大大降低
#因为输出写入到中断而花费的时间比将图形绘制到游戏窗口花费的时间还多
#如果运行该语句会发现其数量一直更新,比如如果是0,会输出很多0
#print(len(bullets))
"""
"""
#个人理解:当鼠标点击右上角关闭按钮时,该程序将退出
#监视键盘和鼠标事件
#为访问Pygame检测到的事件,我们使用方法pygame.event.get()
#所有键盘和鼠标事件都将促使for循环运行
for event in pygame.event.get():
#玩家单击游戏窗口的