pygame小游戏之飞机拼音大作战( 送给娃学拼音的礼物,星际旅行)

2023-11-19

二娃再过一年就该上一年级了,但现阶段的拼音咋都学不进去。买了拼音挂图贴在墙上,拉都拉不到旁边。突发奇想,何不用python的pygame做个小游戏?在玩中也能学习,让学变得有趣!这对搞编程的来说小菜一碟,于是说干就干,两个晚上就成型啦,这里总结分享给有需要的小伙伴。

前言

这不只是个游戏,更是一部科普小电影,带你体验一把星际穿越。认识星系、银河、星座、黑洞。满天繁星,璀璨的星空,总能给人带来无尽的想象和激发探索的欲望,激起求知的本能。

pygame小游戏之飞机拼音大作战,是一个专为孩子设计的游戏,旨在帮助他们学习拼音字母并激发他们对编程的兴趣,对太空的好奇心。这款游戏既有趣又教育,通过简单的Python小游戏制作过程,让孩子们能够见识游戏的开发,从中学到编程的基础知识。

兴趣是最好的老师。

游戏的背景以宇宙和航空为主题,为孩子们提供了一个奇妙的探索空间。他们可以扮演一位宇航员,驾驶飞机在太空中飞行,同时学习拼音字母。后续计划在游戏中,让孩子们需要根据屏幕上出现的字母或汉字,用正确的拼音字母来击败敌人或通过障碍物。通过这种互动的方式,他们将在玩乐中学习,增长见识,并培养对宇宙未来的探索和想象力,增加对未来的好奇心,探索欲和求知欲。

这款游戏的目的是让孩子们在享受游戏的乐趣的同时,提高他们的拼音字母识别能力和记忆能力。通过与游戏互动,他们将逐渐熟悉拼音字母的发音和书写,为他们日后的语言学习打下坚实的基础。此外,通过参与游戏的制作过程,孩子们还能培养逻辑思维、解决问题的能力和创造力,同时感受编程的乐趣。

其实很早我就曾想,既然孩子们都这么爱玩游戏,为何市面上的游戏大都让上瘾为主,毫无意义的打怪升级?为何不加上以玩儿中学习,科普知识,探索未知,增加好奇心,同步成长为主题搞一些游戏呢?

pygame小游戏飞机之拼音大作战围绕在玩中学,科普知识,激发求知欲这一理念,为孩子们提供了一个有趣而富有教育意义的学习实践,增加他们对拼音字母学习的兴趣,并为他们的未来学习之路打下坚实的基础。让我们一起探索宇宙,学习知识,开启编程的乐趣吧!

喜欢的欢迎点赞收藏,可以做为送娃的礼物。

源码包含全部素材可运行。

下载链接:https://download.csdn.net/download/qq8864/88314308

先来看下效果图:

还记得那部经典电影《星际穿越》吗?这个小游戏带你也体验一把星际穿越,也见识见识黑洞!

仰望星空,总能给人无限的遐想。

玩法介绍

玩法很简单,把原来做的飞机大战游戏从新改版成打击拼音字母,并计算得分。每打中一个字母,就对应发出它的读音。按上下左右几个键,可以控制飞机的上下左右移动。按空格键则可以发送子弹。子弹击中拼音字母,则发出对应的字母的发音。其中还有移动的陨石是不能打的,打到则扣分。游戏的背景各不相同,从网络精选了美妙的宇宙世界,地球、月球、陨石、火星和其他各大行星,银河、星座、黑洞,璀璨的星空。

后续计划在游戏中,让孩子们需要根据屏幕上出现的字母或汉字,用正确的拼音字母来击败敌人或通过障碍物。通过这种互动的方式,他们将在玩乐中学习,增长见识,并培养对宇宙未来的探索和想象力。

设置一系列的关卡,每个的背景图都不一样,让孩子同时领略下神秘的宇宙太空。先从地球起飞,掠过月球,认识八大行星,穿越太阳系,躲过陨石,最后飞向宇宙星空,探索璀璨宇宙。

飞掠地球,下面像是蓝色的海洋,高空中俯视地球有点儿恐惧呢。

飞向月球,月球原来长这样: 

飞掠火星:

火星长啥样?从火星表面经过, 近距离看看。

旁边咋还有一人造卫星,可不能把咱的卫星干下来。

飞掠八大行星: 

八大行星有哪些?记得住吗?依次飞过它就印象深刻了吧。

黑洞长什么样?可能是这样吧:

后面还有飞出银河系,人马星座,到神秘的黑洞去看看。 相当于星际穿越,神秘的宇宙结合飞行动画,相当震撼!

环境准备

1.下载安装python3

Python 官网:Welcome to Python.org

2.安装依赖的模块: pygame,pygame-pgu

python加入环境变量

3.替换pip安装的资源镜像(否则下载模块很慢)

pip  config set  global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

4.图片和语音素材

5.讯飞离线语音合成工具

6.goldwave语音制作裁剪工具

源码实现

源码实现很简单,有点儿基础的都能很容易看懂。这里就不做过多介绍了,基本都是pygame的一些基础用法。挑战失败弹出对话框,使用了pygame-pgu模块。

弹出对话框

弹出对话框的简单示例:

#退出对话框
class QuitDialog(gui.Dialog):
    def __init__(this,main):
        title = gui.Label("Dialog Box")
        gui.Dialog.__init__(this, title, main)
    def close():
        pygame.quit()
        exit()
       

app = gui.App()                       #初始化gui
con = gui.Container() #生成gui的容器
quitDlg = QuitDialog(con)                    #生成弹窗abc
btn = gui.Button("game over")                 #生成文字为a的按钮
btn.connect(gui.CLICK, quitDlg.close, None)#将按钮与弹窗的弹出绑定
label = gui.Label("Are you sure you want to quit?")
quitDlg.add(label, 2, 2)
quitDlg.add(btn,2,3)                       #将按钮安放在容器(0,0)位置    
app.init(con)           

这里需要注意的是pgu这个库的使用,以上代码是有问题的,网上竟然一点有用的资料也没有。会收到报错:

