外星人大战---------------游戏开发(二)

上一节已经完成了飞船的左右移动,这节来完成调节飞船移动的速度,以及射击。


在上一张我们知道飞船每次移动1像素,而且有时候会移动到屏幕之外。我们可以设置飞船移动速度,在Setting  类修改

#存储外星人游戏开发的设置
class Setting():
    def __init__(self):
        self.screen_width=600     #设置屏幕高度宽度,背景颜色
        self.screen_height=600
        self.bg_color=(230,230,230)
        self.ship_speed_factor=1.5   #设置飞船移动

设置移动速度为1.5.但在ship类中因为rect的centerx不能存储小数值,所以创建一个center

#-*-coding:GBK-*-
#-*-coding:utf-8-*-
#创建飞船类
import pygame

class Ship(): 
	def __init__(self,ai_settings,screen):
		self.screen=screen
		self.ai_settings=ai_settings

     #图片存在images文件夹下,名字是ship.bmp    
		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.center=float(self.rect.centerx)   #因为rect的centerx只能储存整数值,在飞船的center储存小数值
		self.moving_right=False            #设置移动标志
		self.moving_left=False

	def update(self):
		if self.moving_right:        #根据移动标志,来调整位置
			self.center+=self.ai_settings.ship_speed_factor      #更新飞船的center的值,不是rect
			
		if self.moving_left:
			self.center-=self.ai_settings.ship_speed_factor
		
		self.rect.centerx=self.center    #来更新rect对象
        

	def blitme(self):
		self.screen.blit(self.image,self.rect)  

 因为我们把速度设置放在setting类里,所以在这里就要有ai_settings的形参,用于传送信息,在主程序里:

#-*-coding:GBK-*-
#-*-coding:utf-8-*-
import pygame

from setting import Setting
from ship import Ship
import game_functions as gf

def run_game():
    pygame.init()  #初始化,创建屏幕对象
    ai_settings=Setting()    #创建一个800*800的屏幕
    screen=pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))  
    pygame.display.set_caption("Alien Invasion")   #对于这个窗口的命名为Alien Invasion

    ship=Ship(ai_settings,screen)   #创建飞船

    while True:
        gf.check_events(ship)
        ship.update()
        gf.update_screen(ai_settings,screen,ship)

run_game()

输出时,速度比之前是快了。

再限制一下飞船的活动范围,防止在游戏屏幕外面,我们可以通过检查self.center的值是否等于屏幕的边缘值,就可以解决该问题。我们在修改ship类:

#-*-coding:GBK-*-
#-*-coding:utf-8-*-
#创建飞船类
import pygame

class Ship(): 
	def __init__(self,ai_settings,screen):
		self.screen=screen
		self.ai_settings=ai_settings

     #图片存在images文件夹下,名字是ship.bmp    
		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.center=float(self.rect.centerx)   #因为rect的centerx只能储存整数值,在飞船的center储存小数值
		self.moving_right=False            #设置移动标志
		self.moving_left=False

	def update(self):
		if self.moving_right and self.rect.right <self.screen_rect.right:        #根据移动标志,来调整位置
			self.center+=self.ai_settings.ship_speed_factor      #更新飞船的center的值,不是rect
			
		if self.moving_left and self.rect.left>0:
			self.center-=self.ai_settings.ship_speed_factor
		
		self.rect.centerx=self.center    #来更新rect对象
        

	def blitme(self):
		self.screen.blit(self.image,self.rect)  

再运行主程序,就会发现飞船就在在屏幕里移动,不会在屏幕之外。

接下来再针对于射击:

我们先编写子弹的矩形,以及按键空格键发送子弹,子弹向上发送,直至上边缘消失,创建一个bullet类。我们先在设置类添子弹设置:

#-*-coding:GBK-*-
#-*-coding:utf-8-*-
#存储外星人游戏开发的设置
class Setting():
    def __init__(self):
        self.screen_width=600     #设置屏幕高度宽度,背景颜色
        self.screen_height=600
        self.bg_color=(230,230,230)
        self.ship_speed_factor=1.5   #设置飞船移动
        #子弹设置
        self.bullet_speed_factor=1
        self.bullet_width=3
        self.bullet_height=15
        self.bullet_color=(0,0,255)

设置子弹的速度,矩形的长宽以及颜色,

接下来就是创建子弹类:

#-*-coding:GBK-*-
#-*-coding:utf-8-*-
#设置子弹类
import pygame
from pygame.sprite import Sprite

