项目一:外星人入侵(上)

0项目规划

0.1项目综述

​ 在游戏《外星人入侵》中,玩家控制一艘出现在屏幕底部中央的飞船。玩家可以使用上下左右键来移动飞船,还可以使用空格键进行射击。游戏开始时,一支外星人军团出现在屏幕上方,他们左右移动的同时,不断向下挺进。游戏任务是射杀这些外星人,玩家将所有外星人击杀后,将出现一批移动速度更快的外星人。只有当飞船撞到外星人,或外星人到达屏幕底部时,玩家损失一艘飞船,当玩家损失三艘飞船后,游戏结束。

0.2工具准备

pygame

要用python写一个小游戏,需要借助pygame的帮助。

pygame的安装也非常的简单

pip install pygame

在cmd中,用以上语句安装即可。

为了在Pycharm中正常使用pygame

需要执行一下步骤:

打开Pycharm,File——Settings——Project:WorkSpace——Python Interpreter

点击右侧加号,在其中搜索Pygame,再点击Install即可(PS:这里可能需要点时间加载,耐心等待)

1开始游戏项目

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

一切准备就绪,运行一个简单的代码,生成一个游戏窗口

#alien_invasion.py
import sys	#退出游戏所需要的包
import pygame	#开发游戏所需要的包

def run_game():	#定义一个函数run_game用来控制游戏启动
	pygame.init()	#初始化背景设置,让Pygame能够正确工作
	screen = pygame.display.set_mode((1200,800))	
    #调用pygame.display.set_mode来创建一个名为screen的显示窗口
	pygame.display.set_caption("Alien Invasion")
	bg_color = (230,230,230)	#定义bg_color为(230,230,230)
	while True:		
        #通过while循环来控制游戏运行,在循环中包含一个事件循环以及管理屏幕更新的代码,整个游戏就是在不断的刷新中进行下去的。
		for event in pygame.event.get():
			if event.type == pygame.QUIT:	
                sys.exit()	#当检测到pygame.QUIT事件后,调用sys.exit()来退出游戏
		screen.fill(bg_color)	#用screen.fill()方法,将前面定义的bg_color用来填充屏幕。
		pygame.display.flip()	#通过调用pygame.display.flip()来实现更新整个屏幕,擦除旧屏幕,保持显示出来的是最新屏幕。Pycharm解释器的解释为 Update the full display Surface to the screen

run_game()

运行结果:

在这里插入图片描述

好啦,一个游戏面板诞生了,之后在上面添加一些有趣的东西吧。

1.2创建设置类

为了能够在后期更方便的进行设置,同时使代码更简单,这里创建一个设置类

#settings.py
class Settings():
    def __init__(self):

        self.screen_width=1200
        self.screen_height=800
        self.bg_color=(230,230,230)

将设置参数放到设置类中以后,alien_invasion.py中的代码也要有一定的变化:

import sys
import pygame
		
def run_game():
	pygame.init()
	ai_settings = Settings()	#另ai_settings为Settings()
	screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
    #直接调用ai_settings中的宽与高
	pygame.display.set_caption("Alien Invasion")
	# bg_color = (230,230,230)
	while True:
		for event in pygame.event.get():
			if event.type == pygame.QUIT:
				sys.exit()
		screen.fill(ai_settings.bg_color)
            #直接调用ai_settings中的背景色
		pygame.display.flip()

run_game()

做到这里,我以为可以运行,但是我发现,运行报错

Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
  File "D:\Dev\Python\WorkSpace\Alienandspace\alien_invasion.py", line 17, in <module>
    run_game()
  File "D:\Dev\Python\WorkSpace\Alienandspace\alien_invasion.py", line 6, in run_game
    ai_settings = Settings()
NameError: name 'Settings' is not defined

Process finished with exit code 1

原因是,我把alien_invasion.py与setting.py分为两个文件,但存放在同一个目录下,我认为这样就可以调用,但是并不行,开始尝试解决。

发现是没有将settings导入。

故将alien_invasion.py中加入语句

from settings import Settings

运行成功!

所以这里可以学到,同一目录下的不同文件需要导入才可以使用其文件中的函数

截至目前两个文件及代码分别是:

#settings.py
class Settings():
    def __init__(self):

        self.screen_width=1200
        self.screen_height=800
        self.bg_color=(230,230,230)
#alien_invasion.py
import sys
import pygame
from settings import Settings

def run_game():
	pygame.init()
	ai_settings = Settings()
	screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
	pygame.display.set_caption("Alien Invasion")
	# bg_color = (230,230,230)
	while True:
		for event in pygame.event.get():
			if event.type == pygame.QUIT:
				sys.exit()
		screen.fill(ai_settings.bg_color)
		pygame.display.flip()

run_game()

初步实现了窗口的绘制,大小背景色的调整。

2添加飞船图像

http://pixabay.com一个免费图库网站,速度慢

在项目的根目录下创建images文件夹,未来的各种图片都将存放在这里

