引言
deltaDNA GmaeMaker SDK允许你的GmaeMaker游戏发送关于游戏内事件和玩家行为的信息到deltaDNA平台。
事件被以JSON对象发送到deltaDNA平台,这些事件被使用在线的显示面板管理和跟踪。
当你的游戏触发事件时,SDK将在本地存储它们并在网络连接可用时按规律的时间间隔或在你选择的时间将其上传。这允许SDK收集事件而无论是否连接网络,并让你控制上传的时间和频率。
事件的复杂度有所不同,但是都源自一个相同的事件格式。本文档和附带的案例应用提供了不断增加事件复杂度的案例。
注意:dletaDNA SDK要求至少GameMaker功能的“标准”版本。deltaDNA SDK使用的HTTP请求和JSON编码功能在“免费”版本中不支持。
下载deltaDNA GameMaker SDK版本v0.1:
下载并解压deltaDNA GameMaker SDK版本v0.1。
还有一个案例项目/a>你可以下载。
复制SDK脚本到你的GameMaker项目脚本文件夹
初始化SDK
在你可以发送事件到deltaDNA平台之前,你需要使用如下参数初始化SDK。
- environmentKey(环境键值)这是一个分配给你的应用的唯一32位字符型字符串。你将被为你的游戏开发和产品版本分配相互分离的应用键值。
- collectURL(收集URL)这是将收集你的事件的服务器地址。
- engageURL(吸引URL)这是将提供实时A/B测试和命中目标(A/B Testing and Targeting)的服务器地址。这只在你的游戏使用这些功能时要求。
- uuserID(用户ID)每个用户需要一个唯一的userID(用户ID)。如果你的游戏可以提供一个唯一的用户ID,你可以使用它。此外,这个平台可以生成一个唯一的用户ID并在所有后来的事件中使用它。要生成一个唯一的用户ID,调用 scr_deltaDNA_generateUUId()函数并使用其返回的字符串值初始化SDK。
- hashsecret(哈希密码)是一个可以用于保护你的事件防止在通信过程中被篡改的保密哈希(hash)值。如果启用它你将看到如下图所示的在你的游戏详情页面的保密哈希值。如果你没有使用哈希,你应当将在初始化SDK时将哈希密码设置为 “no_hashing”
- fileStoreSize(文件存储尺寸)是一个包括事件最大文件存储器字节尺寸的整型值,或者如果没有存储器使用时设置为0。
- fileStorePath(文件存储路径)是一个包括当没有网络连接可用时从工作目录到事件应当存储的文件路径的字符串。
- attemptLimit(尝试限制)是事件应当被丢弃前的事件提交最大尝试次数。
这些参数可以在你的游戏详情页面找到。请注意,你的开发(DEV)和实际(LIVE)环境有不同的environmentKey参数。你将需要从开发和测试转到产品的过程中在你初始化SDK时改变环境键值。
为了这个演示,我们添加初始化代码来创建第一个房间。
初始化SDK的代码看起来应该是这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
globalvar dd_engagement_request_id; globalvar dd_engagement_request_result; dd_engagement_request_result = "no engagement request yet"; dd_engagement_request_id = -1; randomize(); var user_id = scr_deltaDNA_generateUUId(); if os_browser == browser_not_a_browser { // 如果存在则从文件中获取用户ID ini_open("dd_config.ini"); if ini_key_exists("user","userId") { user_id = ini_read_string("user","userId",user_id); } else { ini_write_string("user","userId",user_id); } ini_close(); } scr_deltaDNA_initialize("<Your Environment Key>", "http://<Your Collect URL>/collect/api", "http://<Your Engage URL>", user_id, "no_hashing", 2048, "ddEventStorage", 2); |
初始化函数设置SDK要求的各种全局变量,如果成功其将返回0,任何其他值则表明失败。
添加SDK控制对象
你将需要添加一个对象到你的游戏来控制事件上传和处理来自deltaDNA的响应
- 上传控制器
上传控制器将周期性的调用上传事件(Upload Events)以上传你的事件到deltaDNA。这应当是合理的频率以确保没有事件在用户意外关闭其会话时丢失或者延迟。 - 响应控制器
响应控制器应当监听HTTP响应并调用进程收集响应(Process Collect Response)以在成功上传后删除缓存事件,或者在未成功时标记它们以重试。
这个项目中我们加入我们房间的包括三个行为
创建(Create)事件设置字体为fnt_announce,颜色为black(黑色),在1800步时警报被触发。
当警报触发时其自身重置为在另一个1800步时再次触发,并执行一个脚本来上传所有的缓存事件
1 2 |
dd_announce = "upload timer ticked over"; scr_deltaDNA_uploadEvents(); |
最终的HTTP行为监听事件上传HTTP Post响应,并在响应接收到时执行一个脚本。
这个脚本被调用scr_deltaDNA_processCollectResponses
我们现在准备好开始记录事件,并将其发送到deltaDNA平台,但是在我们这样做之前,让我们快速查看一个事件看起来是什么样子。
事件剖析
所有的事件被使用一个共同的基础格式记录为JSON文件。这个文件对于每个事件类型都是不同的,但是它们所有的都遵循下面的最小格式:
1 2 3 4 5 6 7 8 9 10 |
{ "eventName":"gameEnded", "userID":"a2e92bdd-f59d-498f-9385-2ae6ada432e3", "sessionID":"0bc56224-8939-4639-b5ba-197f84dad4f4", "eventTimestamp":"2014-07-04 11:09:42.491", "eventParams":{ "sdkVersion":"GameMaker SDK v0.1", "platform":"WEB" } } |
在你的JSON事件中参数的顺序并不影响。
你可以在事件管理器中检查每个事件预期的参数,其类型和任何格式或枚举规则。
参数可以是可选的或者必需的。如果你没有一个有效值要放入,任何可选参数都不要求必须包含在你的事件中。最好完全将其删除,而不是将其设置为零(null)或者空(empty)。
基本的事件结构为记录各种复杂程度的事件提供了极大的灵活性,从类似上面的那个简单事件到包含嵌套数组的复杂事件。下面的代码案例将展示从简单到复杂的多种事件。
请注意所有的事件都需要验证,如果其与事件管理器的格式不匹配则将被拒绝。
创建事件
一旦SDK被初始化且你已经创建了你的控制对象,你将可以创建一些事件。
下面的代码明确指出了我们想要发送的事件名称,“gameStarted”和一个空的参数对象,然后触发一个事件。在这个案例游戏中我们添加了一个代码行为到一个对象的“左键单击”事件,
1 2 3 |
var gameStartedEventName = "gameStarted"; var gameStartedEventParams = ds_map_create(); scr_deltaDNA_triggerEvent(gameStartedEventName, gameStartedEventParams); |
那是一个非常简单的事件,其甚至不包含任何事件参数。更多的事件将只包含最多几条参数,但是一些事件可以包含更多,且你当然可以添加你自己的参数。
一个包含一些参数的事件看起来可能像这样。
1 2 3 4 5 6 7 |
var optionsEventName = "options"; var optionsEventParams = ds_map_create(); ds_map_add(optionsEventParams, "option","volume"); ds_map_add(optionsEventParams, "action","set to 80"); scr_deltaDNA_triggerEvent(optionsEventName, optionsEventParams); |
一个例如交易的复杂事件可以由多个对象组成,潜在的跟踪多个产品花费并在相同的交易中接收。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
var eventName = "transaction"; var eventParams = ds_map_create(); var productsSpent = ds_map_create(); var realCurrency = ds_map_create(); ds_map_add(realCurrency, "realCurrencyAmount", 500); ds_map_add(realCurrency, "realCurrencyType", "GBP"); ds_map_add_map(productsSpent, "realCurrency", realCurrency); ds_map_add_map(eventParams, "productsSpent", productsSpent); var productsReceived = ds_map_create(); var items = ds_list_create(); var itemOuter = ds_map_create(); var item = ds_map_create(); ds_map_add(item, "itemAmount", 1); ds_map_add(item, "itemType", "gem"); ds_map_add(item, "itemName", "diamond"); ds_map_add_map(itemOuter, "item", item); ds_list_add(items, itemOuter); var index = ds_list_find_index(items, itemOuter); ds_list_mark_as_map(items, index); ds_map_add_list(productsReceived, "items", items); ds_map_add_map(eventParams, "productsReceived", productsReceived); ds_map_add(eventParams, "transactionType","PURCHASE"); ds_map_add(eventParams, "transactionName","buy_diamond"); scr_deltaDNA_triggerEvent(eventName, eventParams); |
上传事件
SDK将在内部对事件进行排队;如果你在初始化调用中指定文件存储参数且游戏运行的平台具备本地存储的能力则将其存储在一个内部的文件系统中。
你能够通过调用上传事件(uploadEvents)函数 scr_deltaDNA_uploadEvents()来从SDK到deltaDNA平台上传事件。你可能想要设置一个计时器来定期调用这个函数(查看上面的上传控制器章节)或者你可能想要在你的游戏的一个预先确定的点上传事件,例如游戏已经加载和初始化时,玩家开始或者完成一关时等等。
根据网络连接性和本地存储能力,上传功能将:
- 如果网络连接存在:提交所有存储事件的文件、等待重新提交的事件和排队的事件。
- 如果没有网络连接存在且文件存储已经打开,将排队的事件转存到文件。
- 如果没有网络连接存在且文件存储被关闭,删除存储的事件。
如果成功上传函数将返回1,任何其他值表明失败。
关闭
最后当你的游戏结束时,你应当调用Destroy(损毁)函数 scr_deltaDNA_destroy() .
吸引(Engage)
如果你使用吸引A/B测试和命中目标(Engage A/B Testing and Targeting),这个过程与发送事件非常相似,但是其会立刻发生,你的请求将不会像事件那样排队。
- 吸引(Engage)请求
在你的游戏中一个被称为决策点(decisionPoint)的特殊点调用请求吸引(Engagement),并获得一个返回的响应参考。我们的吸引(Engage)请求被使用如下脚本创建。
123dd_engagement_request_id = scr_deltaDNA_requestEngagement("myDecisionPoint", ds_map_create());dd_engagement_request_result = "engagement request id: " + string(dd_engagement_request_id);show_debug_message("Set engagement request result: " + dd_engagement_request_result); - 吸引(Engage)响应
调用类似于调用争论(argument)响应的进程吸引响应(Process Engagement response)添加一个HTTP监听者,并取回响应数据地图。
123456789101112131415161718show_debug_message("Engagement info obj: executing http event code");if dd_engagement_request_id != -1 {var response = scr_deltaDNA_processEngagementResponse(dd_engagement_request_id);if response >= 0 {var resultMap = ds_map_find_value(dd_engage_results_store, dd_engagement_request_id);var transactionID = ds_map_find_value(resultMap, "transactionID");var parameters = ds_map_find_value(resultMap, "parameters");var foo = ds_map_find_value(parameters, "foo");var baz = ds_map_find_value(parameters, "baz");dd_engagement_request_result = "engagement result: transactionID - " + string(transactionID) + ", foo - " + string(foo) + ", baz - " + string(baz);dd_engagement_request_id = -1;ds_map_delete(dd_engage_results_store, dd_engagement_request_id);ds_map_destroy(resultMap);} else {dd_engagement_request_result = "engagement failed";}}show_debug_message("Engagement info obj: finished http event code");
API参考
初始化(Initialize)
- 脚本:scr_deltaDNA_initialize
- 参数:
- dd_environment_key:字符串,游戏的deltaDNA环境键值
- dd_collect_url:字符串,收集的URL
- dd_engage_url:字符串,吸引(Engage)的URL
- dd_user_id:字符串,用于提交事件的用户ID
- dd_hash_secret:字符串,MD5秘密哈希,或者没有使用哈希时为“no_hashing”
- dd_file_store_size:整型,事件文件存储的最大字节尺寸,或者没有存储被使用时为0。
- dd_file_store_path:字符串,如果没有网络可用时从工作目录到事件应当被存储的文件的路径。
- dd_attempt_limit:整型,在事件应当被丢弃前事件提交的最大尝试次数。
- 返回值:如果成功为1,任何其他值表示失败
触发事件(Trigger Event)
- 脚本:scr_deltaDNA_triggerEvent
- 参数:
- event_name:字符串,在控制面板为事件设置的事件名称值
- event_param_ds:参考ds_map,在事件定义中与事件参数结构相匹配的一个GameMaker地图设置的结构。其必须在地图中被创建,并列出在其容器结构内适当的标记。
- 返回值:如果成功为1,任何其他值表示失败
上传事件(Upload Events)
- 脚本:scr_deltaDNA_uploadEvents
- 参数:无
- 返回值:如果成功为1,任何其他值表示失败
- 如果网络连接存在:提交所有存储事件的文件、等待重新提交的事件和排队的事件。
- 如果没有网络连接存在且文件存储已经打开,将排队的事件转存到文件。
- 如果没有网络连接存在且文件存储被关闭,删除存储的事件。
生成UUID(Generate UUID)
- 脚本:scr_deltaDNA_generateUUId
- 参数:无
- 返回值:
- 一个任意格式的UUID
生成平台(Generate Platform)
- 脚本:scr_deltaDNA_generatePlatform
- 参数:无
- 返回值:
- 一个符合任意一个为游戏创建的默认枚举值的平台值。如果游戏开发者没有提供自己的值则其被用于事件中。
进程收集响应(Process Collect Responses)
- 脚本:scr_deltaDNA_processCollectResponses
- 参数:无
- 返回值:如果成功为1,任何其他值表示失败
收集的进程等待响应。如果响应表明一个成功的提交,这个响应被丢弃。否则,如果响应表明一个重试可能会成功且尝试的次数没有超过限制的错误,将请求放回提交队列。
这必须被添加到一个HTTP响应事件以确保提交队列被正确的清除。
损毁(Destroy)
- 脚本:scr_deltaDNA_destroy
- 参数:无
- 返回值:如果成功为1,任何其他值表示失败
删除包括事件队列使用的地图的全局变量。
吸引请求(Request Engagement)
- 脚本:scr_deltaDNA_requestEngagement
- 参数:
- decision_point:字符串,游戏试图触发的决策点
- engagement_parameters:参考ds_map,在控制面板中定义的与吸引(Engagement)参数结构相匹配的一个GameMaker地图设置的结构。其必须在地图中被创建,并列出在其容器结构内适当的标记。
- 返回值:
- 如果有问题为-1,或者一个可以用于获得吸引(Engagement)响应请求的参考值。
请求一个吸引(Engagement)。因此这是一个可以被检查的响应的异步返回参考值。
进程吸引请求(Process Engage Request)
- 脚本:scr_deltaDNA_processEngagementResponse
- 参数:
- engagement_response_ref:由调用返回到请求吸引(Request Engagement)的值。
- 返回值:
- 如果仍然在等待响应则为1,错误则为负数,完成为0。一旦这个方法返回0,dd_engage_results_store地图将产生一个吸引请求参考值和键值的映射以实现地图与响应的JSON结构相符。
一个吸引(Engagement)响应的进程。应当由一个HTTP响应监听器处理。
已知问题
- SSL不能工作。你只能使用纯HTTP。
- 对于HTML5开发的游戏,事件的文件存储不工作。
Android版
- Android应用需要在全局游戏设置的Android标签中获得“ACCESS_NETWORK_STATE”和“WRITE_EXTERNAL_STORAGE”权限。