原来Python这么强大,只要百行代码就能开发出游戏

今天给大家介绍一个小项目,只用一百行代码就可以开发出的游戏

安装pygame

下载对应python版本的pygame 运行以下命令

pip install wheelpip install pygame-1.9.3-cp36-cp36m-win_amd64.whl

创建Pygame窗口及响应用户输入

新建一个文件夹alien_invasion,并在文件夹中新建alien_invasion.py文件,输入如下代码。

运行上述代码,我们可以得到一个灰色界面的窗口:

创建设置类

为了在写游戏的过程中能便捷地创建一些新功能,下面额外编写一个settings模块,其中包含一个Settings类,用于将所有设置存储在一个地方。这样在以后项目增大时修改游戏的外观就更加容易。

我们首先将alien_invasion.py中的显示屏大小及显示屏颜色进行修改。

首先在alien_invasion文件夹下新建python文件settings.py,并向其中添加如下代码​​​​​​​

class Settings(object):    """docstring for Settings""”    def _init__(self):       # initialize setting of game              #screen setting       self.screen_width = 1200       self.screen_height = 800       self.bg_color = (230,230,230)

然后在alien_invasion.py中导入Settings类,并使用相关设置,修改如下:

添加飞船图像

接下来,我们需要将飞船加入游戏中。为了在屏幕上绘制玩家的飞船,我们将加载一幅图像,再使用Pygame()方法blit()绘制它。

在游戏中几乎可以使用各种类型的图像文件,但是使用位图(.bmp)文件最为简单,这是因为Pygame默认加载位图。

虽然其他类型的图像也能加载,但是需要安装额外的库。

我们推荐去免费的图片素材网站上去找图像:pixabay.com/

我们在主项目文件夹(alien_invasion)中新建一个文件夹叫images,将如下bmp图片放入其中。

接下来,我们创建飞船类ship.py:​​​​​​​

import pygameclass Ship():
    def _init__(self,screen) :        #initialize spaceship and its location        self.screen - screen                # 1oad bmp image and get rectangle        self.image = pygame.image.load( ' image/ship.bmp')        self.rect = self.image.get_rect()        self.screen rect = screen.get_rect()        # put spaceship on the bottom of window        self.rect.centerx -self.screen_rect.centerx        self.rect.bottom - self.screen_rect.bottom        def blitme( self):    #buld the spaceship at the specific location    self.screen.blit(self.image,self.rect)

重构:模块game_functions

在大型项目中,经常需要在添加新代码前重构既有代码。重构的目的是为了简化代码的结构,使其更加容易扩展。

我们将实现一个game_functions模块,它将存储大量让游戏Alien invasion运行的函数。通过创建模块game_functions,可避免alien_invasion.py太长,使其逻辑更容易理解。

函数check_events()

首先我们将管理事件的代码移到一个名为check_events()的函数中,目的是为了隔离事件循环​​​​​​​

import sysimport pygame
def check_events():   #trespond to  keyboard and mouse item   for event in pygame.event.get():       if event.type -= pygame.QUIT;           sys.exit()

然后我们修改alien_invasion.py代码,导入game_functions模块,并将事件循环替换成对函数check_events()的调用:

函数update_screen()

将更新屏幕的代码移到一个名为update_screen()函数中,并将这个函数放在模块game_functions中:​​​​​​​

def update_screen(ai settings,screen, ship):    # fi1l color    screen.f111(ai_settings.bg_color)    ship.blitme()    # visualiaze the window    pygame.display.flip()

其中alien_invasion修改如下:​​​​​​​

import sysimport pygamefrom settings inport Settingsfrom ship import Shipimport game_functions as gfdef run_game():    #initialize game and create a dispaly object    pygame.init()    ai_settings = Settings()    screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_h    ship = Ship(screen)    pygame.display.set_caption("Alien Invasion")    # set backgroud color    bg_color = (230,230,230)        # game loop    while True:        # Supervise keyboard and mouse item

从上面一套流程走下来,我们发现:在实际的开发过程中,我们一开始将代码编写得尽可能的简单,并在项目越来越复杂时进行重构。接下来我们开始处理游戏的动态方面。

驾驶飞船

这里我们要实现的就是使玩家通过左右箭头键来控制飞船的左移与右移。

响应按键

因为在pygame中,每次按键都被注册为KEYDOWN事件,在check_events()中,我们通过event.type检测到KEYDOWN事件后还需进一步判断是哪个按键。代码如下:​​​​​​​

def check _ events(ship):    #respond to keyboard and mouse item    for event in PYgame.event.get():        if event.type == pygame.QUIT:            sys.exit()        elif event.type == pYgame.KEYDOWN:

允许不断移动

玩家按住右箭头不动时,我们希望飞船能不断地移动,直到玩家松开为止。这里我们通过KETUO事件来判断。因此我们设置一个标志位moving_right来实现持续移动。原理如下:

飞船不动时,标志moving_right将为false。玩家按下右箭头时,我们将这个标志设置为True;玩家松开时,我们将标志重新设置成False。

这个移动属性是飞船属性的一种,我们用ship类来控制,因此我们给这个类增加一个属性名称叫,moving_right以及一个update()方法来检测标志moving_right的状态。

ship​​​​​​​

    self.moving_right = Falsedef update(self):    if self.moving_right:        self.rect.centerx +=1

game_functions​​​​​​​

elif event.type == pygame.KEYDOWN:    if event.key == pygame.K_RIGHT:        #move right        ship.moving_right = Trueelif event.type == pygame.KEYUP:    if event.key = pygame.K_RIGHT;        ship.moving_right - False

最后在alien_invasion中调用update()方法​​​​​​​

while True:    # supervise keyboard and mouse item    gf.check _events(ship)    ship. update()

左右移动

前面我们实现了向右移动,接下来实现向左移动,逻辑类似,代码就不贴了。

调整飞船的速度

当前,每次执行while循环时,飞船最多移动一个像素,我们可以在Settings中添加ship_speed_factor,用于控制飞船的速度。我们将根据这个属性决定飞船每次循环时最多移动多少距离。

Settings:​​​​​​​

class Settings(object):    """docstring for Settings"""    def _init_(self):        # initialize setting of game        # screen setting        self.screen_width -1208        self.screen_height =800        self.bg_color = (230,230,230)        self.ship_speed_factor = 1.5

Ship:​​​​​​​

class Ship():
    def _init_(self,ai_settings, screen):        #initialize spaceship and its location        self.screen = screen        self.ai _settings = ai_settings

限制飞船的活动范围

如果玩家按住箭头的时间过长,飞船就会消失,那么如何使飞船抵达屏幕边缘时停止移动?这里我们只需要修改Ship类中的update方法,增加一个逻辑判断。

重构

这里我们主要讲check_events()函数进行重构,将其中部分代码分成两部分,一部分处理KEYDOWN事件,一部分处理KEYUP事件。

game_functions:​​​​​​​

def check keydown_events(event,ship):    if event.key == pygame.K_RIGHT:        #move right        ship.moving_right = True    elif event.key "" pygame.K_LEFT:        #move right        ship.moving_left - Truedef check_keyup_events(event ,ship):    if event.key == pygame.K_RIGHT:        ship.moving_right = False    elif event.key == pygame.K_LEFT:        #move right        ship.moving_left = Falsedef check_events(ship):    #respond to keyboard and mouse item    for event in pygame.event.get():        if event.type == pygame.QUIT:            sys.exit()        elif event.type == pygame.KEYDOWN:            check_keydown_events(event , ship)        elif event.type == pygame.KEYUP:            check_keyup_events(event,ship)

射击

接下来添加射击功能,使玩家按空格键时发射子弹,子弹将在屏幕中向上穿行,抵达屏幕后消失。

添加子弹设置

在Settings类中增加一些子弹的属性,这里我们创建一个宽3像素,高15像素的深灰色子弹。子弹的速度比飞船稍低。

创建Bullet类​​​​​​​

import pygamefron pygame.sprite import Sprite
class Bullet(Sprite):    """A class to manage bullets fired from the ship."""
    def_init_(self, ai_settings, screen,ship):    """Create a bullet object,at the ship's current position."""    super()._init_()    seif.screen = screen        # Create bullet rect at (0,0),then set correct posftion.    self.rect = pygame.Rect(0,0, ai_settings.bullet_width,ai_settings.bullet_height)    self.rect.centerx = ship.rect.centerx    self.rect.top n ship.rect.top        # Store a decimal value for the bullet's position.    self.y= float(self.rect.y)        self.color = ai_settings.bullet_color    self.speed_factor = ai_settings.bullet_speed_factordef update(self):    """Move the bullet up the screen . """    # Update the decimal position of the bullet.    self.y -s self.speed_factor    #Update the rect position.    self.rect.y - self.y

将子弹存储到group中

前面定义了Bullet类和必要的设置后,就可以编写代码了,在玩家每次按空格键时都会发射一发子弹。

首先,我们在alien_invasion中创建一个group,用于存储所有的有效子弹。​​​​​​​

def run_game():    #initialize game and create a dispaly object    pygame.init()    ai_settings = Settings()    screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_he    ship = Ship(ai_settings, screen)    bullets - Group()    pygame.display.set_caption("Alien Invasion")    #set backgroud color    bg_color = (230,230,230)        # game,loop    while True:    #supervise keyboard and mouse item    gf.check_events(ai_settings, screen,ship,bullets)

开火

这里我们修改check_keydown_events()函数,来监听玩家按下空格键的事件。这里还需要修改update_screen()函数,确保屏幕每次更新时,都能重绘每一个子弹。

我们来看下效果:

删除消失的子弹

在alien_invasion中删除消失的子弹。

import sysimport pygamefrom settings import Settingsfrom ship import Shipimport game_functions as gffrom pygame.sprite import Groupdef run_game()    #initialize game and create a dispaly object    pygame.init()    ai_settings = Settings()    screen = pygame.display.set_mode((ai_secngs.screen_width.ai_settings, screen_h    ship = Ship(ai_settings,screen)    bullets = Group()    pygame.display.set_caption("Alien Invasion")    # set backgroud color    bg_color = (230,230,230)        # game 1oop    while True:        # supervise keyboard and mouse item        gf.check_events(ai_settings,screen,ship,bullets)        ship.update()        bullets. update()        for bullet in bullets.copy():            if bullet.rect.bottom<=0:

限制子弹数量

为了鼓励玩家有目标的射击,我们规定屏幕上只能同时存在3颗子弹,我们只需要在每次创建子弹前检查未消失的子弹数目是否小于3即可。

创建update_bullets()函数

为了使alien_invasion中代码更加简单,我们将检查子弹管理的代码,移到game_functions模块中:​​​​​​​

def update_bullets(bullets):    bullets.update()    for bullet in bullets.copy():        if bullet.rect.bottom<-0:            bullets.remove(bullet)

创建fire_bullet()函数

这里我们将发射子弹的代码移到一个独立的函数中:

def fire_ bullet(ai_settings, screen, ship,bullets):    if len(bullets)<ai_settings.bullets_allowed:        new_bullet =Bullet(ai_settings,screen, ship)        bullets.add(new_bullet)

添加外星人,并检测碰撞

在我们完成新的任务之前,我们先给游戏添加一个结束游戏的快捷键Q:

创建第一个外星人

这里和创建飞船的方法一样

class Alien(Sprite):    """A class to represent a single alien in the fleet."""        def _init__(self,ai_settings, screen):        """Initialize the alien,and set its starting position."""        super()._init_()        self.screen = screen        self.ai_settings = ai_settings                # Load the alien image,and set its rect attribute.        self.image = pygame.image.load ( " images/alien.bmp ")        self.rect - self.image.get_rect()                # Start each new alien near the top left of the screen.        self.rect.x = self.rect.width        self.rect.y - self.rect.height

创建一群外星人

这里我们首先确定一行能容纳多少个外星人以及要绘制几行。这里改动代码较多,直接看效果:

移动外星人

前面我们创建的是静态的外星人,现在我们需要让外星人动起来。这里我们在Settings类中设置外星人移动的速度,然后通过Alien类中的update的方法来实现移动

射杀外星人

要想射杀外星人,就必须先检测两个编组成员之间是否发生碰撞,在游戏中,碰撞就是游戏元素重叠在一起。

这里我们使用sprite.groupcollide()来检测两个编组的成员之间的碰撞。

子弹击中外星人时,需要立马知道,并同时使被碰撞的外星人立即消失,因此我们需要在更新子弹的位置后立即检测碰撞。

结束游戏

这里我们还需要知道何时该结束游戏,有以下几种情况:

飞船全部被摧毁

外星人到达屏幕底部

实际效果:

计分

最后我们将给游戏添加一个Play按钮,用于根据需要启动游戏以及在游戏结束后重启游戏。

我们还将实现一个计分系统,能够在玩家等级提高时加快节奏。

添加Play按钮

这里可以先将游戏初始化为非活动状态,当我们点击了按钮,就开始游戏。

由于Pygame中没有内置的创建按钮的方法。因此我们可以通过创建一个Button类来创建一个自带标签的实心矩形。

我们通过检测鼠标发生点击后的坐标是否与我们绘制的按钮发生碰撞与否来判断是否发生了点击事件。

提高等级

为了使玩家将敌人消灭干净后能够提高游戏难度,增加趣味性,这里我们可以在Settings类中进行修改,增加静态初始值,和动态初始值。

记分、等级、剩余飞船

打包成exe可执行文件

这样上面游戏开发完了!!

动手能力强的的小伙伴可以试着自己做一下哦

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值