《Pygame游戏编程入门》学习——第4章 用户输入:Bomb Catcher游戏


第4章 挑战1

问题1. Bomb Catching游戏太小了,玩起来不是很过瘾。毕竟,它只是一个所谓的鼠标演示程序。让它更漂亮些如何?首先,当炸弹撞击到屏幕底部的时候,我们需要一个延迟。这似乎反映出炸弹“爆炸”的样子,但实际上并没有发生什么。当炸弹撞击到屏幕底部,让程序暂停片刻,显示出一条“BOOM!”消息或其他内容,并且等待用户再次点击鼠标,然后再继续游戏。或者,更好一些的办法是,使用本章前面的Keyboard演示程序中的定时代码,在炸弹爆炸后暂停数秒,然后再继续。

思路:在BombCatcher类中建立一个布尔变量crashed,如果没有接住炸弹,则crashedTrue,否则为False

代码片段如下:

		if self.crashed == True:						
			self.print_text( font2, 220, 200, 'BOOM!', RGB.Red )
				
		pygame.display.update()	

		if self.crashed == True:						
			pygame.time.wait( 2000 )	# 延迟2秒	
			self.crashed = False	

注意一定要先调用pygame.display.update()方法,将"BOOM!"消息显示在屏幕,再延迟。

问题2. 使用pygame.draw.arc()函数,在炸弹顶部添加一个引线,并且用一种随机的颜色重复地绘制它,使得看上去好像引线真的在燃烧一样!可能需要做一些工作让引线朝向正确的方向。如果需要帮助,回过头去参考第2章,其中详细介绍了弧线(还记得Pie游戏吗)。

思路:在BombCatcher类中记录当前炸弹的x坐标bomb_x和y坐标bomb_y,将这两个坐标作为弧线的起始位置(再加一个小的相对偏移),就能保证引线随着炸弹同步移动。

代码片段如下:

			# 画引线
			color = random.randint( 0, 255 ), random.randint( 0, 255 ), random.randint( 0, 255 )	
			pygame.draw.arc( screen, color, ( int( self.bomb_x ), int( self.bomb_y ) - 30 - 10, 10, 10 ), 0, 180, 2 )

问题3. 给Bomb Catching游戏增加些难度,添加一个vel_x变量并且使用它(和当前的vel_y一起)来移动炸弹,让炸弹按照一定角度落下!确保使用一个较小的vel_x值,以免炸弹还没有到达底部就跑出屏幕的左边界和右边界之外了。

思路:在BombCatcher类中的run()方法中不断使bomb_x减少vel_x(偶尔可能增加vel_x),当bomb_x小于0(跳出屏幕左边界),则增加一个屏幕的宽度。

代码片段如下:

			r = random.randint(0, 3)
			if r == 0:
				self.bomb_x += self.vel_x
			else:
				self.bomb_x -= self.vel_x
				if self.bomb_x < 0:
					self.bomb_x += screen_width	

4.4_bomb_catcher.py代码如下:

import sys, pygame, random, time, RGB
from pygame.locals import *

