pygame安装好了,经过很长的时间python基本语法也已经学习完了,接下来继续进行项目的开发:
导入sys模块控制退出游戏
导入pygame模块
主程序代码:
import sys
import pygame
from settings import Settings
class AlienInvasion:
def __init__(self):
pygame.init()
self.settings = Settings()
self.screen = pygame.display.set_mode(
(self.settings.screen_width, self.settings.screen_height))
pygame.display.set_caption("Alien Invasion")
def run_game(self):
while True:
# Watch for keyboard and mouse events.
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
self.screen.fill(self.settings.bg_color)
pygame.display.flip()
if __name__ == '__main__':
ai = AlienInvasion()
ai.run_game()
设置部分代码:(创建设置类),并用他来访问设置
class Settings:
def __init__(self):
self.screen_width = 1200
self.screen_height = 800
self.bg_color = (230, 230, 230)
现在窗口设置好了,可以出现游戏窗口了,一切正常,进行添加游戏元素:
同理,设置一个新的模块ship.py
用于管理飞船的大部分行为:
import pygame
class Ship:
"""管理飞船的类"""
def __init__(self, ai_game):
"""初始化飞船并设置其初始位置"""
self.screen = ai_game.screen
self.screen_rect = ai_game.screen.get_rect()
#加载飞船图像并获取其外接矩形
self.image = pygame.image.load(
r'C:/Users/TOMMY/Documents/coding/.vscode/alien_invasion/ship.bmp')
self.rect = self.image.get_rect()
#对于每艘新飞船,都将其放置在屏幕底部
self.rect.midbottom = self.screen_rect.midbottom
def blitme(self):
"""在指定位置绘制飞船"""
self.screen.blit(self.image, self.rect)
更新一下alien_invasion.py,创建一艘飞船:
import pygame, sys
from settings import Settings
from ship import Ship
class AlienInvasion:
def __init__(self):
"""初始化游戏并创建游戏资源"""
pygame.init()
self.settings = Settings()
self.screen = pygame.display.set_mode(
(self.settings.screen_width, self.settings.screen_height))
pygame.display.set_caption("Alien Invasion")
#set screen's color
self.bg_color = (230, 230, 230)
self.ship = Ship(self)
def run_game(self):
"""开始游戏的主循环"""
while True:
self._check_events()
self._update_screen()
def _check_events(self):
# 监视键盘和鼠标事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
def _update_screen(self):
#每次循环时都重绘屏幕
self.screen.fill(self.settings.bg_color)
self.ship.blitme()
#更新屏幕使屏幕可视化
pygame.display.flip()
if __name__ == '__main__':
#创建游戏实例并运行游戏
ai = AlienInvasion()
ai.run_game()
其中上述操作中都包含了对主程序的重构,把主程序的游戏循环进行了重构,这样能一眼就明白游戏循环到底是干嘛的,它的功能是什么,把他们独立到两个单独的方法中实现时,利用他的功能可以使用句点访问法。
调用过程:
def run_game(self):
while True:
self._check_events()
self._update_screen()
def _check_events(self):
-----snip------
def _update_screen():
----snip-----
尽量先在主程序内编写,等调试成功后吗,在进行代码的重构,使主程序更清晰,简单,有助于对主程序功能的更新以及下一步的代码编写!!!
通过方法pygame.event.get()
获取事件,每次按下键盘都被注册为一次KEYDOWN事件,所以在__check_events()
方法内的循环内添加一个选项,如果用户按下一个键盘右箭头,那么图像就向右移动一个位置:
def _check_event(self):
--snip--
elif event.type == pygame.KEYDOWN:
if event.type == pygame.K_RIGHT:
self.ship.rect.x += 1
每按右箭头一次,飞船就向右移动一个像素,但是不能连续移动,现在令移动高效:支持连续移动:
def _check_events(self):
# 监视键盘和鼠标事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
self.ship.moving_right = True
elif event.key == pygame.K_LEFT:
self.ship.moving_left = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
self.ship.moving_right = False
elif event.key == pygame.K_LEFT:
self.ship.moving_left = False
在这里能使用elif代码块,是因为每个键只与一个事件相关联,每一个事件有单独的两个区块分别执行,是分开执行的,所以当同时按下左右键时他时两个不同的事件,所以分别进入到两个分区进行处理,互不影响,表现出来飞船在原位置不动。
在ship模块内进行更新:
import pygame
class Ship:
"""管理飞船的类"""
def __init__(self, ai_game):
--snip--
self.moving_right = False
self.moving_left = False
def update(self):
if self.moving_right:
self.rect.x += 1
if self.moving_left:
self.rect.x -= 1
def blitme(self):
"""在指定位置绘制飞船"""
self.screen.blit(self.image, self.rect)
添加一个设置飞船移动速度的设置,以便于控制飞船的移动速度,并且设置一个每一次移动一个小数的像素,以便于精准的控制,但是rect无法储存小数,只能自动转化成整数,所以要想实现精准控制,要加一个变量,间接的实现飞船的像素位置更新:
class Settings:
--snip--
self.ship_speed = 0.5
接下来对ship类进行更新:
import pygame
class Ship:
"""管理飞船的类"""
def __init__(self, ai_game):
"""初始化飞船并设置其初始位置"""
self.screen = ai_game.screen
self.settings = ai_game.settings
self.screen_rect = ai_game.screen.get_rect()
#加载飞船图像并获取其外接矩形
self.image = pygame.image.load(
r'C:/Users/TOMMY/Documents/coding/.vscode/alien_invasion/ship.bmp')
self.rect = self.image.get_rect()
#对于每艘新飞船,都将其放置在屏幕底部
self.rect.midbottom = self.screen_rect.midbottom
self.x = float(self.rect.x)
self.moving_right = False
self.moving_left = False
def update(self):
if self.moving_right:
self.x += self.settings.ship_speed
if self.moving_left:
self.x -= self.settings.ship_speed
self.rect.x = self.x
def blitme(self):
"""在指定位置绘制飞船"""
self.screen.blit(self.image, self.rect)
给ship类添加属性seetings以便能在update方法中使用它
self.rect.x = self.x
这一行代码是设置小数位像素的核心,就算是这样赋值后他的最后的值即便是小数,赋值给rect后,也会转化成整数型,但是如果在settings类中设置的初始移动位数为0.5,那么第一次的更新和赋值在飞船的像素位置变化转化为整形后为0,所以这个位置的变化的奇数次看来是无效的,在偶数次是有效的,所以有效的实际的移动时间差变长了,所以在连续移动的效果下看到的是移动速度变慢,并且更精准。
当飞船到达游戏窗口的左或右边界时,停止运动:
def update(self):
if self.moving_right and self.rect.right < self.screen_rect.right:
self.x += self.settings.ship_speed
if self.moving_left and self.rect.left > 0:
self.x -= self.settings.ship_speed
self.rect.x = self.x