Chapter12/Chapter13(外星人入侵之武装飞船,之外星人)

本文详细介绍使用Pygame库进行游戏开发的过程,包括创建背景、控制游戏角色移动、实现侧面射击游戏和处理用户输入等核心功能。文章通过具体示例,如蓝色天空背景、可控制的火箭移动、按键响应和星星图案生成等,展示了Pygame在游戏开发中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

#12-1 蓝色天空 :创建一个背景为蓝色的Pygame窗口
import pygame
def show_sky():
	pygame.init()
	screen=pygame.display.set_mode((1200,800))
	pygame.display.set_caption("Blue Sky")
	while True:
		screen.fill((135,206,250))
		pygame.display.flip()
show_sky()

结果:

import pygame,sys
#12-2 游戏角色 :找一幅你喜欢的游戏角色位图图像或将一幅图像转换为位图。创建一个类,将该角色绘制到屏幕中央,
# 并将该图像的背景色设置为屏幕背景色,或将屏幕背景色设置为该图像的背景色。
class Draw_center():
	"""绘制到屏幕中央"""
	def __init__(self,screen):
		self.screen=screen
		self.image=pygame.image.load("image/dog.bmp")
		self.rect=self.image.get_rect()
		self.screen_rect=screen.get_rect()
		self.rect.centerx=self.screen_rect.centerx
		self.rect.centery = self.screen_rect.centery
	def blitme(self):
		self.screen.blit(self.image, self.rect)
#12-1 蓝色天空 :创建一个背景为蓝色的Pygame窗口
def show_sky():
	pygame.init()
	screen=pygame.display.set_mode((1200,800))
	pygame.display.set_caption("Blue Sky")
	draw_center=Draw_center(screen)
	while True:
		for event in pygame.event.get():
			if event.type == pygame.QUIT:
				sys.exit()
		screen.fill((135,206,250))
		draw_center.blitme()
		pygame.display.flip()
show_sky()

结果:

#12-3 火箭 :编写一个游戏,开始时屏幕中央有一个火箭,而玩家可使用四个方向键上下左右移动火箭。
# 请务必确保火箭不会移到屏幕外面。
import pygame,sys
class Settings():
	"""存储《外星人入侵》的所有设置的类"""
	def __init__(self):
		"""初始化游戏的设置"""
		# 屏幕设置
		self.screen_width = 1200
		self.screen_height = 800
		self.bg_color = (135,206,250)
		self.ship_speed_factor = 10
#-----------------------------------------------------
class Ship():
	def __init__(self, ai_settings,screen):
		"""初始化飞船并设置其初始位置"""
		self.screen = screen
		self.ai_settings=ai_settings
		# 加载飞船图像并获取其外接矩形
		self.image = pygame.image.load('image/ship.bmp')
		self.rect = self.image.get_rect()
		self.screen_rect = screen.get_rect()
		# 将每艘新飞船放在屏幕底部中央
		self.rect.centerx = self.screen_rect.centerx
		self.rect.centery= self.screen_rect.centery
		self.moving_right=False
		self.moving_left=False
		self.moving_top = False
		self.moving_bottom = False
	    #在飞船的属性center中存储小数值
		self.center = float(self.rect.centerx)
	def update(self):
		"""根据移动标志调整飞船的位置"""
		# 更新飞船的center值,而不是rect
		if self.moving_right and self.rect.right < self.screen_rect.right:
			self.rect.centerx += self.ai_settings.ship_speed_factor
		if self.moving_left and self.rect.left > 0:
			self.rect.centerx  -= self.ai_settings.ship_speed_factor
		if self.moving_top and self.rect.top >0:
			self.rect.centery  -= self.ai_settings.ship_speed_factor
		if self.moving_bottom and self.rect.bottom <self.screen_rect.bottom:
			self.rect.centery  += self.ai_settings.ship_speed_factor
	def blitme(self):
		"""在指定位置绘制飞船"""
		self.screen.blit(self.image, self.rect)
