热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

二郎蛇

通过布鲁霍贝纳维德斯免责声明自我支撑……漫长的帖子即将到来。我花了很长时间写这篇博客文章,主要原因是它涵盖了许多不同的主题。这将是关于的博客文章黑客马拉松TDD游戏开

通过布鲁霍·贝纳维德斯

免责声明

自我支撑……漫长的帖子即将到来。

我花了很长时间写这篇博客文章,主要原因是它涵盖了许多不同的主题。 这将是关于的博客文章

  • 黑客马拉松
  • TDD
  • 游戏开发
  • 功能语言中的数据类型抽象
  • Erlang
  • 位串语法
  • RESTful API
  • 多种工具,例如牛仔,混合器,步道,大摇大摆,拉塞等。

历史

很久以前,当我还是个孩子的时候,我就开始用QBasic编程,而且,众所周知,QBasic附带了两个小游戏。 其中之一就是半字节

快进了25年……您会在Erlang Solutions找到我,试图在Roberto Romero和HernánRivas Acosta的帮助下为我们的下一次黑客马拉松提出主题。 我们想要一个可以在单个屏幕上观看的多人游戏。 当然我们想出了 !

黑客马拉松

每年在Erlang Solutions,我们都会从项目中休假一天,我们将所有的时间花在庆祝我们最爱的项目上: 编程 。 2014年,我们举办了“一日构建您的应用”竞赛,并取得了不错的成绩。 对于2015年的版本,我们决定推出一款多人游戏,由组织者设置服务器,然后由团队开发客户。 我将在本博文的其余部分中显示的代码全部来自Hernán,Roberto和我自己开发的游戏服务器。

目标

的主要目标当然是用于Hackathon。 但是我也有一个隐藏的议程:由于该项目将在github上开源,因此我想以此为例来说明我们的工作方式。 我希望能够使人们了解IRC,erlang问题,reddit,stackoverflow等问题,并提出诸如“嘿! 您如何在Erlang中建立网络服务器?” 告诉他们“看看这里。 这就是您的做法!”。 考虑到这一点,我们面对这个项目就好像它是一个客户项目一样,事实证明,我们的客户 (我们的开发人员)实际上是我们遇到过的最艰难的客户之一。

建筑

那么,我们如何为蛇游戏构建多人服务器? 我们首先将其分为3个主要部分:

  • 一个显示游戏进度的网页。
  • 提供网页并提供RESTful API以便实时更新的Web服务器。
  • 一个游戏服务器,它为客户端提供了连接方法。

对于网页,我们使用纯HTML和一些Javascript(至少可以告诉我,这对我来说不是很有趣:P)。 有趣的 实时的一部分。 我们在SSE上实现了该功能(通常如此)。 在游戏中,网站看起来像这样:

从服务器的角度来看,我们使用Cowboy on Trails实现了RESTful API,并使用swagger对其进行了文档记录。 最终看起来像这样:

另一方面,我们决定为客户开发人员提供2个选择。 他们可以只使用相同的RESTful API和SSE连接与服务器进行通信,也可以使用我们的HDP协议。

HDP是运行在UDP上的快速协议。 它由Hernán开发,并以kafka风格记录下来,供所有人使用。 它专门用于蛇,但可以轻松地在其他项目中复制。

内部架构

在内部,正如您在github上看到的那样,代码分为多个文件夹和多个模块,我们可以分别对其进行测试。

一方面,我们拥有游戏的基本构建块:规则(在spts_core )被实现为每个游戏及其实体(表示为Data TypesModels ,每个都有其自己的模块和不透明类型)的gen_fsm 。 您可以在spts_serpents看到我们的方法:

%%% @doc Serpent model
-module(spts_serpents).
-author('elbrujohalcon@inaka.net').

-type status() :: alive | dead.
-type name() :: binary().
-opaque serpent() ::
#{ name => name()
, numeric_id => pos_integer()
, token => binary()
, body => [spts_games:position()]
, direction => spts_games:direction()
, food => pos_integer()
, status => status()
}.
-export_type([serpent/0, status/0, name/0]).

-export([new/6]).
-export([ name/1
, numeric_id/1
, direction/1
, direction/2
, to_json/1
, to_json/2
, to_binary/2
% ...
]).

-spec name(serpent()) -> name().
name(#{name := Name}) -> Name.

-spec direction(
serpent(), spts_games:direction()) ->
serpent().
direction(Serpent, Direction) ->
Serpent#{direction := Direction}.

% ...

我们还为API的不同端点提供了多个牛仔处理程序。 所有这些都是使用混合器构建的,以“继承”来自spts_base_handler功能。

%%% @doc /games/:game_id/serpents handler
-module(spts_serpents_handler).
-author('elbrujohalcon@inaka.net').

-include_lib("mixer/include/mixer.hrl").
-mixin([{ spts_base_handler
, [ init/3
, rest_init/2
, allowed_methods/2
, content_types_accepted/2
, content_types_provided/2
, resource_exists/2
]
}]).

-export([ handle_post/2
, trails/0
]).

-type state() :: spts_base_handler:state().

-behaviour(trails_handler).

-spec trails() -> trails:trails().
trails() ->
Metadata =
#{ post =>
#{ tags => ["serpents"]
, description =>
"Adds a serpent to a game"
, consumes => ["application/json"]
, produces => ["application/json"]
, parameters =>
[ spts_web:param(request_body)
, spts_web:param(game_id)
]
}
},
Path = "/api/games/:game_id/serpents",
Opts = #{path => Path},
[trails:trail(Path, ?MODULE, Opts, Metadata)].

