完整代码

Squish.py

import os, sys, pygame
from pygame.locals import *
import objects, config
"这个模块包含游戏Squish的主游戏逻辑"class State:'''游戏状态超类,能够处理事件以及在指定表面上显示自己'''def handle(self, event):"""只处理退出事件的默认事件处理"""if event.type == QUIT:sys.exit()if event.type == KEYDOWN and event.key == K_ESCAPE:sys.exit()def first_display(self, screen):"""在首次显示状态时使用,它使用背景色填充屏幕"""screen.fill(config.background_color)# 调用flip,将修改反映出来:pygame.display.flip()def display(self, screen):"""在后续显示状态时使用,其默认行为是什么都不做"""pass
class Level(State):"""游戏关卡。它计算落下了多少个铅锤,移动精灵并执行其他与游戏逻辑相关的任务"""def __init__(self,number = 1):self.number = number# 还需要躲开多少个铅锤才能通过当前关卡?self.remaining = config.weights_per_levelspeed = config.drop_speed# 每过一关都将速度提高speed_increase:speed +=(self.number-1) * config.speed_increase# 创建铅锤和香蕉:self.weight = objects.Weight(speed)self.banana = objects.Banana()both = self.weight, self.banana #可包含更多精灵self.sprites = pygame.sprite.RenderUpdates(both)def update(self, game):"更新游戏状态"# 更新所有的精灵:self.sprites.update()# 如果香蕉和铅锤发生了碰撞,就让游戏切换到GameOver状态:if self.banana.touches(self.weight):game.next_state = GameOver()# 否则,如果铅锤已落到地上,就将其复位#如果躲开了当前关卡内的所有铅锤,就让游戏切换到LevelCleared状态elif self.weight.landed:self.weight.reset()self.remaining -=1if self.remaining ==0:game.next_state = LevelCleared(self.number)def update(self, game):"更新游戏状态" # 更新所有的精灵:self.sprites.update() # 如果香蕉和铅锤发生了碰撞,就让游戏切换到GameOver状态:if self.banana.touches(self.weight): game.next_state = GameOver() # 否则,如果铅锤已落到地上,就将其复位# 如果躲开了当前关卡内的所有铅锤,就让游戏切换到LevelCleared状态:elif self.weight.landed: self.weight.reset() self.remaining -= 1 if self.remaining == 0: game.next_state = LevelCleared(self.number)def display(self, screen): """ 在第一次显示(清屏)后显示状态。不同于firstDisplay,这个方法调用pygame.display.update并向它传递一个需要更新的矩形列表,这个列表是由self.sprites.draw提供的""" screen.fill(config.background_color) updates = self.sprites.draw(screen) pygame.display.update(updates) class Paused(State): """简单的游戏暂停状态,用户可通过按任何键盘键或单击鼠标来结束这种状态""" finished = 0 # 用户结束暂停了吗?image = None # 如果需要显示图像,将这个属性设置为一个文件名text = '' # 将这个属性设置为一些说明性文本def handle(self, event): """ 这样来处理事件:将这项任务委托给State(它只处理退出事件),并对按键和鼠标单击做出响应。如果用户按下了键盘键或单击了鼠标,就将self.finished设置为True """ State.handle(self, event) if event.type in [MOUSEBUTTONDOWN, KEYDOWN]: self.finished = 1 def update(self, game): """ 更新关卡。如果用户按下了键盘键或单击了鼠标(即self.finished为True),就让游戏切换到(由子类实现的方法)self.next_state()返回的状态""" if self.finished: game.next_state = self.next_state() def first_display(self, screen): """ 在首次显示暂停状态时调用,它绘制图像(如果指定了)并渲染文本""" # 首先,通过使用背景色填充屏幕来清屏:screen.fill(config.background_color) # 创建一个使用默认外观和指定字号的Font对象:font = pygame.font.Font(None, config.font_size) # 获取self.text中的文本行,但忽略开头和末尾的空行:lines = self.text.strip().splitlines() # 使用font.get_linesize()获取每行文本的高度,并计算文本的总高度:height = len(lines) * font.get_linesize() # 计算文本的位置(在屏幕上居中):center, top = screen.get_rect().center top -= height // 2 # 如果有图像要显示:if self.image: # 加载该图像:image = pygame.image.load(self.image).convert()# 获取其rect:r = image.get_rect() # 将文本下移图像高度一半的距离top += r.height // 2 # 将图像放在文本上方20像素处:r.midbottom = center, top - 20# 将图像传输到屏幕上:screen.blit(image, r)antialias = 1 # 消除文本的锯齿black = 0, 0, 0 # 使用黑色渲染文本# 从计算得到的top处开始渲染所有的文本行,# 每渲染一行都向下移动font.get_linesize()像素:for line in lines: text = font.render(line.strip(), antialias, black) r = text.get_rect() r.midtop = center, topscreen.blit(text, r) top += font.get_linesize() # 显示所做的所有修改:pygame.display.flip()class Info(Paused): """ 显示一些游戏信息的简单暂停状态,紧跟在这个状态后面的是Level状态(第一关)""" next_state = Level text = ''' In this game you are a banana, trying to survive a course in self-defense against fruit, where the participants will "defend" themselves against you with a 16 ton weight.'''
class StartUp(Paused): """ 显示启动图像和欢迎消息的暂停状态,紧跟在它后面的是Info状态""" next_state = Info image = config.splash_image text = ''' Welcome to Squish, the game of Fruit Self-Defense'''
class LevelCleared(Paused): """ 指出用户已过关的暂停状态,紧跟在它后面的是表示下一关的Level状态""" def __init__(self, number): self.number = number self.text = '''Level {} cleared Click to start next level'''.format(self.number) def next_state(self): return Level(self.number + 1)class GameOver(Paused): """ 指出游戏已结束的状态,紧跟在它后面的是表示第一关的Level状态""" next_state = Level text = ''' Game Over Click to Restart, Esc to Quit
''' class Game: """ 负责主事件循环(包括在不同游戏状态之间切换)的游戏对象""" def __init__(self, *args): # 获取游戏和图像所在的目录:path = os.path.abspath(args[0]) dir = os.path.split(path)[0] # 切换到这个目录,以便之后能够打开图像文件:os.chdir(dir) # 最初不处于任何状态:self.state = None # 在第一次事件循环迭代中切换到StartUp状态:self.next_state = StartUp() def run(self): """ 这个方法设置一些变量。它执行一些重要的初始化任务,并进入主事件循环""" pygame.init()# 初始化所有的Pygame模块# 决定在窗口还是整个屏幕中显示游戏:flag = 0 # 默认在窗口中显示游戏if config.full_screen: flag = FULLSCREEN # 全屏模式screen_size = config.screen_size screen = pygame.display.set_mode(screen_size, flag) pygame.display.set_caption('Fruit Self Defense') pygame.mouse.set_visible(False) # 主事件循环:while True: # (1)如果nextState被修改,就切换到修改后的状态并显示它(首次):if self.state != self.next_state: self.state = self.next_state self.state.first_display(screen) # (2)将事件处理工作委托给当前状态:for event in pygame.event.get():self.state.handle(event) # (3)更新当前状态:self.state.update(self) # (4)显示当前状态:self.state.display(screen)
if __name__ == '__main__': game = Game(*sys.argv)
game.run()

