您的位置:首页 > 编程语言 > Python开发

使用_Python_和_Asyncio_编写在线多用人游戏(二)

2017-06-09 13:50 309 查看


摘要: 你在 Python 中用过异步编程吗?本文中我会告诉你怎样做,而且用一个能工作的例子来展示它:这是一个流行的贪吃蛇游戏,而且是为多人游戏而设计的。 介绍和理论部分参见“第一部分 异步化”。 游戏入口在此,点此体验。

你在 Python 中用过异步编程吗?本文中我会告诉你怎样做,而且用一个能工作的例子来展示它:这是一个流行的贪吃蛇游戏,而且是为多人游戏而设计的。

介绍和理论部分参见“第一部分
异步化”。
游戏入口在此,点此体验。






3、编写游戏循环主体

游戏循环是每一个游戏的核心。它持续地运行以读取玩家的输入、更新游戏的状态,并且在屏幕上渲染游戏结果。在在线游戏中,游戏循环分为客户端和服务端两部分,所以一般有两个循环通过网络通信。通常客户端的角色是获取玩家输入,比如按键或者鼠标移动,将数据传输给服务端,然后接收需要渲染的数据。服务端处理来自玩家的所有数据,更新游戏的状态,执行渲染下一帧的必要计算,然后将结果传回客户端,例如游戏中对象的新位置。如果没有可靠的理由,不混淆客户端和服务端的角色是一件很重要的事。如果你在客户端执行游戏逻辑的计算,很容易就会和其它客户端失去同步,其实你的游戏也可以通过简单地传递客户端的数据来创建。

游戏循环的一次迭代称为一个嘀嗒tick。嘀嗒是一个事件,表示当前游戏循环的迭代已经结束,下一帧(或者多帧)的数据已经就绪。

在后面的例子中,我们使用相同的客户端,它使用 WebSocket 从一个网页上连接到服务端。它执行一个简单的循环,将按键码发送给服务端,并显示来自服务端的所有信息。客户端代码戳这里。


例子 3.1:基本游戏循环

例子
3.1 源码。

我们使用 aiohttp 库来创建游戏服务器。它可以通过
asyncio 创建网页服务器和客户端。这个库的一个优势是它同时支持普通 http 请求和 websocket。所以我们不用其他网页服务器来渲染游戏的 html 页面。

下面是启动服务器的方法:


app = web.Application()


app["sockets"] = []




asyncio.ensure_future(game_loop(app))




app.router.add_route('GET', '/connect', wshandler)


app.router.add_route('GET', '/', handle)




web.run_app(app)


web.run_app
 是创建服务主任务的快捷方法,通过它的 
run_forever()
 方法来执行 
asyncio
 事件循环。建议你查看这个方法的源码,弄清楚服务器到底是如何创建和结束的。


app
 变量就是一个类似于字典的对象,它用于在所连接的客户端之间共享数据。我们使用它来存储连接的套接字的列表。随后会用这个列表来给所有连接的客户端发送消息。
asyncio.ensure_future()
 调用会启动主游戏循环的任务,每隔2
秒向客户端发送嘀嗒消息。这个任务会在同样的 asyncio 事件循环中和网页服务器并行执行。

有两个网页请求处理器:
handle
 是提供
html 页面的处理器;
wshandler
 是主要的 websocket 服务器任务,处理和客户端之间的交互。在事件循环中,每一个连接的客户端都会创建一个新的 
wshandler
 任务。这个任务会添加客户端的套接字到列表中,以便 
game_loop
 任务可以给所有的客户端发送消息。然后它将随同消息回显客户端的每个击键。

在启动的任务中,我们在 
asyncio
 的主事件循环中启动
worker 循环。任务之间的切换发生在它们之间任何一个使用 
await
语句来等待某个协程结束时。例如 
asyncio.sleep
 仅仅是将程序执行权交给调度器一段指定的时间;
ws.receive
 等待
websocket 的消息,此时调度器可能切换到其它任务。

在浏览器中打开主页,连接上服务器后,试试随便按下键。它们的键值会从服务端返回,每隔 2 秒这个数字会被游戏循环中发给所有客户端的嘀嗒消息所覆盖。

我们刚刚创建了一个处理客户端按键的服务器,主游戏循环在后台做一些处理,周期性地同时更新所有的客户端。
原文链接



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: