《零基础入门学习Python》第088讲:Pygame:摩擦摩擦
Play The Ball 这个小游戏现在已经有了背景音乐,有了小球,有了碰撞检测,接下来我们要做的就是摩擦摩擦。
我们有一块玻璃面板的图片,如下图所示:为了方便,我把文字也打上去了。(是透明的哦)
(还是老样子,有需要素材的可以在评论区留下邮箱或者其他的啥)
现在我们的要求就是把这块玻璃面板加载到程序底部的中央位置。
import pygame
import sys
from pygame.locals import *
from random import *# 球类继承自Spirte类
class Ball(pygame.sprite.Sprite):def __init__(self, image, position, speed, bg_size):# 初始化动画精灵pygame.sprite.Sprite.__init__(self)self.image = pygame.image.load(image).convert_alpha()self.rect = self.image.get_rect()# 将小球放在指定位置self.rect.left, self.rect.top = positionself.speed = speedself.width, self.height = bg_size[0], bg_size[1]self.radius = self.rect.width / 2 #增加半径属性def move(self):self.rect = self.rect.move(self.speed)# 如果小球的左侧出了边界,那么将小球左侧的位置改为右侧的边界# 这样便实现了从左边进入,右边出来的效果if self.rect.right < 0:self.rect.left = self.widthelif self.rect.left > self.width:self.rect.right = 0elif self.rect.bottom < 0:self.rect.top = self.heightelif self.rect.top > self.height:self.rect.bottom = 0
##############################################################
class Glass(pygame.sprite.Sprite):def __init__(self, glass_image, bg_size):#初始化动画精灵pygame.sprite.Sprite.__init__(self)self.glass_image = pygame.image.load(glass_image).convert_alpha()self.glass_rect = self.glass_image.get_rect()self.glass_rect.left, self.glass_rect.top = \(bg_size[0] - self.glass_rect.width) // 2, \bg_size[1] - self.glass_rect.height
##############################################################def main():pygame.init()ball_image = "gray_ball.png"bg_image = "background.png"glass_image = "glass.png"running = True#添加背景音乐pygame.mixer.music.load('bg_music.ogg')pygame.mixer.music.set_volume(0.2)#设置音量 pygame.mixer.music.play(1, 160)#播放#加载音效winner_sound = pygame.mixer.Sound("winner.wav")winner_sound.set_volume(0.2)loser_sound = pygame.mixer.Sound("loser.wav")loser_sound.set_volume(0.2)laugh_sound = pygame.mixer.Sound("laugh.wav")laugh_sound.set_volume(0.2)hole_sound = pygame.mixer.Sound("hole.wav")hole_sound.set_volume(0.2)#背景音乐会贯穿游戏的始终,背景音乐完整播放一次我们视为游戏的时间,#音乐播放完时,游戏结束GAMEOVER = USEREVENTpygame.mixer.music.set_endevent(GAMEOVER) # 根据背景图片指定游戏界面尺寸bg_size = width, height = 1024, 681screen = pygame.display.set_mode(bg_size)pygame.display.set_caption("Play the ball - Python Demo")background = pygame.image.load(bg_image).convert_alpha()# 用来存放小球对象的列表balls = []group = pygame.sprite.Group()# 创建五个小球for i in range(5):# 位置随机,速度随机position = randint(0, width-100), randint(0, height-100)speed = [randint(-10, 10), randint(-10, 10)]ball = Ball(ball_image, position, speed, bg_size)while pygame.sprite.spritecollide(ball, group, False, pygame.sprite.collide_circle):#在创建小球这里必须进行一下碰撞检测ball.rect.left, ball.rect.top = randint(0, width-100), randint(0, height-100)balls.append(ball)group.add(ball)###########################################################glass = Glass(glass_image, bg_size) ###########################################################clock = pygame.time.Clock()while running:for event in pygame.event.get():if event.type == QUIT:sys.exit()elif event.type == GAMEOVER: #判断事件是否为我们自定义的GAMEOVER事件loser_sound.play() pygame.time.delay(2000)#暂停2秒laugh_sound.play()running = Falsescreen.blit(background, (0, 0))#############################################screen.blit(glass.glass_image, glass.glass_rect)#############################################for each in balls:each.move()screen.blit(each.image, each.rect)for each in group:group.remove(each) #把自身拿出来if pygame.sprite.spritecollide(each, group, False, pygame.sprite.collide_circle):#把自己和别的球进行碰撞检测each.speed[0] = -each.speed[0]each.speed[1] = -each.speed[1]group.add(each)#还要把自己放进去pygame.display.flip()clock.tick(30)if __name__ == "__main__":main()
接下来我们就需要对鼠标动手了,大家也看到了,Pygame 默认的鼠标非常难看,又小又黑又土,而作为一个游戏的话,漂亮的光标往往就是决胜的关键,游戏开发注重的就是细节,现在我们就用自定义的光标图片替换原来又小又黑又土的光标。如图·所示:
接下来要做的事就是自定义光标,然后把这个小手(光标)限制在玻璃面板内。
关于自定义鼠标的光标:
我们的做法就是使用 set_visible() 方法来将光标设为不可见,然后使用 get_pos() 方法获取鼠标的实时位置,获取之后,我们实时的把 hand.png 图片画到这个位置上去,这样子就相当于实现了自定义光标。
- pygame.mouse.set_visible() —— 隐藏或显示鼠标光标
- pygame.mouse.get_pos() —— 获取鼠标光标的位置
我们来代码实现:
import pygame
import sys
from pygame.locals import *
from random import *# 球类继承自Spirte类
class Ball(pygame.sprite.Sprite):def __init__(self, image, position, speed, bg_size):# 初始化动画精灵pygame.sprite.Sprite.__init__(self)self.image = pygame.image.load(image).convert_alpha()self.rect = self.image.get_rect()# 将小球放在指定位置self.rect.left, self.rect.top = positionself.speed = speedself.width, self.height = bg_size[0], bg_size[1]self.radius = self.rect.width / 2 #增加半径属性def move(self):self.rect = self.rect.move(self.speed)# 如果小球的左侧出了边界,那么将小球左侧的位置改为右侧的边界# 这样便实现了从左边进入,右边出来的效果if self.rect.right < 0:self.rect.left = self.widthelif self.rect.left > self.width:self.rect.right = 0elif self.rect.bottom < 0:self.rect.top = self.heightelif self.rect.top > self.height:self.rect.bottom = 0
##############################################################
class Glass(pygame.sprite.Sprite):def __init__(self, glass_image, mouse_image, bg_size):#初始化动画精灵pygame.sprite.Sprite.__init__(self)self.glass_image = pygame.image.load(glass_image).convert_alpha()self.glass_rect = self.glass_image.get_rect()self.glass_rect.left, self.glass_rect.top = \(bg_size[0] - self.glass_rect.width) // 2, \bg_size[1] - self.glass_rect.heightself.mouse_image = pygame.image.load(mouse_image).convert_alpha()#加载小手光标self.mouse_rect = self.mouse_image.get_rect()#获取小手光标矩形位置self.mouse_rect.left, self.mouse_rect.top = \self.glass_rect.left, self.glass_rect.top #小手光标初始在玻璃面板左上角pygame.mouse.set_visible(False)#设置Pygame 光标不可见##############################################################def main():pygame.init()ball_image = "gray_ball.png"bg_image = "background.png"glass_image = "glass.png"mouse_image = "hand.png"running = True#添加背景音乐pygame.mixer.music.load('bg_music.ogg')pygame.mixer.music.set_volume(0.2)#设置音量 pygame.mixer.music.play(1, 160)#播放#加载音效winner_sound = pygame.mixer.Sound("winner.wav")winner_sound.set_volume(0.2)loser_sound = pygame.mixer.Sound("loser.wav")loser_sound.set_volume(0.2)laugh_sound = pygame.mixer.Sound("laugh.wav")laugh_sound.set_volume(0.2)hole_sound = pygame.mixer.Sound("hole.wav")hole_sound.set_volume(0.2)#背景音乐会贯穿游戏的始终,背景音乐完整播放一次我们视为游戏的时间,#音乐播放完时,游戏结束GAMEOVER = USEREVENTpygame.mixer.music.set_endevent(GAMEOVER) # 根据背景图片指定游戏界面尺寸bg_size = width, height = 1024, 681screen = pygame.display.set_mode(bg_size)pygame.display.set_caption("Play the ball - Python Demo")background = pygame.image.load(bg_image).convert_alpha()# 用来存放小球对象的列表balls = []group = pygame.sprite.Group()# 创建五个小球for i in range(5):# 位置随机,速度随机position = randint(0, width-100), randint(0, height-100)speed = [randint(-10, 10), randint(-10, 10)]ball = Ball(ball_image, position, speed, bg_size)while pygame.sprite.spritecollide(ball, group, False, pygame.sprite.collide_circle):#在创建小球这里必须进行一下碰撞检测ball.rect.left, ball.rect.top = randint(0, width-100), randint(0, height-100)balls.append(ball)group.add(ball)###########################################################glass = Glass(glass_image, mouse_image, bg_size) ###########################################################clock = pygame.time.Clock()while running:for event in pygame.event.get():if event.type == QUIT:sys.exit()elif event.type == GAMEOVER: #判断事件是否为我们自定义的GAMEOVER事件loser_sound.play() pygame.time.delay(2000)#暂停2秒laugh_sound.play()running = Falsescreen.blit(background, (0, 0))#############################################screen.blit(glass.glass_image, glass.glass_rect)##############################################将小手光标画在Pygame 默认光标位置上glass.mouse_rect.left, glass.mouse_rect.top = pygame.mouse.get_pos()#限制光标只能在玻璃面板范围内移动(摩擦摩擦)if glass.mouse_rect.left < glass.glass_rect.left:glass.mouse_rect.left = glass.glass_rect.leftif glass.mouse_rect.left > glass.glass_rect.right - glass.mouse_rect.width:glass.mouse_rect.left = glass.glass_rect.right - glass.mouse_rect.widthif glass.mouse_rect.top < glass.glass_rect.top:glass.mouse_rect.top = glass.glass_rect.topif glass.mouse_rect.top > glass.mouse_rect.bottom - glass.mouse_rect.height:glass.mouse_rect.top = glass.mouse_rect.bottom - glass.mouse_rect.heightscreen.blit(glass.mouse_image, glass.mouse_rect)#############################################for each in balls:each.move()screen.blit(each.image, each.rect)for each in group:group.remove(each) #把自身拿出来if pygame.sprite.spritecollide(each, group, False, pygame.sprite.collide_circle):#把自己和别的球进行碰撞检测each.speed[0] = -each.speed[0]each.speed[1] = -each.speed[1]group.add(each)#还要把自己放进去pygame.display.flip()clock.tick(30)if __name__ == "__main__":main()
下一步,让小球响应光标的移动频率。
我们需要让小球响应光标一定频率的摩擦摩擦而停下来变成绿色,就是说,鼠标在玻璃面板上摩擦,达到一定频率的时候,某一个匹配的小球会停下来,而不是所有小球,停下来的小球就任你操作了。
我们知道,鼠标的一定会产生事件,我们可以利用这一点。假设单位时间是一秒,我们检测一秒内鼠标在玻璃面板内产生多少事件,从而判定每一秒产生的事件数是否能够匹配到某一个小球需要的要求。
步骤如下:
1、为每个小球设定一个不同的目标;
2、创建一个motion 变量来记录每一秒钟产生事件数量;
3、为小球添加一个 check() 方法,用于判断鼠标在1秒钟内产生的事件数量是否匹配此目标;
4、添加一个自定义事件,每一秒钟触发一次。调用每个小球的 check() 检测 motion 的值是否匹配某一个小球的目标,并将motion重新初始化,以便记录下1秒鼠标事件数量;
5、小球应该添加一个 control 属性,用于记录当前的状态(绿色 -> 玩家控制 or 灰色 -> 随机移动)。
6、通过检查 control 属性决定绘制什么颜色的小球。
import pygame
import sys
from pygame.locals import *
from random import *# 球类继承自Spirte类
class Ball(pygame.sprite.Sprite):def __init__(self, grayball_image, greenball_image, position, speed, bg_size, target):# 初始化动画精灵pygame.sprite.Sprite.__init__(self)self.grayball_image = pygame.image.load(grayball_image).convert_alpha() #加载灰色小球self.greenball_image = pygame.image.load(greenball_image).convert_alpha() #加载绿色小球self.rect = self.grayball_image.get_rect() #两颜色小球矩形位置是一样的# 将小球放在指定位置self.rect.left, self.rect.top = positionself.speed = speed#############################################1、为每个小球设定一个不同的目标;self.target = target##############################################5、小球应该添加一个 control 属性,用于记录当前的状态(绿色 -> 玩家控制 or 灰色 -> 随机移动)。self.control = False##################################################self.width, self.height = bg_size[0], bg_size[1]self.radius = self.rect.width / 2 #增加半径属性def move(self):self.rect = self.rect.move(self.speed)# 如果小球的左侧出了边界,那么将小球左侧的位置改为右侧的边界# 这样便实现了从左边进入,右边出来的效果if self.rect.right < 0:self.rect.left = self.widthelif self.rect.left > self.width:self.rect.right = 0elif self.rect.bottom < 0:self.rect.top = self.heightelif self.rect.top > self.height:self.rect.bottom = 0#############################################################################3、为小球添加一个 check() 方法,用于判断鼠标在1秒钟内产生的事件数量是否匹配此目标;def check(self, motion):if self.target < motion < self.target + 5:return Trueelse:return False############################################################################class Glass(pygame.sprite.Sprite):def __init__(self, glass_image, mouse_image, bg_size):#初始化动画精灵pygame.sprite.Sprite.__init__(self)self.glass_image = pygame.image.load(glass_image).convert_alpha()self.glass_rect = self.glass_image.get_rect()self.glass_rect.left, self.glass_rect.top = \(bg_size[0] - self.glass_rect.width) // 2, \bg_size[1] - self.glass_rect.heightself.mouse_image = pygame.image.load(mouse_image).convert_alpha()#加载小手光标self.mouse_rect = self.mouse_image.get_rect()#获取小手光标矩形位置self.mouse_rect.left, self.mouse_rect.top = \self.glass_rect.left, self.glass_rect.top #小手光标初始在玻璃面板左上角pygame.mouse.set_visible(False)#设置Pygame 光标不可见def main():pygame.init()grayball_image = "gray_ball.png"greenball_image = "green_ball.png"bg_image = "background.png"glass_image = "glass.png"mouse_image = "hand.png"running = True#添加背景音乐pygame.mixer.music.load('bg_music.ogg')pygame.mixer.music.set_volume(0.2)#设置音量 pygame.mixer.music.play()#播放#加载音效winner_sound = pygame.mixer.Sound("winner.wav")winner_sound.set_volume(0.2)loser_sound = pygame.mixer.Sound("loser.wav")loser_sound.set_volume(0.2)laugh_sound = pygame.mixer.Sound("laugh.wav")laugh_sound.set_volume(0.2)hole_sound = pygame.mixer.Sound("hole.wav")hole_sound.set_volume(0.2)#背景音乐会贯穿游戏的始终,背景音乐完整播放一次我们视为游戏的时间,#音乐播放完时,游戏结束GAMEOVER = USEREVENTpygame.mixer.music.set_endevent(GAMEOVER) # 根据背景图片指定游戏界面尺寸bg_size = width, height = 1024, 681screen = pygame.display.set_mode(bg_size)pygame.display.set_caption("Play the ball - Python Demo")background = pygame.image.load(bg_image).convert_alpha()# 用来存放小球对象的列表balls = []group = pygame.sprite.Group()# 创建五个小球for i in range(5):# 位置随机,速度随机position = randint(0, width-100), randint(0, height-100)speed = [randint(-10, 10), randint(-10, 10)]ball = Ball(grayball_image, greenball_image, position, speed, bg_size, 5 * (i + 1)) #target 设为5-30,比较适中while pygame.sprite.spritecollide(ball, group, False, pygame.sprite.collide_circle):#在创建小球这里必须进行一下碰撞检测ball.rect.left, ball.rect.top = randint(0, width-100), randint(0, height-100)balls.append(ball)group.add(ball)glass = Glass(glass_image, mouse_image, bg_size)##########################################2、创建一个motion 变量来记录每一秒钟产生事件数量;motion = 0##########################################4.1、添加一个自定义事件,每一秒钟触发一次。MYTIMER = USEREVENT + 1 #自定义事件的知识点可以查看上一节课的末尾注解pygame.time.set_timer(MYTIMER, 1000)##############################################################clock = pygame.time.Clock()while running:for event in pygame.event.get():if event.type == QUIT:sys.exit()elif event.type == GAMEOVER: #判断事件是否为我们自定义的GAMEOVER事件loser_sound.play() pygame.time.delay(2000)#暂停2秒laugh_sound.play()running = False###############################################4.2、 调用每个小球的 check() 检测 motion 的值是否匹配某一个小球的目标,并将motion重新初始化,以便记录下1秒鼠标事件数量;elif event.type == MYTIMER:if motion:for each in group:if each.check(motion):each.speed = [0, 0]each.control = Truemotion = 0###############################################需要计算一下motionelif event.type == MOUSEMOTION:motion += 1##############################################screen.blit(background, (0, 0))screen.blit(glass.glass_image, glass.glass_rect)#将小手光标画在Pygame 默认光标位置上glass.mouse_rect.left, glass.mouse_rect.top = pygame.mouse.get_pos()#限制光标只能在玻璃面板范围内移动(摩擦摩擦)if glass.mouse_rect.left < glass.glass_rect.left:glass.mouse_rect.left = glass.glass_rect.leftif glass.mouse_rect.left > glass.glass_rect.right - glass.mouse_rect.width:glass.mouse_rect.left = glass.glass_rect.right - glass.mouse_rect.widthif glass.mouse_rect.top < glass.glass_rect.top:glass.mouse_rect.top = glass.glass_rect.topif glass.mouse_rect.top > glass.mouse_rect.bottom - glass.mouse_rect.height:glass.mouse_rect.top = glass.mouse_rect.bottom - glass.mouse_rect.heightscreen.blit(glass.mouse_image, glass.mouse_rect)for each in balls:each.move()###############################如果小球的 control 属性为 True,就画绿球if each.control:#画绿色小球screen.blit(each.greenball_image, each.rect)else:#画灰色小球screen.blit(each.grayball_image, each.rect)##############################for each in group:group.remove(each) #把自身拿出来if pygame.sprite.spritecollide(each, group, False, pygame.sprite.collide_circle):#把自己和别的球进行碰撞检测each.speed[0] = -each.speed[0]each.speed[1] = -each.speed[1]group.add(each)#还要把自己放进去pygame.display.flip()clock.tick(30)if __name__ == "__main__":main()
《零基础入门学习Python》第088讲:Pygame:摩擦摩擦相关推荐
- 第031讲:永久存储,腌制一缸美味的泡菜 | 学习记录(小甲鱼零基础入门学习Python)
(标答出处: 鱼C论坛) <零基础入门学习Python> 测试题: 0.pickle的实质是什么? pickle的实质是利用一些算法,将你的数据对象腌制成二进制文件,存储在磁盘上,也可以放 ...
- 第023、024讲:这帮小兔崽子汉诺塔 | 学习记录(小甲鱼零基础入门学习Python)
(标答出处: 鱼C论坛) <零基础入门学习Python> 测试题: 0.使用递归编写一个十进制转换为二进制的函数(要求采用'取2取余'的方式,结果与调用bin()函数一样返回字符串形式) ...
- 第019讲:我的地盘听我的 | 学习记录(小甲鱼零基础入门学习Python)
(标答出处: 鱼C论坛) <零基础入门学习Python> 测试题: 0.下边程序会输入什么? def next():print('我在next()函数里...')pre()def pre( ...
- 零基础python必背代码-零基础入门学习python 96集全
零基础入门学习python 96集全 第000讲 愉快的开始(视频+课件)xa0 第001讲 我和Python第一次亲密接触(视频+课件)xa0 第002讲 用Python设第一个游戏(视频+课件+源 ...
- 零基础入门学习Python,我与python的第一次亲密接触后的感受!
前言:Python是适合初学者入门最好的语言 Python适合初学者入门最好的语言 人工智能用Python?高考要加入Python?现在连微软官方Excel都要把Python作为官方语言!Python ...
- 零基础入门学习Python,我与python的第一次亲密接触后的感受
前言:Python是适合初学者入门最好的语言 Python适合初学者入门最好的语言 人工智能用Python?高考要加入Python?现在连微软官方Excel都要把Python作为官方语言!Python ...
- 零基础学python鱼c-鱼C-小甲鱼 零基础入门学习Python 97节课程
释放双眼,带上耳机,听听看~! 前言 鱼C-小甲鱼 零基础入门学习Python 97课程 ,这教程Go破解是有学习过的,讲得通俗易懂,即使是小白也能完全掌握里面内容. 其实我一直在Go破解教程这块对大 ...
- 零基础入门python小甲鱼-小甲鱼零基础入门学习Python百度云下载 | 宅男君
Python编程语言可以在不同平台上使用,比如Windows.MAC.Linux操作系统.通常情况下,一个Python程序在你自己的Windows系统上运行,也可以在别人的MAC系统上运行.Pytho ...
- python零基础入门教程百度云-小甲鱼零基础入门学习Python百度云下载 | 宅男君
Python编程语言可以在不同平台上使用,比如Windows.MAC.Linux操作系统.通常情况下,一个Python程序在你自己的Windows系统上运行,也可以在别人的MAC系统上运行.Pytho ...
- 小甲鱼零基础学python pdf_鱼C论坛小甲鱼《零基础入门学习python》课程课后题.pdf...
第 1 课 0. Python 是什么类型的语言? Python 是脚本语言 脚本语言 (Scripting language) 是电脑编程语言,因此也能让开发者藉以编写出 让电脑听命行事的程序. 以 ...
最新文章
- 路由框架ARouter最全源码解析
- c语言解析json报文源码,GitHub - faycheng/cJSON: cJson源码和源码分析
- 建站手册-语义网:语义网
- JoyOI(TYVJ)1071-LCIS【线性dp,LIS,LCS】
- 写一函数,将两个字符串连接
- [深度学习-原理篇]什么是循环神经网络RNN与LSTM
- 害怕运维做到30岁还一事无成?你应该来这里看看
- [Node.js]Domain模块
- Memcached:高性能分布式对象缓存系统
- mac本常用快捷键大全
- 大数据Hadoop原理介绍+安装+实战操作(HDFS+YARN+MapReduce)
- 他抛了27亿粒米粒儿近似计算出了圆周率
- xubuntu language support
- 读 《异类》—马尔科姆·格拉德威尔 文摘
- 关于位运算符号的辨识及运用示例
- 华为手机怎么使用分屏_这是一份华为手机必备小技巧使用说明
- JMicroVision教程-应用于测井岩层电镜图像分析
- 轻松玩转新编日语2 zz江沪
- mac虚拟摄像头插件_Mobiola WebCamera(网络虚拟摄像头) V2.4 Mac版
- 防爆等级介绍 - IP65防爆等级和dIIBT4防爆等级的有什么区别?