手把手教你写Python小游戏——外星人入侵

本文将引导你逐步创建一个Python小游戏——外星人入侵,涉及Pygame库的使用、游戏窗口创建、飞船操控、子弹射击、外星人群生成与移动、碰撞检测以及游戏结束条件等内容。通过实践,你将了解游戏开发的基本流程和技术要点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章目录


前言

开发游戏是学习语言的理想方式。看别人玩你写的游戏能获得满足感,而编写简单的游戏有助于你明白专业级游戏是怎样编写出来的。在阅读本文章的同时,请手动输入每一行代码,以明白各行代码的用处,并尝试不同的值和设置,以对如何改进游戏的交互性有更深的认识。


提示:以下为本文主要内容,共分为六个部分,具体可以参考本文目录。
 

1、写在前面

本文时基于Python开发的一款小游戏,你必须具备一定的Python基础,这样你写起来才能得心应手。
如果你对Python游戏感兴趣,请接着看下去。

 

2、对游戏的基本介绍

2.1 游戏界面

这款游戏类似于“飞机大战”,就是一开始你会控制一架飞机,在屏幕的底端,你可以左右移动,发射子弹,然后射杀外星人。随着游戏的进行,游戏的节奏会越来越快,飞船的移动速度加快,外星人的下降速度也会变快。界面大概长这个样子:游戏主界面
 

2.2 项目规划

开发大型项目时,制定好规划后再动手编写代码很重要。规划可以确保你不偏离轨道,从而提高项目成功的可能性。
这是有关“外星人入侵”游戏的描述,其中大概的描述了游戏的玩法:
游戏开始时,玩家驾驶一架飞船出现在屏幕的底部中央,玩家可以通过方向键控制飞船的左右移动,还可以按空格键发射子弹,用来射杀出现在屏幕顶部的外星人。当所有的外星人都被射杀后,将会出现一群新的外星人,并且移动速度更快,但同时你的飞船移动速度也会变快,子弹飞行速度也会更快。当由外星人碰到飞船或到达屏幕底部时,玩家就损失一架飞船,当所有飞船都损坏时,游戏结束。

3、安装库

该游戏使用到的库有Pygame.

3.1使用pycharm安装

我使用的编译器是pycharm,如果有想了解的可以自行搜索。下面来介绍安装流程。
1.打开pycharm设置(Ctrl+Alt+s)
2.找到Project:(Project name)
3.点击Python Interpreter
4.点击左上角的加号(版本可能不同,找那个小加号就行)
5.搜索Pygame
6.点击Install Package
7.安装完成会弹出一个绿色的条儿
安装Pygame包

3.2 使用cmd安装

快捷键:
1.win+R
2.输入cmd
3.输入pip install Pygame
安装完成会显示Successfully installed Pygame

4、着手编写程序

做好一切准备工作后,现在来正式编写代码。
首先创建一个Pygame窗口,在这个窗口里我们来显示我们的游戏画面。

4.1 创建Pygame游戏窗口以及响应用户输入

在文本编辑器中新建一个文件,将其保存为alien_invasion.py 在其中输入以下代码:

import sys

import pygame


class AlienInvasion:
    """管理游戏资源和行为的类"""

    def __init__(self):
        """初始化游戏并创建游戏资源"""
        pygame.init()    # 对硬件的初始化(initialize) 可以看下面的链接

        self.screen = pygame.display.set_mode((1200, 800))   # 设置窗口大小
        pygame.display.set_caption("Alien Invasion")   # 设置窗口上的游戏名

    def run_game(self):
        """开始游戏的主循环"""
        while True:
            # 监视键盘和鼠标事件。
            for event in pygame.event.get():
                if event.type == pygame.QUIT:   # 鼠标点击右上角的叉叉时就退出
                    sys.exit()

            # 让最近绘制的屏幕可见
            pygame.display.flip()


if __name__ == '__main__':   # 见下方链接
    # 创建游戏实例并运行游戏
    ai = AlienInvasion()   # 创建一个AlienInvasion实例
    ai.run_game()   # 调用run_game方法

pygame.init()初始化链接