2.1创建Ship类

#ship.py
import pygame
class Ship():
    def __init__(self,screen):
        self.screen = screen
        self.image = pygame.image.load('images/ship.bmp')	#加载图形
        self.rect = self.image.get_rect()	#获取相应属性,将image视为一个矩形,之后的操作就可以仅针对这个矩形进行操作
        self.screen_rect = screen.get_rect()	#为了将飞船放在屏幕中央,所以也需要通过screen.get_rect()将整个屏幕视作一个矩形

        self.rect.centerx = self.screen_rect.centerx
        self.rect.bottom = self.screen_rect.bottom
		#以上两行代码,表示将飞船中心的x坐标设置为屏幕矩形的属性centerx;将飞船下边缘的y坐标,设置为屏幕矩形的属性bottom
        
        
    def blitme(self):	#定义方法blitme()
        self.screen.blit(self.image,self.rect)
        #.blit()有两个参数,它可以根据self.rect设置的位置,将self.image绘制到屏幕上

至此一个Ship类就创建完成

要想让飞船出现在屏幕上,还需要在alien_invasion.py中做一些更改

#alien_invasion.py
import sys
import pygame
from settings import Settings
from ship import Ship  #导入ship类


def run_game():
	pygame.init()
	ai_settings = Settings()
	screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
	pygame.display.set_caption("Alien Invasion")
    
	ship = Ship(screen)		#创建一搜飞船,将创建飞船的操作放在while之外
    
	# bg_color = (230,230,230)
	while True:
		for event in pygame.event.get():
			if event.type == pygame.QUIT:
				sys.exit()
		screen.fill(ai_settings.bg_color)
        
		ship.blitme()	#绘制飞船
        
		pygame.display.flip()

run_game()

3重构

之前的代码结构较为繁琐,比如控制事件监听,屏幕更新的代码直接写在alien_invasion.py的while循环中,其实可以将其提取出来,单独写在一个文件中,需要使用时再进行调取。

因此建立一个新文件:game_functions.py

#game_functions.py
import sys
import pygame

def check_events():		#检查事件,以实现退出游戏
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

def update_screen(ai_settings,screen,ship):		#更新屏幕,包括绘制屏幕、背景色、飞船
    screen.fill(ai_settings.bg_color)
    ship.blitme()
    pygame.display.flip()

在此基础上,就可以将alien_invasion.py的代码进行简化

#alien_invasion.py
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf

def run_game():
	pygame.init()
	ai_settings = Settings()
	screen=pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
	pygame.display.set_caption("Alien Invasion")
	ship = Ship(screen)
	# bg_color = (230,230,230)
	while True:		#可以明显看出,while循环中的语句大大减少
		gf.check_events()
		gf.update_screen(ai_settings,screen,ship)

run_game()

4驾驶飞船

4.1响应按键

为了使飞船移动,通常是由上下左右方向键来实现,因为事件都是通过方法pygame.event.get()来获取的,因此在函数check_event()中,可以加入控制飞船移动的语句

上代码#game_functions.py

#game_functions.py
import sys
import pygame

def check_events(ship):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                ship.rect.centerx+=1

def update_screen(ai_settings,screen,ship):
    screen.fill(ai_settings.bg_color)
    ship.blitme()
    pygame.display.flip()

测试发现,这样只能不断地按方向键才能使飞船不断移动,按一下移动一下。无法按住方向键一直移动。

捋一下逻辑,之前实现飞船按一下键右移一下,是通过if语句,判断当监测到KEYDOWN和K_RIGHT时进行ship.rect.centerx+=1 通过这个方法,导致每监测到一次时,移动一下。

4.2连续移动

如果改变一个逻辑,当监测到KEYDOWN和K_RIGHT时使飞船进入一个转态(即:一直右移的状态)。

所以这里考虑用一个moving_right的标志来实现持续移动。

设,moving_right=True表示移动,moving_right=False表示不移动。

在初始,将飞船的默认moving_ringt设置为False,使飞船静止不动。

在监测到KEYDOWN和K_RIGHT时,使飞船获得moving_ring=True状态后,使飞船保持持续向右移动。

首先对ship.py进行修改

#ship.py
#ship.py
import pygame
class Ship():
    def __init__(self,screen):
        self.screen = screen
        self.image = pygame.image.load('images/ship.bmp')	
        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
		
        self.moving_right = False	#设置默认为False
    def update(self):
        if self.moving_right:	#当moving_right的值为真时,右移一位
            self.rect.centerx += 1
        
    def blitme(self):	#定义方法blitme()
        self.screen.blit(self.image,self.rect)
        #.blit()有两个参数,它可以根据self.rect设置的位置,将self.image绘制到屏幕上

接下来对game_functions.py进行修改

#game_functions.py
import sys
import pygame

def check_events(ship):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                ship.moving_right = True
        elif event.type == pygame.KEYUP:
            if event.key ==pygame.K_RIGHT:
                ship.moving_right = False

