翼度科技»论坛 编程开发 python 查看内容

wasm+pygbag让你在网页上也能运行Python代码:【贪吃蛇游戏】

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
引言

最近小伙伴告诉我一种新的方法,可以使用wasm来使浏览器网页能够运行Python代码。这一下子激起了我的兴趣,因为这意味着用户无需安装Python环境就能直接运行我的demo,这真是太方便了。所以,我们的主要目标今天就是让网页能够直接运行我的贪吃蛇游戏。贪吃蛇游戏其实很简单,因为Python有一个很棒的pygame库可以供我们使用。所以编写起来也不会太复杂。废话不多说,让我们开始吧。
何为wasm

全称为WebAssembly ,简称为Wasm,是一种能够在web上加载非常快速的一种格式。它可以被视为HTML、JS等其他表达形式的一种补充。对于我来说,这就是它的简单定义。然而,我们今天的任务并不是去介绍Wasm,而是探讨如何实现Python在web中直接运行的方法。
当然有兴趣的同学可以直接去看官方网站:https://webassembly.org/
emscripten

我们现在已经了解到,WebAssembly可以在web上运行,但我想知道如何将我的Python代码转换成WebAssembly。当然,肯定有相应的工具可供使用。在网上,最常被提及的工具就是emscripten,可以说是WebAssembly的核心工具。它的主要功能是将其他高级语言编译成WebAssembly。然而,我在本地尝试过后发现,emscripten无法直接将Python代码转换成WebAssembly格式。你需要使用其他工具先将Python转换成其他高级语言如C语言,然后再使用emscripten将其转换成WebAssembly。如果你知道其他更好的方法,可以在下方提出来,非常感谢。
我就不实验了,毕竟后台报错,如果你有兴趣可以看看emscripten官方网站:https://emscripten.org/
在网站的顶部导航栏中,找到并点击 "Get Started"(开始使用)。
pyodide