if name == ‘main’:链接
 
 
首先,导入模块sys和pygame,模块中包含了开发游戏所具有的功能,玩家退出时,就使用了模块sys中的工具退出游戏。
 
接下来,创建了一个类AlienInvasion,在这个类中调用pygame.display.set_mode来设置窗口大小,并将此赋给属性self.screen,目的是让这个类中的所有方法都可以使用它。
 
这个游戏由方法run_game控制。该方法包含一个while循环,这个循环包含一个事件循环管理屏幕更新的代码事件是用户玩游戏时进行的操作,如按键或移动鼠标。
 
为访问Pygame检测到的事件,这里使用了pygame.event.get(),并创建了一个循环,在这个循环中,使用if语句来检测并响应特定的事件。例如,当玩家单击右上角的关闭按钮时,将检测到pygame.QUIT事件,进而调用sys.exit()来退出游戏。
 
在while循环的最后,调用了pygame.display.flip()函数,这个函数在每次执行while循环时,都会被调用。玩家对游戏做出一定操作后,pygame.display.flip()将不断更新屏幕,所以玩家可以看到游戏元素的移动。
 
在文件的末尾,创建一个游戏实例并调用run_game()。这时如果运行alien_invasion.py,将看到一个空的Pygame 窗口。

4.2 设置背景色

Pygame默认创建一个黑色的屏幕,我们来添加一个属性,改变一下游戏窗口的背景颜色。
 
在方法__init()__的末尾添加属性bg_color:

        self.bg_color = (230, 230, 230)   # 这是一种浅灰色

然后在方法run_game()中调用此属性:

    def run_game(self):
        """开始游戏的主循环"""
        while True:
            # 监视键盘和鼠标事件。
            for event in pygame.event.get():
                if event.type == pygame.QUIT:   # 鼠标点击右上角的叉叉时就退出
                    sys.exit()

            # 每次循环时都重新绘制屏幕
            self.screen.fill(self.bg_color)

            # 让最近绘制的屏幕可见
            pygame.display.flip()

 
如果现在运行代码,将会出现一个灰色的窗口。
在这里插入图片描述
 

4.3 创建一个设置的类

一个游戏通常由很多的设置,下面我们创建一个settings模块,将所有的设置都放在其中。这样,每当需要访问设置时,只需使用一个设置对象。另外,在项目增大时,每次修改设置将变得更加容易。
 
创建一个新文件,并命名为setting.py。并添加一个类Settings:

class Settings:
    """存储游戏Alien_invasion中所有设置的类"""

    def __init__(self):
        """初始化游戏的设置"""
        # 屏幕设置
        self.screen_width = 1200
        self.screen_height = 800
        self.bg_color = (230, 230, 230)
        

 
为了在项目中创建Settings实例并用它来访问设置,需要将alien_invasion.py修改成这样:
首先在主程序文件alien_invasion.py中导入Settings类:

from settings import Settings

然后修改类AlienInvasion:

    def __init__(self):
        """初始化游戏并创建游戏资源"""
        pygame.init()    # 对硬件的初始化(initialize) 可以看下面的链接
        self.settings = Settings()

        self.screen = pygame.display.set_mode((self.settings.screen_width, self.settings.screen_height))

        pygame.display.set_caption("Alien Invasion")   # 设置窗口上的游戏名


    def run_game(self):
        """开始游戏的主循环"""
        while True:
            # 监视键盘和鼠标事件。
            for event in pygame.event.get():
                if event.type == pygame.QUIT:   # 鼠标点击右上角的叉叉时就退出
                    sys.exit()

            # 每次循环时都重新绘制屏幕
            self.screen.fill(self.settings.bg_color)

            # 让最近绘制的屏幕可见
            pygame.display.flip()

如果这时运行代码,结果不会有任何不同。
 

4.4 添加飞船图像

在这里插入图片描述

这就是飞船的图像,可右键保存到本地。
 

4.4.1 创建ship类

创建一个新的文件,命名为ship,并创建Ship类。提前将小飞船的图像和程序放在一个文件夹里。

import pygame