class Bullet(Sprite):   #一个对子弹管理的类,继承Sprite类
	def __init__(self,ai_settings,screen,ship):
		super().__init__()
		self.screen=screen
		
		#在(0,0)创建一个表示子弹的矩形,在设置正确的位置
		self.rect=pygame.Rect(0,0,ai_settings.bullet_width,ai_settings.bullet_height)
		self.rect.centerx=ship.rect.centerx
		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
		self.rect.y=self.y
		
	def draw_bullet(self):   #绘制子弹
		pygame.draw.rect(self.screen,self.color,self.rect)
		

 导入pygame,因为子弹不是基于图像的,所以就使用pygame.Rect类来从空白开始创建一个矩形,创建这个这个类的实例的时候,必提供矩形左上角的x.y坐标以及矩形的长宽,我们在(0.0)创建这个矩形,接下来的两行代码将它移到正确的位置,子弹的初始位置是取决于飞船的位置。

主程序如下:

在主程序里创造一个编组,用于存储所有的有效的子弹,用于管理发射出去的子弹。这个编组是pygame.sprite.Group 的一个实例,类似于列表,它绘制子弹以及更新每个子弹的位置。

#-*-coding:GBK-*-
#-*-coding:utf-8-*-
import pygame

from setting import Setting
from ship import Ship
import game_functions as gf
from pygame.sprite import Group

def run_game():
    pygame.init()  #初始化,创建屏幕对象
    ai_settings=Setting()    #创建一个800*800的屏幕
    screen=pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))  
    pygame.display.set_caption("Alien Invasion")   #对于这个窗口的命名为Alien Invasion

    ship=Ship(ai_settings,screen)   #创建飞船
    bullets=Group()    

    while True:
        gf.check_events(ai_settings,screen,ship,bullets)
        ship.update()
        bullets.update()
        gf.update_screen(ai_settings,screen,ship,bullets)

run_game()

功能模块:

#-*-coding:GBK-*-
#-*-coding:utf-8-*-
#游戏的功能模块,包括响应键盘鼠标事件,移动飞船等

import sys
import pygame
from bullet import Bullet

def check_keydown_events(event,ai_settings,screen,ship,bullets):           #响应按键
	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_SPACE:      #响应按空格键
		new_bullet=Bullet(ai_settings,screen,ship)
		bullets.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
	

def check_events(ai_settings,screen,ship,bullets):     #响应键盘和鼠标事件
	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,bullets)

		elif event.type==pygame.KEYUP:       #监测是否放开键盘
			check_keyup_events(event,ship)
         
def update_screen(ai_settings,screen,ship,bullets):   # 更新屏幕
	screen.fill(ai_settings.bg_color)
	for bullet in bullets.sprites():
		bullet.draw_bullet()
	ship.blitme()

	pygame.display.flip()

编组bullets传递给check_keydown_events(),按下空格键的时候,创建一颗新子弹,并使用方法add将其加入到编组bullets中,之后,bullets.sprites()返回一个列表,包含于编组里的所有子弹,我们在遍历列表,对所有的子弹调用draw_bullet()。

删除已经消失的子弹:

子弹到达顶部消失,并不是因为说它不存在了,而是因为pygame无法在屏幕外绘制他们,他们的坐标为负值,会一直消耗内存和处理能力。我们要将这些子弹删除,怎么删除,我们可以 检查子弹的坐标位置,当bottom=0的时候就代表到达顶部。

主程序如下:

#-*-coding:GBK-*-
#-*-coding:utf-8-*-
import pygame

from setting import Setting
from ship import Ship
import game_functions as gf
from pygame.sprite import Group

def run_game():
    pygame.init()  #初始化,创建屏幕对象
    ai_settings=Setting()    #创建一个800*800的屏幕
    screen=pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))  
    pygame.display.set_caption("Alien Invasion")   #对于这个窗口的命名为Alien Invasion

    ship=Ship(ai_settings,screen)   #创建飞船
    bullets=Group()    

    while True:
        gf.check_events(ai_settings,screen,ship,bullets)
        ship.update()
        bullets.update()

       #删除子弹
        for bullet in bullets.copy():
            if bullet.rect.bottom<=0:
               bullets.remove(bullet)
        print(len(bullets))      #打印长度。只是为了确认下有没有消失,后面可以删掉
 
        gf.update_screen(ai_settings,screen,ship,bullets)

run_game()

我们使用copy来产生一个bullets的副本,遍历这个副本。

