树莓派音乐盒,让你像DJ一样玩音乐

用按钮来控制LED灯,是树莓派比较经典的一种应用。

那用按钮来控制音乐呢?

我们这次的任务是做个树莓派音乐盒,以便你能像DJ一样,通过它不停的切换和调整音乐。

硬件需求:

  • 树莓派1个
  • 面包板1个
  • 接触式开关4个
  • 公对母跳线5根
  • 母对母跳线4根
  • 扬声器或耳机1个

软件需求:

Raspbian 最新版

制作过程:

先找到你想播放的音频文件,如果你自己没有什么准备,可以在Raspbian系统的/usr/share/sonic-pi/samples目录中找一些示例音乐。

不过你要用Python播放声音的话,得将里面的.flac文件转换为.wav文件。

批量转换命令:

for f in *.flac; do ffmpeg -i "$f" "${f%.flac}.wav"; done

如果没出错,你现在应该得到大量的wav文件了。

挑出四个备用,对应4个按钮。将其保存在gpio-music-box目录中

drum_tom_mid_hard.wav
drum_cymbal_hard.wav
drum_snare_hard.wav
drum_cowbell.wav

电路最基本的接法:

当然,用面包板会让你更方便。

示例程序中有四个按钮,所以我们要分别接入GPIO4、10、17、27四个口。

接下来开始撸代码。

import pygame
from gpiozero import Button

pygame.init()

drum = pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_tom_mid_hard.wav")
cymbal = pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_cymbal_hard.wav")
snare = pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_snare_hard.wav")
bell = pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_cowbell.wav")

btn_drum = Button(4)
btn_cymbal = Button(17)
btn_snare= Button(27)
btn_bell = Button(10)

btn_drum.when_pressed = drum.play
btn_cymbal.when_pressed = cymbal.play
btn_snare.when_pressed = snare.play
btn_bell.when_pressed = bell.play

以上的代码应该能正常工作,但不够简洁优雅,我们用Python的字典功能来优化一下。

创建一个字典。