Objects.py

import pygame, config, os
from random import randrange"这个模块包含游戏Squish使用的游戏对象"class SquishSprite(pygame.sprite.Sprite):'''游戏Squish中所有精灵(sprite)的超类。构造函数加载一幅图像,设置精灵的外接矩形和移动范围。移动范围取决于屏幕尺寸和边距'''def __init__(self, image):super().__init__()self.image = pygame.image.load(image).convert()self.rect = self.image.get_rect()screen = pygame.display.get_surface()shrink = -config.margin *2self.area = screen.get_rect().inflate(shrink,shrink)
class Weight(SquishSprite):'''从天而降的铅锤,使用SquishSprite的构造函数设置表示铅锤的图像,并以其构造函数的一个参数指定的速度下降'''def __init__(self, speed):super().__init__(config.weight_image)self.speed = speedself.reset()def reset(self):'''将铅锤移到屏幕顶端(使其刚好看不到),并放在一个随机的水平位置'''x = randrange(self.area.left,self.area.right)self.rect.midbottom = x, 0def update(self):'''根据铅锤的速度垂直向下移动相应的距离。根据铅锤是否已到达屏幕底部相应地设置属性landed'''self.rect.top +=self.speedself.landed = self.rect.top >=self.area.bottomclass Banana(SquishSprite):'''绝望的香蕉。它使用SquishSprite的构造函数来设置香蕉图像,停留在屏幕底部附近,且水平位置由鼠标的当前位置决定(有一定的限制)'''def __init__(self):super().__init__(config.banana_image)self.rect.bottom = self.area.bottom# 内边距表示图像中不属于香蕉的部分# 如果铅锤进入这些区域,并不认为它砸到了香蕉:self.pad_top = config.banana_pad_topself.pad_side = config.banana_pad_sidedef update(self):"""将香蕉中心的x坐标设置为鼠标的当前x坐标,再使用矩形的方法clamp确保香蕉位于允许的移动范围内"""self.rect.centerx = pygame.mouse.get_pos()[0]self.rect = self.rect.clamp(self.area)def touches(self, other):"""判断香蕉是否与另一个精灵(铅锤)发生了碰撞,这里没有直接使用矩形的方法colliderect,而是先使用矩形的方法inflat以及pad_side和pad_top计算出一个新的矩形,这个矩形不包含香蕉图像顶部和两边的“空白”区域"""# 通过剔除内边距来计算bounds:bounds = self.rect.inflate(-self.pad_side, -self.pad_top)# 将bounds移动到与香蕉底部对齐bounds.bottom = self.rect.bottom# 检查bounds是否与另一个对象的rect重叠return bounds.colliderect(other.rect)

Config.py