限制子弹数量:

在设置类修改程序:

#-*-coding:GBK-*-
#-*-coding:utf-8-*-
#存储外星人游戏开发的设置
class Setting():
    def __init__(self):
        self.screen_width=600     #设置屏幕高度宽度,背景颜色
        self.screen_height=600
        self.bg_color=(230,230,230)
        self.ship_speed_factor=1.5   #设置飞船移动
        #子弹设置
        self.bullet_speed_factor=1
        self.bullet_width=3
        self.bullet_height=15
        self.bullet_color=(0,0,255)
        self.bullets_allowed=3

接下来在功能模块来检查子弹数:

#-*-coding:GBK-*-
#-*-coding:utf-8-*-
#游戏的功能模块,包括响应键盘鼠标事件,移动飞船等

import sys
import pygame
from bullet import Bullet

def check_keydown_events(event,ai_settings,screen,ship,bullets):           #响应按键
	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_SPACE:      #响应按空格键
                if len(bullets)<ai_settings.bullets_allowed:    
		    new_bullet=Bullet(ai_settings,screen,ship)
		    bullets.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
	

def check_events(ai_settings,screen,ship,bullets):     #响应键盘和鼠标事件
	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,bullets)

		elif event.type==pygame.KEYUP:       #监测是否放开键盘
			check_keyup_events(event,ship)
         
def update_screen(ai_settings,screen,ship,bullets):   # 更新屏幕
	screen.fill(ai_settings.bg_color)
	for bullet in bullets.sprites():
		bullet.draw_bullet()
	ship.blitme()

	pygame.display.flip()

再运行主程序看看实际结果:

重构整个函数:

1.功能模块:

#-*-coding:GBK-*-
#-*-coding:utf-8-*-
#游戏的功能模块,包括响应键盘鼠标事件,移动飞船等

import sys
import pygame
from bullet import Bullet

def check_keydown_events(event,ai_settings,screen,ship,bullets):           #响应按键
	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_SPACE:      #响应按空格键
                fire_bullet(ai_settings,screen,ship,bullets)

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)

		
		
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
	

def check_events(ai_settings,screen,ship,bullets):     #响应键盘和鼠标事件
	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,bullets)

		elif event.type==pygame.KEYUP:       #监测是否放开键盘
			check_keyup_events(event,ship)
         
def update_screen(ai_settings,screen,ship,bullets):   # 更新屏幕
	screen.fill(ai_settings.bg_color)
	for bullet in bullets.sprites():
		bullet.draw_bullet()
	ship.blitme()

	pygame.display.flip()

def update_bullets(bullets):  #更新子弹的位置,并删除已消失的子弹
        bullets.update()
        for bullet in bullets.copy():
                if bullet.rect.bottom<=0:
                          bullets.remove(bullet)  
        

主程序如下:

#-*-coding:GBK-*-
#-*-coding:utf-8-*-
import pygame

from setting import Setting
from ship import Ship
import game_functions as gf
from pygame.sprite import Group

def run_game():
    pygame.init()  #初始化,创建屏幕对象
    ai_settings=Setting()    #创建一个800*800的屏幕
    screen=pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))  
    pygame.display.set_caption("Alien Invasion")   #对于这个窗口的命名为Alien Invasion

    ship=Ship(ai_settings,screen)   #创建飞船
    bullets=Group()    

    while True:
        gf.check_events(ai_settings,screen,ship,bullets)
        ship.update()
        gf.update_bullets(bullets)
        gf.update_screen(ai_settings,screen,ship,bullets)

run_game()

简单理下逻辑:

首先整个程序分为五大部分:设置、飞船、子弹、功能、主程序

1.设置类:

设置屏幕的宽高与背景颜色,设置飞船的移动速度,设置子弹的移动速度,矩形的宽高,颜色,数量限制

2.飞船类:

加载要展示的图片,设置图片出现在屏幕的初始位置,对于左右移动的位置更新与方法、在屏幕里绘制飞船

3.子弹类:

与飞船类类似,加载创建子弹矩形,设置矩形出现的位置,对于子弹的位置更新方法,加载在屏幕上

4.功能模块:

按键之后的功能例如按左键飞船左移、松开键盘后的功能、监听事件(例如按键,松键),发射子弹的方法,删除屏幕外的子弹,更新子弹、更新屏幕。

5.主程序:

创建各个类的实例,在循环里加功能模块。

 

 

阅读更多

没有更多推荐了,返回首页