def update_screen(ai_settings,screen,ship):
    screen.fill(ai_settings.bg_color)
    ship.blitme()
    pygame.display.flip()

最后在alien_invasion.py中进行调用

#alien_invasion.py
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf

def run_game():
	pygame.init()
	ai_settings = Settings()
	screen=pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
	pygame.display.set_caption("Alien Invasion")
	ship = Ship(screen)
	while True:		
		gf.check_events()	#一、监听,判断情况
        ship.update()       #二、根据情况更新状态
		gf.update_screen(ai_settings,screen,ship)#三、根据更新的状态,刷新屏幕

run_game()

4.3上下左右移动

同理可的,对飞船实现上下左右移动,代码如下:

#ship.py
import pygame
class Ship():
    def __init__(self,screen):
        self.screen = screen
        self.image = pygame.image.load('images/ship.bmp')
        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

        self.moving_right = False
        self.moving_left = False
        self.moving_up = False
        self.moving_down =False
    def update(self):
        if self.moving_right:
            self.rect.centerx += 1
        if self.moving_left:
            self.rect.centerx -= 1
        if self.moving_up:
            self.rect.centery -= 1
        if self.moving_down:
            self.rect.centery += 1
    def blitme(self):
        self.screen.blit(self.image,self.rect)
#game_functions.py		
import sys
import pygame

def check_events(ship):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            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.type == pygame.KEYUP:
            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 update_screen(ai_settings,screen,ship):
    screen.fill(ai_settings.bg_color)
    ship.blitme()
    pygame.display.flip()
#alien_invasion.py
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf

def run_game():
	pygame.init()
	ai_settings = Settings()
	screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
	pygame.display.set_caption("Alien Invasion")
	ship = Ship(screen)
	while True:
		gf.check_events(ship)
		ship.update()
		gf.update_screen(ai_settings,screen,ship)

run_game()

4.4调整飞船的速度&控制飞船行动范围&设置飞船大小&重构check_events()

这几件事一起做的,过程中没停下来,所以文档也就一起写吧,直接放代码

#ship.py
import pygame
class Ship():
    def __init__(self,ai_settings,screen):
        self.screen = screen
        self.ai_settings = ai_settings
        self.ship = pygame.image.load('images/ship.bmp')
        image = self.ship	#为了能单独设置飞船图片的大小,将上传的图片定义为ship,之后再定义为image,然后再用pygame.transform.scale(surface,(int,int))语句来自定义图片的大小。
        #self.image = pygame.transform.scale(image,(200,110))为了代码的整洁,将这句代码改写如下
        self.image = pygame.transform.scale(image,ai_settings.ship_size)
        #这里的ship_size同样设置在settings.py中
        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

        self.center = float(self.rect.centerx)
        self.middle = float(self.rect.centery)

        self.moving_right = False
        self.moving_left = False
        self.moving_up = False
        self.moving_down = False


    def update(self):
        if self.moving_right and self.rect.right < self.screen_rect.right:
            #这里通过比较飞船image的rect的右侧与screen的rect的右侧来限制飞船不可超过屏幕右侧,下同
            self.center += self.ai_settings.ship_speed_factor	
            #这里飞船的速度用self.ai_settings.ship_speed_factor来表示,这是在在settings中预设的一个值
        if self.moving_left and self.rect.left > 0:
            self.center -= self.ai_settings.ship_speed_factor
        if self.moving_up and self.rect.top > self.screen_rect.top:
            self.middle -= self.ai_settings.ship_speed_factor
        if self.moving_down and self.rect.bottom < self.screen_rect.bottom:
            self.middle += self.ai_settings.ship_speed_factor

        self.rect.centerx = self.center
        self.rect.centery = self.middle

    def blitme(self):
        self.screen.blit(self.image,self.rect)
#game_functions.py
#这里对check_events进行重构,由于check_events要检查keydown与keyup两件事,而且每件事中所包含的内容也不少,所以这里考虑将其按keydown与keyup进行分离。将所有keydown状态下的操作写到check_keydown_events()中;将所有keyup状态下的操作写到check_keyup_events()中;最后在check_events()中再设置好这两种事件的相应条件即可
import sys
import pygame
def check_keydown_events(event,ship):
    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
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(ship):
    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)

def update_screen(ai_settings,screen,ship):
    screen.fill(ai_settings.bg_color)
    ship.blitme()
    pygame.display.flip()
#settings.py
class Settings():
    def __init__(self):

        self.screen_width=1200
        self.screen_height=800
        self.bg_color=(230,230,230)
        self.ship_speed_factor = 1.5	#飞船移动速度
        self.ship_size=(200,110)	#飞船大小

#alien_invasion.py
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf

def run_game():
	pygame.init()
	ai_settings = Settings()
	screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
	pygame.display.set_caption("Alien Invasion")
	ship = Ship(ai_settings,screen)
	while True:
		gf.check_events(ship)
		ship.update()
		gf.update_screen(ai_settings,screen,ship)

run_game()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值