class BombCatcher():
	def __init__( self ):
		self.lives = 3
		self.score = 0
		self.game_over = True
		self.mouse_x = 0
		self.mouse_y = 0
		self.pos_x = 300 # 挡板的x坐标
		self.pos_y = 460 # 挡板的y坐标
		self.bomb_x = random.randint( 0, screen_width - 100 ) # 炸弹球体的横坐标
		self.bomb_y = -50 # 炸弹球体的纵坐标
		self.vel_x = 0.3
		self.vel_y = 0.7
		self.crashed = False

	def print_text( self, font, x, y, text, color=RGB.White, shadow=True ):
		imgText = font.render( text, True, color )
		screen.blit( imgText, ( x, y ) )

	def restart( self ):
		if self.game_over:
			self.game_over = False
			self.lives = 3
			self.score = 0
	
	def run( self ):
		screen.fill( RGB.NavyBlue )
	
		if self.game_over:
			self.print_text( font1, 150, 200, '【单击】鼠标以开始游戏' )
		else:
			self.bomb_y += self.vel_y + self.score / 1000
			r = random.randint(0, 3)
			if r == 0:
				self.bomb_x += self.vel_x
			else:
				self.bomb_x -= self.vel_x
				if self.bomb_x < 0:
					self.bomb_x += screen_width	
		
			if self.bomb_y > screen_height:
				self.bomb_x = random.randint( 0, screen_width - 100 )
				self.bomb_y = -50
				self.lives -= 1
				if self.lives == 0:
					self.game_over = True				
				self.crashed = True		
			elif self.bomb_y > self.pos_y:
				if self.bomb_x > self.pos_x and self.bomb_x < self.pos_x + 120:
					self.score += 10
					self.bomb_x = random.randint( 0, screen_width - 100 )
					self.bomb_y = -50				
			
			# 画炸弹球体
			pygame.draw.circle( screen, RGB.Black, ( int( self.bomb_x ) - 4, int( self.bomb_y ) - 4 ), 30, 0 )
			pygame.draw.circle( screen, RGB.Yellow, ( int( self.bomb_x ), int( self.bomb_y ) ), 30, 0 )
			# 画引线
			color = random.randint( 0, 255 ), random.randint( 0, 255 ), random.randint( 0, 255 )	
			pygame.draw.arc( screen, color, ( int( self.bomb_x ), int( self.bomb_y ) - 30 - 10, 10, 10 ), 0, 180, 2 )
			
			# 移动挡板
			self.pos_x = self.mouse_x
			if self.pos_x < 0:
				self.pos_x = 0
			elif self.pos_x > screen_width - 100:
				self.pos_x = screen_width - 100
			
			# 画挡板
			pygame.draw.rect( screen, RGB.Black, ( self.pos_x - 4, self.pos_y - 4, 120, 40 ), 0 )
			pygame.draw.rect( screen, RGB.Red, ( self.pos_x, self.pos_y, 120, 40 ), 0 )		
		
		self.print_text( font1, 10, 0, '生命:' + str( self.lives ) )			
		self.print_text( font1, 450, 0, '得分: ' + str( self.score ) )
		
		if self.crashed == True:						
			self.print_text( font2, 220, 200, 'BOOM!', RGB.Red )
				
		pygame.display.update()	

		if self.crashed == True:						
			pygame.time.wait( 2000 )	# 延迟2秒	
			self.crashed = False		
		
screen_width, screen_height = 600, 500
pygame.init()
screen = pygame.display.set_mode( ( screen_width, screen_height ) )
pygame.display.set_caption( '炸弹拦截游戏' )
font1 = pygame.font.SysFont( 'stzhongsong', 24 )
font2 = pygame.font.SysFont( 'stxihei', 50 )
bomb_catcher = BombCatcher()

while True:
	for event in pygame.event.get():
		if event.type == QUIT:
			sys.exit()
		elif event.type == MOUSEMOTION:
			bomb_catcher.mouse_x, bomb_catcher.mouse_y = event.pos
		elif event.type == MOUSEBUTTONUP:
			bomb_catcher.restart()
		
	keys = pygame.key.get_pressed()
	if keys[K_ESCAPE]:
		sys.exit()
	
	bomb_catcher.run()

游戏模块RGB.py的部分代码如下:

White = ( 255, 255, 255 )
NavyBlue = ( 0, 0, 128 )
Yellow = ( 255, 255, 0 )
Red = ( 255, 0, 0 )
Black = ( 0, 0, 0 )

以上是本游戏用到的颜色,全部RGB的颜色代码可以查RGB颜色表

运行结果:
在这里插入图片描述


  1. [美] Jonathan S. Harbour 著,李强 译,Python游戏编程入门,人民邮电出版社,2015.1 ↩︎

猜你喜欢

转载自blog.csdn.net/quanet_033/article/details/126937786