% ...

为了将事件从核心报告给SSE或HDP客户端,我们使用gen_event但是为了简化我们的生活,我们实现了一个简单的gen_event处理程序,该处理程序反过来只需要在您的客户端中实现一个功能: notify(pid(), event()) 。 我们称它为spts_gen_event_handler 。 我们使用相同的处理程序为核心编写测试,而无需依赖任何类型的客户端。

对于HDP,我们编写了一个异步UDP侦听器,该侦听器为每个连接的客户端启动gen_server (UDP中没有实际的连接)。 之所以简单,是因为我们将所有协议解析/验证逻辑抽象到了自己的模块: spts_hdp 。 该模块本身就是Erlang 位语法的强大示例。 它展示了列表综合,结合了二进制综合和许多惊人的二进制模式匹配表达式。 我的最爱:

%% @doc Parses a list of serpent diffs.
%% Each one includes the serpent id and the
%% length of its body, followed by each of
%% the body cells.
parse_diff_serpents(0, Next, Acc) ->
{lists:reverse(Acc), Next};
parse_diff_serpents(
N,
< , BodyLength:?USHORT
, Body1:BodyLength/binary
, Body2:BodyLength/binary
, Next/binary
>>,
Acc) ->
Body &#61; <>,
Serpent &#61;
#{ id &#61;> SerpentId
, body &#61;>
[ {Row, Col}
|| <> <&#61; Body]
},
parse_diff_serpents(N-1, Next, [Serpent|Acc]).

开发方法论

并且&#xff0c;为了创建所有这些&#xff0c;我们使用了通常的方法&#xff1a; TDD 。 为此&#xff0c;我们使用common_test进行了工作&#xff0c;您可以在此处看到一些冗长的测试套件列表。 我们已经写了许多有关TDD&#xff0c;代码覆盖率甚至是元测试的博客文章&#xff0c;因此在这里我不再赘述。 请记住&#xff0c;如果您需要这些示例&#xff0c;那么这里就足够了。

客户

如果您问自己&#xff0c;那里有没有客户的例子&#xff1f; 是的&#xff0c;他们在这里 。 我自己开发了所有这些程序&#xff0c;您可以从头开始或使用spts_cli创建自己的程序 。

结果

结论

我们最终实现了我的两个目标。 一方面&#xff0c;我可以说我们举办了一场非同寻常的Hackathon&#xff0c;很多人在编码时开心地玩耍。 另一方面&#xff0c;现在我们有了一个很好的例子&#xff0c;说明了如何在Erlang Solutions上构建东西以向全世界展示。 您也可以享受它&#xff01; 做就是了…

$ git clone https://github.com/inaka/serpents.git
$ cd serpents
$ make
$ _rel/serpents/bin/serpents start

…并在浏览器中打开http&#xff1a;// localhost&#xff1a;8585开始播放&#xff01;

而且&#xff0c;当然&#xff0c;就像我小时候对Nibbles所做的那样&#xff0c;最有趣的部分是当您开始修改代码以使毒蛇吃了毒果后变得更胖&#xff0c;更瘦&#xff0c;随意喝酒时……

天啊&#xff01;必须执行&#xff01; 再见&#xff0c;我9岁&#xff0c;我有重要的事情要做...

最初于 2018 年4月26日 发布在 www.erlang-solutions.com 上。

该博客文章最初于2015年11月13日为inaka.net撰写。

From: https://hackernoon.com/erlang-serpents-3eca35bf7c6d



推荐阅读
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 本文介绍了在wepy中运用小顺序页面受权的计划,包含了用户点击作废后的从新受权计划。 ... [详细]
  • node.jsrequire和ES6导入导出的区别原 ... [详细]
  • 本文介绍了网络编程的要点,包括InetAddress类获取IP地址的方法,IP地址的定义和表示方法,IPv4和IPv6的区别,以及网络通信协议中的端口和协议类型。 ... [详细]
  • Python已成为全球最受欢迎的编程语言之一,然而Python程序的安全运行存在一定的风险。本文介绍了Python程序安全运行需要满足的三个条件,即系统路径上的每个条目都处于安全的位置、"主脚本"所在的目录始终位于系统路径中、若python命令使用-c和-m选项,调用程序的目录也必须是安全的。同时,文章还提出了一些预防措施,如避免将下载文件夹作为当前工作目录、使用pip所在路径而不是直接使用python命令等。对于初学Python的读者来说,这些内容将有所帮助。 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了VoLTE端到端业务详解|VoLTE用户注册流程相关的知识,希望对你有一定的参考价值。书籍来源:艾怀丽 ... [详细]
  • Ansem 最新雄文:软着陆后,加密市场下阶段趋势与核心叙事
    市场最糟糕的时候已经过去,以太坊合并前不太会看到新的低点;但仍需来自关注宏观市场的不确定风险。撰文:Ansem ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 开发笔记:计网局域网:NAT 是如何工作的?
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了计网-局域网:NAT是如何工作的?相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • c# java socketn 字节流_C#Socket编程详解(一)TCP与UDP简介
    一、TCP与UDP(转载)1、TCP1.1定义TCP(TransmissionControlProtocol)传输控制协议。是一种可靠的、面向连接的协议(eg:打电话)、传输效率低 ... [详细]
author-avatar
白珍茜登陆_585
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有