''' 游戏Squish的配置文件
可根据偏好随意修改配置变量
'''# 游戏中使用的变量
banana_image = 'images/banana120.png'
weight_image = 'images/weight20.jpg'
splash_image = 'images/weight20.jpg'# 游戏的外观设置
screen_size = 800, 600
background_color = 255, 255, 255
margin = 30
full_screen = 1
font_size = 48# 游戏的行为设置
drop_speed = 1
banana_speed = 10
speed_increase =1
weights_per_level = 10
banana_pad_top = 40
banana_pad_side = 20

python基础教程:第29章街机游戏代码相关推荐

  1. python基础读后感_《python基础教程 》第一章 读书笔记

    python是一个简单强大的直译语言,它同样提供交互式编译环境,学起来还算有趣,在学习的过程中,同样体会了动态语言的直接与强大. 第一章 基础知识 一 运行python 在ubuntu终端输入 pyt ...

  2. 杨桃的Python基础教程——第4章:Python基础语法

    本人CSDN博客专栏:https://blog.csdn.net/yty_7 Github地址:https://github.com/yot777/Python-Primary-Learning 4. ...

  3. 杨桃的Python基础教程——第1章:Python简介

    本人CSDN博客专栏:https://blog.csdn.net/yty_7 Github地址:https://github.com/yot777/Python-Primary-Learning Py ...

  4. Python基础教程第七章学习笔记——更加抽象

    7 更加抽象-创建自己的对象 前面讲了: Python主要的内建对象类型(数字.字符串.列表.元组和字典) 内建函数和标准库的用法 自定义函数的方式 本章主讲: 创建自己的对象(尤其是类型或者被称为类 ...

  5. Python基础教程-第9章-魔法方法、特性和迭代器

    在Python中,有些名称很特别,开头和结尾都是两个下划线.你在本书前面已经见过一些, 如__future__. 在这样的名称中,很大一部分都是魔法(特殊)方法的名称.如果你的对象实现了这些方法,它们 ...

  6. Python基础教程-第6章-函数

    6.1 自定义函数 函数执行特定的操作并返回一个值1,你可以调用它.一般而言,要判断某个对象是否可调用,可使用内置函数callable. import math x = 1 y = math.sqrt ...

  7. Python基础教程-第4章-字典

    可通过名称来访问其各个值的数据结构.这种数据结构称为映射(mapping).字典是Python中唯一的内置映射类型,其中的值不按顺序排列,而是存储在键下. 4.1 字典的用途 字典(日常生活中的字典和 ...

  8. 【书山有路】Python基础教程 第5章

    这章的主题是"条件.循环和其他语句".主要介绍if for之类的语句的使用,能大大丰富可以做的事情. 赋值魔法 序列解包 多个赋值操作可以同时进行: >>> x, ...

  9. Python基础教程第1章:基础知识---学习记录

    1.python官方学习相关资料 (1) 下载安装python,见python官网:https://www.python.org/downloads/ (2) python官方文档 1)chm格式,安 ...

最新文章

  1. 环信 之 通信过程及聊天记录保存
  2. [Oracle]理解undo表空间
  3. ESP8266烧写时的各种参数设置
  4. task文件服务器无法输入,求助大神,win10的输入法无法使用,去开task sche
  5. 脚本升级_手把手教你升级到Database 19c(3)| 终章教程
  6. Error:Can’t find import 2508 in coredll.dll问题解决
  7. mysql命令教学_mysql常用命令有什么
  8. 部署WEB项目到服务器(三)安装mysql到linux服务器(Ubuntu)详解
  9. UE4在VS2013中各个编译配置代表意义
  10. php yii应用运维,Windows运维之Windows下用cmd命令实例讲解yii2.0在php命令行中运行的步骤...
  11. iOS之正则表达式的使用
  12. bootice添加linux_如何使用老毛桃winpe的Bootice工具还原SYSLINUX引导程序?
  13. 带计算机功能的私有云,网盘关停不用愁 教你打造个人私有云
  14. WebSphere概述
  15. linux运行igv报错,IGV 哐当就不能用了,除了换台电脑还能怎么办?
  16. 服务器无线组网,物联网无线组网介绍
  17. 使用大华NetSDK对接大华相机
  18. oracle的闪存_ORACLEFS1-2闪存存储系统.PDF
  19. SVM学习总结(三)SMO算法流程图及注释源码
  20. html5 swipe滑动选择身高,Swipe 移动端滑动插件使用详解

热门文章

  1. STM入门32(二十七)----FSMC
  2. kaggle平台的使用
  3. 慈善机构的“委屈”,区块链能否吹散信任阴霾?
  4. ROS多机通信中ROS_MASTER_URI的配置
  5. 潍坊工厂车间数字化vr三维仿真系统,vr电力虚拟仿真培训系统,vr消防安全教育体验馆
  6. SteamVR---抓取物体
  7. UE4中实现截图功能并保存到指定路径
  8. Linux命令之dhclient,dhclient命令
  9. Ros机器人之(二)两个小海龟画圈圈
  10. javascript比较时间大小