#----------------------------------------------------------
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_top = True
	elif event.key == pygame.K_DOWN:
		ship.moving_bottom = 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_top = False
	elif event.key == pygame.K_DOWN:
		ship.moving_bottom = 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()
def show_sky():
	pygame.init()
	screen=pygame.display.set_mode((1200,800))
	ai_settings=Settings()
	pygame.display.set_caption("ship moving")
	ship=Ship(ai_settings,screen)
	while True:
		update_screen(ai_settings,screen,ship)
		ship.update()
		check_events(ship)
show_sky()

#结果

# 12-4 按键 :创建一个程序,显示一个空屏幕。在事件循环中,每当检测到pygame.KEYDOWN 事件时都打印属性event.key 。
# 运行这个程序,并按各种键,看看Pygame如何响应。
def show_void():
	pygame.init()
	screens=pygame.display.set_mode((800,300))
	pygame.display.set_caption('Nothing hey')
	bg=(230,230,230)
	while True:
		for event in pygame.event.get():
			if event.type == pygame.QUIT:
				sys.exit()
			elif event.type == pygame.KEYDOWN:
				if event.key == pygame.K_UP:
					bg=(0,255,0)
				else:
					bg=(255,0,0)
		screens.fill(bg)
		pygame.display.flip()
show_void()

结果:

        按下UP键:

      按下DOWN/LEFT/RIGHT键:

# 12-5 侧面射击 :编写一个游戏,将一艘飞船放在屏幕左边,并允许玩家上下移动飞船。
#在玩家按空格键时,让飞船发射一颗在屏幕中向右穿行的子弹,并在子弹离开屏幕而消失后将其删除。
#########bullet.py#################
import pygame
from  pygame.sprite import Sprite
class Bullet(Sprite):
	def __init__(self,setting,screen,ship):
		super().__init__()
		self.screen=screen
		#在(0,0)处创建一个表示子弹的矩形,再设置正确的位置
		self.rect = pygame.Rect(0,0,setting.bullet_width,setting.bullet_height)
		self.rect.centery = ship.rect.centery
		self.rect.right = ship.rect.right
		# 存储用小数表示的子弹位置
		self.x = float(self.rect.x)
		self.color = setting.bullet_color
		self.speed_factor = setting.bullet_speed_factor
	def update(self):
		"""向右移动子弹"""
		# 更新表示子弹位置的小数值
		self.x += self.speed_factor
		#更新表示子弹的rect的位置
		self.rect.x = self.x
	def draw_bullets(self):
		"""在屏幕上绘制子弹"""
		pygame.draw.rect(self.screen,self.color,self.rect)
#########ship.py###################
import pygame
class Ship():
	def __init__(self,setting,screen):
		"""初始化飞船并设置其初始位置"""
		self.screen = screen
		self.setting = setting
		# 加载飞船图像并获取其外接矩形
		self.image =  pygame.image.load('images/ships.bmp')
		self.rect = self.image.get_rect()
		self.screen_rect = self.screen.get_rect()
		# 将每艘新飞船放在屏幕左边中央
		self.rect.centery = self.screen_rect.centery
		self.rect.left = self.screen_rect.left
		self.moving_top = False
		self.moving_bottom = False
		# 在飞船的属性center中存储小数值(因为rect的centery等属性只能存储整数值)
		self.center = float(self.rect.centery)
	def update(self):
		"""根据移动标志调整飞船的位置"""
		# 更新飞船的center值,而不是rect
		if self.moving_top and self.rect.top > 0:
			self.center -= self.setting.ship_speed_factor
		if self.moving_bottom and self.rect.bottom < self.screen_rect.bottom:
			self.center += self.setting.ship_speed_factor
		# 根据self.center更新rect对象
		self.rect.centery=self.center
	def blitme(self):
		"""在指定位置绘制飞船"""
		self.screen.blit(self.image,self.rect)