Traceback (most recent call last):
  File "d:\test3\plangame\Plane.py", line 243, in <module>
    app.event(event)
  File "D:\Python\Python310\lib\site-packages\pgu\gui\app.py", line 177, in event
    container.Container.event(self,sub)
  File "D:\Python\Python310\lib\site-packages\pgu\gui\container.py", line 233, in event
    used = w._event(sub)
  File "D:\Python\Python310\lib\site-packages\pgu\gui\widget.py", line 323, in _event
    return self.event(e)
  File "D:\Python\Python310\lib\site-packages\pgu\gui\theme.py", line 354, in theme_event
    return func(sub)
  File "D:\Python\Python310\lib\site-packages\pgu\gui\container.py", line 233, in event
    used = w._event(sub)
  File "D:\Python\Python310\lib\site-packages\pgu\gui\widget.py", line 322, in _event
    self.send(e.type,e)
  File "D:\Python\Python310\lib\site-packages\pgu\gui\widget.py", line 306, in send
    names.pop(0)
IndexError: pop from empty list

自己摸索出来的关于pgu弹出对话框的正确做法如下:

#退出对话框
class QuitDialog(gui.Dialog):
    def __init__(this,main):
        title = gui.Label("Dialog Box")
        gui.Dialog.__init__(this, title, main)
    #注意这里的close1,被button绑定了,除了self,还必须得有个参数
    def close1(self,w):
        print("close")
        pygame.quit()
        exit()

app = gui.App()                       #初始化gui
con = gui.Container() #生成gui的容器
quitDlg = QuitDialog(con)                    #生成弹窗abc
btn = gui.Button("game over")                 #生成文字为a的按钮
btn.connect(gui.CLICK, quitDlg.close1, None)#将按钮与弹窗的弹出绑定
label = gui.Label("Are you sure you want to quit?")
quitDlg.add(label, 2, 2)
quitDlg.add(btn,2,3)                       #将按钮安放在容器(0,0)位置    
app.init(con)    

注意def close1这个函数是需要两个参数的,一个不行。 

显示得分实现

显示得分,字母和汉字显示的实现:

# 加载字体文件
font_path = "./font/SIMYOU.ttf"  # 替换为你的字体文件路径
font_size = 24
font = pygame.font.Font(font_path, font_size)

score = 0
score_txt = "得分:"+str(score) # 要显示的文本
text_surface = font.render(score_txt, True, (255, 255, 255))


#......

    score_txt = "得分:"+str(score)
    text_surface = font.render(score_txt, True, (255, 0, 255))
    screen.blit(text_surface, (680, 10)) 
    
    if show_image:
        screen.blit(fail_image, (300, 100))  # 绘制图像
        
    app.paint()
    pygame.display.update()

精灵动画的实现

动画的原理:其实动画就是用一张张静态的图片按顺序展示,如果顺序展示的速度比较快,人脑就会人物这是连续的。该小游戏中的动画如子弹打中后的爆破效果,就是个动画实现。其实就是提前加载好三幅图片,然后按照一定时间间隔,让精灵类的update方法自己来更新图片。

实现如下:

class Explode(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.images = [pygame.image.load('./image/explode' + str(i) + '.png') for i in range(1, 4)]
        self.image_index = 0
        self.image = self.images[self.image_index]
        self.rect = self.image.get_rect()
        self.readt_to_change = 0
        sound = pygame.mixer.Sound('./sound/enemyExplode.wav')
        sound.play()

    def update(self, *args):
        if self.image_index < 2:
            self.readt_to_change += 1
            if self.readt_to_change % 4 == 0:
                self.image_index += 1
                self.image = self.images[self.image_index]
        else:
            self.kill()

Pygame中的精灵 

在 Pygame 中,精灵(Sprites)是游戏中各种角色、物体和效果的基本元素。精灵可以包含图像、位置、速度和其他属性。使用 Pygame 中的精灵类可以有效地管理和更新多个精灵对象。

可以通过继承 Pygame 中的 pygame.sprite.Sprite 类来定义自己的精灵类。在定义精灵类时,通常需要在 __init__ 方法中设置精灵的初始位置、图像和其他属性。例如,以下代码定义了一个简单的精灵类 MySprite:

import pygame

class MySprite(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = pygame.Surface((50, 50))
        self.image.fill((255, 0, 0))
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y 

处理精灵对象和事件

在游戏中,通常需要处理精灵对象的交互和事件。例如,检测精灵之间的碰撞、移动精灵、响应键盘和鼠标事件等。要处理精灵对象和事件,可以使用以下代码:

for event in pygame.event.get():
    if event.type == pygame.QUIT:
        pygame.quit()
        sys.exit()

# 处理键盘事件
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
    my_sprite.rect.x -= 5
if keys[pygame.K_RIGHT]:
    my_sprite.rect.x += 5
if keys[pygame.K_UP]:
    my_sprite.rect.y -= 5
if keys[pygame.K_DOWN]:
    my_sprite.rect.y += 5

# 处理碰撞事件
collision_list = pygame.sprite.spritecollide(my_sprite, my_group, False)
for sprite in collision_list:
    

pygame.event.get() 方法用于获取所有的 Pygame 事件。pygame.key.get_pressed() 方法用于检测键盘按键的状态。pygame.sprite.spritecollide() 方法用于检测精灵对象之间的碰撞。您可以根据具体情况添加其他事件处理代码。 

关于精灵类,有一个地方容易迷惑,在pygame的sprite类定义中,翻看源码只有__g一个属性,它的img和rect属性哪里来的?

这是python语法中一个强大有有点儿奇怪的地方(区别于其他语言)。在python父类能够访问子类属性,即使没在父类中定义的属性。举例如下:

print('Hello World')
class Sprite:
    """simple base class for visible game objects
     """
    def __init__(self, *groups):
        self.__g = set()  # The groups the sprite is in
        if groups:
            self.add(*groups)
    def add(self, *groups):
        """add the sprite to groups
         Sprite.add(*groups): return None
         Any number of Group instances can be passed as arguments. The
        Sprite will be added to the Groups it is not already a member of.
         """
        has = self.__g.__contains__
        for group in groups:
            if hasattr(group, "_spritegroup"):
                if not has(group):
                    group.add_internal(self)
                    self.add_internal(group)
            else:
                self.add(*group)
    def add_internal(self, group):
        """
        For adding this sprite to a group internally.
         :param group: The group we are adding to.
        """
        self.__g.add(group)
        
    def update(self, *args, **kwargs):
        print("Sprite update")
        print(self.image)
        print(self.rect)
        """method to control sprite behavior"""


class Bullet(Sprite):
    def __init__(self, speed):
        super().__init__()
        self.image =4
        self.rect = 5
        self.speed = speed

    def update(self, *args):
        super().update()
        print("Bullet update")
        
b = Bullet(5) 
b.update()

print("over")

结果输出:

Hello World
Sprite update
4
5
Bullet update
over

在父类Sprite中并没有定义image和rect属性,但是竟还可以使用,输出了子类中赋值过的4,5。

如果在上述Bullet的update函数中,调用super.update()方法时传个参,会改变image和rect的值吗?如下:

class Bullet(Sprite):
    def __init__(self, speed):
        super().__init__()
        self.image =4
        self.rect = 5
        self.speed = speed

    def update(self, *args):
        #调用父类方法并传参8,9
        super().update(8,9)
        print("Bullet update")

答案是不会改变image和rect的值的,因为在Python中 *** 是用作函数参数的特殊符号,用于处理可变数量的位置参数和关键字参数。  

Python中星号*和**的含义

*args 表示接受任意数量的位置参数,并将它们作为一个元组传递给函数。在这个示例中, add() 方法的 *groups 参数表示可以传入任意数量的 Group 实例,这些实例将被作为元组传递给 groups 参数。在函数内部,可以使用 groups 变量来访问传递的参数元组。

在代码中的 update() 方法中, *args**kwargs 参数表示接受任意数量的位置参数和关键字参数。总结起来, *args 用于接受任意数量的位置参数, **kwargs 用于接受任意数量的关键字参数。这样可以使函数更加灵活,能够处理不同数量和类型的参数。

举例,看一下示例会输出什么:

 def update(self, *args, **kwargs):
        print("Sprite update")
        #print(self.image)
        #print(self.rect)
        print("args:")
        print(args)
        print("kwargs:")
        print(kwargs)


update(8,9)

update(8,9,a="1",b="2")

update(a="1",b="2")

结果输出:

args:
(8, 9)
kwargs:
{}

args:
(8, 9)
kwargs:
{'a': '1', 'b': '2'}

args:
()
kwargs:
{'a': '1', 'b': '2'}

 以上是定义函数时参数带*或**的情况,那么可能还见到过调用函数时,传递*和**的又是什么含义呢?如调用:test(*args)

test(*args),星号的作用其实就是把序列 args 中的每个元素,当作位置参数传进去。比如test(*args)这个代码,如果 args 等于 (1,2,3) ,那么这个代码就等价于 test(1, 2, 3) 。

def foo(a,b):
    print(a)
    print(b)

args = [1,2]   #这里只能有两个元素
foo(*args)

同理,调用test(**kwargs),双星号的作用则是把字典 kwargs 变成关键字参数传递。比如test(**kwargs)这个代码,如果 kwargs 等于 {“a”:1,“b”:2,“c”:3} ,那这个代码就等价于 test(a=1,b=2,c=3) 。

def foo(a,b):
    print(a)
    print(b)

kwargs = {'a':1,'b':2}   #这里只能是'a'和'b'
foo(**kwargs)

猜下以下代码会输出什么?

#示例一
def foo(a,b,c,*args):
    print("a=%s" % (a,))
    print("b=%s" % (b,))
    print("c=%s" % (c,))
    print("args=%s" % (args,))

argtuple = ("testa","testb","testc","excess1","excess2")
foo(*argtuple)

#示例二
def foo1(a,b,c,**args):
    print("a=%s" % (a,))
    print("b=%s" % (b,))
    print("c=%s" % (c,))
    print("args=%s" % (args,))

argdict = dict(a="testa", b="testb", c="testc", excessarg="string")
foo1(**argdict)

 输出:

a=testa
b=testb
c=testc
args=(‘excess’,‘excess2’)

a=testa
b=testb
c=testc
args={‘excessarg’: ‘string’}

再举个例子,注意观察调用方式的不同:

def foo1(*args):
    print("args=%s" % (args,))
    print(args[0])

argtuple1 = ("testa","testb","testc","excess1","excess2")

foo1(argtuple1)
foo1(*argtuple1)

 foo1的两种调用一样吗?

肯定不一样有区别。记住foo1(*argtuple1)调用中,*argtuple1就相当于把tulpe中的元素给解包了。相当于调用的foo1("testa","testb","testc","excess1","excess2"),因此arg[0]输出就是testa 

上述代码的执行结果:

args=(('testa', 'testb', 'testc', 'excess1', 'excess2'),)

('testa', 'testb', 'testc', 'excess1', 'excess2')

args=('testa', 'testb', 'testc', 'excess1', 'excess2')

testa

完整源码实现 

import pygame
import random
from pgu import gui,timer

# 常量
WIDTH, HEIGHT = 800, 600

# 初始化操作
pygame.init()
pygame.mixer.init()
# 创建游戏窗口
screen = pygame.display.set_mode((WIDTH, HEIGHT))

# 设置游戏标题
pygame.display.set_caption('飞机拼音大作战--关注作者:blog.csdn.net/qq8864')

# 添加音乐
pygame.mixer.music.load('./sound/bgLoop.wav')
pygame.mixer.music.set_volume(0.5)  # 音量
pygame.mixer.music.play(-1, 0)
# 添加系统时钟
FPS = 40
clock = pygame.time.Clock()
# 创建用户自定义事件,每隔2000毫秒触发一次事件,随机创建敌人
CREATE_ENEMY = pygame.USEREVENT
pygame.time.set_timer(CREATE_ENEMY, 2000)

# 加载字体文件
font_path = "./font/SIMYOU.ttf"  # 替换为你的字体文件路径
font_size = 24
font = pygame.font.Font(font_path, font_size)

score = 0
score_txt = "得分:"+str(score) # 要显示的文本
text_surface = font.render(score_txt, True, (255, 255, 255))

fail_image = pygame.image.load("./image/failed.png")
show_image = False  # 控制是否显示图片

tup_target = ('a','o','e','i','u','ü','b','p','m','f','d','t','n','l')
#退出对话框
class QuitDialog(gui.Dialog):
    def __init__(this,main):
        title = gui.Label("Dialog Box")
        gui.Dialog.__init__(this, title, main)
    def close():
        pygame.quit()
        exit()
       

app = gui.App()                       #初始化gui
con = gui.Container() #生成gui的容器
quitDlg = QuitDialog(con)                    #生成弹窗abc
btn = gui.Button("game over")                 #生成文字为a的按钮
btn.connect(gui.CLICK, quitDlg.close, None)#将按钮与弹窗的弹出绑定
label = gui.Label("Are you sure you want to quit?")
quitDlg.add(label, 2, 2)
quitDlg.add(btn,2,3)                       #将按钮安放在容器(0,0)位置    
app.init(con)           
# ========游戏开始页面静态效果==========
# class Hero(pygame.sprite.Sprite)
# class Bullet(pygame.sprite.Sprite)
# class Enemy(pygame.sprite.Sprite)
# class Explode(pygame.sprite.Sprite)
# class BackGround(pygame.sprite.Sprite)
# 主角
class Hero(pygame.sprite.Sprite):
    def __init__(self, speed):
        super().__init__()
        self.image = pygame.image.load('./image/plane.png')
        self.images = [pygame.image.load('./image/planeDie' + str(i) + '.png') for i in range(1, 4)]
        self.image_index = 0
        self.readt_to_change = 0
        self.dired = 0 #默认三条命
        self.rect = self.image.get_rect()
        self.rect.width *= 0.5
        self.rect.height *= 0.5
        self.image = pygame.transform.scale(self.image, (self.rect.width, self.rect.height))
        self.rect.x, self.rect.y = 0, 100
        self.speed = speed
        self.ready_to_fire = 0

    def update(self, *args):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_UP]:
            self.rect.y -= self.speed
        if keys[pygame.K_DOWN]:
            self.rect.y += self.speed
        if keys[pygame.K_LEFT]:
            self.rect.x -= self.speed
        if keys[pygame.K_RIGHT]:
            self.rect.x += self.speed
        if keys[pygame.K_SPACE]:
            if self.ready_to_fire == 0:
                self.fire()
            self.ready_to_fire += 1
            if self.ready_to_fire > 5:
                self.ready_to_fire = 0
        else:
            self.ready_to_fire = 0
        if self.rect.x < 0:
            self.rect.x = 0
        if self.rect.y < 0:
            self.rect.y = 0
        if self.rect.y > HEIGHT - self.rect.height:
            self.rect.y = HEIGHT - self.rect.height
            
        if self.dired != 0:
            if self.image_index <= 2:
                self.readt_to_change += 1
                if self.readt_to_change % 4 == 0:
                    self.image = self.images[self.image_index]
                    self.image_index += 1
            else:
                self.image_index = 0
                self.kill()
            

    def fire(self):
        bullet = Bullet(10)
        bullet.rect.x = self.rect.right
        bullet.rect.centery = self.rect.centery
        bullet_sprite.add(bullet)
        # 音效
        sound = pygame.mixer.Sound('./sound/laser.wav')
        sound.play()


class Bullet(pygame.sprite.Sprite):
    def __init__(self, speed):
        super().__init__()
        self.image = pygame.image.load('./image/bullet.png')
        self.rect = self.image.get_rect()
        self.speed = speed

    def update(self, *args):
        self.rect.x += self.speed
        if self.rect.x > WIDTH:
            self.kill()


class Enemy(pygame.sprite.Sprite):
    count_ = 0
    def __init__(self, speed):
        super().__init__()
        Enemy.count_ += 1
        self.image = pygame.image.load('./image/'+'enemy'+str( Enemy.count_)+".png")
        self.rect = self.image.get_rect()
        self.rect.x = 800
        self.rect.y = random.randint(0, HEIGHT)
        self.speed = speed
        self.id = Enemy.count_
        self.name = 'enemy'+str( Enemy.count_)
        print("self.id=",self.id)
        print("Enemy.count=",Enemy.count_)
        if Enemy.count_ >= 50:
            Enemy.count_=0

    def update(self, *args):
        self.rect.x -= self.speed
        if self.rect.right < 0:
            self.kill()


class Explode(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.images = [pygame.image.load('./image/explode' + str(i) + '.png') for i in range(1, 4)]
        self.image_index = 0
        self.image = self.images[self.image_index]
        self.rect = self.image.get_rect()
        self.readt_to_change = 0
        sound = pygame.mixer.Sound('./sound/enemyExplode.wav')
        sound.play()

    def update(self, *args):
        if self.image_index < 2:
            self.readt_to_change += 1
            if self.readt_to_change % 4 == 0:
                self.image_index += 1
                self.image = self.images[self.image_index]
        else:
            self.kill()


class BackGround(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load('./image/background1.jpg')
        self.rect = self.image.get_rect()
        self.ready_to_move = 0
        self.index = 1

    def update(self, *args):
        self.rect.x -= 3
        if self.rect.right <= 0:
            self.index+=1
            self.image = pygame.image.load('./image/background'+str(self.index)+'.jpg')
            self.rect = self.image.get_rect()
            self.rect.x = self.rect.width
            if self.index == 4:
                self.index = 3


# 初始化精灵组
bg_sprite = pygame.sprite.Group()
hero_sprite = pygame.sprite.Group()
enemy_sprite = pygame.sprite.Group()
bullet_sprite = pygame.sprite.Group()
explode_sprite = pygame.sprite.Group()

# 定义人物

hero1 = Hero(4)
hero_sprite.add(hero1)

enemy1 = Enemy(5)
enemy2 = Enemy(7)

bg1 = BackGround()
bg2 = BackGround()
bg2.rect.x = bg2.rect.width
bg_sprite.add(bg1, bg2)

# 保持游戏运行状态(游戏循环)
while True:
    # ===========游戏帧的刷新===========
    clock.tick(FPS)

    # 检测事件
    for event in pygame.event.get():
        # 检测关闭按钮被点击的事件
        if event.type == pygame.QUIT:
            # 退出
            pygame.quit()
            exit()
        if event.type == CREATE_ENEMY:
            enemy_sprite.add(Enemy(random.randint(1, 4)))
        app.event(event)    #将pygame的事件传递给pgu,很重要

    # 碰撞检测,返回字典,得到二者信息
    collision = pygame.sprite.groupcollide(enemy_sprite, bullet_sprite, True, True)
    for enemy in collision.keys():
        explode = Explode()
        explode.rect = enemy.rect
        explode_sprite.add(explode)
        print("enemy.id:"+str(enemy.id))
        score+=1

    # 碰撞检测,返回字典,得到二者信息
    collision1 = pygame.sprite.groupcollide(enemy_sprite, hero_sprite, True, False)
    for enemy in collision1.keys():
        hero1.dired += 1
        quitDlg.open()
        show_image = True
        break
        #explode = Explode()
        #explode.rect = enemy.rect
        #explode_sprite.add(explode)
        #quitDlg.open()
        
    # screen.fill((0,0,0))
    for group in [bg_sprite, hero_sprite, enemy_sprite, bullet_sprite, explode_sprite]:
        group.update()
        group.draw(screen)
    #screen.fill((0,0,0))    #生成一个屏幕  
    score_txt = "得分:"+str(score)
    text_surface = font.render(score_txt, True, (255, 0, 255))
    screen.blit(text_surface, (680, 10)) 
    
    if show_image:
        screen.blit(fail_image, (300, 100))  # 绘制图像
        
    app.paint()
    pygame.display.update()
    #app.paint()             #将pgu容器的内容画出

语音素材制作

一个好玩的游戏肯定少不了精美的图片和声音的制作。这里制作背景图片,从网上精选了一些好看且震撼的宇宙图片作为背景。其它拼音字母则从网上截取好看的彩色的拼音字母。

这里着重说下拼音发音文件的制作,网上几乎很难搜到现成的汉语拼音的单个的wav文件。这里介绍两种办法,一种是找到涵盖所有正规完整拼音字母发音的音频文件,使用goldwave软件进行剪辑,优点是发音标准些,但是剪辑麻烦些,需要从里面去找对应的音频。

还有一种方法是使用科大讯飞的离线语音合成技术合成语音。如输入字母'a' ,让其合成发音。但是我试过了发现竟然是英文。不过还是有办法啦,直接输入a - 阿 o - 哦 e - 额 i - 一 u - 乌对应的汉字即可,合成整个语音,然后再通过goldwave软件裁剪。

const char* text  = "啊,我,额,一,无,与,波,破,摸,佛,的,特,呢,了,个,可,和,及,器,洗,之,吃,时,日,子,此,思,一,无"; //合成文本

比如使用科大讯飞的离线语言合成技术合成上面这么一段话,逗号作为分隔。然后使用goldwave音频裁剪制作工具,对每段音频进行裁剪和保存成拼音字母的wav格式音频文件。然而发音可能因为音调的原因不标准,所以尽量找发音准且音调为一声的字。

我找的发音最接近的如下:

韵母:a, o, e, i, u, ü, ai, ei, ui, ao, ou, iu, ie, üe, er, an, en, in, un, ün, ang, eng, ing, ong

阿,窝,额,一,屋,迂,挨,诶,微,凹,欧,优,页,约,儿,安,恩,音,温,晕,盎,鞥,英,翁

声母:b, p, m, f, d, t, n, l, g, k, h, j, q, x, zh, ch, sh, r, z, c, s ,y,w

播,泼,摸,佛,的,特,呢,嘞,哥,蝌,喝,机,其,西,织,吃,狮,日,资,疵,丝,衣,屋

剪辑也很方便,因为有逗号分隔,以下每个小绿色的波形都是一段发音文件。 

声音合成的c代码:

/*
* 语音合成(Text To Speech,TTS)技术能够自动将任意文字实时转换为连续的
* 自然语音,是一种能够在任何时间、任何地点,向任何人提供语音信息服务的
* 高效便捷手段,非常符合信息时代海量数据、动态更新和个性化查询的需求。
*/

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include "../../include/qtts.h"
#include "../../include/msp_cmn.h"
#include "../../include/msp_errors.h"
typedef int SR_DWORD;
typedef short int SR_WORD ;

/* wav音频头部格式 */
typedef struct _wave_pcm_hdr
{
	char            riff[4];                // = "RIFF"
	int				size_8;                 // = FileSize - 8
	char            wave[4];                // = "WAVE"
	char            fmt[4];                 // = "fmt "
	int				fmt_size;				// = 下一个结构体的大小 : 16

	short int       format_tag;             // = PCM : 1
	short int       channels;               // = 通道数 : 1
	int				samples_per_sec;        // = 采样率 : 8000 | 6000 | 11025 | 16000
	int				avg_bytes_per_sec;      // = 每秒字节数 : samples_per_sec * bits_per_sample / 8
	short int       block_align;            // = 每采样点字节数 : wBitsPerSample / 8
	short int       bits_per_sample;        // = 量化比特数: 8 | 16

	char            data[4];                // = "data";
	int				data_size;              // = 纯数据长度 : FileSize - 44 
} wave_pcm_hdr;

/* 默认wav音频头部数据 */
wave_pcm_hdr default_wav_hdr = 
{
	{ 'R', 'I', 'F', 'F' },
	0,
	{'W', 'A', 'V', 'E'},
	{'f', 'm', 't', ' '},
	16,
	1,
	1,
	16000,
	32000,
	2,
	16,
	{'d', 'a', 't', 'a'},
	0  
};
/* 文本合成 */
int text_to_speech(const char* src_text, const char* des_path, const char* params)
{
	int          ret          = -1;
	FILE*        fp           = NULL;
	const char*  sessionID    = NULL;
	unsigned int audio_len    = 0;
	wave_pcm_hdr wav_hdr      = default_wav_hdr;
	int          synth_status = MSP_TTS_FLAG_STILL_HAVE_DATA;

	if (NULL == src_text || NULL == des_path)
	{
		printf("params is error!\n");
		return ret;
	}
	fp = fopen(des_path, "wb");
	if (NULL == fp)
	{
		printf("open %s error.\n", des_path);
		return ret;
	}
	/* 开始合成 */
	sessionID = QTTSSessionBegin(params, &ret);
	if (MSP_SUCCESS != ret)
	{
		printf("QTTSSessionBegin failed, error code: %d.\n", ret);
		fclose(fp);
		return ret;
	}
	ret = QTTSTextPut(sessionID, src_text, (unsigned int)strlen(src_text), NULL);
	if (MSP_SUCCESS != ret)
	{
		printf("QTTSTextPut failed, error code: %d.\n",ret);
		QTTSSessionEnd(sessionID, "TextPutError");
		fclose(fp);
		return ret;
	}
	printf("正在合成 ...\n");
	fwrite(&wav_hdr, sizeof(wav_hdr) ,1, fp); //添加wav音频头,使用采样率为16000
	while (1) 
	{
		/* 获取合成音频 */
		const void* data = QTTSAudioGet(sessionID, &audio_len, &synth_status, &ret);
		if (MSP_SUCCESS != ret)
			break;
		if (NULL != data)
		{
			fwrite(data, audio_len, 1, fp);
		    wav_hdr.data_size += audio_len; //计算data_size大小
		}
		if (MSP_TTS_FLAG_DATA_END == synth_status)
			break;
	}
	printf("\n");
	if (MSP_SUCCESS != ret)
	{
		printf("QTTSAudioGet failed, error code: %d.\n",ret);
		QTTSSessionEnd(sessionID, "AudioGetError");
		fclose(fp);
		return ret;
	}
	/* 修正wav文件头数据的大小 */
	wav_hdr.size_8 += wav_hdr.data_size + (sizeof(wav_hdr) - 8);
	
	/* 将修正过的数据写回文件头部,音频文件为wav格式 */
	fseek(fp, 4, 0);
	fwrite(&wav_hdr.size_8,sizeof(wav_hdr.size_8), 1, fp); //写入size_8的值
	fseek(fp, 40, 0); //将文件指针偏移到存储data_size值的位置
	fwrite(&wav_hdr.data_size,sizeof(wav_hdr.data_size), 1, fp); //写入data_size的值
	fclose(fp);
	fp = NULL;
	/* 合成完毕 */
	ret = QTTSSessionEnd(sessionID, "Normal");
	if (MSP_SUCCESS != ret)
	{
		printf("QTTSSessionEnd failed, error code: %d.\n",ret);
	}

	return ret;
}

int main(int argc, char* argv[])
{
	int         ret                  = MSP_SUCCESS;
	const char* login_params         = "appid = 99999, work_dir = .";//登录参数,appid与msc库绑定,请勿随意改动
	/*
	* rdn:           合成音频数字发音方式
	* volume:        合成音频的音量
	* pitch:         合成音频的音调
	* speed:         合成音频对应的语速
	* voice_name:    合成发音人
	* sample_rate:   合成音频采样率
	* text_encoding: 合成文本编码格式
	*
	*/
	const char* session_begin_params = "engine_type = local,voice_name=xiaoyan, text_encoding = UTF8, tts_res_path = fo|res/tts/xiaoyan.jet;fo|res/tts/common.jet, sample_rate = 16000, speed = 50, volume = 50, pitch = 50, rdn = 2";
	const char* filename             = "tts_sample.wav"; //合成的语音文件名称
	const char* text                 = "啊,我,额,一,无,与,波,破,摸,佛,的,特,呢,了,个,可,和,及,器,洗,之,吃,时,日,子,此,思,一,无"; //合成文本
	/* 用户登录 */
	ret = MSPLogin(NULL, NULL, login_params); //第一个参数是用户名,第二个参数是密码,第三个参数是登录参数,用户名和密码可在http://www.xfyun.cn注册获取
	if (MSP_SUCCESS != ret)
	{
		printf("MSPLogin failed, error code: %d.\n", ret);
		goto exit ;//登录失败,退出登录
	}

	printf("\n###########################################################################\n");
	printf("###########################################################################\n\n");

	/* 文本合成 */
	printf("开始合成 ...\n");
	ret = text_to_speech(text, filename, session_begin_params);
	if (MSP_SUCCESS != ret)
	{
		printf("text_to_speech failed, error code: %d.\n", ret);
	}
	printf("合成完毕\n");

exit:
	printf("按任意键退出 ...\n");
	getchar();
	MSPLogout(); //退出登录

	return 0;
}

对应的makefile文件:

#common makefile header

DIR_INC = ../../include
DIR_BIN = ../../bin
DIR_LIB = ../../libs

TARGET	= tts_offline_sample
BIN_TARGET = $(DIR_BIN)/$(TARGET)

CROSS_COMPILE = 
CFLAGS = -g -Wall -I$(DIR_INC)

ifdef LINUX64
LDFLAGS := -L$(DIR_LIB)/x64
else
LDFLAGS := -L$(DIR_LIB)/x86 
endif
LDFLAGS += -lmsc -lrt -ldl -lpthread -lstdc++

OBJECTS := $(patsubst %.c,%.o,$(wildcard *.c))

$(BIN_TARGET) : $(OBJECTS)
	$(CROSS_COMPILE)gcc $(CFLAGS) $^ -o $@ $(LDFLAGS)

%.o : %.c
	$(CROSS_COMPILE)gcc -c $(CFLAGS) $< -o $@
clean:
	@rm -f *.o $(BIN_TARGET)

.PHONY:clean

#common makefile foot

Pygame开发游戏过程总结

以下是一般的使用流程:

1. 设置Pygame:使用pip安装Pygame库,并在Python脚本中导入它。

2. 初始化Pygame:使用 pygame.init() 初始化Pygame模块。

3. 设置游戏窗口:使用 pygame.display.set_mode() 创建游戏窗口。设置窗口大小、标题和其他属性。

4. 游戏循环:创建一个循环来持续运行游戏。该循环处理用户输入、更新游戏逻辑和渲染游戏图形。

5. 处理事件:在游戏循环内部,使用 pygame.event.get() 处理各种事件,如键盘或鼠标输入。根据游戏的需求响应这些事件。

6. 更新游戏状态:根据用户输入和其他因素更新游戏状态。包括移动游戏对象、检测碰撞、更新得分等。

7. 渲染图形:使用 pygame.Surfacepygame.draw 函数将游戏图形渲染到游戏窗口上。包括绘制游戏对象、背景、文本和其他可视元素。

8. 显示更新:使用 pygame.display.flip()pygame.display.update() 更新游戏窗口,显示当前帧的变化。

9. 游戏逻辑:实现特定于游戏的逻辑、规则和机制。这可能包括关卡、得分、道具、敌人AI等。

10. 退出游戏:处理游戏退出事件,并使用 pygame.quit() 清理资源。

以下是一个简单的Pygame游戏示例,显示一个窗口和一个移动的角色:

import pygame
from pygame.locals import *

# 初始化Pygame
pygame.init()

# 设置游戏窗口
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption('我的游戏')

# 游戏循环
running = True
while running:
    # 处理事件
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False

    # 更新游戏状态

    # 渲染图形
    screen.fill((0, 0, 0))  # 用黑色填充屏幕
    pygame.draw.rect(screen, (255, 0, 0), (100, 100, 50, 50))  # 在(100, 100)处绘制一个红色矩形

    # 显示更新
    pygame.display.flip()

# 退出游戏
pygame.quit()

最后,需要完整可运行程序的,请在首页添加作者微信或者关注公众号留言索取。

其他资源

python+pygame游戏开发之使用Py2exe打包游戏-腾讯云开发者社区-腾讯云

百度安全验证

python模块打包成.exe文件过程 详解 - 知乎

6种打包Python代码的方法,让你的程序变成exe应用!_python打包exe_JPX-NO的博客-CSDN博客

pip国内镜像源-Python安装第三方库(一篇足以、都是干货) - 知乎

python--pygame实现各级菜单栏目设置_pygame 下拉菜单_DY.work的博客-CSDN博客

python玄阶斗技--tkinter库_马骁尧的博客-CSDN博客

python常用第三方库总结 - 知乎

GitHub - ppizarror/pygame-menu: A menu for pygame (pygame-ce also supported!). Simple, and easy to use

Python pygame(GUI编程)模块最完整教程(1)_pygame模块详解_Python-ZZY的博客-CSDN博客

Pygame教程(非常详细)

Python中星号*和**的含义-CSDN博客

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pygame小游戏之飞机拼音大作战( 送给娃学拼音的礼物,星际旅行) 的相关文章

  • 从 Django 调用 Postgres SQL 存储过程

    我正在开发一个带有 Postgresql 数据库的 Django 项目 我编写了一个可以在 Postgres 上完美运行的存储过程 现在我想从 Django 1 5 调用该存储过程 我已经编写了代码 但它提示错误 CREATE FUNCTI
  • 如何覆盖 Django 的默认管理模板和布局

    我正在尝试覆盖 Django 的默认模板 现在只有base site html 我正在尝试更改 django 管理文本 我做了以下事情 我在我的应用程序目录中创建了一个文件夹 opt mydjangoapp templates admin
  • 将 transaction.commit_manually() 升级到 Django > 1.6

    我继承了为 Django 1 4 编写的应用程序的一些代码 我们需要更新代码库以使用 Django 1 7 并最终更新到 1 8 作为下一个长期支持版本 在一些地方它使用旧风格 transaction commit manually and
  • 在 Pandas 中,如何从基于另一个数据框的数据框中删除行?

    我有 2 个数据框 一个名为 USERS 另一个名为 EXCLUDE 他们都有一个名为 电子邮件 的字段 基本上 我想删除 USERS 中包含 EXCLUDE 中包含电子邮件的每一行 我该怎么做 您可以使用boolean indexing
  • 如何在 Jupyter Notebook 中运行 Python 异步代码?

    我有一些 asyncio 代码在 Python 解释器 CPython 3 6 2 中运行良好 我现在想在具有 IPython 内核的 Jupyter 笔记本中运行它 我可以运行它 import asyncio asyncio get ev
  • ctypes 错误:libdc1394 错误:无法初始化 libdc1394

    我正在尝试将程序编译为共享库 我可以使用 ctypes 在 Python 代码中使用该库 使用以下命令该库可以正常编译 g shared Wl soname mylib O3 o mylib so fPIC files pkg config
  • 在Python中如何获取字典的部分视图?

    是否有可能获得部分视图dict在Python中类似于pandasdf tail df head 说你有很长一段时间dict 而您只想检查某些元素 开头 结尾等 dict 就像是 dict head 3 To see the first 3
  • 更改 x 轴比例

    我使用 Matlab 创建了这个图 使用 matplotlib x 轴绘制大数字 例如 100000 200000 300000 我想要 1 2 3 和 10 5 之类的值来指示它实际上是 100000 200000 300000 有没有一
  • 编辑 Jupyter Notebook 时 VS Code 中缺少“在选择中查找”

    使用 Jupyter Notebook 时 VSCode 中缺少 在选择中查找 按钮 它会减慢开发速度 所以我想请问有人知道如何激活它吗 第一张图显示了在 python 文件中的搜索 替换 第二张图显示了笔记本电脑中缺少的按钮 Python
  • 如何使用 javascript/jquery/AJAX 调用 Django REST API?

    我想使用 Javascript jQuery AJAX 在前端调用 Django Rest API 请求方法是 POST 但当我看到 API 调用它的调用 OPTIONS 方法时 所以 我开始了解access control allow o
  • 如何在 Django 中使用基于类的视图创建注册视图?

    当我开始使用 Django 时 我几乎使用 FBV 基于函数的视图 来处理所有事情 包括注册新用户 但当我更深入地研究项目时 我意识到基于类的视图通常更适合大型项目 因为它们更干净且可维护 但这并不是说 FBV 不是 无论如何 我将整个项目
  • Pandas 堆积条形图中元素的排序

    我正在尝试绘制有关某个地区 5 个地区的家庭在特定行业赚取的收入比例的信息 我使用 groupby 按地区对数据框中的信息进行排序 df df orig groupby District Portion of income value co
  • GradientTape 根据损失函数是否被 tf.function 修饰给出不同的梯度

    我发现计算的梯度取决于 tf function 装饰器的相互作用 如下所示 首先 我为二元分类创建一些合成数据 tf random set seed 42 np random seed 42 x tf random normal 2 1 y
  • `pyqt5'错误`元数据生成失败`

    我正在尝试安装pyqt5使用带有 M1 芯片和 Python 3 9 12 的 mac 操作系统 我怀疑M1芯片可能是原因 我收到一个错误metadata generation failed 最小工作示例 directly in the t
  • 使用 NLP 进行地址分割

    我目前正在开发一个项目 该项目应识别地址的每个部分 例如来自 str Jack London 121 Corvallis ARAD ap 1603 973130 输出应如下所示 street name Jack London no 121
  • Flask 应用程序的测试覆盖率不起作用

    您好 想在终端的 Flask 应用程序中测试 删除路由 我可以看到测试已经过去 它说 test user delete test app LayoutTestCase ok 但是当我打开封面时 它仍然是红色的 这意味着没有覆盖它 请有人向我
  • 导入错误:无法导入名称“时间戳”

    我使用以下代码在 python 3 6 3 中成功安装了 ggplot conda install c conda forge ggplot 但是当我使用下面的代码将其导入笔记本时 出现错误 from ggplot import Impor
  • Python问题:打开和关闭文件返回语法错误

    大家好 我发现了这个有用的 python 脚本 它允许我从网站获取一些天气数据 我将创建一个文件和其中的数据集 有些东西不起作用 它返回此错误 File
  • python 日志记录会刷新每个日志吗?

    当我使用标准模块将日志写入文件时logging 每个日志会分别刷新到磁盘吗 例如 下面的代码会将日志刷新 10 次吗 logging basicConfig level logging DEBUG filename debug log fo
  • 使用Multiprocessing和Pool时如何访问全局变量?

    我试图避免将变量冗余地传递到dataList e g 1 globalDict 2 globalDict 3 globalDict 并在全球范围内使用它们 global globalDict然而 在下面的代码中并不是这样做的解决方案 是否有

随机推荐

  • paramiko sftp 问题记录

    paramiko 是一款非常优秀得远程ssh库 能够ssh远程到主机 并执行命令 而且还能通过sftp连接主机 笔者得测试环境 因为安全关系 ssh默认端口修改成其他端口 再往上查阅资料 连接sftp 代码 t paramiko Trans
  • 坐标移动c语言,C语言 坐标移动详解及实例代码

    搜索热词 题目描述 开发一个坐标计算工具 A表示向左移动 D表示向右移动 W表示向上移动 S表示向下移动 从 0 0 点开始移动 从输入字符串里面读取一些坐标 并将最终输入结果输出到输出文件里面 输入 合法坐标为A 或者D或者W或者S 数字
  • 【狂神说】Mybatis学习笔记(全)

    文章目录 前言 1 简介 1 1 什么是MyBatis 1 2 如何获得Mybatis 1 3 持久化 1 3 1 数据持久化 1 3 2 为什么需要持久化 1 4 持久层 1 5 为什么需要MyBatis 2 第一个Mybatis程序 2
  • 《IT项目管理》-大题&计算题保分秘籍

    经过今天的努力 已经把大部分大题和计算题全部总结完了 希望对你们有用 查看链接自取 百度网盘 APP即可获取 链接 https pan baidu com s 1U0EFY23KgTtM8lKlYnjrug pwd tehx 提取码 teh
  • 软考-嵌入式系统设计师-笔记:历年专业英语题

    文章目录 2020年 2019年 2018年 2017年 2016年 2015年 2014年 2013年 2020年 题目 加粗的为各题答案 Fog computing is a mid layer between cloud data c
  • deepIn 、 DDE 系统桌面黑屏解决方案

    桌面黑屏有两种情况 1 桌面除了底部菜单栏 其它全是黑的 解决方案 Deepin sudo apt install reinstall dde DDE sudo apt fix broken install sudo apt install
  • 基于SpringBoot和vue的若依后台管理系统 部署

    RuoYi Vue是一款前后端分离的极速后台开发框架 基于SpringBoot和Vue 目录 一 准备 二 启动前端项目 解决报错 digital envelope routines unsupported 测试 三 启动后端项目 四 运行
  • 8个适合新手的Python小项目

    这是我挑出来的8个适合新手的小项目 涉及了爬虫 多线程 selenium PhantomJs itchat 邮件发送 crontab 命令行颜色显示 excel操作 PIL 识别验证码 首先说明 天下没有免费的午餐 每个项目平均下来2元多一
  • 根据子网掩码算出 IP 地址 的网络号和主机号

    我们如何根据子网掩码算出 IP 地址 的网络号和主机号呢 举个例子 比如 10 100 122 0 24 后面的 24表示就是 255 255 255 0 子网掩码 255 255 255 0 二进制是 11111111 11111111
  • Ant design Pro V5 +Typescript + Hooks + Umi + Dev + SpringBoot + mysql + redis + scrity 实现动态菜单权限管理

    Ant design Pro V5 Typescript Hooks Umi Dev SpringBoot mysql redis scrity 实现动态菜单权限管理 企业中台架构 1 app tsx页面配置 该页面集成了登陆权限控制 动态
  • Android实战系列(三)---级联菜单

    需求A 一级菜单 多级菜单联动 1 在activity上弹出多个pop窗口 达到父菜单与子菜单级联的效果 2 多个Activity页面相互的嵌套实现多级菜单 考虑 传值 数据结构的定义 之前在用前端写Android构造级联菜单出现过标题栏不
  • 算法系列15天速成——第八天 线性表【下】

    一 线性表的简单回顾 上一篇跟大家聊过 线性表 顺序存储 通过实验 大家也知道 如果我每次向 顺序表的头部插入元素 都会引起痉挛 效率比较低下 第二点我们用顺序存储时 容 易受到长度的限制 反之就会造成空间资源的浪费 二 链表 对于顺序表存
  • Finetuner+:为企业实现大模型微调和私有化部署

    如 ChatGPT GPT4 这样的大型语言模型就像是你为公司请的一个牛人顾问 他在 OpenAI Google 等大公司被预训练了不少的行业内专业知识 所以加入你的公司后 你只需要输入 Prompt 给他 介绍一些业务上的背景知识 他就能
  • 2021-01-08

    问题 F 有序数组中插入元素 时间限制 1 Sec 内存限制 128 MB 提交 2116 解决 967 提交 状态 讨论版 题目描述 输入n n lt 20 输入n个有序整数 降序或升序 插入元素e 使新序列仍按原来的排序规则为有序序列
  • 【Java】Java中的String类

    文章目录 一 认识 String 类 二 String 类的常用方法 2 1 构造方法 2 2 String 类对象之间的比较 2 3 字符串查找 2 4 字符串的转换 2 5 字符串替换 2 6 字符串拆分 2 7 字符串截取 2 8 字
  • Java语言 ASCII to Hex 互转(IOT-示例)

    概述 最近想起之前做的IOT项目 使用JAVA写了一个
  • libcurl交叉编译支持https

    简介 libcurl是一个跨平台的网络协议库 支持dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
  • Android Ble 连接设备失败 onConnectionStateChange status 返回133

    Android Ble 连接设备失败时回调函数 onConnectionStateChange status 返回133 开始找问题 各种mac地址 权限 线程 找了个遍 结果就是返回纹丝不动 又因为 mBluetoothGatt mBlu
  • BUUCTF [极客大挑战 2019]Knife

    打开一看结合题目 就是连接一下菜刀蚁剑 菜刀没用过只有蚁剑 下面用蚁剑实现 设置好URL和链接密码 找到flag文件 打开后找到flag 文件上传漏洞 一句话木马 php Asp Aspx 前端判断文件后缀名可以Burp Suite配置好P
  • pygame小游戏之飞机拼音大作战( 送给娃学拼音的礼物,星际旅行)

    二娃再过一年就该上一年级了 但现阶段的拼音咋都学不进去 买了拼音挂图贴在墙上 拉都拉不到旁边 突发奇想 何不用python的pygame做个小游戏 在玩中也能学习 让学变得有趣 这对搞编程的来说小菜一碟 于是说干就干 两个晚上就成型啦 这里