Vielen Dank für Ihren Besuch. Diese Seite ist momentan nur auf Englisch verfügbar. Wir arbeiten an der deutschen Version. Vielen Dank für Ihr Verständnis.
Appstore Blogs Appstore DeveloperBlog /blogs/appstore/feed/entries/atom 2018-05-22T23:16:53+00:00 Apache Roller /blogs/appstore/post/06811337-e461-4635-8f31-936e86142cae/why-you-should-care-about-mobile-ad-fraud Why You Should Care About Mobile Ad Fraud Emily Esposito Fulkerson 2018-05-22T21:45:15+00:00 2018-05-22T23:16:53+00:00 <p><img alt="0522-adfraud-hero.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Influencerblogs/0522-adfraud-hero._CB477551915_.png?t=true" style="display:block; height:311px; margin-left:auto; margin-right:auto; width:700px" /><br /> Mobile ad install fraud remains one of the biggest challenges for app marketers. Fake installs affect your app metrics, forcing you to throw more and more money down the tube</p> <p><img alt="0522-adfraud-hero.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Influencerblogs/0522-adfraud-hero._CB477551915_.png?t=true" style="display:block; height:356px; margin-left:auto; margin-right:auto; width:800px" /><br /> Mobile ad install fraud remains one of the biggest challenges for app marketers. Fake installs affect your app metrics, forcing you to throw more and more money down the tube. At the same time, according to eMarketer.com, <a href="https://www.emarketer.com/Article/Europe-74-of-Mobile-App-Marketers-See-Ad-Fraud-Problem/1016718" target="_blank">only 44% of app marketers</a> in Europe said they had a strong understanding of mobile fraud and its potential impact on campaigns.</p> <p>Another problem is that the bad guys have moved past one hacker operations to more advanced organization whose main goal is to not be caught. As a result, at least&nbsp;<a href="https://www.mobivisits.com/category/mobile-advertising/" target="_blank">10% and up to 70%</a> of marketing budgets are lost due to app install ad fraud. So now that I’ve made your day, what to do about it? First, understand where the threat is.</p> <h2>The bad guys are getting smarter</h2> <p>To understand and address the issues of mobile ad install fraud, we analyzed a lot of information from marketers and talked to <a href="http://scalarr.io/" target="_blank">Scalarr</a>, a fraud prevention company.</p> <p>Let's take a look what fraudsters are doing today in order to effectively deal with tomorrow’s attacks.</p> <p>Fake incentive installs or fraudulent downloads coming from click farms are no longer the primary attacks used by advanced fraudsters. Those types of fraud can now be detected by fairly simple metrics, such as ID / IP / VPN / PROXY and TTI between click and install.</p> <p>Today’s newest bad guys prefer more advanced techniques for fraud, like financial emulators, CPE incentive, and mixed traffic generators, which make fraud harder to detect. Scalarr reports that only 1-2% of fraud could be detected by such basic metrics.</p> <p>Let’s take a look at which fraud tech are used by the&nbsp;most successful fraudsters.</p> <ol> <li>Since fraudsters are stealing mostly organic installs (<strong>classic click-spamming, modified click-spamming, click injection</strong>), app marketers see them as a good source of traffic and spend more and more money. Unfortunately “last-action” attribution used in app install tracking&nbsp;only helps fraudsters here. These types of fraud are generally categorized in the <strong>attribution fraud category.</strong><br /> &nbsp;</li> <li>After a player installs an app, another fraud can be attempted programmatically. Bots can simulate average user behavior within an app, tricking the advertisers into believing that they acquired a high-value user. And while basic bots are becoming outdated, new <strong>sophisticated bots</strong>&nbsp;or <strong>smart bots</strong>&nbsp;are becoming more and more widespread. Sophisticated bots emulate a wide variety of user behavior by doing all post-install activities over a long period of time. From a human perspective,<strong> </strong>they are hard to distinguish&nbsp;from real users.<br /> &nbsp;</li> <li>Real users and fake installs, or real users and different types of fraud (like attribution fraud and bots), are now being mixed together in order to mislead advertisers, creating a new and very dangerous type of fraud called <strong>mixes.</strong><br /> &nbsp;</li> <li>Last but not a least&nbsp;is <strong>financial fraud. </strong>This type of fraud is often recognized as a part of sophisticated bot fraud in order to convince a user acquisition manager that fraudulent traffic is real and encourage the manager to scale the source. A lot of payments may be made by the bot and reported to the developer, but the majority of those transactions will themselves be fraudulent, and made from stolen credit cards.</li> </ol> <p><img alt="scalar-image-mobileadfraud-0522.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Influencerblogs/scalar-image-mobileadfraud-0522._CB477548594_.jpg?t=true" style="display:block; height:694px; margin-left:auto; margin-right:auto; width:900px" /></p> <p>This will not be a definitive list as long as fraudsters take further steps in advancing their game, presenting fraud types like emulators, click farms, incentive injections, and so on. The presence of these fraud types is less common,&nbsp;but they still have their place on the app install map.</p> <h2>What now? Get started fighting fraud</h2> <p>The paid user acquisition market is already substantial (<a href="https://www.emarketer.com/Article/More-Than-Third-of-UK-Ad-Spend-Going-Mobile-2017/1015375" target="_blank">$14bn in 2017</a>) and it’s growing. With constantly increasing marketing budgets, it’s becoming more and more attractive for increasingly clever fraudulent activity.</p> <p>Fraud prevention is a constant cat-and-mouse game that requires increasingly advanced solutions that can detect current mobile ad install fraud and ideally, one that can adapt to identify new patters of fraud in the future.&nbsp;</p> <p>One thing is for sure: The worst thing you can do is ignore the problem or do nothing about it.</p> <p>&nbsp;</p> /blogs/appstore/post/6488e739-0b7a-44f6-9283-2a82c2f19e51/exploring-the-gameon-api-with-postman-standard-security Exploring the Standard Security GameOn API with Postman Laura Pezdek 2018-05-17T22:57:59+00:00 2018-05-17T22:59:40+00:00 <p><img alt="BLOGBANNER.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Laura/BLOGBANNER._CB495959732_.png?t=true" style="display:block; height:400px; margin-left:auto; margin-right:auto; width:1000px" /></p> <p>In this post, I will demonstrate how to craft your first API calls with the tool <strong>Postman</strong>. Postman is a tool for developing and testing APIs, and is available as a Windows, Mac, or Linux native client for free at <a href="https://www.getpostman.com" target="_blank">https://www.getpostman.com</a>.</p> <p><img alt="BLOGBANNER.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Laura/BLOGBANNER._CB495959732_.png?t=true" style="display:block; height:400px; margin-left:auto; margin-right:auto; width:1000px" /></p> <p><em><strong>Note</strong>: This post refers to the standard security workflow for GameOn Integration. For more information on the standard and advanced security options, click&nbsp;<a href="https://developer.amazon.com/docs/gameon/game-api.html#standard-and-advanced-security" target="_blank">here</a>.</em></p> <p>In this post, I will demonstrate how to craft your first API calls with the tool <strong>Postman</strong>. Postman is a tool for developing and testing APIs, and is available as a Windows, Mac, or Linux native client for free at <a href="https://www.getpostman.com" target="_blank">https://www.getpostman.com</a>. If you haven’t installed Postman, I recommend you do this step right away.</p> <p>As you design your tournaments and plan your GameOn integration, you can also begin to familiarize yourself with how the GameOn API works. GameOn uses a RESTful API – this means that your game will communicate with the GameOn servers through HTTP requests such as GET and POST, the same data requests that browsers use on the web.</p> <h2>Benefits of REST APIs</h2> <p>HTTP calls are well supported across game engines and operating systems if you want to jump right into coding, but it can be helpful to make a few test calls so you can see what format the request and replies are in.</p> <p>Once you have Postman installed and have the API keys for a standard security game, here’s how to create a <a href="https://developer.amazon.com/docs/gameon/game-api-ref.html#register-player" target="_blank">Register Player API call</a>.</p> <h2>Getting started</h2> <p>First, create a new API request in Postman:</p> <p><img alt="GameOnAPIPostman_Image1_051618.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Laura/GameOnAPIPostman_Image1_051618._CB495903564_.png?t=true" style="display:block; height:282px; margin-left:auto; margin-right:auto; width:700px" /></p> <p>Save it with a descriptive name:</p> <p><img alt="GameOnAPIPostman_Image2_051618.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Laura/GameOnAPIPostman_Image2_051618._CB495903566_.png?t=true" style="display:block; height:989px; margin-left:auto; margin-right:auto; width:700px" /></p> <p>Go to the <em>New Tab</em> for the request. Change the request type from GET to POST and enter as the request URL:</p> <p style="text-align:center"><strong>https://api.amazongameon.com/v1/players/register</strong></p> <p>Next, open up the <em>Headers</em>&nbsp;tab and enter the following two keys and values:</p> <p style="margin-left:.5in"><strong>Key&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Value</strong></p> <p style="margin-left:.5in">Content-Type &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; application/json</p> <p style="margin-left:.5in">X-Api-Key&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [the key labeled “Public API”]</p> <p>The request should look like this:</p> <p><img alt="GameOnAPIPostman_Image3_051618.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Laura/GameOnAPIPostman_Image3_051618._CB495903560_.png?t=true" style="display:block; height:229px; margin-left:auto; margin-right:auto; width:700px" /></p> <p>Now switch to the <em>Body</em> section, select “raw,&quot;&nbsp;and enter the following text into the text field (I just used the “advertisingId” value from the documentation, you can use whatever ID or identifier you want, if any):</p> <pre> <code>{ &quot;advertisingId&quot; : &quot;54d8fd8d-e349-49d8-902c-0558365ac22b&quot; } </code></pre> <p>Finally, click <em>Send,</em>&nbsp;and if all goes well, you should get a response at the bottom that looks like this:</p> <p><img alt="GameOnAPIPostman_Image4_051618.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Laura/GameOnAPIPostman_Image4_051618._CB495903563_.png?t=true" style="display:block; height:154px; margin-left:auto; margin-right:auto; width:700px" /></p> <p>You’ve just created your first GameOn REST API call! This response contains the player token and external player ID that associates this player with this game. In an actual game you would save these values with your player information for authenticating in game, but here, we’ll just copy the playerToken and craft the authentication step in Postman.</p> <h2>Authenticating</h2> <p>Players only need to be registered once, but authenticating needs to be done for every player session. You will use the player tokens you received from the registration call and do an authentication.</p> <p>In order to do this, we will be making an <a href="https://developer.amazon.com/docs/gameon/game-api-ref.html#authenticate-player" target="_blank">Authenticate Player</a> call. Add a new tab in Postman (don’t forget to save the request and give it a descriptive name), and, similar to the Register Player call, change the request to POST and enter the new URL:</p> <p style="text-align:center"><strong>https://api.amazongameon.com/v1/players/auth</strong></p> <p>Use the following headers:</p> <p style="margin-left:.5in"><strong>Key&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Value</strong></p> <p style="margin-left:.5in">Content-Type &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; application/json</p> <p style="margin-left:.5in">X-Api-Key&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [the key labeled “Public API”]</p> <p>You will then send the “playerToken” value received earlier in the body, along with advertising ID, player name, and some other information. There are several optional parameters that we’ll ignore:</p> <pre> <code>{ &quot;advertisingId&quot; : &quot;54d8fd8d-e349-49d8-902c-0558365ac22b&quot;, &quot;playerToken&quot; : &quot;&quot;, &quot;playerName&quot; : &quot;&quot;, &quot;deviceOSType&quot; : &quot;iOS&quot;, &quot;appBuildType&quot; : &quot;development&quot; } </code></pre> <p>And, once again, if all goes well, you should see something like this:</p> <p><img alt="GameOnAPIPostman_Image5_051618.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Laura/GameOnAPIPostman_Image5_051618._CB495903557_.png?t=true" style="display:block; height:496px; margin-left:auto; margin-right:auto; width:700px" /></p> <h2>Sign up for my webinar to learn more</h2> <p>Congratulations! You have now successfully registered and authenticated a player on GameOn.</p> <p>From here, you can create additional API calls to try the other interfaces, as well as test the Admin API functions.</p> <p>I’ve just scratched the surface of what Postman can do, but I’ve found it to be an invaluable resource during GameOn integration to debug my REST calls or even just to prototype a use case. I’ve also found it particularly useful to double-check what the API request or response actually looks like on the live servers.</p> <p>You can get started now by visiting us at <a href="https://developer.amazon.com/gameon" target="_blank">developer.amazon.com/gameon</a>. If you’re interested in learning more about this process, be sure to sign up for my <a href="https://goto.webcasts.com/starthere.jsp?ei=1191432&amp;tp_key=07575f899f" target="_blank">webinar</a> on <strong>May 21 at 10:00 AM PT</strong> where I’ll take you through the steps in more detail.</p> /blogs/appstore/post/f3a9c9fa-b8e6-401b-acd5-bead94678059/gamemaker-basics-timers GameMaker Basics: Timers Emily Esposito Fulkerson 2018-05-17T16:55:49+00:00 2018-05-17T16:55:49+00:00 <p><img alt="Timers-NathanRanney-may2018.gif" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/NathanRanneyblogposts/Timers-NathanRanney-may2018._CB496946730_.gif?t=true" style="display:block; height:394px; margin-left:auto; margin-right:auto; width:700px" /></p> <p>In this entry, I will go over how to write your own timers&nbsp;and how to use them.</p> <h1>&nbsp;</h1> <div> <p><img alt="Timers-NathanRanney-may2018.gif" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/NathanRanneyblogposts/Timers-NathanRanney-may2018._CB496946730_.gif?t=true" style="display:block; height:394px; margin-left:auto; margin-right:auto; width:700px" /></p> <p>Howdy folks! If you have been following along with <a href="http://m.amazonappservices.com/GameMakerResources" target="_blank">my previous blog entries</a> you may have noticed I used a lot of self coded timers, rather than the alarm system that is built into GameMaker. I prefer to code my own timers for two reasons. One, the alarms in GameMaker are somewhat limited. You can only have a set amount of alarms per object. Two, alarms aren’t very transparent and I get lost trying to remember what alarm[0] was set to. In this entry, I will go over how to write your own timers, and how to use them.</p> <h1>Overview and set up</h1> <p>So what exactly is a timer? A timer is a mechanism that allows you to count up, or down, to a certain value and then trigger something once that value is reached. So for example, let’s say you have a character who has been poisoned. Poison damage is generally a damage over time status effect, that deals a small amount of damage every so often. Imagine your game runs at 60 frames per second, and you decided that poison damage should be 1 damage. Your character has 100 hp and your code looks like this.</p> <strong>Example poison code</strong> <pre> <code>poisonDamage = 1; if(poisoned){ hp -= poisonDamage; }</code></pre> <p>This does not have a timer, or any sort of limitation on it, so it ticks down your hp by 1 every frame at 60 frames per second. Which means… your character with 100 hp dies in 1.6 seconds! That is some pretty hardcore poison! What you would really want to do, is tick down your poison damage every couple of frames. Maybe even every second. That code looks something like this.</p> <p><strong>Example poison timer code</strong></p> <pre> <code>poisonDamage = 1; if(poisoned){ poisonTick --; if(poisonTick &lt;= 0){ hp -= poisonDamage; poisonTick = 60; } }</code></pre> <p>In this example I am using a new variable, <strong>poisonTick</strong>, to determine when to apply poison damage. So now, what took 1.6 seconds previously, takes 100 seconds. <strong>poisonTick</strong> counts down by 1 every frame. Once <strong>poisonTick</strong> reaches 0, the player hp is reduced by the <strong>poisonDamage</strong> value, and <strong>poisonTick</strong> is reset back to its maximum of 60. This requires slightly more management than using alarms, but is much more versatile.</p> <p>To use timers in this way you need at least one variable, which is the variable that stores whatever you are counting. In the above example that is <strong>poisonTick</strong>. I would highly recommend a second variable to use when you reset your counted variable. This makes it much easier to manage. I’ll go over this in an example below.</p> <h1>More examples</h1> <p>Another benefit to using manual timers is you can use the same timer variable in multiple cases. I often use a variable called <strong>actionDur (action duration)</strong> in my games to determine how long any one character action can be performed. Let’s say a character has two actions, attack and dash, both of which are timer dependent. The character is locked into either action for the duration of the timer. You could use two timers to manage this. Say something like <strong>attackDur</strong> and <strong>dashDur</strong>. Or you can use a single timer, and use it in both places. Check out the example below.</p> <p><strong>Multi-use timer</strong></p> <pre> <code> actionDurMax = 60; actionDur = actionDurMax; if(attack){ actionDur --; if(actionDur &lt;= 0){ actionDur = actionDurMax; attack = false; } } if(dash){ actionDur --; if(actionDur &lt;= 0){ actionDur = actionDurMax; dash = false; } }</code></pre> <p>As you can see, both actions are able to use the same timer variables. Be aware that if you are using the same timer variable in multiple places, each use of the timer has to be completely independent of the other uses. So, using the above example again, I have to make sure that <strong>attack</strong> and <strong>dash</strong> cannot be true at the same time. If both variables were ever true at the same time, <strong>actionDur</strong> would countdown twice as fast. I highly recommend setting up a state machine for your character (see link at the end of this blog) which will help you manage what code is running when.</p> <p>You can also count up with your timers, which changes the structure slightly. It is somewhat personal preference whether you choose to count up or down. You may run into some cases where counting up or down is more beneficial than the alternative.</p> <p><strong>Timer counting up</strong></p> <pre> <code> actionDur = 0; actionDurMax = 60; if(attack){ actionDur ++; if(actionDur &gt;= actionDurMax){ actionDur = 0; attack = false; } }</code></pre> <p>There are some slight differences here. Our timer starts at 0, rather than the max, and counts up towards the max.</p> <p>So what happens if you want to use a single timer for multiple actions, but have those action durations differ? The easiest way to do this, if you are using the same kind of setup that I’ve been talking about, is to define the starting point of your timer when the action happens. Using the <strong>attack</strong> action again, let’s see how that might work.</p> <p><strong>Different timer duration with a single timer variable</strong></p> <pre> <code> actionDur = 0; actionDurMax = 60; if(attack_button){ attack = true; actionDur = 30; } if(attack){ actionDur ++; if(actionDur &gt;= actionDurMax){ actionDur = 0; attack = false; } }</code></pre> <p>In this example we had to make use of a new block of code. We’ve added the <strong>attack_button</strong> variable, which you can imagine is a player pushing the attack button in a game. When that button is pressed, <strong>attack </strong>becomes true, and <strong>actionDur</strong> is set to 30. By default <strong>actionDur </strong>is set to 0, and we are overriding that when pressing our imaginary attack button. However <strong>actionDur</strong> is still counting up to the <strong>actionDurMax</strong> when <strong>attack</strong> is set to true. Only this time, instead of starting from 0, it starts from 30. This effectively halves the duration of our <strong>attack</strong> action. Here is another example using a second action.</p> <p><strong>Multiple actions with different timer durations</strong></p> <pre> <code> actionDur = 0; actionDurMax = 60; if(attack_button){ attack = true; actionDur = 30; } if(attack){ actionDur ++; if(actionDur &gt;= actionDurMax){ actionDur = 0; attack = false; } } if(dash_button){ dash= true; actionDur = 10; } if(dash){ actionDur ++; if(actionDur &gt;= actionDurMax){ actionDur = 0; dash = false; } }</code></pre> <h1>Additional resources</h1> <ul> <li><a href="http://blog.markshead.com/869/state-machines-computer-science/" target="_blank">State Machines</a></li> <li><a href="https://docs.yoyogames.com/source/dadiospice/000_using%20gamemaker/events/alarm%20event.html" target="_blank">Alarms</a></li> </ul> <p>That about wraps it up for timers. Though it requires a teeny tiny bit more management than using alarms, using timers is a much more flexible and transparent setup. Thank you for taking the time to read over this, and I’ll catch you next time. As always, you can reach me on <a href="https://www.twitter.com/ratcasket">Twitter</a> or visit my <a href="http://www.ratcasket.com/">website</a> for more gamedev stuff.</p> &nbsp; <div> &nbsp; </div> </div> <p style="text-align:center"><a href="https://www.twitter.com/ratcasket"><img alt="NathanRBio.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/default/NathanRBio._CB513300692_.jpg?t=true" /></a></p> <p style="text-align:center"><em>Nathan Ranney is the founder of game development studio <a href="http://www.gutterarcade.com" target="_blank">Gutter Arcade</a>. He's best known for the creation and development of Knight Club, an online indie fighting game.&nbsp;</em></p> /blogs/appstore/post/e428cc32-0b5e-4281-bcda-6dbae0923e88/survey-amazon-appstore-developers-on-competitive-mobile-gaming Survey: Amazon Appstore Developers on Competitive Mobile Gaming Emily Esposito Fulkerson 2018-05-15T17:23:55+00:00 2018-05-15T17:23:55+00:00 <p><img alt="ebook-announce.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/GameOn/ebook-announce._CB498870180_.jpg?t=true" style="display:block; height:267px; margin-left:auto; margin-right:auto; width:900px" /><br /> We wanted to learn about the current sentiment and behavior around competitive mobile gaming among Amazon Appstore developers. So, we surveyed a pool of 1,290 U.S.-based developers published on the Amazon Appstore to get their thoughts.</p> <p>&nbsp;</p> <p><img alt="ebook-announce.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/GameOn/ebook-announce._CB498870180_.jpg?t=true" style="display:block; height:267px; margin-left:auto; margin-right:auto; width:800px" /><br /> We wanted to learn about the current sentiment and behavior around competitive mobile gaming among Amazon Appstore developers. So, we surveyed a pool of 1,290 U.S.-based developers published on the Amazon Appstore to get their thoughts. <em>Note: for this survey, we defined an organized competition as a game including tournaments like leaderboards, double elimination, leagues, etc. </em><br /> <br /> We learned that the majority of developers, 74%, have never run an organized competition. We wanted to find out why, and also learn about the experience of developers who have run them.<br /> <br /> Here’s what we discovered:</p> <h2>Developers cite a “lack of resources” as the main reason for not running organized competitions</h2> <p>Of the developers who have never run an organized competition, 31% point to a “lack of resources” as the number one cause. This makes sense, as 62% of those developers are the only person on their development team. Developers say they “simply do not have the time.”<br /> <br /> Developers also expect to spend hours running an organized competition, with 40% saying they would expect to spend more than two hours running one from start to finish.</p> <h2>Knowledge and information would make developers more inclined to run a tournament</h2> <p>What would make these developers more inclined to run a tournament? Two main themes emerged:<br /> <br /> <u>Knowledge of how to run a competition </u><br /> <br /> Many developers don’t know where to start. Developers say they were “just not familiar with the process” and want to understand “actually knowing how to implement it.” They focus on ease, looking for an “easy way to do it, with very little ramp up time” and “documentation to do so on my platform.”<br /> <br /> <u>Understanding the value of the competition </u><br /> <br /> In addition to understanding how to run a competition, developers also want to learn <em>why</em> they should invest the resources in doing so. They want to “read about success stories,” “have good samples and tutorials,” and “know the results of other competitions.” Data would be especially meaningful, helping developers “know there would be a big enough return vs the effort.”</p> <h2>Leaderboards are the most popular type of tournament</h2> <p>Leaderboards are the most popular type of tournament among developers who have run an organized competition. This makes sense, as leaderboards are the most flexible competition style that can be incorporated in most games. After leaderboards, 18% of developers have used leagues, 14% have used round-robin, and 10% have used double elimination.<br /> <br /> More than half of developers (51%)&nbsp;said these types of competitions were run through features built into their game. Twenty-nine percent&nbsp;used a third-party site or service, 13% used message boards, and 7% used other ways (like using a whiteboard at a physical location).</p> <h2>Developers run organized competitions to increase user engagement</h2> <p>One-third&nbsp;of developers decided to run organized competitions in order to increase user engagement. They see competitions as another way to incentive users to keep playing their games, and keep coming back.<br /> <br /> Other top benefits of organized competitions include rewarding users, increasing retention, and building a robust community.</p> <h2>The biggest challenge is promoting the tournament</h2> <p>Of the developers who ran an organized competition, 24% said the biggest challenged they faced was promoting the tournament. After all, once you invest the time and effort into organizing a competition, you want enough players to participate. And it can be challenging to attract new users to a tournament.<br /> <br /> Other top challenges included maintaining player participation (22%) and registering users (15%).</p> <h2>Learn more with our free eBook</h2> <p>Want to learn more about competitive mobile gaming? Get our free eBook titled, &quot;<a href="http://m.amazonappservices.com/Competitive-Mobile-Gaming-eBook" target="_blank">Developer First Look: Competitive Mobile Gaming</a>.&quot; You'll read about who is watching and playing competitive games, best practices for adding competition into your game, and more.<br /> &nbsp;</p> <p><a href="http://m.amazonappservices.com/Competitive-Mobile-Gaming-eBook" target="_blank"><img alt="GameOn-button.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/GameOn/GameOn-button._CB495535022_.png?t=true" style="display:block; margin-left:auto; margin-right:auto" /></a></p> <p>&nbsp;</p> /blogs/appstore/post/502737fb-1bc1-4374-b5eb-a473bb59ff18/case-study-a-success-story-of-japanese-developers-using-ip-content Case Study: How Japanese Developers Are Successfully Using IP Content Nanaho Nishiyama 2018-05-11T17:30:00+00:00 2018-05-11T17:30:00+00:00 <p><img alt="gamegate-top.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/JPAppstore/gamegate-top._CB498585034_.jpg?t=true" style="display:block; margin-left:auto; margin-right:auto" /></p> <p>In Japan, smartphone games that utilize IP are gaining popularity. On the one hand, this also means that meeting fan expectations can be a challenge. Gamegate shared their experiences&nbsp;developing the app, levaraging Amazon's catalog of existing Anime content, and using IP content.</p> <p><img alt="gamegate-top.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/JPAppstore/gamegate-top._CB498585034_.jpg?t=true" style="display:block; margin-left:auto; margin-right:auto" /></p> <p>In Japan, smartphone games that utilize IP (intellectual property) are gaining popularity. If the original anime or character is popular, the game can easily garner attention. But, on the other hand, this also means that meeting fan expectations can be a challenge.</p> <p>We visited Gamegate, the company that developed and manages the smartphone app for the popular anime Girls und Panzer. We spoke with the developers who released the app on the Amazon Appstore about their experiences developing the app, leveraging Amazon's catalog of existing Anime content, and using IP content.</p> <p>&nbsp;</p> <table border="0" cellpadding="1" cellspacing="1" style="width:100%"> <tbody> <tr> <td><img alt="gamegate-hosono-san-150px.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/JPAppstore/gamegate-hosono-san-150px._CB498585140_.png?t=true" /></td> <td> <p><strong>Hirotaka Hosono</strong></p> <p>CEO of Gamegate Inc.</p> <p>After switching from system engineering to the content industry, Hosono&nbsp;became involved in the online gaming<br /> and anime business in Japan and overseas, and founded Gamegate in 2011. He develops a broad range of content business focusing on Asia.</p> </td> </tr> </tbody> </table> <table border="0" cellpadding="1" cellspacing="1" style="width:100%"> <tbody> <tr> <td><img alt="gamegate-bando-san-150.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/JPAppstore/gamegate-bando-san-150._CB498583889_.png?t=true" /></td> <td> <p><strong>Masafumi Bando</strong></p> <p>Manager, Marketing and Sales Department, Gamegate Inc.</p> <p>Bando&nbsp;joined Gamegate in 2014. Before that, he&nbsp;was in charge of anime IP-related mobile site marketing<br /> and sales at his previous company.&nbsp;He has been working on a wide variety of anime IP-related digital content and online game promotion.&nbsp;</p> </td> </tr> </tbody> </table> <p>&nbsp;</p> <p>&nbsp;</p> <h3><strong>About the smartphone app Girls und Panzer: Sensha-do Strategy!</strong></h3> <p>&nbsp;</p> <h4><strong>- First, please give us a brief overview of your app</strong></h4> <p><strong>Bando:</strong> This is a smartphone app currently available in Japan, Taiwan, Hong Kong and Macau, called <a href="https://www.amazon.co.jp/%E3%82%B7%E3%83%A7%E3%82%A6%E3%82%B2%E3%83%BC%E3%83%88-%E3%82%AC%E3%83%BC%E3%83%AB%E3%82%BA-%E3%83%91%E3%83%B3%E3%83%84%E3%82%A1%E3%83%BC-%E6%88%A6%E8%BB%8A%E9%81%93%E5%A4%A7%E4%BD%9C%E6%88%A6%EF%BC%81/dp/B072BXY5VL/ref=sr_1_5?ie=UTF8&amp;qid=1522404947&amp;sr=8-5&amp;keywords=%E3%82%AC%E3%83%BC%E3%83%AB%E3%82%BA%EF%BC%86%E3%83%91%E3%83%B3%E3%83%84%E3%82%A1%E3%83%BC+%E6%88%A6%E8%BB%8A%E9%81%93%E5%A4%A7%E4%BD%9C%E6%88%A6" target="_blank">Girls und Panzer: Sensha-do Strategy!</a> It's a game based on the anime series Girls und Panzer, and was first released for iOS and Android in November 2015 (the Amazon version was launched in May 2017). The game involves having the characters ride in tanks and form teams to battle.</p> <p>The anime series itself first aired in 2012. The Girls und Panzer der Film hit theaters in November 2015, so the game was released to coincide with that.</p> <p>&nbsp;</p> <p><img alt="gamegate-girlsundpanzer.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/JPAppstore/gamegate-girlsundpanzer._CB498482625_.jpg?t=true" /></p> <p><em>In the world of Girls und Panzer, Sensha-do (&quot;the way of the tank&quot;) is considered a traditional art alongside flower arrangement and the tea ceremony. It is a popular anime, mostly among Japanese men, for its depiction of the development and friendship of female high school students practicing tank warfare.</em></p> <p>&nbsp;</p> <h4><strong>- What is difference&nbsp;between your game and the anime?</strong></h4> <p><strong>Bando:</strong> There are many characters wearing original outfits that didn't appear in the anime. Also, characters outside the confines of the school can be added to your team, and you can choose the tanks you would like to use. This allows fans to create their own dream teams. The game is already into its second year, and there are still a lot of people playing it.</p> <p>&nbsp;</p> <p><img alt="gamegate-001.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/JPAppstore/gamegate-001._CB498585038_.jpg?t=true" /></p> <p>&nbsp;</p> <h4><strong>- It's very easy to gauge fan reaction with games that use IP. It seems that they will either be really well received, or deeply hated. What were you conscious of during the development stage?</strong></h4> <p><strong>Bando:</strong> The first thing is whether or not it will be well received by fans of the anime. The basic worldview and the settings of the anime are faithfully reproduced in the game, with the added bonus that there are images that aren't in the anime that do appear in the game. We also paid attention to how the Sensha-do in the anime would be portrayed on a smartphone.</p> <p>&nbsp;</p> <p>&nbsp;</p> <h3><strong>The story behind the development - About the release of the Amazon version</strong></h3> <p>&nbsp;</p> <h4><strong>- It's been almost a year since the app was released on the Amazon Appstore. Please tell us about your experience so far.</strong></h4> <p><strong>Bando:</strong> The game was released on Amazon at the end of May 2017. The biggest thing I can point out is that a higher percentage of Amazon users purchase <em>sensha-damashii</em> (the in-game items that allow the user to play Gacha*, etc.). On top of that, I think that the number of purchases per user is higher compared to the other platforms.</p> <p><strong>Hosono:</strong> Amazon Appstore has more than twice the paid user ratio than other platforms.</p> <p><strong>Bando:</strong> In terms of sales, about 10% of our sales on the title is driven by Amazon Appstore.</p> <p>&nbsp;</p> <p><img alt="Gacha.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/JPAppstore/Gacha._CB497865025_.jpg?t=true" /></p> <p><em>*Gacha: The game utilizes a lottery mechanism to randomly let players obtain in-game items and characters. This is a popular business model for Japanese online games and smartphone games.</em></p> <p>&nbsp;</p> <h4><strong>- What has the reaction from users been like?</strong></h4> <p><strong>Bando:</strong>&nbsp;Thanks&nbsp;to Amazon&nbsp;<a href="https://www.amazon.com/Amazon-500-Coins/dp/B0096E8CQA/ref=sr_1_1?ie=UTF8&amp;qid=1524551827&amp;sr=8-1&amp;keywords=amazon+coins&amp;dpID=418TAh9NMuL&amp;preST=_QL70_&amp;dpSrc=srch" target="_blank">Coins</a>, we have received many Coins-related inquiries and feedback. I also get the sense that Amazon Appstore customers also use other Amazon services in their daily lives. For example, I have seen users of Fire tablets mentioning that they learned about the release of the Girls und Panzer app through the tablets. The impression I have is that these users were well connected to our app.</p> <p>&nbsp;</p> <p><img alt="gamegate-004.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/JPAppstore/gamegate-004._CB498584982_.jpg?t=true" /></p> <p>&nbsp;</p> <h4><strong>- Is there anything else you liked about releasing the app on the Amazon Appstore?</strong></h4> <p><strong>Hosono:</strong> Besides IAP purchases, I would say promotion. There was a Girls und Panzer Festival, and the Amazon Coins campaign was announced to those who bought Girls und Panzer DVDs and Blu-rays. I think the fact that Amazon promoted the app to draw in people beyond gamers had a big impact. App sales in November 2017 when the Girls und Panzer Festival was held were about the same as when the Amazon version was first launched.</p> <p><strong>Bando:</strong> There were about ten times the number of new registered users the month of the festival compared to the previous month.</p> <p><strong>Hosono:</strong> Since Amazon also sells DVDs, Blu-rays, and other related goods, I feel that there is good affinity for mixed-media titles.</p> <p>&nbsp;</p> <p><img alt="gamegate-garupan-matsuri.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/JPAppstore/gamegate-garupan-matsuri._CB498475921_.jpg?t=true" /></p> <p><em>The Girls und Panzer Festival campaign on Amazon.co.jp, which coincided with the release of Girls und Panzer das Finale in November 2017. During this period, anyone who downloaded the Girls und Panzer app received free Amazon Coins.&nbsp;At the same time, those who purchased a Girls und Panzer&nbsp;<a href="https://www.amazon.co.jp/%E3%82%AC%E3%83%BC%E3%83%AB%E3%82%BA%EF%BC%86%E3%83%91%E3%83%B3%E3%83%84%E3%82%A1%E3%83%BC-%E6%9C%80%E7%B5%82%E7%AB%A0-%E7%AC%AC1%E8%A9%B1-DVD-%E6%B8%95%E4%B8%8A%E8%88%9E/dp/B078W8B335/ref=sr_1_3?s=dvd&amp;ie=UTF8&amp;qid=1522405117&amp;sr=1-3&amp;keywords=%E3%82%AC%E3%83%BC%E3%83%AB%E3%82%BA%EF%BC%86%E3%83%91%E3%83%B3%E3%83%84%E3%82%A1%E3%83%BC" target="_blank">DVD</a> or <a href="https://www.amazon.co.jp/%E3%80%90Amazon-co-jp%E9%99%90%E5%AE%9A%E3%80%91-%E3%83%91%E3%83%B3%E3%83%84%E3%82%A1%E3%83%BC-%E3%82%A2%E3%83%92%E3%83%AB%E3%81%95%E3%82%93%E3%81%A7%E3%82%82%E5%88%86%E3%81%8B%E3%82%8B-%E7%B7%8F%E7%81%AB%E6%BC%94%E3%81%AE%E6%A5%BD%E3%81%97%E3%81%BF%E6%96%B9%E8%AC%9B%E5%BA%A7%E3%80%8DBD%E4%BB%98-Blu-ray/dp/B078W883KG/ref=sr_1_2?s=dvd&amp;ie=UTF8&amp;qid=1522405117&amp;sr=1-2&amp;keywords=%E3%82%AC%E3%83%BC%E3%83%AB%E3%82%BA%EF%BC%86%E3%83%91%E3%83%B3%E3%83%84%E3%82%A1%E3%83%BC" target="_blank">Blu-ray</a> or watched <a href="https://www.amazon.co.jp/%E3%82%AC%E3%83%BC%E3%83%AB%E3%82%BA%EF%BC%86%E3%83%91%E3%83%B3%E3%83%84%E3%82%A1%E3%83%BC-%E5%8A%87%E5%A0%B4%E7%89%88%EF%BC%88%E3%82%BB%E3%83%AB%E7%89%88%EF%BC%89-%E6%B8%95%E4%B8%8A-%E8%88%9E/dp/B01DSH2ZV8/ref=sr_1_3?s=instant-video&amp;ie=UTF8&amp;qid=1522405187&amp;sr=1-3&amp;keywords=%E3%82%AC%E3%83%BC%E3%83%AB%E3%82%BA%EF%BC%86%E3%83%91%E3%83%B3%E3%83%84%E3%82%A1%E3%83%BC" target="_blank">Girls und Panzer der Film</a> on Prime Video received an email about the campaign, which motivated fans of the anime who didn't know about the game to play it.</em></p> <p style="text-align:center">&nbsp;</p> <h4><strong>- Were there any challenges or impediments you faced with releasing on the Amazon Appstore?</strong></h4> <p><strong>Bando:</strong> I don't think there were any major problems or challenges in terms of development. The implementation itself took about one&nbsp;month for development, two weeks for development verification, and two&nbsp;weeks for release preparation including QA, so around two&nbsp;months in total. Development verification went smoothly, and the app was released as planned. There were no major issues on the technology side as well.</p> <p>&nbsp;</p> <p>&nbsp;</p> <h3><strong>Looking ahead</strong></h3> <p>&nbsp;</p> <h4><strong>- Please tell us about your company's vision for the future.</strong></h4> <p><strong>Hosono:</strong> Our main focus is the development and management of smartphone games and browser games that use IP. We plan to continue the business we have cultivated up to this point, but we also plan to focus our efforts on content creation.</p> <p>We already made an announcement about an original title currently in development, called&nbsp;<a href="http://akanesasushojo.com/" target="_blank">Akanesasu Shojo</a>. Gamegate holds a joint copyright, and is investing in both a game and an anime.</p> <p>&nbsp;</p> <p><img alt="gamegate-005.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/JPAppstore/gamegate-005._CB499066742_.jpg?t=true" /></p> <p>&nbsp;</p> <h4><strong>- Is there anything else you would like to add?</strong></h4> <p><strong>Hosono:</strong> I'd first like to say that it was the right decision we released our game on the Amazon Appstore. Also, we appreciate that Amazon Japan launched the Coins campaign and the Girls und Panzer Festival, as this increased the number of users and IAP purchases.</p> <p>Amazon itself handles a variety of content, not just games, but also movies, manga, music, and so on. In the past, they announced Amazon Coins campaigns to DVD and Blu-ray purchasers, and Prime Video viewers, but I think it could be interesting if they allowed game players to watch videos, read manga, and listen to music related to the game for free.</p> <p>We would be grateful if we can continue leveraging the multi-tenant value propositions from Amazon to boost the engagement of our apps and games.</p> <p>&nbsp;</p> <p>&nbsp;</p> <p><em>*&nbsp;This article was translated from Japanese. You can read the original post&nbsp;<a href="https://developer.amazon.com/blogs/appstore/post/b999ab53-e321-42f2-a4a8-dedd9aa26ed4/japan-voice-of-developers-gamegate-interview">here</a>.</em></p> <p>&nbsp;</p> <hr /> <p>&nbsp;</p> <ul> <li><a href="https://developer.amazon.com/apps-and-games" target="_blank">Interested in Amazon Appstore? Create your free developer account</a>!<br /> &nbsp;</li> <li><a href="https://developer.amazon.com/app-submission" target="_blank">Submit your apps on Amazon Appstore</a></li> </ul> <p>&nbsp;</p> <hr /> <p>&nbsp;</p> <p><img alt="gamegate-000.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/JPAppstore/gamegate-000._CB498585036_.jpg?t=true" /></p> <p>&nbsp;</p> <hr /> <p>Interviewer: Kazuyuki Tanaka<br /> Article writer &amp; photographer: Nanaho Nishiyama<br /> Editor: Emily Esposito Fulkerson</p> /blogs/appstore/post/34c544b8-68e8-4f49-88c9-a99922a03211/new-ebook-behind-the-scenes-lessons-learned-from-the-making-of-missile-cards New eBook - Behind the Scenes: Lessons Learned from the Making of Missile Cards Emily Esposito Fulkerson 2018-05-11T16:21:15+00:00 2018-05-11T16:21:15+00:00 <p><img alt="Missile-Cards-Blog-Banner.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/NathanRanneyblogposts/Missile-Cards-Blog-Banner._CB496945316_.png?t=true" style="display:block; margin-left:auto; margin-right:auto" /><br /> In this eBook, Nathan pulls back the curtain on everything from game design to creative processes to tackling tough mechanics.</p> <div> <img alt="Missile-Cards-Blog-Banner.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/NathanRanneyblogposts/Missile-Cards-Blog-Banner._CB496945316_.png?t=true" style="display:block; height:320px; margin-left:auto; margin-right:auto; width:800px" /> </div> <div> &nbsp; </div> <div> With powerful tools that speed up&nbsp;development and an abundance of diverse frameworks that let you self-publish your games, there’s never been an easier, more accessible time to create something unique for the world to play. </div> <div> &nbsp; </div> <div> For Nathan Meunier, creator of <a href="https://www.amazon.com/Nathan-Meunier-Missile-Cards/dp/B07CVM9S4V" target="_blank">Missile Cards</a>, GameMaker:Studio was the catalyst that changed everything. In three years of part-time tinkering, he went from having zero knowledge about what goes into creating a game to rolling up his sleeves and bringing games from concept to launch. </div> <div> &nbsp; </div> <div> Missile Cards isn't his first commerical project, but it's one of the weirdest, most ambitious, and most successful games he's created to date.&nbsp; </div> <div> &nbsp; </div> <div> In this eBook, Nathan pulls back the curtain on everything from game design to creative processes to tackling tough mechanics. </div> <div> <br /> You'll learn: </div> <div> &nbsp; </div> <ul> <li>How to design for multiple devices</li> <li>The complexities of card-game design</li> <li>How to port your game to Fire devices</li> <li>Tips to bring your game to life</li> </ul> <p>&nbsp;</p> <p><a href="http://m.amazonappservices.com/missile-cards-ebook" target="_blank"><img alt="eBook_Button.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Unity/eBook_Button._CB489599759_.png?t=true" style="display:block; margin-left:auto; margin-right:auto" /></a></p> /blogs/appstore/post/3968f20d-3f41-443d-9f7e-de21e98a4c29/amazon-gameon-adds-an-additional-security-model Amazon GameOn Adds an Additional Security Model Tess Selim 2018-05-10T17:19:44+00:00 2018-05-10T19:26:39+00:00 <p><img alt="" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/default/blog_post_._CB495376814_.jpg" style="display:block; margin-left:auto; margin-right:auto" /><img alt="" /></p> <p>On May 8, we released a security update to <a href="https://developer.amazon.com/gameon" target="_blank">Amazon GameOn</a>. One of the developer requests we addressed in this update is to provide both a standard and an advanced security model. &nbsp;</p> <p><img alt="" style="display:block; margin-left:auto; margin-right:auto" /><img alt="" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/default/blog_post_._CB495376814_.jpg" style="display:block; margin-left:auto; margin-right:auto" /><img alt="" /></p> <p>On May 8, we released a security update to <a href="https://developer.amazon.com/gameon" target="_blank">Amazon GameOn</a>, a set of REST APIs that help you build cross-platform competitions into your games. One of the developer requests we addressed in this update is to provide both a standard and an advanced security model. &nbsp;</p> <h3><strong>Standard vs. advanced security model</strong></h3> <p>The new standard security model authenticates players using a simple exchange of a player token. The network traffic between the device and the Amazon servers is protected with Transport Layer Security (TLS).</p> <p>The advanced security model adds data encryption for sensitive data in the exchange between the client and server. The advanced security model uses public/private key encryption to help secure player registration, authentication, and prize claim information.</p> <p>For both models, you will need to supply your API key whenever you make a call, and you’ll need to have your GameID to identify your game.</p> <p>Why have two security models? Some developers have told us that standard security is their preferred method for accessing GameOn. Others have told us that they want to use standard security while in development, but they want to launch with advanced security.</p> <p>Here are the differences between the standard and advanced models to help you choose which is right for you.</p> <p>&nbsp;</p> <h4>Standard security:</h4> <ul> <li><strong>Advanced Setup</strong> – Not required</li> <li><strong>Player Registration and Authentication</strong> – Communication secured with TLS</li> <li><strong>PrizeInfo </strong>– Communication secured with TLS</li> </ul> <p>&nbsp;</p> <h4>Advanced security:</h4> <ul> <li><strong>Advanced Setup</strong> – Creation of a public/private key pair required</li> <li><strong>Player Registration and Authentication</strong> – Communication secured with TLS and content is encrypted</li> <li><strong>Prizeinfo </strong>&nbsp;– Communication secured with TLS and prize info is encrypted</li> </ul> <h3>&nbsp;</h3> <h3><strong>The standard GameOn security model</strong></h3> <p>Using the standard security model looks like this:</p> <p>&nbsp;</p> <ol> <li> <p><strong>Register your player:</strong> Register your player by providing the Game API key in the header of the Register Player method. The Register Player response will include a playerToken that you store for long term use, sending it in all Authenticate Player requests for that player.</p> </li> <li> <p><strong>Authenticate your player:</strong> You call Authenticate Player and send the playerToken to create a session for your player. You will get a session API key and a session ID in the response. Hang on to these, you’ll need these for future API requests.</p> </li> <li> <p><strong>Flow through competition takes</strong> as per the <a href="https://developer.amazon.com/docs/gameon/game-api.html" target="_blank">listed workflows</a> using sessionApi and sessionId in the API calls.</p> </li> </ol> <p style="margin-left:.25in">Here is a sample of the Authenticate Player request body:</p> <pre> <code>{ &nbsp; &quot;advertisingId&quot; : &quot;54d8fd8d-e349-49d8-902c-0558365ac22b&quot;, &nbsp; &quot;payload&quot; : &quot;&lt;player token&gt;&quot;, &nbsp; &quot;playerName&quot; : &quot;hunkdory&quot;, &nbsp; &quot;devicePushNotificationToken&quot; : &quot;392340e57e4a7c646326b1cf96931d97f22ab163f23b3d3605fc5698d3788xx9&quot;, &nbsp; &quot;deviceOSType&quot; : &quot;iOS&quot;, &nbsp; &quot;appBuildType&quot; : &quot;development&quot; }</code></pre> <p>&nbsp;</p> <h3><strong>The GameOn advanced security model</strong></h3> <p>Advanced security registers and authenticates players with additional security for player authorization (in addition to the API key) by using an encrypted player token in the exchange between the client and server. Here is how that works:</p> <p style="margin-left:40px"><strong>1. Generate encryption key pair</strong>: Step one is to generate the public/private key pair that will be used to pass encrypted player information to GameOn, and to receive encrypted information back from the GameOn service. We’ll call these the client keys and suggest each player have their own unique set. To create these keys, it’s probably best to use a tool like <a href="http://www.bouncycastle.org/">Bouncy Castle</a> to help make this easy.</p> <p style="margin-left:40px"><strong>2. Prepare to send GameOn the client public key:</strong> You’ll need to send the client public key to GameOn, so GameOn can use it to encrypt sensitive information sent in response to future API requests.</p> <p style="margin-left:40px"><strong>3. Encrypt the client public key:</strong> GameOn provides you with a public key which is used to encrypt the client public key before sending it. This GameOn public key can be found in the GameOn admin console, and is provided during registration. It is unique to each registered game.</p> <p>&nbsp;</p> <p><img alt="" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/default/GameOnConsoleCapture._CB495333194_.png" style="display:block; margin-left:auto; margin-right:auto" /></p> <p>&nbsp;</p> <p style="margin-left:40px"><strong>4. Send the encrypted client public key: </strong>Every time a player needs to register with GameOn, Register Player will conduct the key exchange, taking the client public key and using that to encrypt and send an encrypted Player Token in the response. For a diagram showing the workflow in more detail, <a href="https://m.media-amazon.com/images/G/01/mobile-apps/dex/gameon/gameon-register-player-diagram">click here</a>.</p> <p style="margin-left:40px"><strong>5. Decrypt the Encrypted Player Token</strong>: This token is encrypted with the client public key and should be decrypted with the client private key (which is only known to you).</p> <p style="margin-left:40px"><strong>6. Now you have a Player Token</strong>: When you send the Player Token back to GameOn (e.g. for authentication), you’ll encrypt it with the GameOn public key.</p> <p>In the advanced model, the only other time (besides Player Registration and Authentication) where you’ll need to use your key pair is when you get Prize Info from claiming or fulfilling a prize. That will come encrypted with the client public key provided to GameOn when the player was registered.</p> <h3>&nbsp;</h3> <h3><strong>Choose your model when you register your game</strong></h3> <p>You make the choice between standard and advanced security when you register your game in the GameOn console and it is not possible to switch security modes for your game once registered. To develop with one model and release with another, you will need to create two games in the GameOn console; one with standard and one with advanced security. Here is how that works.<br /> &nbsp;</p> <h3><strong>Developing in standard security and releasing with advanced security</strong></h3> <p>If you have developed the game using standard security, and you wish to release with advanced security, use the GameOn console to register a new game with the same name and select the advanced security model option. A new entry will be created in your GameOn console with new keys that you must use in your code for the new security mode. Because this is a new game entry in GameOn, user data from the first game will not be available in the new game. Quick tip: remember to switch all the keys to match the new game.</p> <h3>&nbsp;</h3> <h3><strong>More help</strong></h3> <p>For more details about the API parameters and responses, please see the <a href="https://developer.amazon.com/docs/gameon/game-api-ref.html" target="_blank">GameOn API reference</a>. We also have some <a href="https://s3-us-west-1.amazonaws.com/gameon-samples/CryptoSamples/GameOn-Crypto-Samples.zip" target="_blank">cryptography code samples</a> you can download. If you still want more help, you can check out our <a href="https://forums.developer.amazon.com/spaces/392/index.html" target="_blank">Knowledge Base</a> or ping our <a href="https://forums.developer.amazon.com/spaces/351/index.html" target="_blank">GameOn support forum</a>.</p> <p>Remember, GameOn is <a href="https://developer.amazon.com/blogs/appstore/post/0a662002-2550-4686-a0e3-20948081af43/gameon-free-until-june-1" target="_blank">free until June 1</a>! Some developers have been able to set up competitions in their game with GameOn in as little as one day. Integrate today to take full advantage of our launch offer. You can also learn more about how to integrate competitive play into your game by watching <a href="https://developer.amazon.com/blogs/appstore/post/b29e1e3a-0b86-4e6a-b842-bd799a89ccd2/webinar-introducing-amazon-gameon-how-to-integrate-competitive-play-into-your-game" target="_blank">this webinar</a> on-demand.</p> <ul> <li><a href="https://twitter.com/mikefhines" target="_blank">@MikeFHines</a></li> <li><a href="https://www.facebook.com/MikeFHines" target="_blank">Facebook/MikeFHines</a></li> </ul> /blogs/appstore/post/11f78b59-33bf-40cc-b869-78276d728372/object-type-introspection-in-gamemaker-part-1 Object Type Introspection in GameMaker - Part 1 Emily Esposito Fulkerson 2018-05-08T16:37:32+00:00 2018-05-08T16:37:32+00:00 <p><img alt="alejandro_objectintrospection_3.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/AlejandroHitti/alejandro_objectintrospection_3(1)._CB495111267_.gif._CB495111264_.png?t=true" style="display:block; height:320px; margin-left:auto; margin-right:auto; width:800px" /><br /> Object introspection (also called metadata or reflection) is a cool feature that&nbsp;gives users information about their objects and data types at run time. This means you can use information about an object in your favor to perform cool tricks.</p> <p><img alt="alejandro_objectintrospection_3.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/AlejandroHitti/alejandro_objectintrospection_3(1)._CB495111267_.gif._CB495111264_.png?t=true" style="display:block; height:320px; margin-left:auto; margin-right:auto; width:800px" /></p> <p>Object introspection (also called metadata or reflection) is a cool feature that&nbsp;gives users information about their objects and data types at run time. This means you can check which variables an object has, their values, and their types, and use this information in your favor to perform cool tricks. GameMaker has some of this functionality implemented already, but due to backward compatibility and decisions on how to handle their data types, a few of these functions don’t work as you’d expect them to. Maybe once they implement data structures as true types and not just handles, and treat boolean as its own type, we could come back to this project and improve how it works. However, this is the best solution I could find with what we have today.</p> <p>It may not be obvious at first what you can do with this metadata from your objects, but here are a few examples of what is possible:</p> <div> <ul> <li> <p>Serialization and deserialization</p> </li> <li> <p>Debug draw information about an object to the GUI</p> </li> <li> <p>Inspect and modify all the values from an object using a custom editor</p> </li> </ul> <p>A decent approach to all these problems would be to write a script or user event for every object you want to serialize/inspect and call that. The problem is that this solution isn’t scalable, and would get harder to maintain as the project grows. My solution is to have scripts for every data basic data type, alongside a database of objects with their variables and types. We can then use this information to create a generic function that achieves our purpose trivially since we can reuse the same functions for every object. It is also possible to do this recursively, so you can inspect the variables of an object if you have a reference to it inside of another one.</p> <p>That last paragraph may have been a tad confusing, so let’s get started with the code and it should make more sense.</p> <p>First, we’ll make an object that will hold the information about every object. I called it <strong>oOI_Manager</strong>. Activate the <strong>persistent</strong> flag on the object since we need it to be active all the time. Next, write this code in the create event:</p> <pre> <code>// oOI_Manager Create event // Ensures there's only one instance of this manager Singleton(); // Enum that lists all valid data types (more can be added if needed) enum OI_VarTypes { Int = 0, Float, Bool, String, Enum, Object } // Create a global variable to easily access the manager global.OI_Manager = id; _objTypeMap = ds_map_create(); // Map of 2D arrays to store objects and variable definitions _currObject = noone; // Keeps track of the object we are defining _currIndex = 0; // Keeps track of the variable index for the current object </code></pre> <p>Breaking the code down, we first see we have a script called <strong>Singleton</strong> that ensures there’s only one copy of this object in the game. It’s a simple script that looks like this:</p> <pre> <code>// Singleton Script if (instance_number(object_index) &gt; 1) instance_destroy();</code></pre> <p>We then create an enumerator with all the data types we will be storing for now. Since this is part one of the article, I will cover the basic ones, and we will address data structures in the next post because it requires a bit more work. It is also useful to create a global variable and pass it the id of this object so we can access it easily, but it’s not necessary as you can use <strong>instance_find</strong> to get the first instance which should be the only one.</p> <p>Last, we have the map where we will store the description about our objects, and two variables to keep track of which object we are describing and the variable index we are on. I will cover that later.</p> <p>When I’m working on new features like this one, I usually start by writing how I want the interface to look like, and then I code the actual functions. Here, I decided this is what I was going for:</p> <pre> <code>// Create event of the object you want to describe if (OI_DefineBegin(object_index) { OI_Add(&quot;varName&quot;, OI_VarTypes.Int); OI_Add(&quot;varName2&quot;, OI_VarTypes.String); OI_DefineEnd(); }</code></pre> <p>It is pretty straightforward. You call a function to start the description (which returns false if the object has already been described, skipping the rest of the function calls). You then add all the variables you want to keep track of, and you end it.&nbsp;</p> <p>Let’s write these three functions now, starting with <strong>OI_DefineBegin</strong>. Our goal with this function is to set all the initial values to our variables and to set the <strong>currObject</strong> variable to the one that called the function. This is what it all looks like:</p> <pre> <code>// OI_DefineBegin // Get the parameters var object = argument0; // Get a handle to the OI_Manager var manager = global.OI_Manager; // Show warning for misuse of the function if (manager._currObject != noone) { show_debug_message(&quot;Warning: OI_DefineBegin was called, but a previous call wasn't closed using OI_DefineEnd.&quot;); Return false; } // If the object already has a definition, skip it. if (ds_map_exists(manager._objTypeMap, object)) Return false; // Set initial values manager._currObject = object; manager._currIndex = 0; // Set an empty 2D in the object's map slot var arr2D; arr2D[0, 0] = 0; manager._objTypeMap[? object] = arr2D; // We are ready to accept variables now return true;</code></pre> <p>The first few lines are making a variable for the argument passed in, getting a reference to the manager, and checking if the function is being used correctly and there isn’t another object being described. Next, we check to see if the object has already been described, since multiple instances of the same object can call this function and we only need it to happen once, so we return false. We then set the current object to the one passed in, and set our current variable to zero. The next section may seem weird, but this is the only way I found worked to make each entry in the map be an empty 2D array, which is how we will be storing our variables and information. The data structure will look something like this:</p> <p>&nbsp;</p> <p><img alt="alejandro_objectintrospection_1.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/AlejandroHitti/alejandro_objectintrospection_1(1)._CB495111264_.png?t=true" style="display:block; height:320px; margin-left:auto; margin-right:auto; width:800px" /></p> <p style="text-align:center"><em>This is a rough representation of the data structure we are using. Maps are usually represented by trees, but in order to keep the drawing simple, I made it look like an array or list.</em></p> <p>Once we create the array and assign it to the map entry, we return true to specify that we are ready to receive variables. But before we write the code for adding variables, let’s close the loop and work on the <strong>OI_DefineEnd</strong> script, which will clean up variables and prepare us for the next object description.</p> <pre> <code>// OI_DefineEnd Script // Get a handle to the manager var manager = global.OI_Manager; // Warning if the functions is being misused if (manager._currObject == noone) { show_debug_message(&quot;Warning: OI_DefineEnd was called with no prior call to OI_DefineBegin.&quot;); return; } // Unset the current object manager._currObject = noone; manager._currIndex = 0;</code></pre> <p>Above we are checking to see if the function is being used correctly, and if it is, we are unsetting the current object and resetting the current variable index.</p> <p>Finally, we will write what is arguably the most important part of this system, the <strong>OI_Add</strong> script. Note that this script will be changed slightly later on to account for variable types that require more information, such as enumerators and data structures, but let’s keep it simple for now. Our aim is to take in the variable name and type passed in and set it in the correct position in the map entry and the 2D array inside. Here is the code:</p> <pre> <code>// OI_Add Script // Get the parameters var varName = argument[0]; var type = argument[1]; // Get a handle to the OI_Manager var manager = global.OI_Manager; // Warning if the functions is being misused if (manager._currObject == noone) { show_debug_message(&quot;Warning: OI_Add was called without calling OI_DefineBegin first.&quot;); return; } // Set the variable name and type in the current index of the array, in the object map slot. var definition = manager._objTypeMap[? manager._currObject]; definition[@ manager._currIndex, 0] = varName; definition[@ manager._currIndex, 1] = type; // Advance the index ++manager._currIndex;</code></pre> <p>We will grab the first two variables, using the array notation this time around, since later on we might get more than two variables, so we need the flexibility. We then do error checking which should look familiar by now. Last, we find the map slot for this object, access the current array index, and set the variable name in the first slot, followed by the variable type in the second slot. We then advance the current index and wait for more input.</p> <p>That is all! We are now ready to describe our objects and keep a database handy to access at run time. Let’s make a test object to see how it should be used. I called mine <strong>oPlayerTest</strong>. In the create event, set all your variables and descriptions like this:</p> <pre> <code>// oPlayerTest Create Event if (OI_DefineBegin(object_index)) { OI_Add(&quot;_hp&quot;, OI_VarTypes.Int); OI_Add(&quot;_name&quot;, OI_VarTypes.String); OI_Add(&quot;_isMoving&quot;, OI_VarTypes.Bool); OI_Add(&quot;_mana&quot;, OI_VarTypes.Float); OI_DefineEnd(); } _hp = 10; _name = &quot;Terry&quot;; _isMoving = false; _mana = 15.3; </code></pre> <p>It doesn’t matter if you describe the object first and declare the variables later, or vice-versa. It works either way, but I prefer it this way. To avoid trying to add variables on an object that has already been described, wrap the entire thing inside an if-statement, with the condition being the return value from <strong>OI_DefineBegin</strong> (it will work if you don’t, but you will see all those warning messages we wrote).</p> <h2>Optional change</h2> <p>The begin script takes the object index as a parameter. You can remove it and grab the object_index from the script itself, but if you do it this way, you can have object descriptions anywhere in your code, not just the create event of that object.</p> <p>Inside the conditional, we will add all the variables we want to keep track of. It doesn’t have to be every variable, but in this case it is. We need to pass two parameters for these basic types, which is the name of the variable as a string, and then the enum value corresponding to the data type. Remember that the string name has to be exactly the same as the variable, or else it won’t work when trying to retrieve the value. Once we are done adding variables, we have to call <strong>OI_DefineEnd()</strong> to close the loop, and we are done.</p> <p>Great! Now we have a way to build our database of objects and their types, so let’s move on to doing something useful with it. The easiest way to test it is working correctly is to create an inspect function that draws all the variables and their values to the GUI. We will start with the generic function the user will call, and it will handle every data type itself. Here’s what the <strong>OI_Inspect</strong> function looks like:</p> <pre> <code>// OI_Inspect Script // Get the parameters var instance = argument0; // Get a handle to the manager var manager = global.OI_Manager; // Get the object index from the instance var object = instance.object_index; var definition = manager._objTypeMap[? object]; if (!is_array(definition)) { show_debug_message(&quot;Warning: The object hasn't been defined yet.&quot;); return; } for (var i = 0; i &lt; array_height_2d(definition); ++i) { var varName = definition[i, 0]; // Get the variable value, if it exists var value; if (variable_instance_exists(instance, varName)) value = variable_instance_get(instance, varName); else { show_debug_message(&quot;Warning: The variable \&quot;&quot; + varName + &quot;\&quot; does not exist in the &quot; + object_get_name(instance.object_index) + &quot; object.&quot;); return; } switch(definition[i, 1]) { case OI_VarTypes.Int: OI_InspectInt(varName, value); break; case OI_VarTypes.Float: OI_InspectFloat(varName, value); break; case OI_VarTypes.Bool: OI_InspectBool(varName, value); break; case OI_VarTypes.String: OI_InspectString(varName, value); break; } ++manager._currIndex; } manager._currIndex = 0;</code></pre> <p>It may look like a long function, but it is mostly doing error checking. The important sections are where we grab the object description of the instance we passed in. We then loop through every variable, grabbing its value, and then we call the appropriate specific inspect function depending on the variable type. We do this by using a switch statement on the variable type and passing in the value. The function currently doesn’t work recursively, but we will fix that in part 2 of the article.</p> <p>We are almost there! We now have to create a function for every data type we want to inspect. It may seem like a lot, but in most projects the number will be smaller than the number of objects, if we had taken that approach from the beginning. I will list all the functions below since most are just one line.</p> <p><strong>OI_InspectInt</strong></p> <pre> <code>// Get the parameters var name = argument0; var value = argument1; // Draw the variable to the GUI draw_text(10, 15 * global.OI_Manager._currIndex, name + &quot;: &quot; + string(floor(value)));</code></pre> <p><strong>OI_InspectFloat</strong></p> <pre> <code>// Get the parameters var name = argument0; var value = argument1; // Draw the variable to the GUI draw_text(10, 15 * global.OI_Manager._currIndex, name + &quot;: &quot; + string(value));</code></pre> <p><strong>OI_InspectBool</strong></p> <pre> <code>// Get the parameters var name = argument0; var value = argument1; // Draw the variable to the GUI draw_text(10, 15 * global.OI_Manager._currIndex, name + &quot;: &quot; + (value ? &quot;True&quot; : &quot;False&quot;));</code></pre> <p><strong>OI_InspectString</strong></p> <pre> <code>// Get the parameters var name = argument0; var value = argument1; // Draw the variable to the GUI draw_text(10, 15 * global.OI_Manager._currIndex, name + &quot;: &quot; + value);</code></pre> <p>Excuse the magic numbers I used to position the items. This was just a quick fix, but you should find a more robust solution if you wish to use this specific functionality in your project.</p> <p>Last, we need to call this function in the Draw GUI event and pass it an instance id. We will do it inside the Draw GUI event of the <strong>oPlayerTest</strong> object for simplicity. It should look like:</p> <pre> <code>// oPlayerTest Draw GUI OI_Inspect(id);</code></pre> <p>I added some extra code to inspect each object only when you click on it, but I won’t show how to do that here. Instead, feel free to download the demo to try it yourself, but it’s quite trivial.</p> <p><img alt="alejandro_objectintrospection_2.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/AlejandroHitti/alejandro_objectintrospection_2(1)._CB495111267_.gif._CB495111264_.png?t=true" style="display:block; height:320px; margin-left:auto; margin-right:auto; width:800px" /></p> <p>I hope this example was useful to see the possibilities having a database like this one opens up. We could write a serialize/deserialize function that works the same way, or maybe add the variables of objects to a menu system (like ImGUI, with the<a href="https://rousr.itch.io/imguigml" target="_blank"> ImGuiGML extension</a> created by<a href="https://twitter.com/babyj3ans" target="_blank"> @babyj3ans</a>).</p> <h2>Adding a complex variable to the system</h2> <p>Before I close this article, I want to show you how to add a more complex variable to the system&nbsp;as a sneak peek of what the second part of this article will be about.</p> <p>We will now add enumerators to our system. Enums hold an integer value, represented as a string which is easier for humans to read. The issue is that there is no good way of grabbing that string from the integer, so we will need to pair them together. The first change will be in the <strong>oPlayerTest</strong> object, which now looks like this:</p> <pre> <code>// oPlayerTest Create Event - With Enums <strong>enum StatesPlayer { Idle, Run, Walk, Attack, Hurt, Dead } var statesArray = [ &quot;Idle&quot;, &quot;Run&quot;, &quot;Walk&quot;, &quot;Attack&quot;, &quot;Hurt&quot;, &quot;Dead&quot; ]</strong>; if (OI_DefineBegin(object_index)) { OI_Add(&quot;_hp&quot;, OI_VarTypes.Int); OI_Add(&quot;_name&quot;, OI_VarTypes.String); OI_Add(&quot;_isMoving&quot;, OI_VarTypes.Bool); OI_Add(&quot;_mana&quot;, OI_VarTypes.Float); <strong>OI_Add(&quot;_state&quot;, OI_VarTypes.Enum, statesArray);</strong> OI_DefineEnd(); } _hp = 10; _name = &quot;Terry&quot;; _isMoving = false; _mana = 15.3; <strong>_state = StatesPlayer.Idle;</strong></code></pre> <p>The sections you see bolded are the ones we added. Having to maintain an enum and an array of strings that match it is not the best choice, since you can forget to sync them leading to issues, but GameMaker doesn’t have a good way of doing this. Just keep both updated and the same moving forward. Next, we will pass the array as a second parameter to the <strong>OI_Add</strong> script. Last, we will add a variable that uses the enum to test.</p> <p>Our next change happens in the <strong>OI_Add</strong>, where we will take in every variable after the first two and save them in an array which will be helpful for passing extra information for more complex data structures.</p> <pre> <code>// OI_Add - With Enums // Get the parameters var varName = argument[0]; var type = argument[1]; <strong>var extras = 0; for (var i = 2; i &lt; argument_count; ++i) extras[i] = argument[i]</strong>; // Get a handle to the OI_Manager var manager = global.OI_Manager; // Warning if the functions is being misused if (manager._currObject == noone) { show_debug_message(&quot;Warning: OI_Add was called without calling OI_DefineBegin first.&quot;); return; } // Set the variable name and type in the current index of the array, in the object map slot. var definition = manager._objTypeMap[? manager._currObject]; definition[@ manager._currIndex, 0] = varName; definition[@ manager._currIndex, 1] = type; <strong>if (is_array(extras)) for (var i = 2; i &lt; array_length_1d(extras); ++i) definition[@ manager._currIndex, i] = extras[i];</strong> // Advance the index ++manager._currIndex;</code></pre> <p>Just like before, the bold text shows the newly added code. We store any extra variables passed in an array, and we later add that information as part of the array entry for that variable&nbsp;to be used later. We then add this new variable type to the switch statement inside <strong>OI_Inspect</strong> and pass the array of strings as the second parameter, like so:</p> <pre> <code>case OI_VarTypes.Enum: OI_InspectEnum(varName, value, definition[i, 2]); break;</code></pre> <p>And the <strong>OI_InspectEnum</strong> function is quite similar to the rest, looking like this:</p> <pre> <code>// Get the parameters var name = argument0; var value = argument1; var strings = argument2; // Draw the variable to the GUI draw_text(10, 15 * global.OI_Manager._currIndex, name + &quot;: &quot; + strings[value]);</code></pre> <p>Now, when we inspect our object, we should see the correct value displayed as a string.</p> <p><img alt="alejandro_objectintrospection_3.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/AlejandroHitti/alejandro_objectintrospection_3(1)._CB495111267_.gif._CB495111264_.png?t=true" style="display:block; height:320px; margin-left:auto; margin-right:auto; width:800px" /></p> <p>In part two of this article, we will add more data structures, such as arrays, lists, and maps, and implementing the ability to pass another object as a parameter, allowing for recursive inspection. I will also cover how to write serialize/deserialize functions using this system, so keep an eye out for it.</p> <h2>Reference links</h2> <ul> <li><a href="https://drive.google.com/open?id=1twv2CUn_WvNeHn3Cf_Z7VYWoZHxlqzx2" target="_blank">Object Introspection - DEMO</a></li> <li><a href="https://docs2.yoyogames.com/source/_build/3_scripting/3_gml_overview/variable_functions/index.html" target="_blank">Variable Functions Documentation</a></li> <li><a href="https://en.wikipedia.org/wiki/Type_introspection" target="_blank">Type Introspection - Wikipedia</a></li> </ul> <h2>Conclusion</h2> <p>I hope this article proved useful! This is a powerful system that can be expanded and tailor it to your project’s needs. If you have questions, feel free to contact me on Twitter (<a href="http://twitter.com/AleHitti" target="_blank">@AleHitti</a>). Also, make sure you follow me to be notified when I release new articles. Until next time!</p> <div> &nbsp; </div> <p style="text-align:center"><img alt="AlejandroBio.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/default/AlejandroBio._CB512098171_.jpg?t=true" style="height:145px; width:583px" /></p> <p style="text-align:center"><em>Alejandro Hitti is a videogame Programmer and Designer from Venezuela. Although his background is in C++ and working using custom-made game engines, his two commercial games, INK and HackyZack, were made using GameMaker Studio 1.4. With the release of GameMaker Studio 2, that became his engine of choice. The novelty of GMS2, paired with his knowledge of the previous version, ignited his interest to create tutorials that focus on this new engine.</em></p> </div> /blogs/appstore/post/3b4da986-260e-464b-b7ad-0dbd4671ef95/amazon-s-mobile-masters-tournament-powered-by-gameon Amazon's Mobile Masters Tournament Powered by GameOn Laura Pezdek 2018-05-04T23:34:58+00:00 2018-05-04T23:36:01+00:00 <p><img alt="MM_banner_050418.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Laura/MM_banner_050418._CB496930786_.png?t=true" style="display:block; height:342px; margin-left:auto; margin-right:auto; width:700px" /></p> <p>We're bringing back <a href="https://www.amazon.com/b?node=17742206011" target="_blank">Mobile Masters</a>, an esports tournament where both casual and pro mobile game players compete side-by-side for a $100,000 prize pool.</p> <p><img alt="MM_banner_050418.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Laura/MM_banner_050418._CB496930786_.png?t=true" style="display:block; height:342px; margin-left:auto; margin-right:auto; width:700px" /></p> <p>We're bringing back <a href="https://www.amazon.com/b?node=17742206011" target="_blank">Mobile Masters</a>, an esports tournament where both casual and pro mobile game players compete side-by-side for a $100,000 prize pool.</p> <h2><strong>Mobile Masters powered by GameOn</strong></h2> <p>This year's lineup of games includes Legacy Wars, Survival Arena, World of Tanks Blitz, and Critical Ops with Legacy Wars and Survival Arena being powered by Amazon <a href="https://developer.amazon.com/gameon" target="_blank">GameOn</a>, a set of flexible APIs built on AWS cloud infrastructure that works on any operating system.<br /> <br /> “In talking with nWay and Game Insight, we recognized both developers were looking for ways to scale their competitive play,” said Marja Koopmans, Director, Amazon Competitive Gaming. “With GameOn, they can now run qualifiers across the globe for Mobile Masters, identify the best players in their games, award prizes to participants, and nurture talent creating a stronger sense of community. We’re thrilled to help these developers realize their vision and host their top players at Mobile Masters this summer.”</p> <h2><strong>Join the qualifiers</strong></h2> <p>If you'd like to earn a spot, Power Rangers: Legacy Wars and Survival Arena will be running early round qualifiers for players to earn a spot in the tournament starting May 5. Winners from qualifying rounds will win an all-expenses paid trip to Seattle for the tournament and will compete for their share of over $40,000 during the Championship. And pre-determined teams will be facing off in World of Tanks Blitz and Critical Ops, where a champion will be crowned for each game.</p> <p>Tune in to watch the action by following us on <a href="https://www.twitch.tv/amazongameon" target="_blank">Twitch</a>, <a href="https://www.facebook.com/amazonappstore/" target="_blank">Facebook Live</a>, and <a href="https://www.youtube.com/user/AmazonAppstore" target="_blank">YouTube</a>.<br /> <br /> For rules and qualifying information, visit <a href="http://www.amazon.com/mobilemasters" target="_blank">www.amazon.com/mobilemasters</a> for more details.<br /> &nbsp;</p> <p style="text-align:center"><a href="https://developer.amazon.com/gameon" target="_blank">Learn more about GameOn</a></p> /blogs/appstore/post/8c7f2f70-b484-4999-9986-c87532157683/gamemaker-basics-vfx GameMaker Basics: VFX Emily Esposito Fulkerson 2018-05-03T17:04:05+00:00 2018-05-03T17:04:05+00:00 <p><img alt="vfx-nathanranney-image5.gif" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/GameMakerStudio2/vfx-nathanranney-image5._CB503247269_.gif?t=true" style="display:block; height:338px; margin-left:auto; margin-right:auto; width:600px" /><br /> Today, I would like to go over how to create effects in your games.&nbsp;We will be creating an effect object, controlling its behavior with a state machine, and using scripts to streamline the creation of these objects in game.</p> <p><img alt="vfx-nathanranney-image5.gif" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/GameMakerStudio2/vfx-nathanranney-image5._CB503247269_.gif?t=true" style="display:block; height:338px; margin-left:auto; margin-right:auto; width:600px" /><br /> Howdy folks! Welcome to yet another GameMaker Basics tutorial.&nbsp;Today, I would like to go over how to create effects in your games. If you have been following along with my previous <a href="http://m.amazonappservices.com/GameMakerResources" target="_blank">GameMaker Basics blogs</a>, then a lot of this may seem familiar to you. We will be creating an effect object, controlling its behavior with a state machine, and using scripts to streamline the creation of these objects in game. I would also like to point out that this is not a tutorial on how to draw, or design, effects. I’m no artist! However, you can click <a href="https://drive.google.com/drive/folders/16_onQR55E9-tf-IEmt_VZZRE2aAS0IBx" target="_blank">here</a> to get the set of effects that I am using in this post.&nbsp;</p> <h2>Set up</h2> <p>If you are following along with the sprites I have provided, go ahead and get those set up in GameMaker. I went ahead and named them after the sprite files.</p> <p><img alt="vfx-nathanranney-image1.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/GameMakerStudio2/vfx-nathanranney-image1._CB503247279_.png?t=true" style="display:block; margin-left:auto; margin-right:auto" /><br /> After you have all of the sprites added to your project, go ahead and create an object called <strong>oEffect</strong>. Do not assign a sprite to this object! We will be changing the sprite based on the type of effect we are creating.</p> <p>Open up the <strong>oEffect </strong>object and add the following code to the <strong>create event</strong>.</p> <p><strong>oEffect Create Event</strong></p> <pre> <code>effectType = -1; animationSpeed = 0.25; xSpeed = 0; ySpeed = 0;</code></pre> <p>Using the <strong>effectType</strong> variable, we will be able to change the behavior and sprite of our effects very easily using a switch statement. <strong>animationSpeed</strong> is pretty much what it sounds like. This will let us control how quickly the animation plays for our effects. <strong>xSpeed</strong> and <strong>ySpeed</strong> will control the horizontal and vertical movement of the effects.</p> <p>While we are working on the <strong>oEffect</strong> object, let's go ahead and set up the switch statement. For this, we want to use the <strong>end step</strong> <strong>event</strong>.</p> <p><strong>oEffect End Step Event</strong></p> <pre> <code>switch ( effectType ) { case 0: //smoke break; case 1: //spark 1 break; case 2: //spark 2 break; case 3: //spark 3 break; }</code></pre> <p>This is just a general outline for our effect controls. We will come back to this later. Now, create one more object and name it <strong>oControl</strong>. This is what we will use to read our button presses, and spawn in our effects. Add the following code.</p> <p><strong>oControl Create Event</strong></p> <pre> <code>effectToCreate = 0;</code></pre> <p>This variable will allow us to easily change the effect we are spawning in game with a mouse click. The last thing we need to do before setup is complete&nbsp;is initialize&nbsp;our enums (for more information on enums, check on this blog post I wrote on <a href="https://developer.amazon.com/blogs/appstore/post/c92030bb-6ab8-421f-b0da-a7231a59561d/gamemaker-basics-state-machines" target="_blank">state machines</a>).</p> <p>Create a new script and name it <strong>enum_init</strong>. Add the following code.</p> <p><strong>enum_init script</strong></p> <pre> <code>enum effects { smoke, spark1, spark2, spark3 }</code></pre> <p>This is basically just a list of variables that equal zero to three. This is what we set up our switch statement to use in the previous step. Finish up by creating a new room, whatever size you want, and drop your <strong>oControl</strong> object in the room.</p> <h2>Creating effect objects</h2> <p>Now that we have the basic setup out of the way, we can start making our effects appear on screen. We will do this by making the <strong>oEffect </strong>objects get created when we click the left mouse button. This is, of course, just an example of how to create these effects. In your game, you may want to create effects when a character is hurt, or when a coin is picked up. The same methods apply.</p> <p>Let’s go back to the <strong>oControl </strong>object and set up some mouse clicks.</p> <p><strong>oControl Step Event</strong></p> <pre> <code>//change effect if ( keyboard_check_pressed( vk_space ) ) { effectToCreate ++; if ( effectToCreate &gt; effects.spark3 ) { effectToCreate = 0; } } //create the effect if ( mouse_check_button_pressed ( mb_left ) ) { //create effect }</code></pre> <p>The first bit of code will allow us to change the effect we are trying to create by clicking the mouse button. It cycles from zero to three,and then back to zero, when the spacebar is pressed. You’ll notice that we don’t actually have any code to create an effect on mouse click. That is because we are going to create a script that will make creating effects much easier. Go ahead and create a new script and name it <strong>effect_create</strong>.</p> <p><strong>effect_create script</strong></p> <pre> <code>///effect_create( effectType, xPosition, yPosition, image_angle ); _e = instance_create(argument1,argument2,oEffect); _e.effectType = argument0; _e.image_angle = argument3; return _e;</code></pre> <p>This script will make it very easy for us to create an effect whenever we want, wherever we want on the screen. When calling this script, four arguments are required. The first is the type of effect we want to create. The second and third arguments are the x and y position of where the effect will be created on screen. The final argument is the angle of the effect.</p> <p>Now that we have the script, we can put it use. Head back to the <strong>oControl step event</strong> and update the //create the effect portion of the code.</p> <p><strong>oControl Step Event</strong></p> <pre> <code>//create the effect if ( mouse_check_button_pressed ( mb_left ) ) { e = effect_create ( effectToCreate, mouse_x, mouse_y, choose(0,90,180,270)); }</code></pre> <p>This will create an effect at the mouse position, at a random 90 degree angle. However, we have yet to define what these effects actually are. If you were to run the game and start clicking, nothing would happen. Which brings us to the next section…</p> <h2>Effect behavior</h2> <p>After setting up the guts, creating new scripts, adding in the sprites, and making our clicker work, we are finally ready to draw some effects to the screen! Open the <strong>oEffect</strong> object and let's look at the <strong>end step event. </strong>We need to add some new code that will be universal to all effects, and some code to assign sprites to each case in the switch statement.</p> <p><strong>oEffect End Step Event</strong></p> <pre> <code>x += xSpeed; y += ySpeed; image_speed = animationSpeed; switch ( effectType ) { case 0: //smoke sprite_index = sprSmoke; break; case 1: //spark 1 sprite_index = sprSpark_1; break; case 2: //spark 2 sprite_index = sprSpark_2; break; case 3: //spark 3 sprite_index = sprSpark_3; break; }</code></pre> <p>First, we want to change the x and y position of the effect based on the current <strong>xSpeed </strong>and <strong>ySpeed</strong>. This is universal for all of our effects. Since both of these variables are initialized as zero, the effect will NOT move unless you adjust either of those variables for the effect in question. I’ve also set the <strong>image_speed </strong>to equal our variable <strong>animationSpeed</strong>. This way we can change <strong>animationSpeed</strong> to whatever we want, whenever we want, and the sprite will be animated at that speed.</p> <p>You’ll also see that I have added a <strong>sprite_index </strong>line to each switch case. By changing the <strong>sprite_index,</strong> we are changing the actual sprite which is drawn on screen.</p> <p>Now, if you run the game, you should be able to click and an effect will be created. If you press the spacebar, the next time you click the effect should be different. However there is a problem… the effects are staying on screen. We need to delete the effect object once the animation has finished playing. For that, we need a script.</p> <p>Create a new script and name it <strong>effect_destroy</strong>.</p> <p><strong>effect_destroy script</strong></p> <pre> <code>if ( floor ( image_index ) &gt;= sprite_get_number ( sprite_index ) - 1 ) { instance_destroy(); }</code></pre> <p>This is a very simple script that checks the current frame of animation the effect object is showing, and destroys the object if the current frame is higher than the maximum number of animation frames in the sprite. The <strong>sprite_get_number();</strong> function will return the total number of frames in whatever sprite it is checking. In this case, our <strong>oEffect</strong> object is a different <strong>sprite_index</strong> based on the kind of effect that is playing. Open your <strong>oEffect end step event</strong> and add <strong>effect_destroy();</strong> to the very last line. Run the game again and your effects should now delete after the animation has played.<br /> &nbsp;</p> <p><img alt="vfx-nathanranney-image2.gif" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/GameMakerStudio2/vfx-nathanranney-image2._CB503247273_.gif?t=true" style="display:block; margin-left:auto; margin-right:auto" /></p> <p>At this point we are technically done, but we have a setup that allows us to make a lot of changes to how effects behave on screen. For example, if I add <strong>ySpeed = -1; </strong>to the first case, the smoke effect will rise. If you were to add <strong>ySpeed = 1;</strong> the smoke would fall.<br /> &nbsp;</p> <p><img alt="vfx-nathanranney-image3.gif" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/GameMakerStudio2/vfx-nathanranney-image3._CB503247272_.gif?t=true" style="display:block; margin-left:auto; margin-right:auto" /></p> <p><img alt="vfx-nathanranney-image4.gif" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/GameMakerStudio2/vfx-nathanranney-image4._CB503247274_.gif?t=true" style="display:block; margin-left:auto; margin-right:auto" /></p> <p>Here are a few more examples using rotation, scale, and a much lower animationSpeed.<br /> &nbsp;</p> <p><img alt="vfx-nathanranney-image5.gif" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/GameMakerStudio2/vfx-nathanranney-image5._CB503247269_.gif?t=true" style="display:block; margin-left:auto; margin-right:auto" /></p> <p><img alt="vfx-nathanranney-image6.gif" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/GameMakerStudio2/vfx-nathanranney-image6._CB503247285_.gif?t=true" style="display:block; margin-left:auto; margin-right:auto" /></p> <p><img alt="vfx-nathanranney-image7.gif" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/GameMakerStudio2/vfx-nathanranney-image7._CB503247287_.gif?t=true" style="display:block; margin-left:auto; margin-right:auto" /><br /> &nbsp;</p> <h2>More resources</h2> <ul> <li><a href="https://developer.amazon.com/blogs/appstore/post/c92030bb-6ab8-421f-b0da-a7231a59561d/gamemaker-basics-state-machines" target="_blank">Blog post on state machines</a>. This covers enums and switch statements in greater detail.</li> <li><a href="https://drive.google.com/open?id=1AkN26prcRnQ4Vf6o05NjROnoi6bZ4Wmm" target="_blank">Project file download</a></li> </ul> <p>So, there you have it. By setting up effects using a single object, and a switch statement, it becomes very easy to manage a large number of different effects from a single location in your GameMaker project. You can add as many cases as you have effects in your game, and make adjustments to each one without having to create new objects or scripts. Thank you for taking the time to read over this, and I’ll catch you next time. As always, you can reach me on <a href="https://www.twitter.com/ratcasket" target="_blank">Twitter</a> or visit my <a href="http://www.ratcasket.com/" target="_blank">website</a> for more gamedev stuff.</p> <div> &nbsp; </div> <p style="text-align:center"><a href="https://www.twitter.com/ratcasket"><img alt="NathanRBio.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/default/NathanRBio._CB513300692_.jpg?t=true" /></a></p> <p style="text-align:center"><em>Nathan Ranney is the founder of game development studio <a href="http://www.gutterarcade.com" target="_blank">Gutter Arcade</a>. He's best known for the creation and development of Knight Club, an online indie fighting game.&nbsp;</em></p>