#########shot_function.py##########
import pygame,sys
from bullet import Bullet
def check_keydown_events(event,setting,screen,ship,bullets):
	"""响应按键"""
	if event.key==pygame.K_UP:
		ship.moving_top=True
	if event.key==pygame.K_DOWN:
		ship.moving_bottom=True
	if event.key==pygame.K_SPACE:
		fire_bullets(setting, screen, ship, bullets)

def check_keyup_events(event,ship):
	"""响应松开"""
	if event.key == pygame.K_UP:
		ship.moving_top = False
	elif event.key == pygame.K_DOWN:
		ship.moving_bottom = False

def check_events(setting,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,setting,screen,ship,bullets)
		elif event.type == pygame.KEYUP:
			check_keyup_events(event,ship)

def update_screen(setting,screen,ship,bullets):
	"""更新屏幕上的图像,并切换到新屏幕"""
	# 每次循环时都重绘屏幕
	# 在飞船和外星人后面重绘所有子弹
	screen.fill(setting.bg)
	for bullet in bullets.sprites():
		bullet.draw_bullets()
	ship.blitme()
	#让最近绘制的屏幕可见
	pygame.display.flip()
def update_bullets(right,bullets):
	"""更新子弹的位置,并删除已消失的子弹"""
	#更新子弹的位置
	bullets.update()
	# 删除已消失的子弹
	for bullet in bullets.copy():
		if bullet.rect.left > right:
			bullets.remove(bullet)
def fire_bullets(setting, screen, ship, bullets):
	"""#创建新子弹并将其加入到编组bullets中"""
	if len(bullets) < setting.bullet_allowed:
		new_bullet = Bullet(setting, screen, ship)
		bullets.add(new_bullet)


#########setting.py##############
class Setting():
	def __init__(self):
		#屏幕
		self.screen_width = 1500
		self.screen_height = 800
		self.bg=(230,230,230)
		self.ship_speed_factor=2.5
		#子弹
		self.bullet_speed_factor = 0.7
		self.bullet_width = 15
		self.bullet_height = 3
		self.bullet_color = 0,0,0
		self.bullet_allowed = 30
########主函数,shot.py###########
import pygame
import shot_functions as sf
from setting import Setting
from pygame.sprite import Group
from ship import Ship
def show_left():
	pygame.init()
	setting = Setting()
	screen=pygame.display.set_mode((setting.screen_width,setting.screen_height ))
	pygame.display.set_caption("侧面射击")
	ship = Ship(setting,screen)
	bullet = Group()
	while True:
		sf.check_events(setting, screen, ship, bullet)
		ship.update()
		sf.update_bullets(screen.get_rect().right,bullet)
		sf.update_screen(setting, screen, ship, bullet)
show_left()

结果:

#13-1 星星 :找一幅星星图像,并在屏幕上显示一系列整齐排列的星星。
import pygame,sys
from pygame.sprite import Group
from pygame.sprite import Sprite
class Star(Sprite):
	def __init__(self,screen):
		super(Star,self).__init__()
		self.screen=screen
		self.image=pygame.image.load("image/starmans.bmp")
		self.rect=self.image.get_rect()
		self.rect.x=self.rect.width
		self.rect.y=self.rect.height
		self.x=float(self.rect.x)
	def blitme(self):
		self.screen.blit(self.image,self.rect)
def get_number_stars_x(screen_width,stars_width):
	available_sapce_x = screen_width-2*stars_width
	number_stars_x = int(available_sapce_x/(2*stars_width))
	return number_stars_x
def get_number_rows(screen_height,stars_height):
	available_sapce_x = screen_height - 2 * stars_height
	number_rows = int(available_sapce_x / (2 * stars_height))
	return  number_rows
def create_stars(screen,stars,star_number,row_number):
	star = Star(screen)
	star.x = star.rect.width + 2*star.rect.width*star_number
	star.rect.x = star.x
	star.rect.y = star.rect.height+2*star.rect.height*row_number
	stars.add(star)