class Ship:
    """管理飞船的类"""

    def __init__(self, ai_game):
        """初始化飞船并设置其初始位置"""
        self.screen = ai_game.screen
        self.screen_rect = ai_game.screen.get_rect()

        # 加载飞船图像并获取其外界矩形
        self.image = pygame.image.load('ship.png')
        self.rect = self.image.get_rect()

        # 对于每艘新的飞船,都将其放在屏幕底部的中央
        self.rect.midbottom = self.screen_rect.midbottom   # 意思是飞船底部中央和屏幕底部中央对齐

    def blitme(self):
        """在指定的位置绘制飞船"""
        self.screen.blit(self.image, self.rect)

ship的方法__init()__接收两个参数:引用self和指向当前AlienInvasion实例的引用。这让ship可以访问AlienInvasion中的所有资源。在第9行,将屏幕赋给了Ship的一个属性,以便在这个类中的所有方法中轻松访问。在第10行,使用方法get_rect()访问屏幕的属性rect,并将其赋给了self.screen_rect,这让我们能够将飞船放到屏幕上合适的位置。
 
第13,14行将小飞船的图像加载进来,然后获取小飞船的图像大小,将其赋给self.rect。
 
最后在方法blitme()中绘制飞船。
 
注意:
在pygame中,原点(0,0) 位于屏幕左上角。在1200*800的屏幕上,右下角的坐标为(1200,800)。
 

4.4.2 在屏幕上绘制飞船

下面更新alien_invasion.py,创建一艘飞船并调用其方法blitme():
首先导入ship类:

from ship import Ship

然后在创建屏幕后创建一个ship实例:

self.ship = Ship(self)

调用Ship()时,必须提供一个参数:一个AlienInvasion实例。在这里,self指向的是当前AlienInvasion实例。这个参数让Ship能访问游戏资源,如对象screen。我们将这个实例赋给了self.ship。
在方法run_game()中,调用self.ship.blitme()将飞船绘制到屏幕上。

self.ship.blitme()

 
修改后的代码:

class AlienInvasion:
    """管理游戏资源和行为的类"""

    def __init__(self):
        --snip--   # 重复部分省略
        pygame.display.set_caption("Alien Invasion")   # 设置窗口上的游戏名

        self.ship = Ship(self)
     def run_game(self):
     		--snip--   # 重复部分省略
            # 每次循环时都重新绘制屏幕
            self.screen.fill(self.settings.bg_color)
            self.ship.blitme()

            # 让最近绘制的屏幕可见
            pygame.display.flip()
--snip--

如果现在运行alien_invasion.py,将看到一艘飞船出现在屏幕底部中央。

4.5重构:方法_check_events()和_update_screen()

在大型项目中,经常需要在添加新代码之前重构既有代码。旨在简化既有代码的结构,使其更容易拓展。本节把越来越长的方法run_game()拆分成两个辅助方法(helper method)。辅助方法在类中执行任务,但并非是通过实例调用的。在python中,辅助方法以单个下划线开头。

4.5.1 新方法_check_events()

我们把管理事件的代码移到一个名为_check_events()的方法中,以简化run_game()并隔离事件管理。通过事件管理循环,可将事件管理与游戏的其他方面分离。
在方法run_game()后新增方法_check_events():

    def _check_events(self):
        """响应键盘和鼠标事件。"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:  # 鼠标点击右上角的叉叉时就退出
                sys.exit()

简化后的run_game()方法:

    def run_game(self):
        """开始游戏的主循环"""
        while True:
        	# 调用方法 _check_events
            self._check_events()
            # 每次循环时都重新绘制屏幕
            self.screen.fill(self.settings.bg_color)
            --snip--

4.5.2 新方法_update_screen()

为进一步简化run_game(),将更新屏幕的代码移到一个名为_update_screen()的方法中。
在方法_check_events后新增方法_update_screen():

    def _update_screen(self):
        """更新屏幕上的图像,并切换到新屏幕"""
        self.screen.fill(self.settings.bg_color)
        self.ship.blitme()

        pygame.display.flip()

简化后的run_game()方法:

    def run_game(self):
        """开始游戏的主循环"""
        while True:
            self._check_events()
            self._update_screen()

经过新增的两个方法的重构,run_game()部分变得简单许多。
 
在开发大型项目时应该遵循的原则:先编写尽可能简单的代码,等项目越来越复杂后再对其进行重构。

4.6 驾驶飞船

这一部分我们将编写代码来让飞船动起来!

4.6.1 响应按键

当用户在按下方向键时,飞船将做出响应。当一个按键被按下时,都会在Pygame中注册一个事件。事件都是通过方法pygame.event.get()获取的,因此需要在方法_check_events()中指定要检查那些类型的事件。每次按键都被注册为一个KEYDOWN事件。
Pygame检测到KEYDOWN事件时,需要检查按下的是否是触发行动的键。例如,如果玩家按下的是右方向键,就增大飞船的rect.centerx值,将飞船向右移动,在方法_check_events中添加以下代码:

    def _check_events(self):
        """# 监视键盘和鼠标事件。"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:  # 鼠标点击右上角的叉叉时就退出
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT:
                    # 向右移动飞船
                    self.ship.rect.x += 1

