1. 程式人生 > >Python程式設計從入門到實踐習題12-5

Python程式設計從入門到實踐習題12-5

12-5  側面射擊:編寫一個遊戲,將一艘飛船放置在螢幕左邊,並允許玩家上下移動飛船。在玩家按空格鍵時,讓飛船發射一顆在螢幕中央向右穿行的子彈,並在子彈離開螢幕而消失後將其刪除。

這個題和書上的程式類似,但自己寫的時候還是遇到了許多問題,磕磕碰碰實現了。

主程式:game

import pygame

from settings import Settings

import func as f

from ship import Ship

from bullet import Bullet

from pygame.sprite import Group

def run_game():
	pygame.init()
	
	settings = Settings()
	                
	screen = pygame.display.set_mode((settings.screen_width, settings.screen_height))
	pygame.display.set_caption("Side Shoot")
	
	ship = Ship(screen)
	
	bullets = Group()
	
	while True:
		
		f.check_keys(settings, screen, ship, bullets)
		ship.update()
		bullets.update()
		
		#刪除已消失的子彈
		for bullet in bullets.copy():
			if bullet.rect.left > screen.get_rect().right:
				bullets.remove(bullet)
				
		f.update_screen(settings, screen, ship, bullets)
	
run_game()

Settings類:

import pygame

class Settings():
	"""所有設定的類"""
	
	def __init__(self):
		
		#設定螢幕的屬性
		self.screen_width = 1200
		self.screen_height = 600
		self.bg_color = (230, 230, 230)

		#設定子彈屬性
		self.bullet_speed_factor = 1
		self.bullet_width = 5
		self.bullet_height = 5
		self.bullet_color = 0, 0, 0

Ship類:

import pygame

class Ship():
	
	def __init__(self, screen):
		"""設定飛船的屬性"""
		self.screen = screen#EEEE:忘記寫
		
		self.image = pygame.image.load('ship.bmp')#讀取飛船圖片
		self.image = pygame.transform.rotate(self.image, -90)#將飛船順時針旋轉90°
		self.rect = self.image.get_rect()#獲取飛船圖片外接矩形
		self.screen_rect = screen.get_rect()#獲取螢幕的外接矩形
		
		#設定飛船的位置,將飛船放置在螢幕左側中間
		self.rect.centery = self.screen_rect.centery
		self.rect.left = self.screen_rect.left
		
		#初始化飛船上下移動屬性
		self.moving_up = False
		self.moving_down = False
	
	def update(self):
		"""更新飛船位置"""
		if self.moving_up and self.rect.top > 0:
			self.rect.centery -= 1
		elif self.moving_down and self.rect.bottom < self.screen_rect.bottom:
			self.rect.centery += 1	
	
	def blitme(self):
		"""繪製飛船"""
		self.screen.blit(self.image, self.rect)
		
		
		

Bullet類:

import pygame

from pygame.sprite import Sprite

class Bullet(Sprite):
	"""一個對子彈進行管理的類"""
	
	def __init__(self, settings, screen, ship):
		"""在飛船出建立一個子彈物件"""
		
		#繼承父類的屬性
		super().__init__()
		
		self.screen = screen
		
		#在(0, 0)處建立一個子彈的矩形,再設定其準確位置
		self.rect = pygame.Rect(0, 0, settings.bullet_width, settings.bullet_height)
		self.rect.centery = ship.rect.centery
		self.rect.right = ship.rect.right
		
		#儲存用小數表示的子彈位置
		self.x = float(self.rect.x)
		
		self.color = settings.bullet_color
		self.speed_factor = settings.bullet_speed_factor
		
	def update(self):
		"""更新子彈位置"""
		self.x += self.speed_factor
		self.rect.x = self.x
		
	def draw_bullet(self):
		"""在螢幕上繪製子彈"""
		pygame.draw.rect(self.screen, self.color, self.rect)

函式模組func:

import pygame

import sys

from ship import Ship

from bullet import Bullet

def check_keys(settings, screen, ship, bullets):
	for event in pygame.event.get():
		if event.type == pygame.QUIT:
			sys.exit()
		elif event.type == pygame.KEYDOWN:
			check_keys_down(event, settings, screen, ship, bullets)
		elif event.type == pygame.KEYUP:
			check_keys_up(event, ship)
		
def check_keys_down(event,settings, screen, ship, bullets):
	if event.key == pygame.K_UP:
		ship.moving_up = True
	if event.key == pygame.K_DOWN:
		ship.moving_down = True
	elif event.key == pygame.K_SPACE:
		#建立一顆子彈,並加入到Group編組中
		new_bullet = Bullet(settings, screen, ship)
		bullets.add(new_bullet)
	
def check_keys_up(event,ship):
	if event.key == pygame.K_UP:
		ship.moving_up = False
	if event.key == pygame.K_DOWN:
		ship.moving_down = False
		
def update_screen(settings, screen, ship, bullets):
	screen.fill(settings.bg_color)
	ship.blitme()
	for bullet in bullets.sprites():
		bullet.draw_bullet()
	pygame.display.flip()

效果圖:


這子彈模型讓我想起了小時候掌機上一個像彈乒乓球的遊戲,呵呵!

問題與總結:

1.初始化Ship類時,忘記寫self.screen = screen

2.當按住↑鍵時,飛船直接到了螢幕頂部,經檢查是在check_keys_down()中,moving_up拼寫出錯

3.對編組bullets中的bullet使用for迴圈時,應寫成for bullet in bullet.sprites():

4.各處形參傳遞順序應一致,本次因為沒注意一直出現 AttributeError,值得注意