目录
前言
一、12-1蓝色天空
二、12-2游戏角色
三、12-3Pygame文档
四、12-4火箭
五、12-5按键
六、12-6侧面射击
总结
前言
这里是Python从入门到实践的练习答案,本人也是初学python,在这里把我的答案记录下来。如果有错误或者可以改进的地方欢迎在评论区留言。另外,所有代码均按照书上方式重构,便于阅读和理解。
大家要提前下载pygame,并且获取到相关的图片资源。文中使用的相对路径由文件的存储位置决定,不能照抄。
一、12-1蓝色天空
mygame1.0.py
import sys
import pygame
from settings import Settings
class MyGame:
"""管理游戏资源和行为的类"""
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("MyGame 1.0")
def run_game(self):
""""开始游戏的主循环"""
while True:
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 = MyGame()
ai.run_game()
settings.py
class Settings:
"""储存游戏《外星人入侵》中所有设置的类"""
def __init__(self):
"""初始化游戏的设置"""
# 屏幕设置
self.screen_width = 1000
self.screen_height = 600
self.bg_color = (0, 200, 255)
这里是Python从入门到实践的练习答案,本人也是初学python,在这里把我的答案记录下来。如果有错误或者可以改进的地方欢迎在评论区留言。另外,所有代码均按照书上方式重构,便于阅读和理解。
大家要提前下载pygame,并且获取到相关的图片资源。文中使用的相对路径由文件的存储位置决定,不能照抄。
mygame1.0.py
import sys
import pygame
from settings import Settings
class MyGame:
"""管理游戏资源和行为的类"""
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("MyGame 1.0")
def run_game(self):
""""开始游戏的主循环"""
while True:
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 = MyGame()
ai.run_game()
settings.py
class Settings:
"""储存游戏《外星人入侵》中所有设置的类"""
def __init__(self):
"""初始化游戏的设置"""
# 屏幕设置
self.screen_width = 1000
self.screen_height = 600
self.bg_color = (0, 200, 255)
结果是这样的
二、12-2游戏角色
图片大家找自己喜欢的就可以。设置图像的背景色这一步我也没有好的方法,大家可以试试抠图软件。
在这里我把游戏角色命名为ship,储存到新建的Ship.py文件中。
我用的是无背景的图,如果是有背景的图就改设置的背景颜色吧。
图我放在下面了
新建 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('me.png')
self.rect = self.image.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)
稍微修改mygame1.0.py
import sys
import pygame
from settings import Settings
from ship import Ship
class MyGame:
"""管理游戏资源和行为的类"""
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("MyGame 1.0")
self.ship = Ship(self)
def run_game(self):
""""开始游戏的主循环"""
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
self.screen.fill(self.settings.bg_color)
self.ship.blitme()
# 让最近绘制的屏幕可见
pygame.display.flip()
if __name__ == '__main__':
ai = MyGame()
ai.run_game()
来看看结果
三、12-3Pygame文档
如果你想修改游戏或者编写自己的游戏,这些文档将会有所帮助
如果你想修改游戏或者编写自己的游戏,这些文档将会有所帮助
pygame文档https://www.pygame.org/docs/
链接在这里了,这是我在官网上搜的文档应该就是官方文档了吧(不确定),有懂哥可以在评论区说一下哦
四、12-4火箭
在题目要求的基础上 加了按“q”退出的功能
代码按照书上的样子进行了重构
settings.py 增加了速度设置
class Settings:
"""储存游戏《外星人入侵》中所有设置的类"""
def __init__(self):
"""初始化游戏的设置"""
# 屏幕设置
self.screen_width = 1000
self.screen_height = 600
self.bg_color = (0, 200, 255)
#飞船设置
self.ship_speed = 0.5
ship.py
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('me.png')
self.rect = self.image.get_rect()
#绘制到屏幕中央
self.rect.centerx = self.screen_rect.centerx
self.rect.centery = self.screen_rect.centery
# 在飞船的属性 x,y 中储存小数值
self.x = float(self.rect.x)
self.y = float(self.rect.y)
#移动标志
self.moving_right = False
self.moving_left = False
self.moving_up = False
self.moving_down = False
def update(self):
"""根据移动标志调整角色的位置"""
#更新角色而不是rect对象的x,y值
if self.moving_right and self.rect.right < self.screen_rect.right:
self.x += self.settings.ship_speed
elif self.moving_left and self.rect.left > 0:
self.x += -1 * self.settings.ship_speed
elif self.moving_up and self.rect.top > 0:
self.y += -1 * self.settings.ship_speed
elif self.moving_down and self.rect.bottom < self.screen_rect.bottom:
self.y += self.settings.ship_speed
#更新rect对象
self.rect.x = self.x
self.rect.y = self.y
def blitme(self):
"""在指定的位置绘制飞船"""
self.screen.blit(self.image, self.rect)
mygame1.0.py
import sys
import pygame
from settings import Settings
from ship import Ship
class MyGame:
"""管理游戏资源和行为的类"""
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("MyGame 1.0")
self.ship = Ship(self)
def _update_screen(self):
"""更新屏幕上的图像,并切换到新图像"""
self.screen.fill(self.settings.bg_color)
self.ship.blitme()
# 让最近绘制的屏幕可见
pygame.display.flip()
def _check_events(self):
"""相应按键和鼠标事件"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
self._check_keydown_events(event)
elif event.type == pygame.KEYUP:
self._check_keyup_events(event)
def _check_keydown_events(self, event):
"""响应按键"""
if event.key == pygame.K_RIGHT:
# 向右移动角色
self.ship.moving_right = True
elif event.key == pygame.K_LEFT:
# 向左移动角色
self.ship.moving_left = True
elif event.key == pygame.K_UP:
# 向上移动角色
self.ship.moving_up = True
elif event.key == pygame.K_DOWN:
# 向下移动角色
self.ship.moving_down = True
elif event.key == pygame.K_q:
#按 q 退出
sys.exit()
def _check_keyup_events(self, event):
"""响应松开"""
if event.key == pygame.K_RIGHT:
self.ship.moving_right = False
elif event.key == pygame.K_LEFT:
self.ship.moving_left = False
elif event.key == pygame.K_UP:
self.ship.moving_up = False
elif event.key == pygame.K_DOWN:
self.ship.moving_down = False
def run_game(self):
""""开始游戏的主循环"""
while True:
self._check_events()
self.ship.update()
self._update_screen()
if __name__ == '__main__':
ai = MyGame()
ai.run_game()
温馨提示:折叠起来看更一目了然哦~
五、12-5按键
新建 eventkey.py
仿照之前的文件写就行了
主要是加一个print(event.key)
import pygame
from settings import Settings
import sys
class MyGame:
"""管理游戏资源和行为的类"""
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("MyGame 1.0")
def _update_screen(self):
"""更新屏幕上的图像,并切换到新图像"""
self.screen.fill(self.settings.bg_color)
# 让最近绘制的屏幕可见
pygame.display.flip()
def _check_keydown_events(self, event):
"""响应按键"""
print(event.key)
def run_game(self):
""""开始游戏的主循环"""
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
self._check_keydown_events(event)
self._update_screen()
if __name__ == '__main__':
ai = MyGame()
ai.run_game()
不创建新文件,在原有文件上加一句也行
来看看结果:
输入为:abcd左上右下
初步判定为ascll码值
六、12-6侧面射击
修改一下 ship.py
让角色只能上下移动
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('me.png')
self.rect = self.image.get_rect()
#绘制到屏幕中央
self.rect.midleft = self.screen_rect.midleft
# 在飞船的属性 x,y 中储存小数值
self.y = float(self.rect.y)
#移动标志
self.moving_up = False
self.moving_down = False
def update(self):
"""根据移动标志调整角色的位置"""
#更新角色而不是rect对象的y值
if self.moving_up and self.rect.top > 0:
self.y += -1 * self.settings.ship_speed
elif self.moving_down and self.rect.bottom < self.screen_rect.bottom:
self.y += self.settings.ship_speed
#更新rect对象
self.rect.y = self.y
def blitme(self):
"""在指定的位置绘制飞船"""
self.screen.blit(self.image, self.rect)
修改一下 settings.py
加入子弹的设置
class Settings:
"""储存游戏《外星人入侵》中所有设置的类"""
def __init__(self):
"""初始化游戏的设置"""
# 屏幕设置
self.screen_width = 1000
self.screen_height = 600
self.bg_color = (0, 200, 255)
#飞船设置
self.ship_speed = 0.5
#子弹设置
self.bullet_speed = 0.6
self.bullet_width = 5
self.bullet_hight = 15
self.bullet_color = (60, 60, 60)
新建 bullet.py
import pygame
from pygame.sprite import Sprite
class Bullet(Sprite):
"""管理飞船所发射子弹的类"""
def __init__(self, ai_game):
"""在飞船当前位置创建一个子弹对象"""
super().__init__()
self.screen = ai_game.screen
self.settings = ai_game.settings
self.color = self.settings.bullet_color
#在(0,0)处创建一个表示子弹的矩形,再设置正确的位置
self.rect = pygame.Rect(0, 0, self.settings.bullet_hight,
self.settings.bullet_width)
self.rect.midleft = ai_game.ship.rect.midleft
self.rect.x = ai_game.ship.rect.right
#使用小数表示的子弹的位置
self.x = float(self.rect.x)
def draw_bullet(self):
"""在屏幕上绘制子弹"""
pygame.draw.rect(self.screen, self.color, self.rect)
def update(self):
"""向右移动子弹"""
#更新表示子弹位置的小数值
self.x += self.settings.bullet_speed
#更新表示 rect 的位置
self.rect.x = self.x
修改一下 mygame1.0.py
import sys
import pygame
from settings import Settings
from ship import Ship
from bullet import Bullet
class MyGame:
"""管理游戏资源和行为的类"""
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("MyGame 1.0")
self.ship = Ship(self)
self.bullets = pygame.sprite.Group()
def _update_screen(self):
"""更新屏幕上的图像,并切换到新图像"""
self.screen.fill(self.settings.bg_color)
self.ship.blitme()
for bullet in self.bullets.sprites():
bullet.draw_bullet()
# 让最近绘制的屏幕可见
pygame.display.flip()
def _update_bullets(self):
"""更新子弹的位置并删除消失的子弹"""
self.bullets.update()
# 删除消失的子弹
for bullet in self.bullets.copy():
if bullet.rect.x > self.settings.screen_width:
self.bullets.remove(bullet)
def _fire_bullet(self):
"""创建一颗子弹,并将其加入编组bullets中"""
new_bullet = Bullet(self)
self.bullets.add(new_bullet)
def _check_events(self):
"""相应按键和鼠标事件"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
self._check_keydown_events(event)
elif event.type == pygame.KEYUP:
self._check_keyup_events(event)
def _check_keydown_events(self, event):
"""响应按键"""
if event.key == pygame.K_UP:
# 向上移动角色
self.ship.moving_up = True
elif event.key == pygame.K_DOWN:
# 向下移动角色
self.ship.moving_down = True
elif event.key == pygame.K_q:
#按 q 退出
sys.exit()
elif event.key == pygame.K_SPACE:
self._fire_bullet()
def _check_keyup_events(self, event):
"""响应松开"""
if event.key == pygame.K_RIGHT:
self.ship.moving_right = False
elif event.key == pygame.K_LEFT:
self.ship.moving_left = False
elif event.key == pygame.K_UP:
self.ship.moving_up = False
elif event.key == pygame.K_DOWN:
self.ship.moving_down = False
def run_game(self):
""""开始游戏的主循环"""
while True:
self._check_events()
self.ship.update()
self._update_bullets()
self._update_screen()
if __name__ == '__main__':
ai = MyGame()
ai.run_game()
这里有一个警告,我也不知道为什么出现怎么消除
有大佬知道的话可以解释一下
不影响运行
来看看结果吧:
总结
在题目要求的基础上 加了按“q”退出的功能
代码按照书上的样子进行了重构
settings.py 增加了速度设置
ship.py
mygame1.0.py
温馨提示:折叠起来看更一目了然哦~
新建 eventkey.py
仿照之前的文件写就行了
主要是加一个print(event.key)
import pygame
from settings import Settings
import sys
class MyGame:
"""管理游戏资源和行为的类"""
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("MyGame 1.0")
def _update_screen(self):
"""更新屏幕上的图像,并切换到新图像"""
self.screen.fill(self.settings.bg_color)
# 让最近绘制的屏幕可见
pygame.display.flip()
def _check_keydown_events(self, event):
"""响应按键"""
print(event.key)
def run_game(self):
""""开始游戏的主循环"""
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
self._check_keydown_events(event)
self._update_screen()
if __name__ == '__main__':
ai = MyGame()
ai.run_game()
不创建新文件,在原有文件上加一句也行
来看看结果:
输入为:abcd左上右下
初步判定为ascll码值
六、12-6侧面射击
修改一下 ship.py
让角色只能上下移动
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('me.png')
self.rect = self.image.get_rect()
#绘制到屏幕中央
self.rect.midleft = self.screen_rect.midleft
# 在飞船的属性 x,y 中储存小数值
self.y = float(self.rect.y)
#移动标志
self.moving_up = False
self.moving_down = False
def update(self):
"""根据移动标志调整角色的位置"""
#更新角色而不是rect对象的y值
if self.moving_up and self.rect.top > 0:
self.y += -1 * self.settings.ship_speed
elif self.moving_down and self.rect.bottom < self.screen_rect.bottom:
self.y += self.settings.ship_speed
#更新rect对象
self.rect.y = self.y
def blitme(self):
"""在指定的位置绘制飞船"""
self.screen.blit(self.image, self.rect)
修改一下 settings.py
加入子弹的设置
class Settings:
"""储存游戏《外星人入侵》中所有设置的类"""
def __init__(self):
"""初始化游戏的设置"""
# 屏幕设置
self.screen_width = 1000
self.screen_height = 600
self.bg_color = (0, 200, 255)
#飞船设置
self.ship_speed = 0.5
#子弹设置
self.bullet_speed = 0.6
self.bullet_width = 5
self.bullet_hight = 15
self.bullet_color = (60, 60, 60)
新建 bullet.py
import pygame
from pygame.sprite import Sprite
class Bullet(Sprite):
"""管理飞船所发射子弹的类"""
def __init__(self, ai_game):
"""在飞船当前位置创建一个子弹对象"""
super().__init__()
self.screen = ai_game.screen
self.settings = ai_game.settings
self.color = self.settings.bullet_color
#在(0,0)处创建一个表示子弹的矩形,再设置正确的位置
self.rect = pygame.Rect(0, 0, self.settings.bullet_hight,
self.settings.bullet_width)
self.rect.midleft = ai_game.ship.rect.midleft
self.rect.x = ai_game.ship.rect.right
#使用小数表示的子弹的位置
self.x = float(self.rect.x)
def draw_bullet(self):
"""在屏幕上绘制子弹"""
pygame.draw.rect(self.screen, self.color, self.rect)
def update(self):
"""向右移动子弹"""
#更新表示子弹位置的小数值
self.x += self.settings.bullet_speed
#更新表示 rect 的位置
self.rect.x = self.x
修改一下 mygame1.0.py
import sys
import pygame
from settings import Settings
from ship import Ship
from bullet import Bullet
class MyGame:
"""管理游戏资源和行为的类"""
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("MyGame 1.0")
self.ship = Ship(self)
self.bullets = pygame.sprite.Group()
def _update_screen(self):
"""更新屏幕上的图像,并切换到新图像"""
self.screen.fill(self.settings.bg_color)
self.ship.blitme()
for bullet in self.bullets.sprites():
bullet.draw_bullet()
# 让最近绘制的屏幕可见
pygame.display.flip()
def _update_bullets(self):
"""更新子弹的位置并删除消失的子弹"""
self.bullets.update()
# 删除消失的子弹
for bullet in self.bullets.copy():
if bullet.rect.x > self.settings.screen_width:
self.bullets.remove(bullet)
def _fire_bullet(self):
"""创建一颗子弹,并将其加入编组bullets中"""
new_bullet = Bullet(self)
self.bullets.add(new_bullet)
def _check_events(self):
"""相应按键和鼠标事件"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
self._check_keydown_events(event)
elif event.type == pygame.KEYUP:
self._check_keyup_events(event)
def _check_keydown_events(self, event):
"""响应按键"""
if event.key == pygame.K_UP:
# 向上移动角色
self.ship.moving_up = True
elif event.key == pygame.K_DOWN:
# 向下移动角色
self.ship.moving_down = True
elif event.key == pygame.K_q:
#按 q 退出
sys.exit()
elif event.key == pygame.K_SPACE:
self._fire_bullet()
def _check_keyup_events(self, event):
"""响应松开"""
if event.key == pygame.K_RIGHT:
self.ship.moving_right = False
elif event.key == pygame.K_LEFT:
self.ship.moving_left = False
elif event.key == pygame.K_UP:
self.ship.moving_up = False
elif event.key == pygame.K_DOWN:
self.ship.moving_down = False
def run_game(self):
""""开始游戏的主循环"""
while True:
self._check_events()
self.ship.update()
self._update_bullets()
self._update_screen()
if __name__ == '__main__':
ai = MyGame()
ai.run_game()
这里有一个警告,我也不知道为什么出现怎么消除
有大佬知道的话可以解释一下
不影响运行
来看看结果吧:
总结
修改一下 ship.py
让角色只能上下移动
修改一下 settings.py
加入子弹的设置
新建 bullet.py
修改一下 mygame1.0.py
这里有一个警告,我也不知道为什么出现怎么消除
有大佬知道的话可以解释一下
不影响运行
来看看结果吧:
学习pygame能让我们对如何管理一个项目有一个初认识,这对于初学者来说绝对是难得的体验,希望大家都能从中体会编程的乐趣。