在方法_check_events()中,为事件添加了一个elif代码块,以便Pygame检测到KEYDOWN事件时做出响应。我们检查按下键(event.key)是否是右方向键(pygame.K_RIGHT),如果是,就将self.ship.rect.centerx的值加1,从而飞船向右移动。
如果现在运行alien_invasion.py,当你每按下一次右方向键,飞船都向右移动1像素。这是一个开端,但并不是控制飞船的高效方式。我们下面来继续改进,让飞船可以持续移动。

4.6.2 允许持续移动

玩家按住右方向键不放时,我们希望飞船不断向右移动,直至松开为止。我们将让游戏检测pygame.KEYUP事件,以便知道玩家何时松开右方向键。然后结合使用KEYDOWN和KEYUP事件以及一个名为moving_right的标志来实现持续移动。
当标志moving_right为False时,飞船不会移动。玩家按下方向键时,我们将此标志设为True,当玩家松开按键时将该标志设为False。
飞船的属性由ship类控制,因此要给这个类添加一个moving_right的属性,再新增一个方法update()。方法update()检查标志的状态。
修改ship.py,首先添加属性self.moving_right,然后新增方法update():

    def __init__(self, ai_game):
    	--snip--
        self.rect.midbottom = self.screen_rect.midbottom   # 意思是飞船底部中央和屏幕底部中央对齐

        # 移动标志
        self.moving_right = False
        
    def update(self):
        """根据移动标志调整飞船的位置"""
        if self.moving_right:
            self.rect.x += 1
	def blitme(self):
    	--snip--

接下来修改alien_invasion.py中的方法_check_events(),使其在玩家按下方向键时将moving_right设为True,松开时设为False。

    def _check_events(self):
        """# 监视键盘和鼠标事件。"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:  # 鼠标点击右上角的叉叉时就退出
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT:
                    self.ship.moving_right = True
                    
            elif event.type == pygame.KEYUP:
                if event.key == pygame.K_RIGHT:
                    self.ship.moving_right = False

最后,修改run_game中的while循环,在每次游戏开始时都能调用方法update()。

    def run_game(self):
        """开始游戏的主循环"""
        while True:
            self._check_events()
            self.ship.update()
            self._update_screen()

如果现在运行代码并按住右箭头键,飞船将持续向右移动。

4.6.3左右移动

和向右持续移动一样,接下来我们来添加持续向左移动的代码。
修改ship.py:

    def __init__(self, ai_game):
        --snip--
        # 移动标志
        self.moving_right = False
        self.moving_left = False

    def update(self):
        """根据移动标志调整飞船的位置"""
        if self.moving_right:
            self.rect.x += 1
        if self.moving_left:
            self.rect.x -= 1
    def blitme(self):
    	--snip--

再修改alien_invasion.py

    def _check_events(self):
        """# 监视键盘和鼠标事件。"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:  # 鼠标点击右上角的叉叉时就退出
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT:
                    self.ship.moving_right = True
                if event.key == pygame.K_LEFT:
                    self.ship.moving_left = True

            elif event.type == pygame.KEYUP:
                if event.key == pygame.K_RIGHT:
                    self.ship.moving_right = 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值