button_sounds = {Button(4): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_tom_mid_hard.wav"),
                 Button(17): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_cymbal_hard.wav"),
                 Button(27): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_snare_hard.wav"),
                 Button(10): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_cowbell.wav")}

然后用Button作为键,Sound作为值。

优化后的代码:

import pygame
from gpiozero import Button

pygame.init()

button_sounds = {Button(4): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_tom_mid_hard.wav"),
                 Button(17): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_cymbal_hard.wav"),
                 Button(27): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_snare_hard.wav"),
                 Button(10): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/drum_cowbell.wav")}

for button, sound in button_sounds.items():
    button.when_pressed = sound.play

是不是简洁多了?

好了,拿去玩吧。

视频讲解地址:

https://v.qq.com/x/page/x0967xsxe7j.html

线索:Raspberrypi.org

编译:王文文

你能不损失数百万美元成功登月吗?

对航空知识有兴趣的朋友都知道,飞行器在月球软着陆不是一件容易的事情。

即使在刚刚过去的2019年,印度也没能成功实现该技术,承载着希望的“月船2号”着陆器在距离月球表面2.1公里的时候失去了信号,从此不知所踪。

迄今为止,只有中美俄三个国家实现了月球软着陆。

印度“月船2号”着陆器失联前的直播画面

在阿波罗11号登月十周年纪念日的时候,阿塔里(Atari)公司曾经出了一款名叫“Lunar Lander”的投币式街机游戏。

游戏的玩法是通过方向调整和推力控制来引导你的着陆器,将其轻轻地放到安全而平坦的停靠区。如果玩家能将着陆器成功停放在更具挑战的险峻区域,将获得额外的积分。

街机的版本是有操纵杆的,玩家可以用其控制方向和大小不同的推力,并以屏幕顶部的海拔,水平速度和垂直速度为指导,在燃料有限的情况下按时降落飞船。

游戏内置了四个难度级别,分别调整了着陆控制器和着陆区域,玩家需要凭借高超的技巧才能涉险过关。

我们这次用Pygame Zero来简单还原一下这款游戏,如果你不打算外接操纵杆,用键盘操作也可以。

构思

首先用绘制好的静态背景替换矢量图形,并将其用作碰撞检测和高度统计。

如果我们的背景是着陆器可以飞行的黑色背景,而着陆区所在的地方是另一种颜色,那么我们可以使用Pygame的image.get_at()函数来测试像素点是否在着陆位置。

我们还可以检测着陆器沿Y轴向下的像素线,直到抵达着陆区,这将让我们获悉着陆器当前的高度。

着陆器的控制非常简单,因为我们可以捕获左右箭头键来增加或减少着陆器的旋转角度。

然而当施加推力(通过按向上箭头)时,事情会变得有些复杂。我们需要记住推力来自哪个方向,让飞船即使打转也将继续沿该方向运动。所以我们在着陆器对象上附加了direction属性。对着陆器的位置施加一点重力,然后我们只需要一点三角函数的知识即可根据着陆器的速度和行进方向算出其运动轨迹。

要判断着陆器安全着陆还是在月球表面撞坏,我们要观察其到达高度1时,飞行器的下降速度和角度。

如果速度足够慢且角度接近垂直,则我们触发着陆成功的消息,游戏结束。

如果着陆器在没有满足这些条件的情况下达到零高度,则我们将判定坠机事故。

有兴趣的话,你还可以在此基础上添加一个有限的燃料表和可变的难度级别之类的东西。甚至可以尝试添加原始街机游戏中火箭助推器噪音的声音。

要点:

推力方位的改变可以有多种方法完成。在本例中我们简单一点,一个方向被施加推力,它就逐渐往那个方向移动,直到新的方向出现推力。你可以尝试对其进行X轴和Y轴方向计算,以获得结合点的坐标值。还可以添加操纵杆控制,提供可变的推力。

以下是核心代码段:

接下来看看效果:

视频:https://v.qq.com/x/page/b095944gc59.html

完整代码请访问:https://github.com/IoToutpost/Python_game

调试前记得先安装Pygame Zero。

线索:Wireframe #37

编译:王文文

创客妹子教你做“一键发Twitter眼镜”

关注“IoT前哨站”的朋友可能记得之前我们发过一篇“让相机根据GPS定位自动拍照”的文章。

是的,那位名叫“Estefannie” 的创客妹子又出现了,这次她给大家带来的是一个可以自动发Twitter的眼镜,而且是“侏罗纪公园模式”。

什么叫侏罗纪公园模式呢?

看看这个眼镜发的Twitter内容就知道了。

发现梁龙一只
发现雷龙一只

准确的说, Estefannie 做的这个装置应该叫“侏罗纪恐龙抓拍系统”。因为她这个发的每张照片都会标一个恐龙的名字,比如:“发现梁龙”,“发现雷龙”……她在眼镜上装了一个按钮。按下就能把照片发到Twitter上。

制作流程:

Estefannie 先是找了一个像护目镜一样的眼镜模型。

用3D打印机把眼镜的原型做出来以后,对其进行打磨、喷漆、抛光。然后在上面接好树莓派Zero W,LED和按钮,加上可调节部分、软垫以及绿色镜片……

大量的涂胶、焊接和布线工作之后,她最终得到了一副漂亮的眼镜。

紧接着,她写了一个Python脚本来拍照、与Twitter交互,并通过LED环来提供眼镜当前的状态信息。树莓派系统启动时,会先连到她手机的无线热点。然后,眼镜上的红色LED亮起,表示程序正常运行。

然后,就可以戴着这个眼镜去抓拍有意思的景物了。

背景:

原本这是她被邀请去“Coolest Projects”青少年创客大会演讲而制作的道具,但你可以根据她的代码自己改改,做一个发微博或者抖音的版本。

关于详细流程,建议大家看视频。

相关视频:https://v.qq.com/x/page/c3010lo613b.html

3D模型文件: https://www.thingiverse.com/thing:3732889

代码下载: https://github.com/IoToutpost/JurassicGoggles

素材:Raspberrypi.org

编译:王文文,前51CTO安全频道主编,RedHat认证工程师,华为HCIP-IoT认证工程师。

解析Python开发的一款迷你跑步游戏

之前“IoT前哨站”上发了一些用Python写文本游戏的文章。不管对于Python开发者来说还是对于游戏爱好者来说,都非常适合打基础。

这次我们迈入图形时代,来看看国外开发者“Rik Cross”制作的一款迷你跑步游戏。

他用了不到一百行代码,就写出了值得一玩的2D动作游戏,怎么做到的?

在此之前,先向大家介绍一个游戏框架:pgzero。

该框架全名Pygame Zero,是一个基于Pygame的游戏编程框架。它可以更容易地编辑游戏,无需模板、不用编写事件循环,也无需学习复杂的Pygame API,而且支持树莓派。

安装
pip install pgzero

需求:
通过键盘的左右键操作,让运动员向前奔跑,每过25米有路标提醒,最后看谁在百米跑步中耗时最少。

代码下载地址:
https://github.com/IoToutpost/Python_game/tree/master/Sprint

素材(地址同上):
Images文件夹中有21张图,包括运动员的动作分解、跑道等。

其中的关键代码,是一个叫做Sprinter()的类。

class Sprinter(Actor):
     def init(self, **kwargs):
         super().init(image='idle', pos=(200,220), **kwargs)
         self.startTime = time()
         self.finishTime = time()
         self.runFrames = ['run' + str(i) for i in range(1,16)]
         self.timeOnCurrentFrame = 0
         self.speed = 0
         self.lastPressed = None
         self.keyPressed = False
         self.distance = 0
# 将运动员推进到下一帧
def nextFrame(self):
    # 如果当前空闲,则启动正在运行的动画。 
    if self.image == 'idle':
        self.image = self.runFrames[0]
    else:
        # 在列表中找到下一个图像,然后返回到第一个图像 
        # 当列表已经到末尾的时候
        nextImageIndex = (self.runFrames.index(self.image) + 1) % len(self.runFrames)
        self.image = self.runFrames[nextImageIndex]

# 检查左右方向键是否正确
# 被交替按下
def isNextKeyPressed(self):
    if keyboard.left and self.lastPressed is not 'left' and not keyboard.right:
        self.lastPressed = 'left'
        return True
    if keyboard.right and self.lastPressed is not 'right' and not keyboard.left:
        self.lastPressed = 'right'
        return True
    return False

def update(self):
    # 更新运动员的速度
    # 交替按键加速
    if self.isNextKeyPressed() and self.distance < 100:
        self.speed = min(self.speed + ACCELERATION, 0.15)
    # 如果没有按键,减速
    else:
        self.speed = max(0, self.speed-DECELERATION)
    # 根据运动员的速度更新距离 
    self.distance += self.speed
    # 根据运动员的速度对其进行动画 
    self.timeOnCurrentFrame += 1
    if self.speed > 0 and self.timeOnCurrentFrame > 10 - (self.speed * 75):
        self.timeOnCurrentFrame = 0
        self.nextFrame()
    # 如果不移动,则设置为空闲
    if self.speed <= 0:
        self.image = 'idle'

里面有一些变量用来跟踪运动员的速度和距离,以及全局的常量(ACCELERATION和DECELERATION的值)。这样可以确定玩家的速度变化。这些数字很小,因为它们代表了玩家加速和减速时,每一帧对应的米数。

玩家通过交替按左右键来增加运动员的速度。这个输入由Sprinter类中的isNextKeyPressed()方法处理,如果按下正确的键,该方法将返回True。

lastPressed变量用于确保左右键被交替按压。如果未按下任何键,玩家会减速,并且该减速程度应小于加速度,以免让玩家突然停下。

在游戏设计中,作者用了gameart2d.com上一个名为“The Boy”的免费形象来作为运动员,里面有15张跑步动作分解图构成的循环。他将从空闲状态开始,只要速度大于0,就切换到跑步动作循环。

这是通过index()在runFrames列表中查找当前运动员图像的名称来实现的,程序会将当前图像设置为列表中的下一个图像(并且在到达列表的末尾时返回第一个图像)。

我们还需要让运动员在跑步动作循环中以成比例的速度向前移动,通过跟踪当前图像显示的帧数来实现(在那个名为timeOnCurrentFrame的变量中)。

为了给玩家一种移动的错觉,作者添加了一些经过玩家的物品:一条终点线和三个显示跑动距离的标记。

这些物品出现的时机是根据运动员在屏幕上的x位置和运动距离计算出来的。

​然而,这意味着每个物品距离玩家最多只有100像素的距离,似乎移动的有点缓慢。我们可以通过SCALE因子来解决,它对应的是运动员跑过的米数和屏幕上像素之间的关系。比如设成1:75。

这些物品最初被绘制在屏幕看不见的右侧,然后向左移动并更快地经过运动员。

最后,startTime和finishTime变量用于计算比赛时间。这两个值最初都设置为比赛开始的时间,只要跑动的距离小于100,finishTime就会更新。使用time模块,比赛时间可以简单地计算为finishTime – startTime。

附注:该游戏在树莓派和Windows PC上都能跑,如果要试玩,记得在Python文件前面加pgzrun命令。

Have fun.

素材:Wireframe #23

编译:王文文,前51CTO安全频道主编,RedHat认证工程师,华为HCIP-IoT认证工程师。

Python图形界面开发入门之Guizero

不管是手机电脑,还是带触摸屏的终端设备,简单易用的图形界面,总是很受欢迎。

而提起Python下的图形界面开发,大家一定都会想到 PyQt 和 wxPython、Kivy 等经典模块。

不过我们这次要介绍的“guizero”,是一个非常易用的GUI库,能让初学者快速、轻松地为他们的程序创建图形界面。

安装很简单:

pip3 install guizero

这里先来个基础的例子。

from guizero import App, Text, PushButton
app = App(title="IoT前哨站")
intro = Text(app, text="试着用guizeo开发图形界面")
ok = PushButton(app, text="Ok")
app.display()

这个例子应该很容易懂,先设置窗体、标题,然后放入一个文本框和一个按钮。

由于文本框没有设置内容,所以不太看得出来,整个窗体只能发现一个按钮孤零零的杵那儿。

下面我们试着给按钮加功能,让它做一个显示字符的操作(准备让文本框发挥作用了)。

from guizero import App, Text, PushButton

def say_hello():
    text.value = "欢迎关注IoT前哨站"

from guizero import App, Text, PushButton
app = App()
text = Text(app)
button = PushButton(app, command=say_hello)
app.display() 

当你单击 Button 按钮时,原本空着的文本框会显示“欢迎关注IoT前哨站”。

如果你的程序功能比较复杂,需要另外一个窗体展示内容的时候……

from guizero import App, Window, Text
app = App(title="主窗体")
window = Window(app, title="第二窗体")
text = Text(window, text="这段文字将在第二窗体显示")
app.display()

默认情况下,guizero是自动布局,或者通过修改窗体内各部件的align属性,来调整它们的基本方位,但那肯定不够。

更细致一点的布局方式 —— 网格。

from guizero import App, PushButton
app = App(title="IoT前哨站",layout="grid")
button1 = PushButton(app, text="1", grid=[0,0])
button2 = PushButton(app, text="2", grid=[1,0])
button3  = PushButton(app, text="3", grid=[2,0])
button4  = PushButton(app, text="4", grid=[0,1])
button5  = PushButton(app, text="5", grid=[1,1])
button6  = PushButton(app, text="6", grid=[2,1])
button7  = PushButton(app, text="7", grid=[0,2])
button8  = PushButton(app, text="8", grid=[1,2])
button9  = PushButton(app, text="9", grid=[2,2])
button0  = PushButton(app, text="0", grid=[1,3])
app.display()

通过grid参数来修改各部件的[x,y]坐标,以此改变它们在窗体中出现的位置。

你也可以通过在网格参数中指定范围,使部件跨越多个列或行。这些都是可选的,但必须用[x,y,xspan,yspan]这样的格式来指定它们。

比如下面这个图片摆放的例子。

from guizero import App, Picture
app = App(title="IoT前哨站",layout="grid")
picture1 = Picture(app, image="Debian.jpg", grid=[0,0])
picture2 = Picture(app, image="IotOutpost.jpg", grid=[1,0])
picture3 = Picture(app, image="wide.jpg", grid=[0,1,2,1])
picture4 = Picture(app, image="tall.jpg", grid=[2,0,2,2])
app.display()

弹出框大家也经常在用,一般经典的就是询问、提示和警告。

from guizero import App
app = App(title="月饼提问")
build_a_snowman = app.yesno("问题", "你喜欢吃蛋黄月饼吗?")
if build_a_snowman == True:
    app.info("月饼", "这就给你拿一块过来。")
else:
    app.error("月饼", "好吧,那就不吃了。")
app.display()

再看一个经典的滑动条,假设要调整空调的温度。

from guizero import App, PushButton, Slider
app = App(title="空调操作")
button = PushButton(app, text="开/关",width=30, height=5)
slider = Slider(app, width=200, height=30)
app.display() 

下面来一个读取传感器数值并每秒钟刷新的例子。当然,为了方便演示,里面用的是随机数。

from guizero import *
import random
def read_sensor():
    return random.randrange(3200, 5310, 10) / 100
def update_label():
    text.value = read_sensor()
    # recursive call
    text.after(1000, update_label)

if name == 'main':
    app = App(title='Sensor Display!',
              height=100,
              width=200,
              layout='grid')

title = Text(app, 'Sensor value:', grid=[0, 0]) 
text = Text(app, "xx", grid=[1, 0]) 
text.after(1000, update_label) 
app.display()

最后,来一个带菜单选项的例子。

 from guizero import *

 def switch_screen(switch_to):
     hide_all()
     switch_to.show()

 def hide_all():
     for screen in all_screens:
         screen.hide()

 app = App("多选择框运用", layout="grid")
 all_screens = []

 创建一个菜单区域
 menu = Box(app, grid=[0,0], layout="grid")
 menu.tk.width = 900
 menu.bg = "gray"

 选项1
 option1 = Box(app, grid=[1,0])
 text1 = Text(option1, text="这是列表区的内容")
 combo = Combo(option1, options=["树莓派","小熊派","香橙派"])
 all_screens.append(option1)

 选项2
 option2 = Box(app, grid=[1,0])
 text2 = Text(option2, text="这是滑动框")
 slider = Slider(option2)
 all_screens.append(option2)
 
 option1_button = PushButton(menu, text="列表区", \
 command=switch_screen, args=[option1], grid=[0,0], align="left")
 option2_button = PushButton(menu, text="滑动框", \
 command=switch_screen, args=[option2], grid=[0,1], align="left")
 hide_all()
 all_screens[0].show()
 app.display()

左侧灰色的两个菜单选项,分别是“列表区”和“滑动框”,单击任意一个按钮后会出现相应内容,列表区中有个下拉式清单,而滑动框点进去是与其对应的部件。

其他的用法大家可以继续挖掘,不管你的系统是 Windows 还是 Mac、Raspbian Linux,Guizero均可支持。

虽然看着似乎有一点糙,但好在上手快。哪怕你是一个刚开始研究图形界面的 Python 开发者,也能轻松掌握。

作者:王文文,前51CTO安全频道主编,RedHat认证工程师,华为HCIP-IoT认证工程师。

拒绝炎热和潮湿 DIY智能换气扇

夏季的上海,烈日炎炎。

白天出门就是一种折磨。

在屋里一直开着空调吧,到了昼夜交替或者深夜的时候,可能又觉得冷。

暴雨的时候,外面空气清新,室内却很闷热……

如果给你两个换气扇,怎样才能让室内空气健康流通呢?

美国有一位名叫 Ishmael Vargas 的创客,给我们带来了他的方案。

在芝加哥地区,夏季的白天和夜晚都是炎热潮湿的。太阳下山的时候外面温度下降,但家里却未必。

这就是窗式换气扇用得着的地方,它可以把冷空气吹进房子里。

但一直这么开着也不行,因为温度在不停变化。

去年夏天,Ishmael Vargas 经常要在半夜起床把换气扇关掉,但他觉得可以用一个更好的方法来控制风扇,无需人工干预,于是他便启动了这个小项目。

Ishmael Vargas 用树莓派和DHT22温湿度传感器来监测室温,然后将其与外部温度进行比较。如果后者更凉爽,则通过智能Wi-Fi电源插头(TP-Link HS100)打开换气扇 —— 这比将风扇连接到继电器要简单得多。

传感器的三根线分别接在树莓派的电源、接地、GPIO 4(建议加上10K电阻)
Smart WiFi Plug 智能插座

室外温度感知

为了简单起见,Ishmael 选择使用 pywapi 库从 Weather Channel 获取室外温度,而不再连接外部传感器。

“Weather Channel 提供的温度和实际温度可能相差一两度。这对于这个项目来说已经足够了。”他解释道。

智能WiFi插座用于打开和关闭窗户风扇

在测试中,Ishmael 发现清晨的风扇可能会把温暖的空气吹进房子里。

他说:“根据风扇的大小、房间的大小和房屋材料的不同,室内的温度可能永远不会像室外那么低。”例如,如果外面的温度是65°F(18°C),那么里面的温度可能会是67°F(19.5°C)。当室外温度开始上升时,你可能需要关掉风扇。”

远程控制

Ishmael 没有让风扇程序在启动时自动运行,而是选择通过Android智能手机手动启动并控制它。后者运行VNC查看器应用程序,允许远程访问Raspberry Pi的桌面,在桌面有一个快捷方式可以启动风扇应用程序。然后显示一个Pygame窗口,其中包含温度信息和控制按钮。

树莓派的桌面

“风扇应用程序有两个按钮,可以向上或向下改变(所需的温度)设定值。”Ishmael说。

此外,右上角的按钮是关闭应用程序并返回桌面。他的目标是在他的树莓派上运行多个项目,并为每个应用程序提供桌面快捷方式。

在手机或PC上,可以通过VNC查看温度数据和控制按钮

虽然最初的项目只使用了一个换气扇,但他后来对其进行了修改,添加了另一个风扇。因为他意识到,要想取得最好的性能,需要两个换气扇。一个吹进来,另一个吹出去。

编者注:最近在上海转悠了几个老小区,发现多户人家的通风问题需要改善。有的是楼道和通风管道设计的问题,这个就不说了。有的纯粹是自己不重视,如果能做科学的改动,应该可以让生活更舒畅。

源码地址:

https://github.com/IoToutpost/Smart-Window-Fan

素材:MagPi,编译:IoT前哨站,转载请注明出处。

王文文,前51CTO安全频道主编,阿里巴巴资深安全工程师。Redhat认证工程师,华为IoT认证工程师。

Python文本游戏之根据提示猜词

之前IoT前哨站上发布了“Python写文本冒险游戏的要点”和“在文本冒险游戏中加入道具”,讲的都是冒险类游戏。

那猜谜类型的文本游戏大家知道怎么做吗?

比如经常被用来练习的猜数字:

这确实是一个经典的入门。不过我们这次要加点难度。让大家来猜词语。

要求:

每次随机给出一部分残缺的字符,让大家回忆并输入完整的词语。

答对输出正确,答错提示错误,并告知正确答案。

思路:

1、创建一个小的词库,这里我们将一部分词语放入数组,命名为:questions。

import random

questions = [“As you like it”, “The Tempest”, “Measure for Measure”, “Much Ado About Nothing”, “The Comedy of Errors”, “King Lear”, “Cymbeline”, “Hamlet”, “Coriolanus”, “Othello”, “Love’s Labour’s Lost”, “King John”, “Julius Caesar”, “Edward III”]

2、随机选择一个短语,并将其转换为大写。

chosen_phrase = random.choice(questions)
chosen_phrase = chosen_phrase.upper()

3、去掉元音、空格和单引号。把删选后的字符拼接起来,赋值给变量puzzle。

vowels = [“A”, “E”, “I”, “O”, “U”, ” “, “‘”]
puzzle = “”
for letter in chosen_phrase:
if not letter in vowels:
puzzle += letter

4、随机插入空格

puzzle_with_spaces = “”

while len(puzzle) > 0:
group_length = random.randint(1,5)
puzzle_with_spaces += puzzle[:group_length] + ” “
puzzle = puzzle[group_length:]

5、最后加入答案检测,如果输入和答案一致,就告知“That’s correct!”,如果答案错误,提示:No,并给出正确答案。

guess = input(“What is your guess? “)
guess = guess.upper()

if guess == chosen_phrase:
print(“That’s correct!”)
else:
print(“No. The answer is “, chosen_phrase)

好了,一个根据提示信息猜短语的文本游戏就写完了。

完整代码可访问:

https://github.com/IoToutpost/Python_game/tree/master/Puzzles

在把这个游戏给别人玩的时候,记得先让玩家看一看你的词库。不然就是瞎猜了。

有能力的朋友可以试着扩展一下,说不定你可以把它改成一个英语学习程序。

注:文中猜词代码来自MagPi 82《Code a quiz game with Python》。

十行代码就能写个整蛊玩具

有时候看国外的街头搞笑节目,经常会看到一种会出声的坐垫。

当不知情的人坐上去时候,椅子上的坐垫便会发出各种奇怪的声音。让人还误以为是自己造成的。

其实做这个并不难,如果用我们这套方法,可能只要十行代码就搞定了,而且还可以指定任意的音乐。

所需工具:

1、树莓派

2、小音箱

3、鳄鱼线和公母跳线各两条

4、几个夹子

5、铝箔

6、硬纸板

7、铜带和海绵若干

开始制作:

从硬纸板上剪两个圆圈,然后把铝箔纸粘在圆圈上。

用一些铜带把铝箔纸和圆纸板的边缘连接起来,做成两个盘子。

把海绵切成长方体,把它们粘在其中一个盘子的箔纸上,这样箔纸就不会互相接触,除非有人坐在盘子上。

它应该是这样的:

把两个盘子叠在一起,铝箔片相对而置。铜带部分不要接触。

你现在有一个“垫子”了。你可以把两个盘子粘在一起,或者用夹子或回形针,这样你就可以测试你的坐垫是否工作正常,并且很容易调试相关硬件。

接下来是树莓派插线位置:

将鳄鱼夹一头接在纸板的铜带部分,然后将另一头夹在所连接的跳线的外销上。两条线同样操作。最后的样子是这样。

硬件部分完成后,先连到树莓派上测试一下声音播放。

接好小音箱,然后在命令行播放你事先准备的wav格式音乐。比如:

aplay burp.wav

确定可以听见音乐之后,开始编码。用Python比较简单,十行就搞定了。

import os,random
from time import sleep
from gpiozero import Button
button = Button(2)

trumps = ['ben-fart.wav','ca-fart.wav','marc-fart.wav']

while True:
    button.wait_for_press()
    parp = random.choice(trumps)
    os.system("aplay {0}".format(parp))
    sleep(2)

三个音乐文件都要提前准备好,最后运行一下看看是否能跑起来。

小心地把“坐垫”放在沙发或椅子上。接好电源(最好用电池组),让程序保持在运行状态。然后……

如果整蛊成功,别忘记回来点个赞。

来源:Raspberrypi.org

编译:IoT前哨站

在文本冒险游戏中加入道具

上次发了一篇“Python写文本冒险游戏的要点”之后,有的朋友说形式太简单了,能不能在游戏中加入道具?

既然如此,我们这次就来给它升一级。

很多人都玩过“刺激战场”类的游戏,进一个房子就拼命捡枪捡子弹什么的。这些都是游戏人物的重要道具。

下面我们就继续以《回村》为例子,在其中加入道具拾取和过关判定。

先把游戏环境概念图画出来。

1、森林里有牛肉

2、小山里有红酒

3、湖泊边有强盗

获胜判定:

带着牛肉和红酒,避开强盗,回到村庄即获胜。否则游戏继续。

好了,现在就在代码中更新道具和强盗。

代码地址:

https://github.com/IoToutpost/Python_game

Gohome.py是之前的版本,Gohome_v0.2.py是我们加了道具的版本。

需要注意的是,我们现在用字典来存储地点、方向和道具了。这样对于数据读写来说会更方便。

Python中的字典是啥?

字典是Python中唯一内建的映射类型。字典中的值并没有特殊的顺序,但是都存储在一个特定的键(Key)里。键可以是数字、字符串甚至是元组。

字典由多个键及与其对应的值构成的对组成。每个键和它的值之间用冒号(:)隔开,项之间用逗号(,)隔开,而整个字典由一对大括号括起来。字典中的键是唯一的,而值并不唯一。

好了,跑一下试试。

到此,一个简单的RPG游戏算是做好了。

如果想让游戏更好玩,要加的东西还很多。比如战斗元素,生命值,时间……探索无止境。

注:这个系列的文章是写给新手的,高手就不用看了哈。当然,欢迎指导,欢迎分享更有意思的版本。

只要有想象力,打印机都能做游戏

不知道为什么,文本冒险游戏最近频频被人提及。这不,现在又出来一个基于实时打印的文本冒险游戏 —— Quest Smith。

这位脑洞较大的创客名叫 Bekir Dağ ,他用微型打印机和树莓派做出了这个手持游戏设备。

关于文本冒险游戏的背景知识:

1975年左右,程序员兼业余洞穴探险者 威尔·克劳瑟(Will Crowther)编写了第一个文本冒险游戏 —— Adventure。最初名为 ADVENT,因为在他使用的操作系统中,文件名不能超过六个字符,后来被命名为《巨大的洞穴冒险》 —— Giant Cave adventure。

玩家需要阅读周围环境的描述并从一组选项中进行选择,或者输入下一步并希望游戏能够理解玩家提及的内容。

Bekir Dağ 的创新之处是他把一个文本冒险游戏做成实时打印剧情了。玩家用 Yes 和No 两个按钮来决定游戏的走向 。

Quest Smith是个啥?

在柏林的一家游戏博物馆里,Bekir Dağ 看到了一个手持式游戏设备,于是他决定用树莓派 Zero W自己做一个。

他设计了Quest Smith 的躯壳,用3d绘图软件输出了 STL 文件并在
Thingiverse 网站上免费分享。

下载地址:

https://www.thingiverse.com/thing:3471217

树莓派 Zero W 与热敏打印机、电池和各种按钮紧密贴合在一起。由安装在外壳上的太阳能电池板供电,所有组件都连接到 TP4056 板,该板允许电池为树莓派供电。

硬件材料:

1、Raspberry Pi Zero Wireless 一个

2、GOOJPRT 热敏打印机一个

3、五伏电压升压模块 一个

4、 TP4056 板 一个

5、 18650电池 一个

6、瞬时触碰式开关

7、 Micro usb 转大口接头

8、螺钉 3.5 x 20毫米 四个

9、 滑动开关 一个

10、太阳能电池板60 x 60毫米 5.5V

另外要准备热熔枪、电烙铁和3D打印机。

相关的代码:

https://github.com/IoToutpost/quest_smith

1、系统需要安装的组件

sudo apt-get install libpython3-dev libpython3-stdlib libqt5printsupport5 php7.0-mbstring python3-rpi.gpio python-rpi.gpio python-setuptools python-dev build-essential

2、安装composer

步骤在此: https://getcomposer.org/download/

3、安装两个python库

pip install setuptools
pip install locustio

4、拉取代码

mkdir quest_smith
cd quest_smith
git clone git@github.com:bekirdag/quest_smith.git .
composer install

5、 在重新启动时,通过在crontab上添加一行来运行 Quest Smith 脚本

crontab -e
@reboot sudo /usr/bin/screen -dmS story-game /usr/bin/python3 /home/pi/thermal/push3.py

6、 再次向 crontab 添加另一行代码,以便在每次重启时更新软件,这样你的故事就会是最新的。

@reboot sudo cd /home/pi/quest_smith && sudo git pull origin master

Quest Smith 目前仍在开发中。虽然用户现在可以构建并开始玩这个游戏,但作者呼吁社区用户提交他们自己的故事(有好的分支剧情就发过去)。

Bekir Dağ 说:“每个关卡都需要两个版本的故事,这使得可能性呈指数级增长。所以一个人完成整个故事线对我来说是非常困难的。比如为了让玩家达到9级,我们需要编写1023个故事部分。如果你能帮我,那就太好了! ”

如果想看这个设备是怎么玩的点这里:

http://v.qq.com/x/page/y0846fbymnz.html

相关阅读:

Python写文本冒险游戏的要点

https://mp.weixin.qq.com/s/jtxOqDlYLt3VjdsnLXfdAg

新手可以在研究这篇文章的同时学会面向对象编程。

来自:Raspberrypi.org

编译:王文文