如果你尝试过在Web上运行Python代码,那你肯定了解到pyodide方案,它确实是一个功能强大的工具。然而,它也存在明显的缺点,例如它所支持的第三方库非常有限,而且加载速度也很慢。尽管如此,它仍然是最便捷的选择,因为你可以直接在HTML中编写代码,而不需要额外的工具。唯一需要注意的是需要引用它的JavaScript文件。test.html代码示例如下:
  1. [/code]对于我们来说,使用pyodide是相对简单的。只需点击文件后,浏览器就能正常运行其中的Python代码。但是要直接使用Python的pygame库是不可能的。不过,一些简单的代码还是可以运行的。那么,是否还有其他解决方案呢?答案是肯定的。
  2. [align=center][/align]
  3. [size=5]pygbag[/size]
  4. 开发人员在寻找解决方案时,最好的资源就是Github了。几乎所有开源的代码仓库都可以在那里找到,只要你能想到的,几乎都能找到。我也是通过搜索找到了一个解决方案,真的有一个开源的第三方库叫做pygbag。虽然这个库很新,但它是由Python官方支持的。只是要依靠官方文档和浏览器去寻找示例代码。连gpt这样的人工智能模型都不知道有这么一个东西存在。此外,pygbag专门集成了pygame,可以直接将Python代码编译成wasm,在浏览器中运行。它还有官方开发人员制作的游戏可供参考,当然如果你也制作了游戏,也可以上传到这里。
  5. 官方Github地址:[url=https://github.com/pygame-web/pygbag]https://github.com/pygame-web/pygbag[/url]
  6. 官方游戏首页:[url=https://itch.io/games/tag-roguelike]https://itch.io/games/tag-roguelike[/url]
  7. 他的宗旨也很简单:Python WebAssembly for everyone ( packager + test server ),但是他也有一些编码要求,我们先来实现一个贪吃蛇游戏吧。
  8. [size=6]贪吃蛇游戏[/size]
  9. 在开始使用pygbag三方库之前,我们需要确保已经在本地实现了贪吃蛇游戏。现在,请跟着我一起按照以下步骤进行操作。
  10. [size=5]安装 Pygame[/size]
  11. 命令如下:pip install pygame
  12. Pygame是一套专门用于编写游戏的Python模组,它在SDL库的基础上添加了各种游戏功能的实现。借助Python语言的灵活性,你可以快速、轻松地创建各种类型的游戏。正如之前所提到的,Python拥有丰富的库和模组,我们只需直接使用它们,而不必重复造轮子。
  13. 我已经为你写好了贪吃蛇游戏的代码,你可以直接使用。这是一个大家都很熟悉的游戏,所以没有太多需要解释的。
  14. [code]import pygame
  15. import random
  16. pygame.init()
  17. screen = pygame.display.set_mode((1280, 720))
  18. clock = pygame.time.Clock()
  19. running = True
  20. dt = 0
  21. player_pos = [pygame.Vector2(screen.get_width() / 2, screen.get_height() / 2)]
  22. player_speed = 300
  23. player_radius = 30
  24. food_pos = pygame.Vector2(random.randint(0, screen.get_width()), random.randint(0, screen.get_height()))
  25. food_radius = 15
  26. direction = pygame.Vector2(0, 0)
  27. while running:
  28.     for event in pygame.event.get():
  29.         if event.type == pygame.QUIT:
  30.             running = False
  31.     screen.fill("black")
  32.     keys = pygame.key.get_pressed()
  33.     if keys[pygame.K_w] or keys[pygame.K_UP]:
  34.         direction = pygame.Vector2(0, -1)
  35.     if keys[pygame.K_s] or keys[pygame.K_DOWN]:
  36.         direction = pygame.Vector2(0, 1)
  37.     if keys[pygame.K_a] or keys[pygame.K_LEFT]:
  38.         direction = pygame.Vector2(-1, 0)
  39.     if keys[pygame.K_d] or keys[pygame.K_RIGHT]:
  40.         direction = pygame.Vector2(1, 0)
  41.     # Move the player's head
  42.     player_pos[0] += direction * player_speed * dt
  43.     # Check if player eats the food
  44.     if player_pos[0].distance_to(food_pos) < player_radius + food_radius:
  45.         player_pos.append(player_pos[-1].copy())  # Add new segment to the player
  46.         food_pos = pygame.Vector2(random.randint(0, screen.get_width()), random.randint(0, screen.get_height()))  # Generate new food
  47.     # Move the player's body
  48.     for i in range(len(player_pos)-1, 0, -1):
  49.         player_pos[i] = player_pos[i-1].copy()
  50.     pygame.draw.circle(screen, "white", food_pos, food_radius)  # Draw the food
  51.     for pos in player_pos:
  52.         pygame.draw.circle(screen, "red", pos, player_radius)  # Draw the player
  53.     pygame.display.flip()
  54.     dt = clock.tick(60) / 1000
  55. pygame.quit()
复制代码
启动命令就是python main.py。运行效果如下:我想要说明的是,我只是简单地实现了一下,并没有进行太多的校验。另外,值得注意的是,尽管我吃完食物后,并没有在身体上感受到太大的变化,但当我吃了很多食物之后,你就可以看到明显的变化了。

pygbag改造

使用 pygbag 将 pygame 制作的游戏打包,使游戏可在浏览器中直接运行。 pygbag 的使用可参考 Pygbag Wiki。官方文档:https://pygame-web.github.io/
使用 pip 安装 pygbag:pip install pygbag
使用 pygbag 打包游戏前,待打包的目录下的游戏代码文件须名为 main.py。 然后仅需对游戏代码做简易修改,修改后代码如下:
  1. import pygame
  2. import random
  3. import asyncio
  4. pygame.init()
  5. screen = pygame.display.set_mode((1280, 720))
  6. clock = pygame.time.Clock()
  7. running = True
  8. dt = 0
  9. player_pos = [pygame.Vector2(screen.get_width() / 2, screen.get_height() / 2)]
  10. player_speed = 300
  11. player_radius = 30
  12. food_pos = pygame.Vector2(random.randint(0, screen.get_width()), random.randint(0, screen.get_height()))
  13. food_radius = 15
  14. direction = pygame.Vector2(0, 0)
  15. async def main():
  16.     global screen, clock, running, dt ,player_pos ,player_speed,player_radius,food_pos,food_radius,direction
  17.     while running:
  18.         for event in pygame.event.get():
  19.             if event.type == pygame.QUIT:
  20.                 running = False
  21.         screen.fill("black")
  22.         keys = pygame.key.get_pressed()
  23.         if keys[pygame.K_w] or keys[pygame.K_UP]:
  24.             direction = pygame.Vector2(0, -1)
  25.         if keys[pygame.K_s] or keys[pygame.K_DOWN]:
  26.             direction = pygame.Vector2(0, 1)
  27.         if keys[pygame.K_a] or keys[pygame.K_LEFT]:
  28.             direction = pygame.Vector2(-1, 0)
  29.         if keys[pygame.K_d] or keys[pygame.K_RIGHT]:
  30.             direction = pygame.Vector2(1, 0)
  31.         # Move the player's head
  32.         player_pos[0] += direction * player_speed * dt
  33.         # Check if player eats the food
  34.         if player_pos[0].distance_to(food_pos) < player_radius + food_radius:
  35.             player_pos.append(player_pos[-1].copy())  # Add new segment to the player
  36.             food_pos = pygame.Vector2(random.randint(0, screen.get_width()), random.randint(0, screen.get_height()))  # Generate new food
  37.         # Move the player's body
  38.         for i in range(len(player_pos)-1, 0, -1):
  39.             player_pos[i] = player_pos[i-1].copy()
  40.         pygame.draw.circle(screen, "white", food_pos, food_radius)  # Draw the food
  41.         for pos in player_pos:
  42.             pygame.draw.circle(screen, "red", pos, player_radius)  # Draw the player
  43.         pygame.display.flip()
  44.         dt = clock.tick(60) / 1000
  45.         await asyncio.sleep(0)
  46.     pygame.quit()
  47. if __name__ == '__main__':
  48.         # 使用 asyncio.run() 调用主函数 main()
  49.         asyncio.run(main())
复制代码
可以看到,基本上必须引入另一个包:导入 asyncio。剩下的就没啥了。我们再来启动下。
启动命令需要修改下:python -m pygbag pyGame,这里注意下,pygbag打包的是整个目录,所以不能像Python那样启动,所以我基本上都是回退到父级目录后,在进行终端控制台打包。命令会直接在本地启动游戏服务。你稍等片刻。

然后直接字啊浏览器查看URL地址:http://localhost:8000/,仍然是稍等片刻,让他加载一下。这时候,你就可以看到浏览器的游戏界面了,如下:

总结

经过努力,我成功完成了任务。如果你有兴趣,也可以将你的游戏上传到官方网站,但作为示例,我并不打算上传。不过,我已经提供了源代码给你,所以你可以直接复制粘贴并运行它。虽然Python现在可以直接在web端使用,但我个人不太喜欢这种方式。

来源:https://www.cnblogs.com/guoxiaoyu/p/17943276
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具