python_pygame.外星人入侵

在期末考试时高数(su)退学的我决定写一篇博客来消解准备回高三复读的心情。python_pygame.外星人入侵_第1张图片
本打算把所有代码都贴出来并对代码作一番详细的解释。但是回想一下,如果你是外行,那么我必须讲很多。内容太多就算是我也懒得看,还不如直接推荐你去读这本书:《Python编程:从入门到实(入)践(坟)》;如果你是内行,说不定你比我更精通,那我跟你讲那么多干嘛?

下面是用来运行这个游戏的文件alien_invasion.py

#coding=gbk	#这个软件的编译器检测到注释里有中文时会报错,加上这条语句就好了
			#我用来敲python的软件是那本书里推荐的Geany,并不像Visual Studio,Jupyter那么高级,豪华
			#但是挺好用的,好像还能写C,C++,Java和D,Vala,Erlang,Pascal,HTML,PHP等一些我没学过的语言
			#不过这个软件的编译报错非常不友好:无法显示中文文字,找bug只能根据traceback
import pygame
from pygame.sprite import Group

from settings import Settings	#游戏的各种属性设置(你可以在这里把游戏变成容易或非常难)
								#比如把子弹宽带调到非常大,一下子击中好几个”外星人“
from ship import Ship
from ship2 import Ship2	#只能一个人玩的游戏有什么意思?我这个可是双人游戏
						#当然了,完全可以把这个游戏变成十人游戏
from game_stats import GameStats	#跟踪游戏的统计信息
from button import Button	#PLAY按钮
from scoreboard import Scoreboard	#显示得分的类
import game_functions as gf	#游戏的绝大多数函数都在此模组中
#from ball import Ball	#这个ball类的灵感来源是某一个“动手试一试”,让我再创一个接球游戏,
						#而我把它与这个游戏融合了,每当飞船接到球时飞船数加一(在不超过上限的情况下)
						#由于Ball类在game_function中才发挥作用,所以这里最好省略,下同
#from bullet import Bullet	#一个对ship发射的子弹进行管理的类
#from bullet2 import Bullet2	#一个对ship2发射的子弹进行管理的类
#from alien import Alien	#表示单个”外星人“的类,我随便找了一张图片来充当。。。

def run_game():
	#初始化pygame,设置和屏幕对象。不作解释,具体请看书
	pygame.init()
	ai_settings=Settings()
	screen=pygame.display.set_mode(
	(ai_settings.screen_width,ai_settings.screen_height))
	pygame.display.set_caption("Alien Invasion")
	
	
	#创建Play按钮
	play_button=Button(ai_settings,screen,"Play")
	
	#创建一艘飞船
	ship=Ship(ai_settings,screen)
	
	#创建一个用于储存游戏统计信息的实例,并创建记分牌
	stats=GameStats(ai_settings)
	sb=Scoreboard(ai_settings,screen,stats,ship)
	
	#创建ship2
	ship2=Ship2(ai_settings,screen,ship)
	
	#创建一个用于储存子弹的编组
	bullets=Group()
	
	#创建一个用于储存子弹的编组
	bullets2=Group()
	
	#创建一个”外星人“编组
	aliens=Group()
	
	#创建”外星人“群
	gf.create_fleet(ai_settings,screen,ship,ship2,aliens)
	
	#创建一个球编组
	balls=Group()

	#创建一个球群
	gf.create_balls(ai_settings,screen,balls)
	
	#开始游戏的主循环
	while True:	#C,C++等编译器省略缩进,但python就不一样了
		gf.check_events(ai_settings,screen,stats,sb,ship,ship2,aliens,bullets,
			bullets2,play_button)
		if stats.game_active:	#仅当游戏处于活跃状态时才更新这些
								#游戏在未开始或GAMEOVER时处于非活跃状态
			ship.update()
			ship2.update()
			gf.update_bullets(ai_settings,screen,stats,sb,ship,ship2,aliens,
				bullets,balls)
			gf.update_bullets2(ai_settings,screen,stats,sb,ship,ship2,aliens,
				bullets2,balls)
			gf.update_aliens(ai_settings,screen,stats,sb,ship,ship2,aliens,
				bullets,bullets2)
			gf.update_ball(ai_settings,screen,sb,ship,ship2,balls,stats)
		gf.update_screen(ai_settings,screen,stats,sb,ship,ship2,aliens,bullets,
			bullets2,balls,play_button)
		
		
run_game()	#前面只是对函数进行定义,直到这里程序才开始运行

python的语法比较简单,语法高亮自然也比较单调,一眼看上去就跟没有差不多。
ship2模组真的不简单,第二个飞船位于屏幕的左端,其初始位置和运动范围由屏幕和第一个飞船的高度共同决定。
python_pygame.外星人入侵_第2张图片

ship2.py

#coding=gbk
import pygame
from pygame.sprite import Sprite