def show_stars():
	pygame.init()
	screen=pygame.display.set_mode((800,600))
	pygame.display.set_caption("starry starry night")
	stars=Group()
	while True:
		for event in pygame.event.get():
			if event.type == pygame.QUIT:
				sys.exit()
		star=Star(screen)
		number_stars_x = get_number_stars_x(800,star.rect.width)
		number_rows = get_number_rows(600,star.rect.height)
		for row_number in range(number_rows):
			for star_number in range(number_stars_x):
				create_stars(star.screen,stars,star_number,row_number)
		screen.fill((230,230,230))
		stars.draw(screen)
		pygame.display.flip()
show_stars()

结果:

#13-2 更逼真的星星 :为让星星的分布更逼真,可随机地放置星星。本书前面说过,可像下面这样来生成随机数:
# from random import randint
# random_number = randint(-10,10)
import pygame,sys
from pygame.sprite import Group
from pygame.sprite import Sprite
from random import randint
class Star(Sprite):
	def __init__(self,screen):
		super().__init__()
		self.screen=screen
		self.image=pygame.image.load("image/starmans.bmp")
		self.rect=self.image.get_rect()
		self.number_random = randint(-10,10)
		self.rect.x=self.rect.width+self.number_random
		self.rect.y=self.rect.height+self.number_random
		self.x=float(self.rect.x)
	def blitme(self):
		self.screen.blit(self.image,self.rect)
def get_number_stars_x(screen_width,stars_width):
	available_space_x = screen_width-2*stars_width
	number_stars_x = int(available_space_x/(2*stars_width))
	return number_stars_x
def get_number_rows(screen_height,stars_height):
	available_space_y = screen_height - 2 * stars_height
	number_rows = int(available_space_y / (2 * stars_height))
	return  number_rows
def create_stars(screen,stars,star_number,row_number):
	star = Star(screen)
	star.x = star.rect.x + 2*star.rect.x*star_number
	star.rect.x = star.x
	star.rect.y = star.rect.y+2*star.rect.y*row_number
	stars.add(star)
def show_stars():
	pygame.init()
	screen=pygame.display.set_mode((800,600))
	pygame.display.set_caption("starry starry night")
	stars=Group()
	star = Star(screen)
	number_stars_x = get_number_stars_x(800, star.rect.width)
	number_rows = get_number_rows(600, star.rect.height)
	for row_number in range(number_rows):
		for star_number in range(number_stars_x):
			create_stars(star.screen, stars, star_number, row_number)
	while True:
		for event in pygame.event.get():
			if event.type == pygame.QUIT:
				sys.exit()
		screen.fill((230,230,230))
		stars.draw(screen)
		pygame.display.flip()
show_stars()

结果:

#13-3 雨滴 :寻找一幅雨滴图像,并创建一系列整齐排列的雨滴。让这些雨滴往下落,直到到达屏幕底端后消失。
#13-4 连绵细雨 :修改为完成练习13-3而编写的代码,使得一行雨滴消失在屏幕底端后,屏幕顶端又出现一行新雨滴,
# 并开始往下落。
import pygame,sys
from pygame.sprite import Group
from pygame.sprite import Sprite
class Raindrop(Sprite):
	def __init__(self,screen):
		super().__init__()
		self.screen=screen
		self.image=pygame.image.load("image/raindrops.bmp")
		self.rect=self.image.get_rect()
		self.rect.x=self.rect.width
		self.rect.y=self.rect.height
		self.drop_speed =1
	def update(self):
		self.rect.y += self.drop_speed
	def blitme(self):
		self.screen.blit(self.image,self.rect)
def get_number_raindrops_x(screen_width,raindrops_width):
	available_space_x = screen_width-2*raindrops_width
	number_raindrops_x = int(available_space_x/(2*raindrops_width))
	return number_raindrops_x
def create_raindrops(screen,raindrops,raindrop_number):
	raindrop=Raindrop(screen)
	raindrop.rect.x = raindrop.rect.x+2*raindrop.rect.x*raindrop_number
	raindrops.add(raindrop)
def create_raindrops_group(screen, raindrops):
	raindrop = Raindrop(screen)
	raindrop_number = get_number_raindrops_x(800, raindrop.rect.width)
	for raindrop_num in range(raindrop_number):
		create_raindrops(raindrop.screen, raindrops, raindrop_num)
