pygame-KidsCanCode系列jumpy-part0-使用sprite
油管(youtube)上有一个号称"史上最好的pygame教程"(传送门:https://www.youtube.com/watch?v=VO8rTszcW4s&list=PLsk-HSGFjnaH5yghzu7PcOzm9NhsW0Urw),作者思路很清晰,循序渐进,很适合大人学会了,然后指导孩子入门。作者还有一个专门的网站:https://www.patreon.com/kidscancode (注:该网站属商业性质,很多高级资源要收费),鉴于国内~翻*墙不方便,把主要内容记录在此备忘。
本篇主要是sprite的入门使用:
pygame开发,有一个所谓的最小框架(或称为模板),大概长下面这个样子:
import pygame
import time # 游戏中的一些常量定义
SIZE = WIDTH, HEIGHT = 300, 100
FPS = 10 # 颜色常量定义
BLACK = 0, 0, 0
WHITE = 255, 255, 255 # 初始化
pygame.init()
pygame.mixer.init() # 窗口、标题等初始化
screen = pygame.display.set_mode(SIZE)
pygame.display.set_caption("My Game")
clock = pygame.time.Clock() # 循环入口
running = True
while running: # 设置帧数
clock.tick(FPS) # 事件处理
for event in pygame.event.get():
# 退出处理
if event.type == pygame.QUIT:
running = False # (update) 游戏更新逻辑(比如:改动角色的位置或一些重要变量等,这里仅演示更新当前时间)
font = pygame.font.SysFont('Menlo', 25, True)
current_time = font.render(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())), 1, WHITE) # (draw)渲染屏幕
screen.fill(BLACK) # 先准备一块黑布
screen.blit(current_time, current_time.get_rect(center=(WIDTH / 2, HEIGHT / 2))) # 把时间显示在画布中央 # 屏幕内容刷新
pygame.display.update() # 循环结束后,退出游戏
pygame.quit()
开发新游戏时,把上面这个模板复制一份新的,然后改改里面update/draw这二个部分即可。为了方便新同学理解"模板"的处理流程,从视频中截了二张图:
可以有同学注意到了,代码头部有很多常量定义,按模块化的思想,可以把这些常量定义单独提取出来,放到一个settings.py文件里,以后修改起来会比较方便。
SIZE = WIDTH, HEIGHT = 480, 320
FPS = 30 TITLE = "sprite sample" # define color
BLACK = 0, 0, 0
WHITE = 255, 255, 255
RED = 255, 0, 0
GREEN = 0, 255, 0
BLUE = 0, 0, 255 # define player bound
PLAYER_TOP_LIMIT = 100
PLAYER_BOTTOM_LIMIT = 250
把刚才的模板,拷一份新的出来,引用这个settings.py,同时把我们的主角Sprite也加进来
import pygame
from part_00.settings import * pygame.init()
pygame.mixer.init() screen = pygame.display.set_mode(SIZE)
pygame.display.set_caption(TITLE)
clock = pygame.time.Clock() # 定义游戏主角类
class Player(pygame.sprite.Sprite):
def __init__(self):
# 第1行,必须调用Sprite父类的构造函数
pygame.sprite.Sprite.__init__(self)
# 注意:sprite必须指定image, rect这二个属性
self.image = pygame.Surface((20, 20))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.center = WIDTH / 2, HEIGHT / 2 # 更新逻辑
def update(self):
self.rect.x += 5
if self.rect.left > WIDTH:
self.rect.right = 0 # 这里要有一个类似分组(或容器)的东西,存放所有游戏中的sprite实例
all_sprites = pygame.sprite.Group()
player = Player()
all_sprites.add(player) running = True
while running: clock.tick(FPS) for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False # update
all_sprites.update() # draw /render
screen.fill(BLACK)
all_sprites.draw(screen) # 绘制所有sprite pygame.display.update() pygame.quit()
注1:第2行导入的写法,留意一下,主要是目录的指定,参考下图的目录结构
注2:pygame.sprite.Sprite这个类,如果查看源码,有一段英文说明
class Sprite(object):
"""simple base class for visible game objects pygame.sprite.Sprite(*groups): return Sprite The base class for visible game objects. Derived classes will want to
override the Sprite.update() method and assign Sprite.image and Sprite.rect
attributes. The initializer can accept any number of Group instances that
the Sprite will become a member of. When subclassing the Sprite class, be sure to call the base initializer
before adding the Sprite to Groups. """
...
大意是说,如果子类继承自Sprite类,可以重写update(),同时可以指定image、rect属性,最后__init__初始化(构造函数)首行,必须调用父类的__init__方法。
我们自定义了一个Player的Sprite,同时在update()方法中,做了一些逻辑处理,主要是让rect对象每帧横向向右移动5px,同时加入了边界检测,如果向右跑出窗口区域,则把它放到左侧,继续运动(视觉上看,感觉运动是连贯的)。
注: 让对象移动的方法有N种,要点无非就是改变对象外切矩形Rect的某个属性,Rect对象提供了N多与位置(及大小)相关的属性,几乎是想你所想:
bottom = property(lambda self: object(), lambda self, v: None, lambda self: None) # default bottomleft = property(lambda self: object(), lambda self, v: None, lambda self: None) # default bottomright = property(lambda self: object(), lambda self, v: None, lambda self: None) # default center = property(lambda self: object(), lambda self, v: None, lambda self: None) # default centerx = property(lambda self: object(), lambda self, v: None, lambda self: None) # default centery = property(lambda self: object(), lambda self, v: None, lambda self: None) # default h = property(lambda self: object(), lambda self, v: None, lambda self: None) # default height = property(lambda self: object(), lambda self, v: None, lambda self: None) # default left = property(lambda self: object(), lambda self, v: None, lambda self: None) # default midbottom = property(lambda self: object(), lambda self, v: None, lambda self: None) # default midleft = property(lambda self: object(), lambda self, v: None, lambda self: None) # default midright = property(lambda self: object(), lambda self, v: None, lambda self: None) # default midtop = property(lambda self: object(), lambda self, v: None, lambda self: None) # default right = property(lambda self: object(), lambda self, v: None, lambda self: None) # default size = property(lambda self: object(), lambda self, v: None, lambda self: None) # default top = property(lambda self: object(), lambda self, v: None, lambda self: None) # default topleft = property(lambda self: object(), lambda self, v: None, lambda self: None) # default topright = property(lambda self: object(), lambda self, v: None, lambda self: None) # default w = property(lambda self: object(), lambda self, v: None, lambda self: None) # default width = property(lambda self: object(), lambda self, v: None, lambda self: None) # default x = property(lambda self: object(), lambda self, v: None, lambda self: None) # default y = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
关于Sprite以及Sprite的Group,有几个重要的属性:
Sprite.kill() --字面上讲,就是杀死精灵,调用该方法后,如果这个sprite加入了多个group,将同步把自己从所有group中移除。
Group.spritecollide() --即:精灵之间的碰撞检测,pygame已经封装好了,不用开发人员再去伤脑筋了(后面我们会大量使用该方法)
def spritecollide(sprite, group, dokill, collided=None):
"""find Sprites in a Group that intersect another Sprite pygame.sprite.spritecollide(sprite, group, dokill, collided=None):
return Sprite_list Return a list containing all Sprites in a Group that intersect with another
Sprite. Intersection is determined by comparing the Sprite.rect attribute
of each Sprite. The dokill argument is a bool. If set to True, all Sprites that collide
will be removed from the Group. The collided argument is a callback function used to calculate if two
sprites are colliding. it should take two sprites as values, and return a
bool value indicating if they are colliding. If collided is not passed, all
sprites must have a "rect" value, which is a rectangle of the sprite area,
which will be used to calculate the collision.
这是该方法的说明,大意是说,返回值是一个列表,里面包含了发生碰撞的所有sprite的Rect对象;另外doKill参数,如果指定为True,则表示将发生碰撞的sprite杀死;最后一个collided可以指定回调方法。
刚才的代码,运动起来后,效果如下:
如果觉得一个小方块,比较枯燥,可以换一个图片,推荐一个网站:https://opengameart.org/ 上面有大量的免费游戏素材,随便挑几张图片:
代码如下:
import pygame
from part_00.settings import *
import os pygame.init()
pygame.mixer.init() screen = pygame.display.set_mode(SIZE)
pygame.display.set_caption(TITLE)
clock = pygame.time.Clock() game_folder = os.path.dirname(__file__)
img_folder = os.path.join(game_folder, "../img/") class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(os.path.join(img_folder, "p1_jump.png"))
# 如果图片显示时,发现不透明(看具体操作系统),可以加下面这行
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.center = WIDTH / 2, HEIGHT / 2
self.y_speed = 5 def update(self):
self.rect.x += 5
self.rect.y += self.y_speed # 边界检测
if self.rect.left > WIDTH:
self.rect.right = 0
if self.rect.top < PLAYER_TOP_LIMIT:
self.y_speed = -self.y_speed
if self.rect.bottom > PLAYER_BOTTOM_LIMIT:
self.y_speed = -self.y_speed all_sprites = pygame.sprite.Group()
player = Player()
all_sprites.add(player) running = True
while running: clock.tick(FPS) # process input (events)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False all_sprites.update() # draw /render
screen.fill(BLACK)
pygame.draw.line(screen, GREEN, (0, PLAYER_TOP_LIMIT), (WIDTH, PLAYER_TOP_LIMIT), 1)
pygame.draw.line(screen, GREEN, (0, PLAYER_BOTTOM_LIMIT), (WIDTH, PLAYER_BOTTOM_LIMIT), 1)
all_sprites.draw(screen) pygame.display.update() pygame.quit()
pygame-KidsCanCode系列jumpy-part0-使用sprite的更多相关文章
- 飞机大战-面向对象-pygame
飞机大战 最近学习了python的面向对象,对面向对象的理解不是很深刻. 面向对象是数据和函数的'打包整理',将相关数据和处理数据的方法集中在一个地方,方便使用和管理. 本着学习的目的,在网上找了这个 ...
- 【python游戏编程之旅】第六篇---pygame中的Sprite(精灵)模块和加载动画
本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 直到现在我们已经学了很多pygame基础知识了,从这篇博客开始我们将会学习pygame中高级部分,更多和精灵 ...
- pygame系列_原创百度随心听音乐播放器_完整版
程序名:PyMusic 解释:pygame+music 之前发布了自己写的小程序:百度随心听音乐播放器的一些效果图 你可以去到这里再次看看效果: pygame系列_百度随心听_完美的UI设计 这个程序 ...
- pygame系列_箭刺Elephant游戏
这个游戏原名为:Chimp,我们可以到: http://www.pygame.org/docs/tut/chimp/ChimpLineByLine.html 获取到源码和详细的源码讲解 下面是我对游戏 ...
- pygame系列
在接下来的blog中,会有一系列的文章来介绍关于pygame的内容,pygame系列偷自http://www.cnblogs.com/hongten/p/hongten_pygame_install. ...
- pygame经典sprite精灵类
import cStringIO, base64 import pygame from pygame.locals import * class Ball(pygame.sprite.Sprite): ...
- pygame系列_箭刺Elephant游戏_源码下载
这个游戏原名为:Chimp,我们可以到: http://www.pygame.org/docs/tut/chimp/ChimpLineByLine.html 获取到源码和详细的源码讲解 下面是我对游戏 ...
- pygame系列_pygame的各模块叙述
在pygame中,有很多模块,每个模块对应着不同的功能,如果我们知道这些模块是做什么的,那么,对我们的游戏开发会起到关键性的作用. 我们就说说pygame中的各个模块吧!!! #pygame modu ...
- pygame系列_pygame安装
在接下来的blog中,会有一系列的文章来介绍关于pygame的内容,所以把标题设置为pygame系列 在这篇blog中,主要描述一下我们怎样来安装pygame 可能很多人像我一样,发现了pygame是 ...
随机推荐
- [转]Linux下is not in the sudoers file解决方法
来源: http://jingyan.baidu.com/article/2a1383284bb3e8074a134f2d.html 当我们使用sudo命令切换用户的时候可能会遇到提示以下错误:xxx ...
- 如何确定系统上的CPU插槽数量
环境 Red Hat Enterprise Linux 7 Red Hat Enterprise Linux 6 Red Hat Enterprise Linux 5 Red Hat Enterpri ...
- Codeforces 965E Short Code 启发式合并 (看题解)
Short Code 我的想法是建出字典树, 然后让后面节点最多的点优先向上移到不能移为止, 然后gg. 正确做法是对于当前的节点如果没有被占, 那么从它的子树中选出一个深度最大的点换到当前位置. 用 ...
- day 47 htm-part2
列表 无序列表====所谓无序就是显示出来的效果没有编号排序 <ul type='disc'> <li>第一项</li> <li>第二项</li& ...
- Maya cmds filterExpand 列出 选择的 uvs vertices faces edges 等 component 类型
Maya cmds filterExpand 列出 选择的 uvs vertices faces edges 等 component 类型 cmds.ls() 的 flags 中没有指明 uvs 等这 ...
- Scala-Unit5-Scala面对对象与模式匹配
Java中的面向对象:万物皆对象. 我们要封装数据,定义模板等操作,素以我们需要面向对象. ====================================================== ...
- HYSBZ 4034 【树链剖分】+【线段树 】
<题目链接> 题目大意: 有一棵点数为 N 的树,以点 1 为根,且树点有权值.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x ...
- Person Re-ID行人重试别梳理
定义 是利用计算机视觉技术判断图像或者视频序列中是否存在特定行人的技术.给定一张切好块的行人图像 (probe image,), 从一大堆切好块的图像 (gallery images) 中找到同一身份 ...
- 使用element-ui table expand展开行实现手风琴效果
写这篇博客的初衷:官网演示效果为点击toggle,已经展开的项不会因为其他项展开而关闭,所以延伸了下,扩展为手风琴效果. 效果前瞻: 官网table expand地址:http://element-c ...
- 实验吧debug
在linux下进行调试时容易出现权限不够的情况:此时解决办法就是chmod 777+文件名提升权限,以实验吧debug为例,给出了简单的32elf文件,我在查看一些资料以后发现,我需要在main函数处 ...