class Ship2(Sprite):
	"""创建一个ship2类"""
	def __init__(self,ai_settings,screen,ship):
		"""初始化飞船并设置其初始位置"""
		super().__init__()
		self.screen=screen	#为了后面避免后面频繁地传参,这里让screen与self(即ship2)关联起来,下同
		self.ai_settings=ai_settings
		self.ship=ship
		
		#加载飞船2图像并获取其外接矩形
		self.image=pygame.image.load('images/ship2.bmp')
		self.rect=self.image.get_rect()
		self.screen_rect=self.screen.get_rect()	#这里也可以写成self.screen_rect=screen.get_rect()
		
		#将飞船放在屏幕左下方
		self.rect.bottom=self.screen_rect.bottom-ship.rect.height
		self.rect.left=self.screen_rect.left
		
		#在飞船的bottom属性中储存小数值
		self.bottom=float(self.rect.bottom)
		
		#移动标志
		self.moving_up=False
		self.moving_down=False
		
	def update(self):
		"""根据移动标志调整飞船位置"""
		#更新bottom属性而不是rect
		if self.moving_up and self.rect.top>0:	#在game_function函数中若玩家按下相应的按键,则self.moving_up会变为True,下同
			self.bottom-=self.ai_settings.ship2_speed_factor
		if self.moving_down and self.rect.bottom<=self.screen_rect.bottom-self.ship.rect.height:
			self.bottom+=self.ai_settings.ship2_speed_factor
			
		#根据bottom更新rect
		self.rect.bottom=self.bottom

	def blitme(self):
		"""在指定位置绘制ship2"""
		self.screen.blit(self.image,self.rect)	#在这里前面把screen与self关联起来的作用就体现出来了
												#如果这里想写成screen.blit(...),那么必须再
												#传递一个参数screen,像这样:def blitme(self,screen)
		
	def center_ship2(self):
		"""让飞船2居中"""
		self.bottom=self.screen_rect.bottom-self.ship.rect.height

既然ship2位于屏幕左端,那么它发射的子弹bullet2当然不是向上而是向右的了。
python_pygame.外星人入侵_第3张图片

bullet2.py

#coding=gbk

import pygame
from pygame.sprite import Sprite

class Bullet2(Sprite):
	"""一个对飞船2发射的子弹进行管理的类"""
	
	def __init__(self,ai_settings,screen,ship2):
		"""在飞船2所处的位置创建一个子弹对象"""
		super().__init__()
		self.screen=screen
		
		#在(0,0)处创建一个表示子弹的矩形,再设置正确的位置
		self.rect=pygame.Rect(0,0,ai_settings.bullet2_width,
								ai_settings.bullet2_height)
		self.rect.centery=ship2.rect.centery	#这里centery不是一个单词,而是表示对象中心坐标(center)中的纵坐标(y)
		self.rect.right=ship2.rect.right
		
		#储存用小数表示的子弹位置
		self.x=float(self.rect.x)
		
		self.color=ai_settings.bullet2_color
		self.speed_factor=ai_settings.bullet2_speed_factor
		
	def update(self):
		"""向右移动子弹"""
		#更新表示子弹位置的小数值
		self.x+=self.speed_factor
		#更新表示子弹的rect的位置
		self.rect.x=self.x
		
	def draw_bullet2(self):
		"""在屏幕上绘制子弹"""
#		pygame.draw.rect(self.screen,self.color,self.rect)
		self.screen.fill(self.color,self.rect)

接下来是这本书里面完全没有介绍的ball模组

ball.py

import pygame
from pygame.sprite import Sprite
from random import randint	#球的初始横坐标是随机的,需要借助randint

class Ball(Sprite):
	"""表示单个球的类"""
	
	def __init__(self,ai_settings,screen):
		"""初始化球并设置其初始位置"""
		super().__init__()
		self.screen=screen
		self.ai_settings=ai_settings
		
		#加载球图像并获取其外接矩形
		self.image=pygame.image.load('images/ball.bmp')
		self.rect=self.image.get_rect()
		self.screen_rect=screen.get_rect()
		
		#将球放在屏幕顶部随机位置
		self.rect.x=randint(self.screen_rect.x,self.ai_settings.screen_width-self.rect.width+1)
		self.rect.y=self.screen_rect.top
		
		#在球的位置属性中储存小数值
		self.x=float(self.rect.x)
		self.y=float(self.rect.y)
		
		
	def blitme(self):
		"""在指定位置绘制球"""
		self.screen.blit(self.image,self.rect)
		
		
	def update(self):
		"""向下移动球"""
		self.y+=self.ai_settings.ball_speed_factor
		self.rect.y=self.y

就讲到这吧,还有问题你就看那本书,也可以在评论区留言,我会尽力解答。

虽然博客写完了,但我的高数还是有可能会挂科QAQ
python_pygame.外星人入侵_第4张图片

你可能感兴趣的:(迷你项目)