Appstore Blogs Appstore DeveloperBlog /blogs/appstore/feed/entries/atom 2018-07-20T19:14:01+00:00 Apache Roller /blogs/appstore/post/28441cc2-c8d8-470d-8486-73ab9ed28a5c/success-story-eden-games-increases-gear-club-s-tournament-retention-by-20-with-gameon Success Story: Eden Games Increases Gear.Club's Tournament Retention by 20% with GameOn Emily Esposito Fulkerson 2018-07-20T18:06:08+00:00 2018-07-20T19:14:01+00:00 <p><img alt="Gearclub-casestudy-hero-0720.png" src="" /></p> <p>Compared to other tournaments they ran in the past, Eden Games reports a 20% increase in retention when real-world prizes were offered via GameOn.</p> <p><img alt="Gearclub-casestudy-hero-0720.png" src="" style="display:block; height:311px; margin-left:auto; margin-right:auto; width:700px" /><br /> We can't all race McLarens down city streets, but we can get one step closer with <a href="" target="_blank">Gear.Club</a>, the ultimate racing game by Eden Games. Gear.Club creates a realistic driving experience, letting you collect the most gorgeous and powerful cars in your performance shop and competing live with your friends through unlimited races, championships, and events.<br /> <br /> Their challenge: bring new users to their game and increase engagement of current players to result&nbsp;in more driving time. To accomplish this, they integrated Amazon GameOn to easily run cross-platform tournaments, including leaderboards, and to award players with real-world prizes fulfilled by Amazon.</p> <p>&nbsp;</p> <p><img alt="gameon-gearclub-casestudy-0720.png" src="" style="display:block; height:349px; margin-left:auto; margin-right:auto; width:700px" /><br /> <br /> “We found the idea of rewarding tournaments with physical products shipping from to be a very compelling proposition for the mobile esports ecosystem,” said David Nadal, CEO of Eden Games. “There's obviously no better partner in the world than Amazon to execute on that vision, taking into consideration the logistics behind the scenes.”</p> <h2>Real-world prizes lead to a boost in tournament retention</h2> <p>In March 2018, Eden Games ran its U.S. Series Tournament in Gear.Club, inviting players to race to the top of the leaderboard for a chance to win an Amazon Echo device. While big cash pools may be successful with PC games, David has seen more success with real-world prizes in mobile games.<br /> <br /> “We are totally in love with the idea of offering physical products to reward competitive mobile gaming. Physical and tangible beats digital when it comes to rewarding players for major achievements. And, real-world prizing feels more playful than straight cash,” said David.<br /> <br /> And, with shorter tournament cycles and more regular chances to win prizes, players are incentivized to keep coming back.<br /> <br /> “They were quite excited about the prospect of winning a device!”<br /> <br /> This excitement is leading to real business results. Compared to other tournaments they ran in the past, Eden Games reports a 20% increase in retention when real-world prizes were offered via GameOn.</p> <h2>No client-side updates required</h2> <p>With a set of flexible APIs built on the AWS cloud infrastructure and compatible with any operating system, GameOn was easy to integrate into Gear.Club's esports tournament design.<br /> <br /> “The GameOn APIs are easy to integrate and can certainly save any developer a lot of time compared to coding and maintaining a tournament system all by yourself. It's been well tested, scales to our needs, and works flawlessly” said David.<br /> <br /> Gear.Club's esports tournament design is essentially one live event composed of three races — each with independent leaderboards with a specific car.</p> <p>&nbsp;</p> <p><img alt="Esport_Introduction_World_Gearclub_Casestudy_0720.png" src="" style="display:block; height:394px; margin-left:auto; margin-right:auto; width:700px" /><br /> <br /> Given the GameOn APIs, David achieved this by creating three GameOn tournaments (one for each race) with the following specifications:</p> <pre> <code>{ ... &quot;matchesMax&quot;: 1, &lt;-- All players should enter the same match to compete against each other &quot;matchesPerPlayer&quot;: 1, &lt;-- Obviously, there can only be one match per player&quot;playerAttemptsPerMatch&quot;: 32767,&lt;-- We want players to be able to improve their time infinitely so we initialize this field to the max allowed value &quot;playersPerMatch&quot;: 1000000000, &lt;-- We want the whole world to play, so we initialize this field to the max allowed value &quot;scoreType&quot;: &quot;INDIVIDUAL&quot;, &lt;-- Individual scoring to take the best score submitted &quot;winType&quot;: &quot;LOWEST&quot;, &lt;-- Lowest to indicate to the API that the best score is the lowest one .... }</code></pre> <p>Eden Games decided to use a classic Java http client to connect to the GameOn API. This way, the server maintains the connection between the game's back-end and the player's client. This is invisible to the player and allows Eden Games to maintain the GameOn API code without disrupting the gameplay or forcing updates to the client.</p> <h2>A natural pillar for competitive mobile gaming</h2> <p>“GameOn is a natural pillar for us to execute our mobile vision. That's why we onboarded as a launch partner in full speed as soon as the lights went green,” said David.<br /> <br /> Competitive gameplay is inherent to the racing genre, thanks to the similarity between virtual racing and actual motorsport. However, David also thinks GameOn would be a strong match for any other competitive title.<br /> <br /> “If your title offers competitive gameplay, I would definitely recommend Amazon GameOn. Shipping physical goods comes with an extra layer that you couldn't even imagine building on your own.”<br /> <br /> “In a way, Amazon has been preparing for this since the late twentieth century. That's a pretty steep head-start in any kind of race!”</p> <h2>Get started with GameOn</h2> <p>Are you new to GameOn? <a href="" target="_blank">Get started today</a> in three easy steps: sign into GameOn console, register your game, and get your API key.<br /> <br /> You can also learn more about how to integrate competitive mobile gaming by watching <a href="" target="_blank">this webinar</a> on-demand.</p> <h2>About Eden Games</h2> <p><img alt="Edenlogo-0720.png" src="" style="display:block; height:226px; margin-left:auto; margin-right:auto; width:200px" /><br /> <a href="" target="_blank">Eden Games</a> was founded in Lyon, France in 1998 to develop one of the most successful game franchises on PlayStation systems: V-Rally. In 2000, the studio expanded its racing expertise with the development of Need For Speed: Porsche for EA. Eden Games experimented in other genres before returning to its roots with Test Drive Unlimited, the first massive open world racing game franchise.<br /> <br /> Eden Games today is managed by two of its original co-founders, David Nadal and Jean-Yves Geffroy. The studio is composed of experienced veterans and talented young developers, all driven by the same passion for cars, high-end design, and technology. Millennial Esports Corp owns 82.5% of the company.</p> /blogs/appstore/post/df6c8b92-a474-446f-87fa-252e3cc93686/object-type-introspection-in-gamemaker-part-2 Object Type Introspection in GameMaker - Part 2 Emily Esposito Fulkerson 2018-07-18T17:53:33+00:00 2018-07-18T17:53:33+00:00 <p><img alt="Object-introspection-image1-0718.png" src="" style="display:block; height:506px; margin-left:auto; margin-right:auto; width:900px" /></p> <p>In<a href=";ch=Inf&amp;chlast=Inf&amp;pub=AlH&amp;publast=AlH&amp;type=org&amp;typelast=org" target="_blank">&nbsp;part one</a> of this article series, we created our database and used it to display the values of each variable on the GUI. We only covered how to add basic data types as well as enums and other objects. This time, we will do some modifications to the original database.</p> <p><img alt="Object-introspection-image1-0718.png" src="" style="display:block; height:506px; margin-left:auto; margin-right:auto; width:900px" /></p> <p>In<a href=";ch=Inf&amp;chlast=Inf&amp;pub=AlH&amp;publast=AlH&amp;type=org&amp;typelast=org" target="_blank">&nbsp;part 1</a> of this article series, we created our database and used it to display the values of each variable on the GUI. We only covered how to add basic data types as well as enums and other objects. This time, we will do some modifications to the original database, and work on including data structures. Because of the nature and size of data structures, we will not be displaying the values on the screen as last time. Instead, we will serialize them into a text file with our custom format, demonstrating a second useful case where we can use this library.</p> <p>Before we begin, I suggest you download this file (<a href="" target="_blank">Object Introspection Part 2 Project Files</a>), and select the one called <strong>ObjectIntrospection_Part2_Start.yyz</strong>, which I will use as our starting point. It’s pretty much what we ended up with after following part 1&nbsp;of the article, but with a couple of name changes, and some tweaks that had to be made to allow for data structures to be added. I also included three objects with several cases to stress test our program at the end.</p> <p>When you run the game, this is what you’ll get:</p> <p><img alt="Object-introspection-image1-0718.png" src="" style="display:block; margin-left:auto; margin-right:auto" /></p> <p>Let's get started.</p> <h2>Changes from the previous version</h2> <p>As mentioned above, I changed a few things to make the code more readable and make some new things possible. These changes are:</p> <ul> <li>Enumerators now have a lowercase E at the beginning of their name, to make them easier to identify.</li> <li> <p>We added a new enum in our <strong>oOI_Manager</strong> object called <strong>eOI_VarInfo</strong>. It is used to address the 2D array in our definitions more clearly, by specifying which part of the data to grab, between the name, type (or types array), and extra data we may need.</p> </li> <li> <p>The type section in our definition can now be an array instead of just an enum value. We will cover later why this change is important.</p> </li> <li> <p>The objects we are using have different values in them as I changed my tests. Also note that all types are passed in as arrays even if it’s just one element. This will make sense later. Know that some lines are commented out in <strong>oPlayer</strong> and <strong>oAlly</strong>, but we will uncomment them when we implement the corresponding functions for testing.</p> </li> </ul> <p>Everything else should be the same. I removed all our <strong>Inspect</strong> functions since we won’t use them this time around.</p> <h2>Serialization format</h2> <p>The format we will use is not a standard one like JSON or XML (but you can definitely implement it to mimic those if you want). The general structure follows this form: the variable name, followed by a colon, then the type of the variable, and last we have an equal sign followed by the value of the variable. With data structures, the equal sign is followed by an opening bracket and then a list of the values using the same format. Here are&nbsp;two examples:</p> <pre> <code>Variable Name : Type (Basic) = Value</code></pre> <pre> <code>Variable Name : Type (Data Structure) = { Index0 : Type = Value Index1 : Type = Value Index2 : Type = Value }</code></pre> <p>Now we know what our end goal is, let’s add some things to the manager to make our life easier later on.</p> <h2>oOI_Manager additional variables</h2> <p>To serialize data structures and objects, we need to go deeper each time. Keeping track of variables when you are inside a recursive call to a function can be tricky. Luckily, we have a global manager that can store that information for us every step of the way. It also makes our function calls a lot cleaner since we don’t have to keep passing the same values around all the time (such as the filename or object ids). At the bottom of your <strong>oOI_Manager’s</strong> create event, these should be your variables:</p> <pre> <code>// oOI_Manager’s Create Event _currObject = noone; // Keeps track of the object we are working on _currInstance = noone; // Keeps track of the object instance we are working on _currIndex = 0; // Keeps track of the variable index for the current object _currDepth = 0; // Keeps track of the current variable depth when using recursion _currExtra = 0; // Stores the extra data information _currTypes = 0; // Stores the types array _currValue = 0; // Stores the value of the current variable _indentLvl = 0; // Indenting level used for serialization _openFile = 0; // Reference to the open file</code></pre> <p>Before we write our actual serialize functions, we will write three utility scripts to help with the formatting of the file.</p> <h2>Utility serialization scripts</h2> <p>The first of these scripts is called <strong>OI_Indent</strong> and, as the name implies, it will help us indent to the correct column depending on how deep we are in a data structure or object. The script looks like this:</p> <pre> <code>// OI_Indent Script // Get the manager var manager = global.OI_Manager; repeat(manager._indentLvl) file_text_write_string(manager._openFile, &quot;\t&quot;);</code></pre> <p>We grab a handle to the manager and then add white space in the form of a <em>tab</em> for every indent level we are in. Notice we are using <em>repeat</em> for our loop. The reason is that we don’t need the index for this operation, so it’s slightly faster to use repeat than a <em>for</em> or <em>while </em>loops.</p> <p>Next we are creating a script called <strong>OI_OpenBlock</strong> to specify how we open objects and data structures (in our case, we use an opening bracket (<strong>{</strong>) on a new line. This is the script:</p> <pre> <code>// OI_OpenBlock Script // Get the manager handle var manager = global.OI_Manager; // Open Block OI_Indent(); file_text_write_string(manager._openFile, &quot;{\n&quot;); ++manager._indentLvl;</code></pre> <p>After we grab the handle to the manager, we indent using the script we wrote, then we place an opening bracket, and go to a new line. We also increase the indent level.</p> <p>Analog to the previous script, we will now create one last script called <strong>OI_CloseBlock</strong>, to specify how we want to finish a block for an object or data structure, like this:</p> <pre> <code>// Close Block Script // Get the manager handle var manager = global.OI_Manager; // Open Block --manager._indentLvl; OI_Indent(); file_text_write_string(manager._openFile, &quot;}\n&quot;);</code></pre> <p>Same idea as before, but we do the process backwards, decreasing the indent level first, then calling our OI_Indent script, and placing our closing bracket with a new line.</p> <p>Now we set up these scripts, we are ready to serialize our object.</p> <h2>Kickstart the recursive serialize function</h2> <p>Last time we had one Inspect function that would do all the legwork. This time though, we will have a special function that will set all the initial values and start the (possibly) recursive call. I called this script <strong>OI_Serialize</strong>, which looks like this:</p> <pre> <code>// OI_Serialize Script // Get the parameters var fileName = argument0; var instance = argument1; // Get a handle to the manager var manager = global.OI_Manager; // File handling var file = file_text_open_write(fileName); // Initialize variables manager._currValue = instance; manager._currObject = instance.object_index; manager._openFile = file; manager._currIndex = 0; manager._currDepth = 0; manager._currTypes = 0; manager._currExtra = 0; // Start the recursive serialization OI_SerializeObject(); // Reset variables manager._currObject = noone; manager._openFile = 0; manager._currIndex = 0; manager._currDepth = 0; manager._currTypes = 0; manager._currExtra = 0; manager._currValue = 0; // Add extra line and close the file file_text_writeln(file); file_text_close(file);</code></pre> <p>We are taking two parameters from the user. The first is the name of the file to write into, and the second is the <strong>id</strong> of the instance we want to serialize. Next, we open the file to write into it (note that when you open as <em>write</em> it will overwrite another file with the same name in that directory, so if you want to keep adding to the same file, open as <em>append</em>, but this works for the goals of this article). Later we set the initial values to all the variables we created in the manager object. We then call our script to serialize the object which is the one that will do most of the work. Last, we reset our variable values, and close the file.</p> <p>Now let’s implement that Serialize Object script and some basic types.</p> <h2>Serialize the initial object and the basic types</h2> <p>This script will be similar to our <strong>OI_Inspect</strong> one from the previous part. It’s by far the longest one, so instead of posting the entire script and explaining it like before, I will post it in chunks, but realize the code is in the same file when you implement it yourself.</p> <pre> <code>// OI_SerializeObject Script - 1/3 // Get a handle to the manager var manager = global.OI_Manager; // Grab the object, instance, and definition var instance = manager._currValue; var object = instance.object_index; var definition = manager._objDefinitions[? object]; var file = manager._openFile; // Error handling if (!is_array(definition)) { show_debug_message(&quot;Warning: The object hasn't been defined yet.&quot;); return; } // Save these variables to use later var prevExtra = manager._currExtra; var prevTypes = manager._currTypes; var prevDepth = manager._currDepth; // Reset depth manager._currDepth = 0; // Print object name, instance ID, and open the block of variables file_text_write_string(file, object_get_name(object) + &quot; = &quot; + string(instance) + &quot;\n&quot;); OI_OpenBlock();</code></pre> <p>Just like in our other scripts, we start by grabbing a handle to the manager. We then grab a few variables we will use throughout (instance, object, definition, and file handle). After we do some error handling, we save the current extra data, types array, and depth. This is so we can restore the values if they are changed when going into the recursive calls. After, we set the current depth to zero. Realize that the depth value is unique per object, even if it’s an object within an object which is why we saved the previous one above (in case this is a nested case). Finally, we write into our file the name of our object and the instance id, followed by a call to <strong>OI_OpenBlock</strong> to have some nice formatting.</p> <p>In the next section, we iterate through every variable in the object and serialize each one in this way:</p> <pre> <code>// OI_SerializeObject Script 2/3 // Print each variable and value for (var i = 0; i &lt; array_height_2d(definition); ++i) { // Variable name OI_Indent(); var varName = definition[i, eOI_VarInfo.Name]; file_text_write_string(file, varName + &quot; : &quot;); // Get the value, or give a warning if the variable doesn't exist in the object if (variable_instance_exists(instance, varName)) manager._currValue = 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(object) + &quot; object.&quot;); return; } // Get the current types and extra manager._currExtra = definition[i, eOI_VarInfo.Extra]; manager._currTypes = definition[i, eOI_VarInfo.Type]; // Pick the correct serialize script depending on the variable type OI_SerializePicker(_currTypes[0]); } </code></pre> <p>We loop into our definition array, indenting first before writing our variable name. We check that the variable is valid (it exists in our object) before proceeding to avoid any issues. We then save in the manager object the types and extra arrays for this variable. Finally, we have a helper script (which I’ll show below) that picks the correct type serialization function depending on the type. Since we explained that objects are always at their own depth zero, we call it for the first element in the types array. The <strong>OI_SerializePicker</strong> script looks like this:</p> <pre> <code>// OI_SerializePicker Script // Get the parameter var type= argument0; switch(type) { case eOI_VarTypes.Int: OI_SerializeInt(); break; case eOI_VarTypes.Float: OI_SerializeFloat(); break; case eOI_VarTypes.Bool: OI_SerializeBool(); break; case eOI_VarTypes.String: OI_SerializeString(); break; case eOI_VarTypes.Enum: OI_SerializeEnum(); break; case eOI_VarTypes.Object: OI_SerializeObject(); break; }</code></pre> <p>This is simply a switch statement that calls the appropriate script depending on the type passed in. When you add your custom data structures or variable types, this is a script you need to come into and add the new type, and adding it to the <strong>eOI_VarTypes</strong> enumerator.</p> <p>Back in the <strong>OI_SerializeObject</strong> script, we close it off with a few lines:</p> <pre> <code>// OI_SerializeObject Script - 3/3 // Close current block OI_CloseBlock(); // Return variables to their initial state manager._currExtra = prevExtra; manager._currTypes = prevTypes; manager._currDepth = prevDepth;</code></pre> <p>We close the block by placing an ending bracket, and we restore the previous values for the extra and type arrays, alongside with the depth. That’s it for this script! We will now quickly show the scripts for all the basic types before jumping into the ones for data structures.</p> <p><strong>OI_SerializeInt</strong></p> <pre> <code>// Get the manager var manager = global.OI_Manager; file_text_write_string(manager._openFile, &quot;int = &quot; + string(floor(manager._currValue)) + &quot;\n&quot;);</code></pre> <p><strong>OI_SerializeFloat</strong></p> <pre> <code>// Get the manager var manager = global.OI_Manager; file_text_write_string(manager._openFile, &quot;float = &quot; + string_format(manager._currValue, 1, 5) + &quot;\n&quot;);</code></pre> <p><strong>OI_SerializeBool</strong></p> <pre> <code>// Get the manager var manager = global.OI_Manager; file_text_write_string(manager._openFile, &quot;bool = &quot; + (manager._currValue ? &quot;True&quot; : &quot;False&quot;) + &quot;\n&quot;);</code></pre> <p><strong>OI_SerializeString</strong></p> <pre> <code>// Get the manager var manager = global.OI_Manager; file_text_write_string(manager._openFile, &quot;string = \&quot;&quot; + manager._currValue + &quot;\&quot;\n&quot;);</code></pre> <p><strong>OI_SerializeEnum</strong></p> <pre> <code>// Get the manager var manager = global.OI_Manager; file_text_write_string(manager._openFile, &quot;enum = &quot; + manager._currExtra[@ manager._currValue] + &quot;\n&quot;);</code></pre> <p>At this point, we should test our progress. In the <strong>oPlayer</strong> object’s step event, add this little piece of code:</p> <p>Then run the game and press the spacebar to create the output. The location GameMaker uses to output files by default is:</p> <p><em>C:\Users\YOUR_USERNAME\AppData\Local\PROJECT_NAME</em></p> <p>Your output should look like this:</p> <div> <img alt="object-introspection-image2-0718.png" src="" style="display:block; margin-left:auto; margin-right:auto" /> </div> <p>We are now ready to try our hand at data structures.</p> <h2>Data structure serialization</h2> <p>The idea to serialize data structures is the same, but one level deeper into our types array. We will loop through every element and call the <strong>OI_SerializePicker</strong> script for every one.</p> <p><strong>Note</strong>: due to the way our database is structured, the objects inside the data structures have to be of the same type. Yes, GameMaker allows for data structure elements to be of any type, but since we need to know the type of the element to call the function, it is a limitation.</p> <p>We will start with the most commonly used data structure: arrays.</p> <p>First, remember to add an array entry into the <strong>eOI_VarTypes</strong> enumerator inside the <strong>oOI_Manager</strong> object. Also, add an extra line in our <strong>OI_SerializePicker</strong> script that will call <strong>OI_SerializeArray</strong> when the type is array.</p> <p>Inside that script, we will write:</p> <pre> <code> // OI_Serialize Array Script // Get a handle to the manager var manager = global.OI_Manager; // Get the definition var definition = manager._objDefinitions[? manager._currObject]; // Open list block file_text_write_string(manager._openFile, &quot;array =\n&quot;); OI_OpenBlock(); ++manager._currDepth; var array = manager._currValue; for (var i = 0; i &lt; array_length_2d(array, 0); ++i) { OI_Indent(); file_text_write_string(manager._openFile, &quot;a&quot; + string(i) + &quot; : &quot;); manager._currValue = array[@ i]; OI_SerializePicker(manager._currTypes[@ manager._currDepth]); } --manager._currDepth; OI_CloseBlock();</code></pre> <p>As always, we get a handle to the manager to simplify our variable names. We get our definition, write the name of the type (in this case array) and open the block. The depth is now increased by one, which will get us the type of each element in our data structure. The current value is set to the array so that we don’t have to pass it to every script in the script. Next, we iterate through every element in the array by using the <strong>array_lenght_2d </strong>function. This is a little trick that works because every array in GameMaker is treated as a two-dimensional array internally, so this will work for 1D and 2D arrays.</p> <p>For each element, we indent it and since each element in an array is not named, we identify them by writing a lowercase <strong>a</strong> and the index number next to it. We then get the value of the element at that index and we call our <strong>OI_SerializePicker</strong> function, passing as our type the index in our types array corresponding to the recursion depth we are at. After all the elements are processed recursively, we reduce our depth by one and close the block.</p> <p>We can now uncomment the line in our <strong>oPlayer</strong> object that has the array so we can test it. The array part should now be displayed like this:</p> <p><img alt="object-introspection-image3-0718.png" src="" style="display:block; margin-left:auto; margin-right:auto" /></p> <p>Also, with what we have, we can also uncomment the line that holds the 2D array in our player object (the one with the variable named <strong>_minimap</strong>) and it should work as expected, since the recursion is working already. That one is longer so I won’t show an image here, but check your file and it should be there now.</p> <p>The last thing we will do in this article is repeat the process for the <strong>ds_list</strong> and the <strong>ds_map</strong>, and you see that the scripts are similar.</p> <p>As before, remember to add lists and maps to your enumerator and to the <strong>OI_SerializePicker</strong> script. Then, create two scripts called<strong> OI_SerializeList</strong> and <strong>OI_SerializeMap</strong> respectively. The one for lists looks like this:</p> <pre> <code>// OI_SerializeList Script // Get a handle to the manager var manager = global.OI_Manager; // Get the definition var definition = manager._objDefinitions[? manager._currObject]; // Open list block file_text_write_string(manager._openFile, &quot;list =\n&quot;); OI_OpenBlock(); ++manager._currDepth; var list = manager._currValue; for (var i = 0; i &lt; ds_list_size(list); ++i) { OI_Indent(); file_text_write_string(manager._openFile, &quot;l&quot; + string(i) + &quot; : &quot;); manager._currValue = list[| i]; OI_SerializePicker(manager._currTypes[@ manager._currDepth]); } --manager._currDepth; OI_CloseBlock();</code></pre> <p>Pretty much the same as the array one. The only differences are the name of the type we write, how we get the size of the data structure, the use of a lowercase <strong>l</strong>&nbsp;for our indexes, and the use of the proper accessor for lists.</p> <p>Moving on to the script for the map, we have:</p> <pre> <code>// OI_SerializeMap Script // Get a handle to the manager var manager = global.OI_Manager; // Get the definition var definition = manager._objDefinitions[? manager._currObject]; // Open list block file_text_write_string(manager._openFile, &quot;map =\n&quot;); OI_OpenBlock(); ++manager._currDepth; var map = manager._currValue; var currKey = ds_map_find_first(map); repeat(ds_map_size(map)) { OI_Indent(); file_text_write_string(manager._openFile, currKey + &quot; : &quot;); manager._currValue = map[? currKey]; OI_SerializePicker(manager._currTypes[manager._currDepth]); currKey = ds_map_find_next(map, currKey); } --manager._currDepth; OI_CloseBlock();</code></pre> <p>Same as the list, but the one thing that may trip you up is how we traverse the map. Because maps are not sequential and we don’t control the order of the elements, GameMaker kindly provided us with some functions (<strong>ds_map_find_first</strong> and <strong>ds_map_find_next</strong>) to allow us to travel through every element as if they were in a sequence. We also take advantage of the fact that maps have keys for each element, so we use that key as our name for each element.</p> <p>We are now free to uncomment all the lines in the definitions of our three objects (<strong>oPlayer</strong>, <strong>oAlly</strong>, and <strong>oEnemy</strong>). Once we do that, we can run the project again, press space, and see if everything is working correctly. You can also download the&nbsp;<a href="" target="_blank">final version of the project</a> if you get stuck somewhere along the way.</p> <p><strong>Note</strong>: I created a good variety of tests to show how you can nest data structures together in as many ways as possible. Theoretically it will work with any combination and however deep you’d like to go, but if there are any issues, please let me know.</p> <h2>Next steps and additions&nbsp;</h2> <p>If you liked the result we got so far and want to take it further, here are some ideas of things you can add to solidify the knowledge and improve your library:</p> <ul> <li> <p><strong>Add the ds_grid</strong>: You may have noticed that we didn’t implement a way to serialize a ds_grid. If you are using those in your project, feel free to add it. The function will be like that of the array.</p> </li> <li> <p><strong>Custom data structures</strong>: If you implemented your own data structure into the game (like a binary tree or a slotmap), it would be a nice challenge to implement a serialization function for those.</p> </li> <li> <p><strong>GameMaker assets</strong>: in the <strong>oEnemy</strong> object, we serialized some of the built-in variables of the object (X and Y positions). Since we know it’s possible, it would be a good idea to add other ones, such as the sprite used by the object. If you are not entirely sure how, read the documentation on these functions: <strong>sprite_get_name</strong>, <strong>asset_get_index</strong>, and <strong>asset_get_type</strong>. It can even work for music, sound effects, tilesets, anything really.</p> </li> <li> <p><strong>Write a deserializer</strong>: We can now save files, but we still can’t read them in. Creating a deserializer shouldn’t be too hard to implement (just do the same we did, but backwards) for every variable type.</p> </li> <li> <p><strong>Use the database for other purposes</strong>: A&nbsp;great way to use this database is to create a nice editor where you can click an object in the scene and it creates a window with all the variables, showing you the values and hopefully letting you edit them. I recommend using the<a href="" target="_blank"> ImGUIGML extension</a> to do this easier, but it can also be done with a custom UI.</p> </li> <li> <p><strong>Change the serializer so it uses JSON format</strong>: If you prefer to use a well-known serializing format like JSON or XML, feel free to modify it to resemble those using the same strategies.</p> </li> </ul> <h2>Project Download</h2> <p><a href="" target="_blank">Object introspection part 2 project files</a></p> <p>Inside you will find two&nbsp;.yyz files, one you should use if you want to follow along with the article (called <strong>ObjectIntrospection_Part2_Start.yyz</strong>), and another one with the final version of the project, if you want to see the source code or get stuck while following along (called <strong>ObjectIntrospection_Part2_Final.yyz</strong>).</p> <h2>Extra Links</h2> <ul> <li><a href="" target="_blank">ImGUIGML extension</a></li> <li><a href="" target="_blank">Object Type Introspection in GameMaker - Part 2</a></li> </ul> <h2>Conclusion</h2> <p>This can be an advanced topic, but a super powerful one that can help you solve complicated problems and automate them to save time. If you have any suggestions or questions, you can contact me on Twitter (<a href="" target="_blank">@AleHitti</a>). Thank you for reading. Until next time!</p> <div> <img alt="AlejandroBio.jpg" src="" style="display:block; height:145px; margin-left:auto; margin-right:auto; width:583px" /> </div> <div> <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> </div> /blogs/appstore/post/ca8ce405-5674-4528-a81d-0584ff1d8bfb/announcing-monthly-gameon-developer-office-hours Announcing Monthly GameOn Developer Office Hours Tess Selim 2018-07-16T21:08:54+00:00 2018-07-16T21:26:01+00:00 <p><img alt="" src="" style="display:block; height:350px; margin-left:auto; margin-right:auto; width:700px" /></p> <p>During these office hours, you will be able to ask your technical questions, view live code demos, and discuss your GameOn use case. We will also explore best practices for competition management, real-world prizes, and more.<br /> &nbsp;</p> <p><img alt="" src="" style="display:block; height:350px; margin-left:auto; margin-right:auto; width:700px" />Over the past few weeks, I've had the opportunity to chat with Amazon GameOn developers at events like Nordic Game Jam and Develop: Brighton. The direct feedback and questions I receive from you help influence the GameOn product roadmap.<br /> <br /> I'm thrilled to extend this conversation to GameOn developers everywhere with the addition of monthly GameOn office hours. Our goal is to help you seamlessly integrate and offer the best competitive play experiences for your players.<br /> <br /> During these office hours, you will be able to ask your technical questions, view live code demos, and discuss your GameOn use case. We will also explore best practices for competition management, real-world prizes, and more.<br /> <br /> Office hours are offered on the second Thursday of every month. Register to reserve your spot for August 9 and send in your questions.</p> <p><a href="" target="_blank"><img alt="" src="" style="display:block; height:50px; margin-left:auto; margin-right:auto; width:200px" /></a></p> <h2>Get started with GameOn</h2> <p>Are you new to GameOn? <a href="" target="_blank">Get started today</a>, it's easy and quick! Some developers have even been able to set up competitions in their game with GameOn in as little as one day. You can also learn more about how to integrate competitive play into your game by watching <a href="" target="_blank">this webinar</a> on-demand.</p> <h2>About GameOn</h2> <p>GameOn is a set of flexible APIs built on AWS cloud infrastructure and works on any operating system, giving you the ability to scale quickly, while allowing you to invest more time in what you do best—designing great games. With GameOn, you have an easy tool to bring more players in on the action—allowing them to compete for real-world prizes fulfilled by Amazon or other in-game rewards. Drive engagement and increase monetization of your games by adding leaderboards, leagues, and multi-round competitions to your games, or strengthen your fanbase by allowing players and streamers to create their own user-generated competitions.</p> /blogs/appstore/post/a0e85b98-c9fc-4369-9ddf-22413c8c769e/the-community-behind-esports The Community Behind Esports Emily Esposito Fulkerson 2018-07-11T16:48:40+00:00 2018-07-11T16:48:40+00:00 <p><img alt="ebook-announce.jpg" src="" /></p> <p>In this blog post, we'll explore the audience watching and playing games, share player vignettes, and give you three tips to engage your players and build community.</p> <p><img alt="ebook-announce.jpg" src="" /></p> <p>“I love gaming because I love to interact and share a passion with my friends and the communities that follow those games.”<br /> <br /> “I have made friends just by wearing something or mentioning something related to the games, which I think is an amazing thing.”<br /> <br /> We all play games for a variety of reasons, but after talking to fellow players at the Amazon headquarters, one thread remains consistent: games provide a sense of belonging. They naturally bring us together in communities of like-minded people, leading to strong bonds and long-lasting relationships. Competitions and tournaments foster socialization, networking, and team spirit.<br /> <br /> By adding competitive elements to your game, like leaderboards, leagues, and multi-round competitions, you can tap into this sense of belonging and foster a vibrant community among your fans — a community that is more likely to be engaged and keep coming back to play.<br /> <br /> In this blog post, we'll explore the audience watching and playing games, share player vignettes, and give you three tips to engage your players and build community.<br /> <br /> To read more about building your community, download our free eBook, “<a href="" target="_blank">Developer First Look: Competitive Mobile Gaming</a>.”</p> <h2>Who is watching and playing games?</h2> <p>We know that players have a desire to belong and compare themselves with others, but what other traits and behaviors do they share? Our friends at Newzoo, the leading provider of market segment intelligence, analyzed players and fans to uncover the following insights:</p> <p><img alt="Whoiswatching-infographic.png" src="" style="display:block; height:445px; margin-left:auto; margin-right:auto; width:800px" /></p> <p>Perhaps most intriguing is the fact that 40% of esports enthusiasts worldwide do not play the games they watch. Not only does this mean esports dominates as a spectator sport, it also means that you need to carefully craft your tournaments to attract this engaged audience. For example, in a traditional esports setting, adding brackets to your tournaments can be a great way for fans to watch the finals.</p> <h2>Vibrant communities come from competitive gaming&nbsp;</h2> <p>The 5.9 billion hours spent watching people play games on Twitch isn't just about entertainment. It's also about developing friendships that begin with competing for the high score, but ultimately have the potential to extend to daily, meaningful interactions.<br /> <br /> For example, Andy Ta, better known as “Smoothie,” has met some of his best friends through competitive gaming.<br /> <br /> Smoothie is a Canadian League of Legends player who plays for Cloud9 of the North American League of Legends Championship Series. When asked whether the majority of friends come from game, Smoothie responded, “Yeah definitely. During high school or junior high I did have a lot of friends but I didn't really consider them like... I would share everything... not best friends... I have some best friends of course but like the people I met online I could trust my life with... really good friends I've known for a couple of years and playing with consistently every day after I got home from school.”<br /> <br /> Esports can also help break the ice when someone is new to a city. After all, what better way to meet new people than to challenge them to a little friendly competition?<br /> <br /> NYU freshman, Kenneth Yu, turned to League of Legends to make new friends in a brand new city and school, saying “Many times I've met somebody because I see that they play League of Legends. Then other times I can bond more with a friend if I know that they play League.”<br /> <br /> And for some, friendships forged through competition can even turn into romance. Redditor Shaushka says, “I met my boyfriend through Dota 2. He would play occasionally with my ex and we became friends through our mutual love of all things awesome: Doctor Who and other TV shows, anime, and games!”</p> <h2>3 tips to engage your players</h2> <p>All games have a niche of players who are looking to make these kinds of relationships. The question is: how do you get more of them to form a strong community with your game at the center? Adding competition to your game is a sure way of building a vibrant community around your game.<br /> <br /> Here are three tips to engage your players:<br /> <br /> <strong>1. Make competitions fun for everyone</strong><br /> <br /> To help make your competitions feel fair to the players, place users into tournament cohorts based on their skill level. For example, you may want to create a tournament that only allows players with a certain top score, location, or possession of a specific item. Test out different approaches and see which ones create the most fun environment for your players.<br /> <br /> <strong>2. Empower players to create their own tournaments </strong><br /> <br /> Not everyone is ready or desires to play in formal competitions. Allow friends and family to easily challenge one another with user-created tournaments. You could restrict invites to in-game only, or allow users to share a link to invite others to play against them. These user-created tournaments bring friends and family together to share the gaming experience, ultimately adding more people to the community around your game.<br /> <br /> <strong>3. Motivate participants to share their performance</strong><br /> <br /> Make it easy for your players to share their results with others. After all, competitive games are all about building a community. So, add social media buttons to let participants share their results with their friends, family, and followers. This will also help engage non-players and promote your game to potential new players.</p> <h2>Learn more with our free eBook</h2> <p>Want to learn more about building community around your game through competitive mobile gaming? Get our free eBook, &quot;<a href="" target="_blank">Developer First Look: Competitive Mobile Gaming</a>.&quot; You'll read about who is watching and playing competitive games, types of organized competition, and more.</p> <p><a href="" target="_blank"><img alt="GameOn-button.png" src="" style="display:block; margin-left:auto; margin-right:auto" /></a></p> <p>&nbsp;</p> /blogs/appstore/post/bb474184-24b1-4d88-8ba1-0af89fd2ebfb/workshop-competitive-play-and-real-world-prizes-with-amazon-gameon Workshop: Competitive Play and Real-World Prizing with Amazon GameOn Tess Selim 2018-07-10T21:13:16+00:00 2018-07-10T21:13:43+00:00 <p><img alt="" src="" style="display:block; height:292px; margin-left:auto; margin-right:auto; width:900px" /></p> <p>&nbsp;</p> <p>In this workshop, developer evangelist Peter Heinrich will share how you can use competition to drive engagement in your game and walk you through the steps to integrate the Amazon GameOn APIs.</p> <p><img alt="" src="" style="display:block; height:292px; margin-left:auto; margin-right:auto; width:750px" /></p> <p>&nbsp;</p> <p>Join us at the AWS loft in San Francisco on&nbsp;Tuesday, July 24 to learn how Amazon is helping developers realize the benefits of competitive gaming with Amazon GameOn. In this workshop, developer evangelist Peter Heinrich will share how you can use competition to drive engagement in your game and walk you through the steps to integrate the Amazon GameOn APIs.</p> <p>At the end of this workshop, you will&nbsp;learn how to:</p> <ul> <li>Engage players and create stronger communities with competition</li> <li>Integrate GameOn's flexible APIs natively into your game</li> <li>Create and manage tournaments, and reward players with prizes using the GameOn console</li> </ul> <p>At the end of the workshop, you'll get to experience&nbsp;a GameOn-enabled tournament in action, and compete to win real-world prizes!</p> <p>Register today to reserve your spot.</p> <p>&nbsp;</p> <p><a href="" target="_blank"><img alt="" src="" style="display:block; height:50px; margin-left:auto; margin-right:auto; width:200px" /></a></p> <h2>Get started with GameOn</h2> <p>Are you new to GameOn?&nbsp;<a href="" target="_blank">Get started today</a>, it's easy!&nbsp;Some developers have even been able to set up competitions in their game with GameOn in as little as one day.</p> /blogs/appstore/post/a5efc464-dd4a-465a-be8e-097adfa60ae6/revamped-experience-of-apk-section-during-app-submission Revamped Experience of APK Section During App Submission Serena McIntire 2018-07-05T23:41:39+00:00 2018-07-10T17:41:52+00:00 <p style="text-align:center"><img alt="APK_Rearchitecture_728x280.png" src="" style="height:346px; width:900px" /></p> <p>Today, Amazon Appstore began the gradual roll out an updated submission experience, which includes improvements to the APK section in the Appstore console.</p> <p style="text-align:center"><img alt="APK_Rearchitecture_728x280.png" src="" /></p> <p>Today, Amazon Appstore began the gradual roll out an updated submission experience, which includes improvements to the APK section in the Appstore console. The new app submission process allows you to submit app metadata, such as descriptions, multimedia files, availability, pricing, and APK file(s), to be published in Amazon Appstore catalog on Fire tablets, Fire TV and Android devices.</p> <p>Throughout 2018, we have been revamping the app submission experience on the developer portal to reduce the effort required to make your app available to your customers via Amazon Appstore. <a href="">Part one</a> of the revamp improved the multimedia asset upload and app description experiences. <a href="">Part two</a> of the revamp improved the availability and pricing section of app submission.</p> <p>For the latest update, we made several usability improvements in the APK section, as stated below:</p> <ul> <li><strong>Single tab for all APKs</strong>: In the new experience, you can upload multiple APKs within the same tab, instead of having to create a separate tab for each APK within the APK File(s) section. Also, while uploading each APK, you will see the upload status and validation steps to track progress.</li> <li><strong>Combine fields at app level</strong>: Now you only have to answer the questions one time for the APKs you upload at the same time. The fields include questions about language support, testing instructions, Amazon map redirection, and export compliance.</li> <li><strong>Increased size limit for APKs</strong>: We have increased the size limit for each APK upload on the UI to 2.5 GB. You no longer have to use a secure file transfer protocol (SFTP) to upload your APKs if they are greater than 150 MB.</li> <li><strong>Device targeting for Fire TV devices</strong>: In the old experience, when an APK compatible on Fire TV devices was uploaded, the device targeting was disabled. You had to manually enable Fire TV devices to make your app available on these devices. With the new experience, we take manifest entries of the APK into account, and if the APK is compatible with Fire TV devices, we automatically enable these devices in the list of targeted devices, as shown below:</li> </ul> <p style="text-align:center"><img alt="Fire_TV_Screenshot.PNG" src="" style="height:504px; width:728px" /></p> <ul> <li><strong>UI refresh</strong>: We have moved the secondary information on Appstore certificate hashes and manifest details as modal pop-ups instead of cluttering the main page. The refreshed UI surfaces improved tool tips, microcopy, and style guides.</li> </ul> <p>You can find detailed documentation on these new features <a href="">here</a>.</p> <p>We hope you enjoy these new improvements. This upgrade will be slowly rolling out to user accounts over the next few weeks. Please keep an eye out for this refresh and share your <a href="">feedback</a> with our support team. We will continuously improve the app submission and related experience throughout 2018.</p> <p><em>Do you have an Android APK? <a href="">Register for your free developer account</a> and publish on Amazon Appstore today!</em></p> /blogs/appstore/post/cc52365a-9535-4c3e-a3e7-44bcaee403b2/4-tips-designing-for-the-10-foot-experience 4 Tips: Designing for the 10-Foot Experience Emily Esposito Fulkerson 2018-07-03T16:49:03+00:00 2018-07-03T16:50:41+00:00 <p style="text-align:center"><img alt="FTV-blog-banner.png" src="" style="height:267px; width:900px" /></p> <p>Designing for the 10-foot experience does require that developers understand the capabilities (and limitations) of TV hardware, and to reconsider how they present information and handle user input. There are a few key design principles that apply.</p> <p style="text-align:center"><img alt="FTV-blog-banner.png" src="" style="height:267px; width:800px" /></p> <p>Streaming media provides nearly instant access to countless movies, TV shows, music videos, live events, and user-generated media. This content is frequently consumed on mobile devices such as tablets and phones, but the family television arguably (still!) provides the best viewing experience. It is undoubtedly the largest screen in the home, usually with the most vivid display, and often providing the most impressive audio as well (either natively, or through an attached sound system).</p> <p>App developers used to publishing on mobile are discovering that bringing their products to a smart TV or set-top box allows their apps to shine. Using an app in the living room—the 10-foot experience—opens a whole new chapter on how they interact with their users: richer content, voice control, deep engagement, and immersive media are just a few of the new elements developers are coming to appreciate.</p> <h2>4 design considerations&nbsp;</h2> <p>Designing for the 10-foot experience does require that developers understand the capabilities (and limitations) of TV hardware, and to reconsider how they present information and handle user input. There are a few key design principles that apply.<br /> &nbsp;</p> <p><strong>1. Remember the 10-foot UI</strong></p> <p>TV interfaces are often referred to as 10-foot user interfaces (10-ft UI), because the typical user views the screen from ten feet away (or more). Although the screen itself can be large, the perceived screen resolution is lower, and distance from the screen results in a smaller angle of view.</p> <p>The design choices you make for an application or web page running on a desktop computer, tablet, or phone are fundamentally different than for a TV app, since users typically view those screens from much closer distances.</p> <p>Also, keep in mind that a television is used in a more relaxed fashion than a computer, tablet, or phone. The UI on the TV should not require as much attention or precision. Designing for the 10-ft UI may require you to wholly rethink the layout and navigation of an existing app.<br /> &nbsp;</p> <p><strong>2. Prioritze clear, simple, and visual design</strong></p> <p>The design of a screen in a 10-ft UI requires simplicity and clarity, with low information density. Limit the number of design elements or UI components on the screen, such as menus, buttons, and images. Make sure that those elements are large enough and spaced far enough apart to be read from a distance. Present a clear set of actions or options for each screen.</p> <p>Minimize the amount of text, since users do not read a lot of text on a television screen. Avoid requiring the user to input a lot of information by providing reasonable defaults where possible.<br /> &nbsp;</p> <p><strong>3. Place important content first</strong></p> <p>Place the most important content or options first on the screen so they are easily viewable and navigable by the user.<br /> &nbsp;</p> <p><strong>4. Focus on consumption</strong></p> <p>Applications should have a clear focus on quickly getting content to users. Television interfaces are primarily about providing entertainment. When users sit down in front of their television, they don’t want to do extra work. They need simple user interfaces that match their primary goal: “Give me something to watch, listen to, or play with right now.”<br /> &nbsp;</p> <h2>Learn more about developing for Amazon Fire TV</h2> <p>To learn more, download our free eBook titled, &quot;<a href="" target="_blank">How to Develop Media Streaming Apps for Amazon Fire TV</a>.&quot; You'll learn best practices for designing for a 10-foot UI, how to use Amazon's dedicated tools and templates, how to publish to the Amazon Appstore, and more.</p> <p><a href="" target="_blank"><img alt="eBook_Button.png" src="" style="display:block; margin-left:auto; margin-right:auto" /></a><br /> <br /> &nbsp;</p> /blogs/appstore/post/8bd19103-d51c-4ecf-bbb5-9dd4b7dc5a8b/free-download-2018-global-games-market-report-by-newzoo Free Download: 2018 Global Games Market Report by Newzoo Emily Esposito Fulkerson 2018-06-28T16:42:24+00:00 2018-06-28T16:42:25+00:00 <p><img alt="2018globalreport-newzoo.png" src="" style="display:block; height:373px; margin-left:auto; margin-right:auto; width:800px" /><br /> Gaming has evolved into an all-around entertainment phenomenon. If you add up all playing and viewing hours, gaming is the world’s favorite pastime. And, with more than 2.3 billion active gamers in the world this year, this trend isn't going anywhere.&nbsp;</p> <p><img alt="2018globalreport-newzoo.png" src="" style="display:block; margin-left:auto; margin-right:auto" /><br /> Gaming has evolved into an all-around entertainment phenomenon. If you add up all playing and viewing hours, gaming is the world’s favorite pastime. And, with more than 2.3 billion active gamers in the world this year, this trend isn't going anywhere.&nbsp;</p> <p>And, for the first time, mobile gaming will contribute more than half of all revenues, with smartphone and tablet gaming growing 25.5% year-over-year to $70.3 billion,&nbsp;according to the <a href="" target="_blank">2018 Global Games Market Report&nbsp;by Newzoo</a>, a global leader in eSports, games, and mobile intelligence. This report provides a detailed breakdown of the market in terms of revenue and gamer forecasts per segment. It also explores market trends that are shaping and driving the game landscape, and provides a detailed look at the latest developers per segment and region.&nbsp;</p> <p>Here are some key takeaways from the report:</p> <ul> <li>In the past year, mobile skeptics were proven wrong as publishers&nbsp;managed&nbsp;to create mobile games in genres that were once considered too complex for mobile screens and controls (like multiplayer online battle arena games). Launched at the end of 2015, Tencent's Honor of Kings was the highest-grossing mobile game in 2017 and boasts 200 million monthly active users in China alone.&nbsp;<br /> &nbsp;</li> <li>Now that publishers have established that mechanics from PC and console games can be successfully adapted to mobile screens, ports to mobile are becoming increasingly popular. Games based on popular franchises or IP are launched on mobile to attract attention for upcoming larger releases, like Pok&eacute;mon Quest in anticipation of two Pok&eacute;mon games launching on Switch later this year.<br /> &nbsp;</li> <li>China leads the top 100 countries by game revenues, with $37.9 billion in revenues in 2018. The U.S. and Japan remain the second and third largest, with $30.4 billion and $19.2 billion, respectively.&nbsp;</li> </ul> <p>To learn more and read all the high-level takeways, download the Newzoo report for free.<br /> &nbsp;</p> <p style="text-align:center"><a href="" target="_blank"><img alt="download-now-button.png" src="" /></a></p> <p><br /> <em>Please note: the report will automatically be downloaded in your browser. If the download does not get initiated, check your pop-up blocker settings in your browser.&nbsp;</em></p> /blogs/appstore/post/11854d23-f795-48f1-8e09-6b69f88b3a62/introduction-to-game-math-bit-manipulation Introduction to Game Math: Bit Manipulation Emily Esposito Fulkerson 2018-06-26T20:26:51+00:00 2018-06-26T20:26:51+00:00 <p><img alt="Amazon_Appstore_BlogPost_V2_121417.png" src="" style="display:block; height:346px; margin-left:auto; margin-right:auto; width:1000px" /><br /> High-level programming languages usually insulate us from the details, but it pays to understand what’s happening under the covers, because knowing how the hardware works helps us to write better code.</p> <p><img alt="Amazon_Appstore_BlogPost_V2_121417.png" src="" style="display:block; height:346px; margin-left:auto; margin-right:auto; width:800px" /><br /> How do you split the check when you dine out with friends? Equal shares, to make it easy on the server, or broken down by individual, to ensure supreme fairness? In either case, you probably don’t give a second thought to how you <em>represent</em> the final number. Unless you’re an extraterrestrial visitor (unlikely) or just exceptionally pedantic (guilty!), decimal numerals are your go-to choice for communicating quantity. The concept of counting ones, tens, hundreds, and thousands is second nature from childhood—even for complex calculations like splitting the check or computing a good-for-karma-but-not-extravagant tip.</p> <p>Why is this important to game math? Because decimal counting and computation are so fundamental to our basic understanding of math, it’s easy to forget that computers represent numbers differently. High-level programming languages usually insulate us from the details, but it pays to understand what’s happening under the covers, because knowing how the hardware works helps us to write better code.</p> <p><img alt="GameMath_0626_Image1.png" src="" style="display:block; height:90px; margin-left:auto; margin-right:auto; width:600px" /></p> <h2>Decimal numbers aren't the only game in town</h2> <p>Having two hands with five fingers each, it’s probably no coincidence that we tend to count by 10, and groups of 10, and groups of groups of 10. This <em>base-10</em> approach means that only 10 unique numerals are needed to represent any integer quantity. In our positional number system, we simply add extra digits to count larger and larger groups, when necessary.<br /> &nbsp;</p> <p><img alt="Image2_GameMath_0626.png" src="" style="display:block; height:259px; margin-left:auto; margin-right:auto; width:700px" /></p> <p>&nbsp;</p> <p><img alt="Image3_GameMath_0626.png" src="" style="display:block; height:175px; margin-left:auto; margin-right:auto; width:250px" /></p> <p><br /> A number’s base, or <em>radix</em>, is the maximum count of items that may be represented by each digit. It can be indicated explicitly by a subscript, as above, or left off to signify a default radix of 10. The radix is also a scale factor: as numbers get bigger and more digits are added, each new digit counts groups that are <em>radix</em> times larger than those counted by the previous digit. In base-10, this is intuitive: we have ones, tens, hundreds, thousands, etc. For other bases, though, the “tens place” or “hundreds place” of a number would be replaced with the “twos place” or “twenty-fives place,” for example.<br /> &nbsp;</p> <p><img alt="Image4_GameMath_0626.png" src="" style="display:block; height:648px; margin-left:auto; margin-right:auto; width:700px" /></p> <p><br /> You can see how quantity may be expressed an infinite number of ways, since we can choose any radix we want. The value 3475<sub>10</sub>, for example, looks very different when rewritten for each alternative radix above: 3475<sub>10 </sub>= 6623<sub>8</sub> = 102400<sub>5</sub> = 110110010011<sub>2</sub>.</p> <h2>Math like you learned in school, if you have extra (or missing) fingers</h2> <p>Conveniently, the mechanics of basic arithmetic are the same regardless of radix. This means you follow the same steps to add, subtract, multiply, or divide base-6 numbers, for example, as you would for base-10 numbers. Sometimes the choice of radix makes a particular operation simpler, such as multiplying a decimal number by 10 (just add a 0 to the end). In those situations, that operation will be simplified in a similar way for <em>every</em> radix:<br /> &nbsp;</p> <p><img alt="Image5_GameMath_0626.png" src="" style="display:block; height:131px; margin-left:auto; margin-right:auto; width:350px" /><br /> <br /> Practically, this means that just as you can tell at a glance when a (base-10) number is divisible by 10, or 100, or 1000, you can tell when numbers in other bases are divisible by their radix or one of its powers.<br /> &nbsp;</p> <p><img alt="Image6_GameMath_0626.png" src="" style="display:block; height:160px; margin-left:auto; margin-right:auto; width:350px" /></p> <p><br /> There are other useful shortcuts—like dropping the last digit to divide by the radix and throw away the remainder—as well as esoteric ones. For example, replacing low digits with 0 effectively rounds down to the nearest multiple of the radix raised to some power (useful for snapping coordinates to a grid). Conversely, replacing high digits with 0 computes the modulus over the radix or one of its powers (useful for clamping values to a range without requiring a bounds check). You can even estimate logarithms simply by counting digits.<br /> &nbsp;</p> <p><img alt="Image7_GameMath_0626.png" src="" style="display:block; height:285px; margin-left:auto; margin-right:auto; width:350px" /></p> <h2>Numbers bit by bit</h2> <p>The point is, how we represent numbers has implications for how we manipulate them. We are conditioned to think in base-10 for physio-historical reasons, but the choice of radix is actually rather arbitrary. Counting by 10 may be <em>handy</em> for us (see what I did there), but it’s not particularly convenient for computers, which do their counting with bits instead of fingers. Each bit, being either OFF or ON, is equivalent to a digit of 0 or 1, so base-2 (binary) arithmetic is perfectly suited to representing integer values for a computer. To store the number 13, for example, would require four bits:<br /> &nbsp;</p> <p><img alt="Image8_GameMath_0626.png" src="" style="display:block; height:171px; margin-left:auto; margin-right:auto; width:700px" /></p> <p><img alt="Image9_GameMath_0626.png" src="" style="display:block; height:146px; margin-left:auto; margin-right:auto; width:350px" /><br /> &nbsp;</p> <p>Those four bits describe the minimum amount of information necessary to convey the value 13. (Note that eight-bit bytes are typically the smallest unit of storage directly accessible by a computer, though, so 13 will be stored in memory as 00001101<sub>2. </sub>Your hardware may be optimized to deal with even longer bit sequences.)</p> <p>Knowing that computers work in binary, we begin to see the benefit to certain “magic” numbers, or at least why they’re so common in computer code.<br /> &nbsp;</p> <p><img alt="Image10_GameMath_0626.png" src="" style="display:block; height:185px; margin-left:auto; margin-right:auto; width:600px" /><br /> &nbsp;</p> <p>Of course, all powers of 2 are automatically interesting by virtue of the fact that they have only a single bit set. As mentioned earlier, this simplifies range checking when they are used as upper bounds. For example, suppose we want to tile an image to fill the screen (with no stretching or clipping). If the image happens to be the same size as the screen, we can simply visit its pixels in order, copying each one to the screen location having the same (x, y) coordinates. Usually, though, the tile image is much smaller than the screen—we want to repeat a patterned background, for example—so we have to transfer the image data more than once, adjusting the destination location as we go.<br /> &nbsp;</p> <p><img alt="Image11_GameMath_0626.png" src="" style="display:block; height:378px; margin-left:auto; margin-right:auto; width:600px" /></p> <p>We could accomplish this with pseudocode like:</p> <pre> <code> for( int x = 0, u = 0; x &lt; screen.width; x++, u++ ) { for( int y = 0, v = 0; y &lt; screen.height; y++, v++ ) { // Copy the pixel value from the image to the screen. int color = image.getPixel( u, v ); screen.setPixel( x, y, color ); // Make sure we don't go outside the image boundary. if( u &gt;= image.width ) u = 0; if( v &gt;= image.height ) v = 0; } }</code></pre> <p>This approach keeps track of the image source (u, v) and screen destination (x, y) coordinates, incrementing both in tandem and adjusting (u, v) as necessary to make sure it always refers to a valid source pixel.</p> <p>If the image dimensions happen to be powers of 2, however, we can eliminate the bounds checking. We can take advantage of the fact that the coordinates for every image pixel will occupy the bits below the dimension value, and <em>only</em> those bits—the higher bits will always be 0.<br /> &nbsp;</p> <p><img alt="Image12_GameMath_0626.png" src="" style="display:block; height:125px; margin-left:auto; margin-right:auto; width:600px" /><br /> &nbsp;</p> <p>That means that for any screen coordinate, clearing the upper bits to 0 will guarantee the resulting value is a valid image coordinate. The bitwise <em>AND</em> operator is tailor-made to help us here. It compares two operands and preserves the bits that are set in both, effectively allowing us to “mask off” bits we don’t care about.<br /> &nbsp;</p> <p><img alt="Image13_GameMath_0626.png" src="" style="display:block; height:165px; margin-left:auto; margin-right:auto; width:600px" /><br /> &nbsp;</p> <p>Adjusting our pseudocode, two inexpensive Boolean operations replace two comparisons and potential branches:</p> <pre> <code> // Assumes image dimensions are powers of 2. int widthMask = image.width - 1; int heightMask = image.height - 1; for( int x = 0; x &lt; screen.width; x++ ) { for( int y = 0; x &lt; screen.height; y++ ) { // No boundary checking necessary. int color = image.getPixel( x &amp; widthMask, y &amp; heightMask ); screen.setPixel( x, y, color ); } }</code></pre> <h2>Bitwise operators: the versatile functions you never knew you needed</h2> <p>The <em>AND</em> operator is great for clearing bits. The <em>OR</em> operator sets them. Other functions invert bits, exchange them, and move them left or right. These operators are <em>fast</em>, in terms of CPU cycles, and can be combined in lots of interesting ways to achieve some really useful results. Here are a few examples.</p> <p><strong>Using OR to combine bits</strong></p> <p>The bitwise <em>OR</em> operator (often denoted by a vertical bar, |) preserves set bits from both operands. If a bit is set in either number, it will appear in the result.<br /> &nbsp;</p> <p><img alt="Image14_GameMath_0626.png" src="" style="display:block; height:162px; margin-left:auto; margin-right:auto; width:600px" /></p> <p>Though similar to simple addition (they are actually equivalent if the operands don’t have any set bits in common), the <em>OR</em> function allows individual bits to be set without consequences.</p> <pre> <code> // Ensure that x is odd. We could do this with simple addition, // but would have to make sure x wasn’t already odd. x |= 1;</code></pre> <p>Together with <em>AND</em>, the OR operator is one of the most commonly used bitwise functions. These two operators turn any integer into cheap and efficient storage for multiple boolean flags.</p> <pre> <code> // Define some power-of-2 flags (numbers with a single set bit). int VISIBLE_FLAG = 1; int MOVING_FLAG = 2; int DAMAGED_FLAG = 4; int TURBO_FLAG = 8; . . . int status = VISIBLE_FLAG | TURBO_FLAG; // Check the ship’s status and disable its engine if damaged. if( status &amp; DAMAGED_FLAG ) status &amp;= ~MOVING_FLAG;</code></pre> <p><strong>Using XOR to combine o<em>nly</em>&nbsp;bits that aren’t shared</strong></p> <p>The bitwise XOR operator (often denoted by a caret, ^) preserves set bits from <em>either</em> operand, but not both. If a bit is set in only one of the operands, it will appear in the result.<br /> &nbsp;</p> <p><img alt="Image15_GameMath_0626.png" src="" style="display:block; height:154px; margin-left:auto; margin-right:auto; width:600px" /></p> <p>This seemingly obscure operation is actually extremely powerful. It finds lots of use when dealing with signed numbers, such as when comparing the sign of two values, or finding the maximum or minimum without branching:</p> <pre> <code> // TRUE if x and y are both positive or both negative. bool haveSameSign = 0 &lt;= (x ^ y); . . . // Find the max/min values of x and y, no branches. int max = x ^ ((x ^ y) &amp; -(x &lt; y)); int min = y ^ ((x ^ y) &amp; -(x &lt; y));</code></pre> <p>It can also be used to compute the absolute value of an integer, or even exchange two values without using an intermediary temporary variable:</p> <pre> <code> // Swap x and y in-place (no temp variable). x ^= y; y ^= x; x ^= y;</code></pre> <p><strong>Shifting bits left or right</strong></p> <p>The bitwise shift operators (often denoted with double angle brackets, &lt;&lt; and) move all bits to the left or right by the amount requested. Shifting signed numbers preserves the sign, although special unsigned versions of the operator are also sometimes available. Bits shifted past either end of the integer are lost.</p> <p><img alt="Image16_GameMath_0626.png" src="" style="display:block; height:367px; margin-left:auto; margin-right:auto; width:600px" /></p> <p><br /> As mentioned earlier, shifting a number left is equivalent to adding 0 to the end—essentially multiplying by the radix. Shifting by 5, as in the first example above, is like multiplying by 2<sup>5</sup> = 32 (verify by noting that, indeed, 79 x 32 = 2528). Similarly, shifting right is the same as dividing by the radix, so the second example shows that -28928 &divide; 2<sup>6</sup> = -452 (the signed is preserved).</p> <p>Technically, using shift operators to scale values by 2 or its powers is always faster than integer multiplication by the same amount, although most applications probably won’t see a significant speedup in practice.</p> <h2>Conclusion</h2> <p>Even though it’s easy to ignore how computers actually store and manipulate numbers, understanding the basics gives us an advantage when creating mathematical programs and games. The hardware representation of integers is fundamental to how computers function, and is the starting point for more exotic number forms like floating- and fixed-point.</p> <p>We’ll explore those number types next as we consider speed, precision, and the trade-offs we’re willing to make for different kinds of games.</p> <p>-peter (<a href="" target="_blank">@peterdotgames</a>)</p> <p>&nbsp;</p> /blogs/appstore/post/3430a447-7f8b-4a76-9dad-2432aa769e69/introducing-toshiba-4k-ultra-hd-fire-tv-edition-a-new-generation-of-smart-tvs Now Shipping: Toshiba 4K Ultra HD - Fire TV Edition, a New Generation of Smart TVs Emily Esposito Fulkerson 2018-06-22T07:00:00+00:00 2018-06-22T15:13:58+00:00 <p><img alt="0530-Roseherobanner-static.PNG" src="" /></p> <p>For developers, this new smart TV adds yet another way to reach potential customers. When you publish on the Amazon Appstore and target Fire TV, your apps and games will be available on the Toshiba 4K Ultra HD - Fire TV Edition out of the box.</p> <p><img alt="0530-Roseherobanner-static.PNG" src="" /></p> <p>Last month,<a href=";p=irol-newsArticle&amp;ID=2343141"> </a><a href="" target="_blank">we announced a multi-year collaboration with Best Buy</a> to bring the next generation of Fire TV Edition smart TVs to customers in the United States and Canada.</p> <p>Today we are excited to announce that the first one, the Toshiba 4K Ultra HD - Fire TV Edition 2018, is now shipping. It is available&nbsp;exclusively online at <a href="" target="_blank"></a> and <a href="" target="_blank"></a>,&nbsp;at Best Buy retail locations.<br /> <br /> The Toshiba 4K Ultra HD - Fire TV Edition delivers stunning picture resolution with vibrant colors and detailed contrast in HD and 4K with High Dynamic Range, and is available in 43”, 50”, and 55” sizes. Combining true-to-life picture quality with the Fire TV experience built in, it seamlessly integrates your favorite content on the home screen, including live over-the-air TV broadcasts, and streaming apps and channels.<br /> <br /> For developers, this new smart TV adds yet another way to reach potential customers. When you publish on the Amazon Appstore and target Fire TV, your apps and games will be available on the Toshiba 4K Ultra HD - Fire TV Edition out of the box.</p> <h2>Bring your apps to life with voice control</h2> <p>The smart home industry is growing rapidly, with no signs of slowing down. Almost <a href="" target="_blank">a third of all households in the U.S. used a smart speaker to make a purchase in Q4 2017</a>. With more customers incorporating smart devices in their daily lives, the Toshiba 4K Ultra HD - Fire TV Edition offers a new, convenient way for developers to engage their users.</p> <p>With the included Voice Remote with Alexa, your customers can use speech to interact with their living room environment. They can browse, navigate, launch apps, and switch inputs, or pair their TV with an Echo device to enable voice control. For example, customers can simply press the microphone button on the Voice Remote with Alexa and say, “Alexa, watch <em>Billions</em>” to instantly watch the show on Hulu.<br /> <br /> Want to create a voice-forward experience for your customers? Here are three steps to enable voice control in your apps:</p> <ol> <li>First, check to see if you have already implemented the Media Sessions API. If you have, all you need to do is add the permission to the manifest file and implement voice commands for transport controls like play, pause, resume, rewind, fast-forward, and skip content. If you haven't, <a href="" target="_blank">click here</a> to get started with Media Session.</li> <li>Integrate your media catalog with Amazon Fire TV so your content can be included in universal browse and search results. Users will be able to find your content in the Fire TV interface and play it directly without needing to open your app first. If your titles are indexed on IMDB or Amazon Video, you are eligible for <a href="" target="_blank">catalog integration</a>.</li> <li>Once your app has gone through catalog integration, you can use the <a href="" target="_blank">Video Skill API</a> to allow customers to launch content, search within your app, change the channel, and use transport controls with their voice.</li> </ol> <h2>Get your Fire TV app ready</h2> <p>If you currently have apps or games on Fire TV, be sure to upgrade them to Fire OS 6 so that they are compatible with the new smart TVs. Notable changes from Fire OS 5 to Fire OS 6 include checking permissions at runtime and linking to private libraries. To learn more about upgrading to Fire OS 6, <a href="" target="_blank">click here</a>.<br /> <br /> If you’ve never released an app or game for Fire TV, head over to <a href="" target="_blank">Getting Started Developing Apps (Amazon Fire TV)</a> for a quick intro. You’ll learn about development options (for example, native versus web apps), device and media specifications, and APIs that are available to you. You can also drag and drop your Android APK into our <a href="" target="_blank">app testing tool</a> to see if your app is already compatible for Fire TV with no additional coding required.</p> <p><a href="" target="_blank">Click here</a> to read the tech docs for the Toshiba 4K Ultra HD - Fire TV Edition.&nbsp;</p>