def update_raindrops(screen,raindrops):
	"""更新雨滴的位置,删除已经消失的雨滴"""
	raindrops.update()
	for raindrop in raindrops:
		if raindrop.rect.top >= 600:
			raindrops.remove(raindrop)
	if raindrop.rect.top >= 600:
		create_raindrops_group(screen,raindrops)

def show_raindrops():
	pygame.init()
	screen = pygame.display.set_mode((800,600))
	pygame.display.set_caption("rainbow raindrops")
	raindrops=Group()
	create_raindrops_group(screen, raindrops)
	while True:
		for event in pygame.event.get():
			if event.type == pygame.QUIT:
				sys.exit()
		screen.fill((230,230,230))
		update_raindrops(screen, raindrops)
		raindrops.draw(screen)
		pygame.display.flip()
show_raindrops()

结果:

#13-5 抓球 :创建一个游戏,在屏幕底端放置一个玩家可左右移动的角色。让一个球出现在屏幕顶端,
# 且水平位置是随机的,并让这个球以固定的速度往下落。如果角色与球发生碰撞(表示将球抓住了),
# 就让球消失。每当角色抓住球或球因抵达屏幕底端而消失后,都创建一个新球。
import pygame,sys
from random import randint
from  pygame.sprite import Sprite
from pygame.sprite import Group
class Ball(Sprite):
	def __init__(self,screen):
		super().__init__()
		self.screen = screen
		self.image = pygame.image.load("image/ball.jpg")
		self.rect = self.image.get_rect()
		self.number_random = randint(10,600)
		self.rect.x = self.rect.width+self.number_random
		self.drop_speed = 1
	def update(self):
		self.rect.y += self.drop_speed
	def blitme(self):
		self.screen.blit(self.image,self.rect)
class Man(Sprite):
	def __init__(self,screen):
		super().__init__()
		self.screen = screen
		self.image = pygame.image.load("image/man.jpg")
		self.rect = self.image.get_rect()
		self.rect.centerx = self.screen.get_rect().centerx
		self.rect.bottom = self.screen.get_rect().bottom
		self.moving_right = False
		self.moving_left = False
		self.center = float(self.rect.centerx)
	def update(self):
		if self.moving_left and self.rect.left > 0:
			self.center -= 50
		if self.moving_right and self.rect.right < 800:
			self.center += 50
		self.rect.centerx = self.center
	def blitme(self):
		self.screen.blit(self.image,self.rect)
def check_keydown(event,man):
	if event.key == pygame.K_RIGHT:
		man.moving_right = True
	elif event.key == pygame.K_LEFT:
		man.moving_left = True
def check_keyup(event,man):
	"""响应松开"""
	if event.key == pygame.K_RIGHT:
		man.moving_right = False
	elif event.key == pygame.K_LEFT:
		man.moving_left = False
def create_ball(balls,screen):
        if len(balls) ==0:
            b = Ball(screen)
            balls.add(b)
        else:
            pass
def update_ball(balls,mans):
	for ball in balls:
		balls.update()
		if ball.rect.y >= 600:
			balls.remove(ball)
	collisions = pygame.sprite.groupcollide(balls, mans, True, True)
def show_ball():
	pygame.init()
	screen = pygame.display.set_mode((800,600))
	mans = Group()
	balls = Group()
	pygame.display.set_caption("Catch the ball!")
	while True:
		screen.fill((230, 230, 230))
		if len(mans) == 0:
			mans.add(Man(screen))
		for man in mans:
			for event in pygame.event.get():
				if event.type == pygame.QUIT:
					sys.exit()
				elif event.type == pygame.KEYDOWN:
					check_keydown(event,man)
				elif event.type == pygame.KEYUP:
					check_keyup(event,man)
				man.update()
		mans.draw(screen)
		create_ball(balls, screen)
		update_ball(balls,mans)
		balls.draw(screen)
		pygame.display.flip()
show_ball()

13-5结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值