アクセスいただきありがとうございます。こちらのページは現在英語のみのご用意となっております。順次日本語化を進めてまいりますので、ご理解のほどよろしくお願いいたします。
Appstore Blogs Appstore DeveloperBlog /blogs/appstore/feed/entries/atom 2018-08-17T14:06:17+00:00 Apache Roller /blogs/appstore/post/32110313-55ac-4109-87a9-e8586ed249ac/designing-for-player-expression Designing for Player Expression Emily Esposito Fulkerson 2018-08-15T20:36:59+00:00 2018-08-15T20:36:59+00:00 <p><img alt="Image2-PlayerExpression-0815.gif" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Influencerblogs/Image2-PlayerExpression-0815._CB470170864_.gif?t=true" style="display:block; margin-left:auto; margin-right:auto; width:800px" /></p> <p>This blog will cover something very near and dear to my heart: player expression through gameplay. Basically, players being able to play how they want to play and not always exactly how the game or the designer wants them to play.</p> <p><img alt="Image2-PlayerExpression-0815.gif" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Influencerblogs/Image2-PlayerExpression-0815._CB470170864_.gif?t=true" style="display:block; margin-left:auto; margin-right:auto; width:800px" /></p> <p>Today, I want to continue talking about game design&nbsp;and some of my personal design philosophies. This blog will cover something very near and dear to my heart: player expression through gameplay. Basically, players being able to play how they want to play and not always exactly how the game or the designer wants them to play.</p> <p>When designing games, action games especially, player expression is the cornerstone of every decision I make. I firmly believe that a player should be able to do whatever they think they can do within the context of the game they are playing.&nbsp;</p> <p>Here are some examples tips for designing for player expression.&nbsp;</p> <h2>1. Design for expectation&nbsp;</h2> <p>Creating a game that has believable and consistent interactions is very important. Players need to be able to apply any and all knowledge of the game to pretty much any situation they are thrown into. This can be as simple as hitting an enemy with a certain attack always knocks them down. It is the job of the designer to anticipate player interactions, and make sure those interactions have an expected outcome.</p> <p>I know that sounds hard, but think about Mario for a moment. Mario jumps on things right? So, the designers that work on Mario have to figure out what happens with Mario tries to jump on or into… pretty much anything in the game, because that is what players are going to do. What happens when Mario jumps on a Goomba? Well it gets smashed. What happens when Mario jumps on a Koopa, or a Piranha Plant? What about when Mario jumps on Toad, or some other non-enemy character? Or a sign? Or a block? Or jumps in the water? You get the idea.</p> <p><img alt="Image1-PlayerExpression-0815.gif" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Influencerblogs/Image1-PlayerExpression-0815._CB470170871_.gif?t=true" style="display:block; margin-left:auto; margin-right:auto" /></p> <p>A very simple example of this idea is blocking! Using my game, Knight Club&nbsp;as an example here, you can see what I mean. Players expect to be able to block an attack if their shield is out.</p> <h2>2. Actions link into other actions</h2> <p>It’s pretty likely that your favorite action game follows this idea of being able to perform an action from another action. Jumping while running, attacking while jumping, rolling while blocking, etc. Being able to smoothly transition between character states (running, blocking, jumping, attacking) at a moment's notice is absolutely key to a great feeling action game, and most games in general really. Imagine how annoying it would be to have to completely stop running before you could jump or attack, and how bad that would feel.</p> <p>Any time there is a disconnect between what the player wants to do (assuming they have an understanding of the game mechanics,&nbsp;of course) and what is actually happening in the game, there&nbsp;is a problem. When the player can easily execute their plan without having to argue with the game, the better the game will feel, and the better the player will feel about what they are doing. This is especially true if players are rewarded for “thinking outside the box.&quot;</p> <p><img alt="Image2-PlayerExpression-0815.gif" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Influencerblogs/Image2-PlayerExpression-0815._CB470170864_.gif?t=true" style="display:block; margin-left:auto; margin-right:auto" /></p> <p>This is also from Knight Club, and it shows the options that players have during their dash. Players can cancel the dash into an attack, or a jump. Players can also cancel the dash and return to neutral at any time by pressing down.</p> <h2>3. Chain reactions</h2> <p>A huge part of this “design for expression” philosophy is to allow for chain reactions. Essentially this means designing your games systems to interact with each other. Everything the player wants to hit&nbsp;should be hitable&nbsp;and have a reaction. Those reactions should then have the possibility of causing additional reactions with other objects. A player throws a rock, the rock hits an enemy, and the enemy gets knocked into another enemy which is also knocked down. This is not necessarily a complex, or nuanced interaction, but if the player expects this to happen and it does NOT happen, then you have a problem.</p> <h2>Closing statements</h2> <p>Keep in mind that this entire blog is my opinion, and I’m in no way saying you have to do any of this stuff, or that it applies to every kind of game. It is purely dependant on the kind of game you want to make. However, I do believe you can apply these ideas to pretty much any sort of game, and the game will benefit, even if there are no direct gameplay changes based on the interaction.</p> <p>Until next time you can follow me on <a href="https://twitter.com/ratcasket" target="_blank">Twitter</a>, and on my <a href="https://www.gutterarcade.com/" target="_blank">website</a> for more gamedev related stuff!</p> <p>&nbsp;</p> <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/b36f82e0-6e2a-4dce-a0d0-acdac6eed808/how-to-navigate-the-complexities-of-digital-card-game-design How to Navigate the Complexities of Digital Card Game Design Emily Esposito Fulkerson 2018-08-07T21:00:00+00:00 2018-08-07T21:00:00+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; height:360px; margin-left:auto; margin-right:auto; width:900px" /><br /> I’ve created dozens of card game prototypes and am working on numerous card-based projects I plan to release in the future. From working on these projects, I’ve noted some common elements that tend to make or break a digital card game’s design.</p> <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; height:320px; margin-left:auto; margin-right:auto; width:800px" /></p> <p>Digital card games are a fun challenge to design because they give you a basic and familiar foundation (a deck of cards) that you can adapt to just about any genre, style of play, or conceptual theme. I based a lot of my prototypes, initially, on a single deck of 52 cards, but in the end, precious few of them wound up resembling anything close to a traditional solitaire card game.</p> <p><a href="https://www.amazon.com/Nathan-Meunier-Missile-Cards/dp/B07CVM9S4V" target="_blank">Missile Cards</a> may be my first commercially released card game, but I’ve created dozens of card game prototypes and am working on numerous card-based projects I plan to release in the future. From working on these projects, I’ve noted some common elements that tend to make or break a digital card game’s design.</p> <p>Here’s a look at some of the core design considerations that you need to think about when making digital card games.</p> <h2>1. A strong theme is everything</h2> <p>A theme is usually the first place I start when I’m thinking about a new card game project, because it quickly helps me figure sort out a visual style for my game.</p> <p>Having a striking visual style is important, but I also find that deciding on a theme helps me come up with interesting ideas for the gameplay itself. Whether you’re making a card game about dungeon crawling, fishing, city building, sci-fi combat, or even relationship building, each potential theme holds an exciting range of possibilities for visual style and unique card mechanics.</p> <h2>2. Figure out your visual layout early on</h2> <p>When designing card games, I often begin mocking up visual layouts very early-on in the process, before I even start coding up the game itself. This lets me adjust card size, play around with positioning, and make important decisions about how the game might play based on the limitations of resolution and screen space. I often find that doing this helps me identify potential design issues right away, saving me a lot of time and energy.</p> <p>It’s also worth mentioning you shouldn’t finalize any of your artwork until you’ve got your core layout locked down, since making layout decisions can have a huge impact on your games visual direction</p> <h2>3. Balance accessibility, depth, and replay</h2> <p>Many mobile players prefer games they can enjoy in short bursts instead of marathon sessions. This is one of the reasons card games are so popular on mobile, because they often balance short, accessible gameplay loops with high replayability and long-term metagame progression.</p> <p>When designing card games, it’s worth paying close attention to how long it takes to play through a game and tuning that to be a short, highly replayable experience. Making sessions fun and punchy is important, but also explore ways to layer on progression mechanics, unlockables, and other goals that give players a reason to keep coming back for more.</p> <h2>4. Make the most of the digital format</h2> <p>Physical card game design often tends to be centered around a limited set of simple rules and mechanics—things that can be easily digested without pushing players over the edge of information overload. With digital card games, however, you can get away with much more complexity because you can build it into the behind-the-scenes system that runs the gameplay.</p> <p>From dice rolls and stat tracking to randomization and special events, a lot of the nitty-gritty can be handled by code, freeing up players to focus on whatever you present to them. This opens the door to weaving lots of unusual genres into card-based designs. Missile Cards, for example, just wouldn’t be possible as a simple card game without forcing players to keep track of an excessive amount of information. But the digital format let me design systems to automatically handle a lot of the complexity, allowing players to concentrate on the strategic defense gameplay and simply enjoy the experience.</p> <h2>Quick tips for digital card design</h2> <ul> <li>Pick a strong, distinct theme</li> <li>Make your visual design pop</li> <li>Aim for short, highly replayable gameplay loops</li> <li>Take advantage of the digital format</li> </ul> <h2>Get my free eBook to learn more</h2> <p>To learn more, download the&nbsp;free eBook titled, &quot;<a href="http://m.amazonappservices.com/missile-cards-ebook" target="_blank">Behind the Scenes: Lessons Learned from the Making of Missile Cards</a>.&quot; I'll share more tips on the complexities of card-game design, how to design for multple devices, and tips to bring your game to life.<br /> &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> <p><br /> <br /> <img alt="Nathan-Meunier-headshot.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Influencerblogs/Nathan-Meunier-headshot._CB472623413_.png?t=true" style="display:block; margin-left:auto; margin-right:auto" /></p> <p style="text-align:center"><a href="https://nathanmeunier.com" target="_blank"><em>Nathan Meunier</em></a>&nbsp;<em>is an indie developer, freelance writer, author, and creator of Missile Cards. His work has appeared in more than 40 publications including Nintendo Power, PC Gamer, GameSpot, EGM, and many others. He is also the co-founder of indie studio <a href="https://touchfightgames.com/" target="_blank">Touchfight Games</a>.&nbsp;</em></p> /blogs/appstore/post/58435b68-fba8-4f5c-8144-3adf8f21f7db/mobile-masters-2018-meet-the-players Mobile Masters 2018: Meet the Players Emily Esposito Fulkerson 2018-08-02T17:05:11+00:00 2018-08-02T18:02:45+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:900px" /><br /> In June, we ran our third Mobile Masters event, an esports tournament where both casual and pro mobile game players compete side-by-side for their share of $100,000. Let's meet some of the players.&nbsp;</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:800px" /></p> <p>In June, we ran our third Mobile Masters event, an esports tournament where both casual and pro mobile game players compete side-by-side for their share of $100,000. The tournament was powered by<a href="https://developer.amazon.com/gameon" target="_blank"> Amazon GameOn</a> and was streamed on <a href="https://www.twitch.tv/amazongameon" target="_blank">Twitch</a>, <a href="https://www.youtube.com/watch?v=ohWB2lv2FGU" target="_blank">YouTube</a>, and <a href="https://www.facebook.com/amazonappstore" target="_blank">Faceboo</a><a href="https://www.facebook.com/amazonappstore">k</a> from the new Amazon Game studio in Seattle. It drew 79 professional and amateur players from around the world, competing in games like <a href="https://www.amazon.com/NWAY-INC-Power-Rangers-Legacy/dp/B072JBBRKM" target="_blank">Power Rangers: Legacy Wars</a>, <a href="https://www.amazon.com/Game-Insight-UAB-Survival-Arena/dp/B06XW9RGBG" target="_blank">Survival Arena</a>, <a href="https://www.amazon.com/Wargaming-Group-World-Tanks-Blitz/dp/B071QXPJTK" target="_blank">World of Tanks: Blitz</a>, and <a href="https://www.amazon.com/Critical-Force-Oy-Ops/dp/B072XRYQL1" target="_blank">Critical Ops</a>.<br /> <br /> These players make up the vibrant community around mobile esports, one where anyone can compete for their chance to win. It also naturally brings players together with like-minded people, leading to strong bonds and long-lasting relationships.<br /> <br /> Let's meet some of the players:</p> <h2>Peter Sudarso, Power Rangers Legacy Wars</h2> <p style="text-align:center"><iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/D3VICWn_uZk?rel=0" width="560"></iframe></p> <p>Actor Peter Sudarso brings something completely unique to Mobile Masters — his experience actually embodying characters, in real life, from the game he's playing. Peter depicted the Blue Ninja in the TV series “Power Rangers Nina Steel” and the Red Ranger in “Power Rangers HyperForce.”<br /> <br /> “Being cast for the TV series was a dream come true. It has helped shape my life: it's one of the things that I've grown up with, it's something I've always enjoyed, it's such a positive brand,” said Peter. “It's brought me here. I'm wearing a jersey! I'm kind of a 'pro player,' which is one of my dreams come true.”<br /> <br /> Peter's dream was a long time in the making. He first auditioned for “Power Rangers Megaforce” in 2011, but didn't make it. He tried again the next season, and his brother, Yoshua Sudarso, ended up booking it and playing the Blue Ranger in “Power Rangers Dino Charge” before Peter ultimately got the role after auditioning for the third time.<br /> <br /> “Being here at Amazon Mobile Masters is something I never thought I'd do. I never thought I would play video games live, so it's really, really exciting to be here,” said Peter.</p> <h2>Gankstars, first place winners for Critical Ops</h2> <p style="text-align:center"><iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/M3WUTahBC6I?rel=0" width="560"></iframe></p> <p>Gankstars are world champions in Critical Ops and won the $15,000 first place prize at Mobile Masters for the game. In addition to raw talent, the five-person team has built a strong brotherhood that has propelled them to success.<br /> <br /> “Gankstars is very welcoming. I have not experienced that anywhere else,” said Nikash Tekkem (Alpha). “They're like my family, like my brothers. It's honestly a blessing to play alongside them.”<br /> <br /> “When we get together in-person, it's like seeing a long-lost brother,” said Aaron Jimenez (Kingeh).<br /> <br /> For Nikash (Alpha) especially, the power of these relationships have transcended just gaming. He found friends when he needed them the most.<br /> <br /> “I used to the play the drums and while I was drumming one day, my skin started to peel off. I actually had a skin disorder,” he sad. “I couldn't wear short sleeves, I couldn't play sports anymore because it hurt to catch a ball. I had a hard time making friends at school. I started playing Critical Ops and met a lot of great people in this game. I realized people don't care about my physical features, they just care about how I play the game.”<br /> <br /> These relationships highlight the fact that gaming can connect people on a real level. As Aaron (Kingeh) says, “People can come together as a group and as a community, and can build something that is really inspiring.”</p> <h2>Kip Yerdon, Survival Arena</h2> <p style="text-align:center"><iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/WL87k_sAfnQ?rel=0" width="560"></iframe></p> <p>The beauty of mobile gaming is that anyone compete. Take Kip Yerdon, a father of four who lives in upstate New York. When he's not gaming, he devotes his time to making YouTube videos with his kids.<br /> <br /> “I got started making videos on YouTube when I realized I wanted to build a kids' indoor paradise (KIP) — a play place for kids. I did a Kickstarter, but we didn't make [the goal]. I figured that we needed to build an audience first, so we started doing YouTube videos. We're up to almost 2,000 subscribers and from that, we want to get to where we can eventually build a kids indoor paradise.”<br /> <br /> Kip is also writing a book on being a parent.<br /> <br /> “I think it's very important that people are good at parenting because good parents will raise good kids. The title of my book will probably be, 'How to Not Suck at Parenting.'”</p> <h2>C4, World of Tanks: Blitz</h2> <p style="text-align:center"><iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/lLnyXQ5nyEQ?rel=0" width="560"></iframe></p> <p>C4 is one of the most titled teams in Russia, winning the Blitz Twister Cup in 2016 and the vice-champions Blitz Twister Cup in 2017. The team is made up of players from around the world who enjoy each other's company.<br /> <br /> “Most of the guys are from different places. When we get together in real life, it's usually a lot of fun,” said Vovko.<br /> <br /> “I'm from Russia, in the Ural mountains on the border of Asia and Europe. We have three weeks per year with minus three degrees Celsius, but I like winter and I like cold weather,” said Jjoskey.<br /> <br /> The international players, like Vovko, have moved to the United States and have had to adjust to their new way of life.<br /> <br /> “I'm from Moscow, Russia. Right now, I live near Monterrey in California. The biggest challenge for me was to move to the US,” said Vovko. “The people usually say language barrier [is the hardest], it's the culture barrier: the memes, the sayings, the slang. Everything is different. The language structure is different. If I say something in Russian and I translate it word for word to English, it'll sound ridiculous. Humor is a huge problem for me.”</p> <h2>Powered by GameOn</h2> <p>Mobile Masters was powered by GameOn, a set of flexible APIs built on AWS cloud infrastructure that works on any operating system. With GameOn, the games were able to run qualifiers across the globe for Mobile Masters, identify the best players, award prizes to participants, and nurture talent to create a stronger sense of community.<br /> <br /> Anyone can foster this sense of community among players with GameOn.<br /> <br /> Here's how to get started in three easy steps:</p> <ol> <li><a href="https://www.amazon.com/ap/signin?clientContext=133-6425390-1301538&amp;openid.return_to=https%3A%2F%2Fdeveloper.amazon.com%2Fgameon%2Fconsole%2Fhome&amp;openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&amp;openid.assoc_handle=mas_dev_portal&amp;openid.mode=checkid_setup&amp;marketPlaceId=ATVPDKIKX0DER&amp;openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&amp;pageId=amzn_developer_portal&amp;openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&amp;siteState=clientContext%3D134-7908455-9440860%2CsourceUrl%3Dhttps%253A%252F%252Fdeveloper.amazon.com%252Fgameon%252Fconsole%252Fhome%2Csignature%3Dnull&amp;language=en_US" target="_blank">Sign into</a> the console with your Amazon developer credentials. If you don't already have an account, registration is easy and free.</li> <li>Register your game.</li> <li>After registering your game, you will gain immediate access to the GameOn API key.</li> </ol> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> /blogs/appstore/post/6dfaf872-474e-444a-bc77-73cadb710d49/game-audio-making-room-in-a-mix Game Audio Part 1: Making Room in a Mix Emily Esposito Fulkerson 2018-08-01T22:40:16+00:00 2018-08-01T22:41:39+00:00 <p style="text-align:center"><img alt="GameAudio-DannyB-Hero-July.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/DannyB/GameAudio-DannyB-Hero-July._CB472712647_.jpg?t=true" /></p> <p>In this post I’ll go through some basics on digital audio and the tools available to shape and refine that audio. In a follow-up post, I’ll talk about how to ultimately combine those elements into a cohesive mix with some audio examples. I will list any important jargon at the end for reference.</p> <p><img alt="GameAudio-DannyB-Hero-July.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/DannyB/GameAudio-DannyB-Hero-July._CB472712647_.jpg?t=true" style="display:block; height:321px; margin-left:auto; margin-right:auto; width:800px" /><br /> Game audio is a complicated thing. To the end user, it should be mostly transparent - player does a thing, thing makes sound. Player is in a place, place has appropriate music. But in order to make sure that all these sounds fit together in a readable, aurally pleasing way, there are a few things to consider.</p> <p>In this post, I’ll go through some basics on digital audio and the tools available to shape and refine that audio. In a follow-up post, I’ll talk about how to ultimately combine those elements into a cohesive mix with some audio examples. I will list any important jargon at the end for reference. This will mostly be oriented toward audio folks, but game designers - a working knowledge of these concepts can be very helpful. Don’t be alarmed if you don’t get it at first, it’s weird stuff!</p> <h2>What is digital audio?</h2> <p><strong>Digital audio</strong> is distinct from <strong>analog audio</strong> in a few key ways. Whereas analog recording is hamstrung by issues like noise, fidelity of playback equipment, decomposure of the medium, etc., digital audio’s primary limitation is that it can only capture audio so many times per second (the <strong>sample rate</strong>), and with only so much precision (<strong>bit depth</strong>). That’s a hilariously oversimplified explanation, but the important thing to understand is that you only have so many 1s and 0s to go around. If you play a sound through a digital medium that is nearly as loud as that medium’s maximum volume (the <strong>headroom</strong>), and layer another sound on top of that, there are no more 1s and 0s left in the headroom to express that extra volume, so any additional audio over the maximum is chopped off (known as <strong>clipping</strong>). This is a cardinal sin in audio production, and it’s a nearly universally reviled sound, except when used to creative effect. But rarely is that effect used on an entire mix.</p> <p><img alt="Updated_Image1-GameAudio-Danny-July.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/DannyB/Updated_Image1-GameAudio-Danny-July._CB472713180_.png?t=true" style="display:block; height:255px; margin-left:auto; margin-right:auto; width:800px" /></p> <p style="text-align:center"><em>Here, a sine wave is not clipped by the headroom - there’s enough to fit it all.</em></p> <p><img alt="Updated_Image2-gameAudio-DannyB-July.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/DannyB/Updated_Image2-gameAudio-DannyB-July._CB472713182_.png?t=true" style="display:block; height:217px; margin-left:auto; margin-right:auto; width:800px" /></p> <p style="text-align:center"><em>But here, the top of the waveform is “clipped” right off. This manifests aurally as bad, ugly distortion!</em></p> <p><br /> So! We want to avoid clipping! How do we do that? First, we select a high enough sample rate and bit depth that allows us to play the audio back at the detail level we want. Arguably the most common setting is 44.1/16, or 44.1 Kilohertz sample rate, 16 bit depth. This is the setting for CD audio, which was the first massively successful digital format. In general, it’s safe to consider 44.1/16 the minimum threshold of quality you should aim for. Personally, I find 24/48 to be much nicer to work with. It gives you a little more room for error, and there’s a perceivable difference in the dynamic range in 24/48, particularly in movie soundtracks or very dynamic music like classical or jazz. Whether end-users can tell the difference or not is the subject of a significant portion of internet arguments and such minefields are out of the scope of this article.</p> <h2>How do you fit all this audio in, then?</h2> <p>One easy solution is: make stuff quieter! But, if you make everything too quiet, not only are you making it harder for users to hear the audio, you’re actually not using the full breadth of the audio headroom, and you’re delivering an audio signal that is more aliased and lower-detail because you’re not using the full resolution of the audio signal available to you.&nbsp;Rarely is this phenomenon the source of audio distortion, but since audio goes through so many processes and may ultimately need to be remastered, higher resolution is virtually always a better idea, as long as your computer can keep up. Like in every computer application, higher fidelity requires more processing power.</p> <p>How do we keep our audio signal loud, but not *too* loud? One of the first-line solutions available to you for this dilemma is the <strong>compressor</strong>. A compressor does one very simple thing: it reduces, or compresses, the volume of an audio signal once it reaches a certain volume level, or threshold. You can think of it as a computerized version of someone turning the volume down when a song is too loud, and turning it up when it’s too soft. Virtually all compressors also utilize make-up gain, which is a fancy audio way of saying “louder.&quot; So when you compress an audio signal, then bring the volume up, the <em>average</em> volume of the signal goes up.&nbsp;This is one of those audio processes that still feels like magic to me. Unfortunately, like real magic, it’s hard to understand and easy to accidentally make horrible things happen. The important thing to understand is that compression sacrifices <strong>dynamic range</strong> to make an audio signal flatter - more consistent in volume, and easier to pair with other signals without exceeding your headroom.</p> <p>&nbsp;</p> <p><img alt="Image3-GameAudio-DannyB-July.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/DannyB/Image3-GameAudio-DannyB-July._CB472712642_.png?t=true" style="display:block; height:605px; margin-left:auto; margin-right:auto; width:800px" /></p> <p style="text-align:center"><br /> <em>Note the whole signal has been squished together! We’ve traded dynamics for consistency.</em><br /> &nbsp;</p> <h2>Help! Everything sounds all mushy now</h2> <p>Whoops! We compressed everything into a lifeless pancake-stew of smush-sounds! Turns out, if you compress everything too much, you squeeze all the life out of it. You’ve got another tool in your front-line arsenal - equalization, or <strong>EQ</strong>.</p> <p>You’ve used EQ before. Trust me. If you’ve ever turned on <em>Ludicrous Bass Mode</em> on your Walkman, or used a setting on a receiver or car stereo that purported to transport you to a lush concert hall in the verdant hills of Albany, you’ve used EQ. EQ can do two things: it can boost certain frequencies&nbsp;and it can&nbsp;cut certain frequencies. How it does that, and how you operate it, depends on the type.</p> <p>&nbsp;</p> <p><img alt="Image4-GameAudio-DannyB-july.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/DannyB/Image4-GameAudio-DannyB-july._CB472712668_.png?t=true" style="display:block; margin-left:auto; margin-right:auto" /></p> <p style="text-align:center"><em>In this parametric EQ, the numbered points above and below the curved line either boost or cut volume, respectively.</em></p> <p><br /> EQ’s primary function is to “shape” sound. There are literally infinite ways to do it, but there are some boiler-plate methodologies that I ascribe to -</p> <h2>The high-pass and the low-pass</h2> <p>Also known as the low-cut and the high-cut respectively, the high-pass or low-pass lets the high or low frequencies, respectively, “pass” through the EQ. This is extremely useful.&nbsp;Remember how we only have enough bit depth resolution for so many 1s and 0s? Well, every sound you’ll ever record contains audio information from across the entire audio spectrum, even the stuff human ears can’t hear! Assuming you’re making audio for human people, there are some things we can strip out to free up some of that excess energy for the frequencies we can hear.</p> <p>Generally speaking, the human ear can perceive frequencies from 20 Hz to 20,000 Hz. This is impacted by age, health, all sorts of factors, but usually it’s safe to assume that frequencies under 40hz, while important and certainly detectable by a very nice pair of ears, can’t be reliably reproduced by the vast majority of speaker systems, and don’t do much more than muddy up the whole mix. <em>There are absolutely exceptions to this, especially in movie theaters, live sound setups, Mad Max flamethrower trucks, etc.; don’t send me hate mail!</em> The point is, if you’ve created an audio environment in your game that sounds muddy, oversaturated, or just noisy, eliminating the very low stuff can do wonders to free up your mix for the frequencies that are more important to the human ear.</p> <p>Cutting high frequencies generally doesn’t have as much of a far-reaching impact. Excessive high frequencies can contribute to a “tinniness,&quot;&nbsp;a “sharpness,&quot;&nbsp;or just make everything more exhausting to listen to. The human ear does not like to hear very high frequencies for very long.</p> <p>Again, remember that compression and EQ are MAGIC. Every sorcerer (audio engineer) implements their pixie dust differently. You will not master these overnight. I’ve been doing audio production for 20 years, and it still feels like guesswork sometimes, particularly in a very crowded mix. There are TONS more audio processors at our disposal that can solve these problems differently, but the lion’s share of audio processing is still compression and EQ.</p> <p>In this post, we’ve equipped ourselves with the knowledge we need to shape sounds into a cohesive mix. In the next post, we’ll explore application with some audio examples.</p> <h2>Important terms and definitions&nbsp;</h2> <ul> <li><strong>Analog audio - </strong>Recording, storage, and playback of audio captured using analog methods like tape, vinyl records, etc. Pros - identical capture and reproduction of sound, insofar as the quality of the media allows. Cons - noise, physical media requirements, physically cutting and splicing tape, no one makes these things anymore.</li> <li><strong>Bit depth - </strong>How detailed is each sample taken? Bit depth is a measure of how many possible levels a sound’s loudness can be captured at. For example, a 1-bit depth (21) could only record two states - sound, or no sound, per sample. Whereas an 8-bit depth (28) can express 256 states, 24-bit (224) 16.78 million, etc.</li> <li><strong>Clipping - </strong>Harsh, aurally displeasing distortion of sound caused by information loss when a digital system is overloaded with loudness.</li> <li><strong>Compressor - </strong>Audio process that reduces audio signal over a certain volume (threshold) at a certain ratio, with controls to re-amplify the signal afterwards, to produce a signal with a more consistent average volume.</li> <li><strong>Digital audio - </strong>Recording, storage, and playback of audio captured using binary digits to encode sounds onto a computer system. Pros - versatility, ease of use, redundancy, duplication. Cons - clipping, more expensive equipment, higher learning curve.</li> <li><strong>EQ (equalization) - </strong>Audio process that boosts or cuts discrete frequencies, in order to “shape” an audio signal, removing/attenuating unwanted frequencies and boosting desired frequencies.</li> <li><strong>Headroom - </strong>Once audio values exceed the bit depth, any additional signal is effectively lost, or clipped. This limit is referred to the headroom.</li> <li><strong>Hz - </strong>Hertz, or cycles per second, indicates the frequency of an audio signal.</li> <li><strong>Sample rate - </strong>How many times per second a sound is recorded or played back. Resolution is a function of time - higher resolutions take more “samples” of the audio signal per second, to allow for a more accurate reproduction.</li> </ul> <p style="text-align:center">&nbsp;</p> <p style="text-align:center">&nbsp;</p> <p style="text-align:center"><img alt="DannyBheadshot.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Influencerblogs/DannyBheadshot._CB500305160_.png?t=true" /></p> <p style="text-align:center"><em>Danny Baranowsky is a composer, musician and larger-than-life personality living in Seattle, Washington by way of Mesa, Arizona.&nbsp;Over the past decade, Danny has risen to the top of his field, composing the music for best-selling games Canabalt, Super Meat Boy, The Binding of Isaac, Desktop Dungeons, Crypt of the Necrodancer, and more.&nbsp;This year, Danny looks to expand his musical misadventures - working on solo material, game prototypes, chicken dinners, and even a live set! No task is too tall for Danny (he is 6’4”). Keep on the lookout for <a href="https://dbsoundworks.bandcamp.com/" target="_blank">more music</a> and <a href="https://twitter.com/dannyBstyle" target="_blank">tweets</a> regarding the refresh rates and input latency of OLED monitors in the future.</em></p> <p>&nbsp;</p> /blogs/appstore/post/a42f7f98-678c-41f9-a0f7-45d3fa265f09/voice-enabling-your-media-transport-controls-with-fire-app-builder-1-0-7 Voice-Enabling Your Media Transport Controls with Fire App Builder 1.0.7 Emily Esposito Fulkerson 2018-07-31T20:01:50+00:00 2018-07-31T20:01:50+00:00 <p><img alt="FAB_HeroImage_0727.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/default/FAB_HeroImage_0727._CB471001680_.png?t=true" /></p> <p>In the <a href="https://developer.amazon.com/docs/fire-app-builder/release-notes-version-1-0-7.html" target="_blank">1.0.7 release of Fire App Builder</a>, we added a new feature that has become more relevant given the release of <a href="https://developer.amazon.com/blogs/appstore/post/28dbde74-ca36-4483-b3fb-91013c011203/now-shipping-the-hands-free-amazon-fire-tv-cube" target="_blank">Fire TV Cube</a>: voice interactivity with the media transport controls. Media transport controls refer to the play, pause, rewind, and fast-forward actions with your media player.</p> <p><img alt="FAB_HeroImage_0727.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/default/FAB_HeroImage_0727._CB471001680_.png?t=true" style="display:block; height:200px; margin-left:auto; margin-right:auto; width:900px" /></p> <p>In the <a href="https://developer.amazon.com/docs/fire-app-builder/release-notes-version-1-0-7.html" target="_blank">1.0.7 release of Fire App Builder</a>, we added a new feature that has become more relevant given the release of <a href="https://developer.amazon.com/blogs/appstore/post/28dbde74-ca36-4483-b3fb-91013c011203/now-shipping-the-hands-free-amazon-fire-tv-cube" target="_blank">Fire TV Cube</a>: voice interactivity with the media transport controls. Media transport controls refer to the play, pause, rewind, and fast-forward actions with your media player. Making these transport controls voice interactive allows users to say utterances such as “Alexa, Play,” “Alexa, Stop,” and “Alexa Rewind” to interact with your content.<br /> <br /> Granted, the voice integration doesn't extend further than this. For example, users can't search and discover your app's media with voice, saying “Alexa, find [TV Show]” from the home screen to find the content — that integration requires you to implement the <a href="https://developer.amazon.com/docs/fire-tv/voice-enable-your-app-and-content.html#video_skill_api" target="_blank">Video Skills Kit</a>. However, allowing users to interact with transport controls alone is a huge win and constitutes a significant use case for voice. (Think about how much time users spend watching a show versus the time they spend getting to the show.)</p> <h2>Far-field voice control&nbsp;</h2> <p>The release of Fire TV Cube provides a significant milestone with voice because it's the first Fire TV device to offer <em>far-field </em>voice control natively. This means users can say utterances <em>far away</em> from the device's microphone and it understands you. (“Near-field” control refers to saying utterances while pressing the microphone button on your remote, with your voice <em>near</em> the remote's microphone.)<br /> <br /> Far-field voice control is simply cool. I've personally found it convenient to say “Alexa, pause” while I'm watching a show so that I can go into the kitchen and stir what I'm cooking, and then “Alexa, resume” when I return. Or when one of my kids gets really loud and I can't hear what people are saying on the TV, I can say “Alexa, rewind 30 seconds.”</p> <p><img alt="firetvcube_living_room3.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/default/firetvcube_living_room3._CB471001683_.png?t=true" style="display:block; margin-left:auto; margin-right:auto" /></p> <p>Sure, you could do all this using your remote, but for these simple utterances, it's much easier to say them rather than hunt around for the remote. Especially considering how we often watch TV in the evenings with the lights dimmed — finding that little black remote can be annoying.<br /> <br /> Fire App Builder now gives you an extremely easy way to incorporate this voice-forward functionality into your apps. If you're using Fire App Builder, you don't need to do anything at all (except upgrade to the latest version). The <a href="https://developer.amazon.com/docs/fire-tv/mediasession-api-integration.html" target="_blank">Media Session API</a> is already integrated, so it just works.<br /> <br /> To try out the voice commands, <a href="https://developer.amazon.com/docs/fire-app-builder/download-and-build.html" target="_blank">download and build</a> the latest version of Fire App Builder in Android and run the sample app on a Fire TV device. Launch a video and <a href="https://developer.amazon.com/docs/fire-app-builder/alexa-integration.html" target="_blank">try out some of these Alexa commands</a>:</p> <ul> <li>&quot;Alexa, stop&quot;</li> <li>&quot;Alexa, resume&quot;</li> <li>&quot;Alexa, pause&quot;</li> <li>&quot;Alexa, rewind 2 minutes&quot;</li> <li>&quot;Alexa, fast-forward 30 seconds&quot;</li> <li>&quot;Alexa, jump back 30 seconds / Alexa, jump forward 30 seconds&quot;</li> <li>&quot;Alexa, go back 30 seconds / Alexa, go forward 30 seconds&quot;</li> <li>&quot;Alexa, next&quot;</li> <li>&quot;Alexa, next episode&quot;</li> <li>“Alexa, previous episode”</li> </ul> <p>If your Fire TV device has only near-field voice control (requiring you to press a microphone button on your remote), you won't experience the full experience of hands-free TV. I suggest that you try out the Fire TV Cube or <a href="https://www.amazon.com/gp/help/customer/display.html?nodeId=202174250" target="_blank">link an Echo or Echo Dot with your Fire TV</a> to provide the far-field voice control. There's quite a difference between hands-free control and pressing a microphone button. Hands-free TV simply frees you up in more liberating ways.</p> <h2>About Fire App Builder</h2> <p>If you're new to Fire App Builder, you can <a href="https://developer.amazon.com/docs/fire-app-builder/overview.html" target="_blank">learn more about it here</a>. Fire App Builder is a Java-based Android project that lets you build a robust Fire TV app (which will also work in Google Play) with little development effort on your part. The idea of Fire App Builder is to provide a complete streaming media app with all the functionality you could want — from authentication to advertising, analytics and in-app purchasing and more — all configurable to your needs.<br /> <br /> Fire App Builder sits between the no-code solution like <a href="https://creator.amazon.com/documentation/ac/overview.html" target="_blank">Amazon Creator</a> and a custom-developed Android app. You don’t need Android development skills to build an app, but you can jump into the code to extend it if you want. Even if you have development skills and the ability to roll your own, you might prefer to start with a robust framework to save time. Fire App Builder helps you get a rich TV app optimized with voice-interactivity for transport controls with comparatively little effort.</p> <p>To learn more about Fire App Builder, see the following:</p> <ul> <li><a href="https://developer.amazon.com/docs/fire-app-builder/overview.html" target="_blank">Fire App Builder: A starter kit for Java-based Amazon Fire TV and Android apps</a></li> <li><a href="https://developer.amazon.com/docs/fire-app-builder/download-and-build.html" target="_blank">Download Fire App Builder and build an app</a></li> <li><a href="https://developer.amazon.com/docs/fire-app-builder/alexa-integration.html" target="_blank">Try out the Alexa integration</a></li> </ul> <p>&nbsp;</p> /blogs/appstore/post/282209bb-c6b1-4c77-80b6-b078398dc38b/behind-the-scenes-designing-missile-cards Behind the Scenes: Designing Missile Cards Emily Esposito Fulkerson 2018-07-26T17:11:02+00:00 2018-07-26T17:12:23+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; height:360px; margin-left:auto; margin-right:auto; width:900px" /><br /> Missile Cards isn’t my first commercial project, but it’s one of the weirdest, most ambitious, and most successful games I’ve created to date. For me, learning is an important part of the process and each project brings new challenges, victories, and opportunities to share my experience with others.</p> <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; height:320px; margin-left:auto; margin-right:auto; width:800px" /></p> <p>What an exciting time to be an indie developer. With powerful tools that speed up 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.</p> <p>For me, Game Maker: Studio was the catalyst that changed everything. I’ve spent most of my professional career writing about other people’s video games for publications like Nintendo Power, IGN, GameSpot, GamePro, and more. I never expected to eventually make my own games, yet here I am. In just three years of part-time tinkering, I’ve gone from having zero knowledge about what goes into creating a game to rolling up my sleeves and bringing games from concept to launch.</p> <p><a href="https://www.amazon.com/Nathan-Meunier-Missile-Cards/dp/B07CVM9S4V" target="_blank">Missile Cards</a> isn’t my first commercial project, but it’s one of the weirdest, most ambitious, and most successful games I’ve created to date. For me, learning is an important part of the process and each project brings new challenges, victories, and opportunities to share my experience with others.</p> <p>In this post, I'll pull back the curtain on my game design and creative processes.&nbsp;</p> <h2>Finding the unusual concept for Missile Cards</h2> <p>It was late fall, 2016. Exhausted from grinding away on a larger indie console project over the course of two years, I found myself desperate to hit the finish line—aching to feel the cathartic rush of completing a game again. The idea of creating something small, polished, and launchable on a very constrained development cycle was immediately appealing. With no end in sight on the larger project I was working on with another team, I needed a temporary change of pace.</p> <p>By this point, I would blow off steam in my spare time by prototyping card game concepts. Making a small card game seemed like a perfect fit for a short-term solo project, given the genre’s modular nature and high replayability. I just had to come up with a strong idea I could realistically build out and finish in a matter of months, instead of years.</p> <p>My favorite mobile card games are the ones that mix bold themes with unusual mechanics to create something funky and fresh. Being largely a solo gamer, I also prefer solitaire-style card games that can be played alone. After a lot of brainstorming, I fixed on the idea of a card game where you would defend yourself from giant doom meteors hurtling down from space. You’d lay down defenses that would have to be charged up before blasting the oncoming debris away, and the deck itself would be your adversary, providing a mix of helpful and harmful resources to juggle.<br /> &nbsp;</p> <p><img alt="image1-Missile-cards-blogpost-0726.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Influencerblogs/image1-Missile-cards-blogpost-0726._CB472623415_.png?t=true" style="display:block; height:394px; margin-left:auto; margin-right:auto; width:700px" /></p> <p><br /> I realized this concept reminded me of a childhood gaming favorite: Missile Command<em>.</em> I decided to roll with the retro vibe this evoked and put a fresh spin on things. The idea of taking the intense arcade defense gameplay of the Atari classic and re-imagining it as a turn-based strategy solo card game was just weird enough to work. Not only that, it had a grabby hook that would potentially appeal both to modern digital card game fans and retro gaming enthusiasts alike.</p> <p>Missile Cards was born, with the tagline “Missile Command meets Solitaire…only with more doomlasers, death, and explosions.” In reality, it’s not quite like either game it pays homage to, but it draws inspiration from both as well as the nostalgia of growing up as a young gamer in the '80s.</p> <p>Armed with a cool theme and a loose battle plan to make something fun in just a few quick months of coding and design, it was time to get to work.</p> <h2>Minimizing risk by making smaller games faster&nbsp;</h2> <p>Game development almost always takes much more time and energy than anyone anticipates. With Missile Cards, I set out to create and launch a polished game in just three short months. It took me six. Every facet of the game’s design was tuned towards creating a minimum viable product, and even then it still took me much longer to complete than I had planned. This shouldn’t be a surprise to anyone who has dabbled in indie game development.</p> <p>So what does “minimum viable product” mean, exactly? My ultimate goal with Missile Cards was to make a finished game I was proud of, all while minimizing my financial risk on the project. The market segment for game genres and trends shifts so rapidly that many developers start making a game based on what’s popular at the moment, only to find that players have already moved on to the next big thing by the time their game finally ships years later.</p> <p>Instead of spending years making a huge game that might not sell, I wanted to create a tightly-scoped project in as short a time as possible. If it sold, great! If not? Well, a few months of part-time work on a project that fails is a lot better than spending three years on a commercial flop with nothing to show for it.</p> <p>Planning for the potential of failure, particularly with more experimental projects, is a smart bet in today’s hyper-competitive industry. You never truly know when a new game is going to resonate with a broader audience until it launches, and the longer it takes to develop a project, the more pressure there is for it to be a success. This is doubly important for solo developers and newcomers seeking to carve out a foothold in the industry for the first time.</p> <p><strong>Ways to help minimize risk:&nbsp;</strong></p> <ul> <li>Keep the development cycle short</li> <li>Create constraints for the project</li> <li>Set internal deadlines and milestones</li> <li>Focus on just the core content and avoid piling on extras</li> <li>Be willing to cut features that aren’t working out</li> </ul> <h2>Keeping scope creep to a minimum&nbsp;</h2> <p>Scope creep is an omnipresent danger in game development, affecting teams of all sizes across all sectors of the industry. It’s all too easy to succumb to the desire to throw every cool idea you come up with into your game. Experimentation is an important part of the design process early on, but there comes a point where continuing to add ideas can easily spiral out of control. Not every neat mechanic or design idea you come up with will make it into your game—and that’s ok.</p> <p>Here are some ways to keep scope creep to a minimum:</p> <p><strong>Constraints breed creativity</strong></p> <p>Setting limitations and learning how to identify unnecessary bloat in your game design are valuable skills. When you set constraints for your game project, it makes it a lot easier to identify and trim the fat. Honing this ability can save you a lot of wasted time and heartache.</p> <p>It’s hard to pin down a realistic deadline when planning out your game in its early stages, but setting a target timetable is invaluable in keeping scope creep to a minimum.</p> <p><strong>Make tough decisions</strong></p> <p>My original plan for Missile Cards was to create three full planets worth of content. This seemed like a reasonable goal at the time, but once I got deeper into development, I quickly realized that building out that much content would take much, much longer than I anticipated.</p> <p>It was a difficult decision, but I opted to pare the game down to one single planet with five bases, then double-down on making the game challenging and replayable enough to give players a solid play experience for their money. This was the right call.</p> <p><strong>Tips for killing scope creep:</strong></p> <ul> <li>Impose creative limitations early on</li> <li>More isn’t always better</li> <li>Be willing to make hard decisions</li> <li>Try making smaller games, faster</li> </ul> <h2>Get the&nbsp;free eBook to learn more</h2> <p>To learn more, download the&nbsp;free eBook titled, &quot;<a href="http://m.amazonappservices.com/missile-cards-ebook" target="_blank">Behind the Scenes: Lessons Learned from the Making of Missile Cards</a>.&quot; I'll share more tips on how to design your game, the complexities of card-game design, and tips to bring your game to life.<br /> &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> <p><br /> <br /> <img alt="Nathan-Meunier-headshot.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/Influencerblogs/Nathan-Meunier-headshot._CB472623413_.png?t=true" style="display:block; margin-left:auto; margin-right:auto" /></p> <p style="text-align:center"><a href="https://nathanmeunier.com" target="_blank"><em>Nathan Meunier</em></a>&nbsp;<em>is an indie developer, freelance writer, author, and creator of Missile Cards. His work has appeared in more than 40 publications including Nintendo Power, PC Gamer, GameSpot, EGM, and many others. He is also the co-founder of indie studio <a href="https://touchfightgames.com/" target="_blank">Touchfight Games</a>.&nbsp;</em></p> /blogs/appstore/post/424728a9-1653-406a-8589-d16adb7842f3/3-best-practices-for-playtesting 3 Best Practices for Playtesting Emily Esposito Fulkerson 2018-07-24T17:17:01+00:00 2018-07-24T17:17:01+00:00 <p><img alt="playtesting-NathanRanneyblogpost.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/NathanRanneyblogposts/playtesting-NathanRanneyblogpost._CB496946095_.jpg?t=true" style="display:block; height:400px; margin-left:auto; margin-right:auto; width:1000px" /></p> <p>As someone who has primarily made multiplayer games, playtesting has been an extremely important part of development. However it can be tricky to get helpful feedback under certain circumstances.</p> <p><img alt="playtesting-NathanRanneyblogpost.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/NathanRanneyblogposts/playtesting-NathanRanneyblogpost._CB496946095_.jpg?t=true" style="display:block; height:320px; margin-left:auto; margin-right:auto; width:800px" /><br /> Howdy, folks! Today I want to talk about playtesting. This is something that can be really hard to nail down for an indie, or hobbyist game developer. As someone who has primarily made multiplayer games, playtesting has been an extremely important part of development. However it can be tricky to get helpful feedback under certain circumstances.</p> <h2>What is playtesting?</h2> <p>For those of you who may not know, playtesting is when you have other people play your game during development to give feedback. This is often done to find bugs, determine if the game is fun, and to help iron out general issues that players may run into. It is very easy to overlook things as a developer, and it is even easier to have bad ideas that don’t turn out well. Playtesting is key in the development of any game.</p> <p>To help you get the most out of player feedback, here are my top three lessons learned about playtesting:</p> <h2>1. Playtest in person</h2> <p>If at all possible, you should be right there next to your play testers. This is difficult for me since I live in the middle of nowhere, and don’t get a chance to make it out to big events too often, but when I can, it makes a huge difference. The reason this is so important is because you are able to watch the body language of your play testers. Anyone can send you an email, a tweet, or a discord message saying “Wow this game was really fun! good job!” but it's entirely possible that the person is… well… just being nice! Being able to watch a person smile, laugh, or sigh in frustration can be a much more honest sign of how your game is doing. You also have the benefit of asking or answering questions in real time with the person, which can make a world of difference for the tester.</p> <p>I remember the first time I went to GDC, I was showing off a fighting game. Prior to going, almost all of my playtesting had been done online, and feedback was always positive. I was so excited to play with people, and it was a complete flatline! No one had any reaction. People played with blank faces. No smiles, no frustration, no excitement. Nothing! When it was over everyone would hand me the controller and say “It's&nbsp;fun.&quot;&nbsp;It definitely wasn’t fun.</p> <p>Later that night, I went back to my hotel room early, and spent almost all night making changes to the game. The next day I wrangled up some play testers, and this time people were having visible reactions to what was happening in the game.</p> <h2>2. Identify the real problem</h2> <p>A play tester's perception of the game, especially if it is early in development, may not always be accurate. Especially gut reactions that you may get from people who only play your game for a few minutes, which you’ll see a lot of if you take your game to shows and conferences. In my case, when making a fighting game, it takes many hours of play to understand the nuance and situations that are presented. When someone who has played for less than thirty minutes tells me that a character, or a special move, is “overpowered,” it likely points to another issue entirely.</p> <p>During the development of the Knight Club prototype, lots of players would pick up the game, play for about 10-15 minutes, and then give some feedback. Almost everyone said that one of the weapons was way overpowered due to its range. Back then Knight Club was a one hit kill style of party game, so long ranged weapons had a big advantage against new players who didn’t understand the ways to get around those weapons. So it wasn’t that the weapon was too strong, it was that the solutions to deal with that weapon were not apparent. After playing for an hour or so, players would easily be able to deal with this weapon and the impression that it was over powered ended up going away.</p> <p>In this case there wasn’t much I could do to help new players overcome this hurdle. They simply had to play, and want to understand the mechanics of the game. Considering that I was trying to make a game for a very specific kind of player, I wasn’t too concerned with some folks just not getting it or not wanting to put in the time to get it. That was okay for me, and for Knight Club.</p> <p>It is very important to break down the feedback you are receiving. Identify if the feedback is describing the problem, or if it is going to lead you to the problem. From there you can determine if this is actually a problem (such as something being literally broken and not functioning as intended) or a problem of player perception. Which, technically, is still a problem! It just has a different solution.</p> <h2>3. Know when to change</h2> <p>A common pitfall with playtesting is wanting to make changes based on every little bit of feedback you receive. Using Knight Club as an example again, I made a conscious decision not to adjust the range and playstyle of a certain weapon because new players were having issues with it. I was confident that they would find ways around it if they wanted to, and they did. We all want people to enjoy our games and it is so easy to let little bits of negative feedback make you want to change things. Do not fall into this trap!</p> <p>Consider your design when making any changes based on player feedback. You will often run into a situation where the feedback is at odds with your initial design, or ideas for the game. Assuming that the feedback you have received is at least a little subjective, It is up to you to decide if you should make those changes. This is a somewhat controversial idea, but I’m not a firm believer that the player needs to understand everything the first time they see it. It's okay if a player has to learn a bit when playing one of my games, and I’m okay with a player not doing that and not playing. That may not be okay for you! That may not be the case for me down the road, depending on the kind of game I’m making.</p> <h2>Recap</h2> <p>All in all, playtesting and parsing feedback is highly subjective. I don’t want any of you to follow what I’ve said here as a hard and fast rule. There are a few key takeaways though.</p> <ol> <li> <p>Playtest in person. Look at the play testers face! Are they smiling!</p> </li> <li> <p>Learn to identify what people really mean when they provide feedback. It isn’t always easy, and it doesn’t always need to be deciphered. Sometimes the feedback is spot on.</p> </li> <li> <p>Understand your game, and what you are trying to do with your game.</p> </li> <li> <p>Try to implement feedback as it aligns with your design and goals.</p> </li> </ol> <p>I hope this was helpful to some of you fledgling developers. 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.gutterarcade.com" target="_blank">website</a>.</p> <p>&nbsp;</p> <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/28441cc2-c8d8-470d-8486-73ab9ed28a5c/success-story-eden-games-increases-gear-club-s-tournament-retention-by-20-with-gameon Success Story: Eden Games Increased Gear.Club's Tournament Retention by 20% with GameOn Emily Esposito Fulkerson 2018-07-20T18:06:08+00:00 2018-07-24T17:55:11+00:00 <p><img alt="Gearclub-casestudy-hero-0720.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/GameOn/Gearclub-casestudy-hero-0720._CB471889902_.png?t=true" /></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="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/GameOn/Gearclub-casestudy-hero-0720._CB471889902_.png?t=true" 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="https://www.amazon.com/Eden-Games-Gear-Club/dp/B06XNQ69MB" 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="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/GameOn/gameon-gearclub-casestudy-0720._CB471889900_.png?t=true" 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 Amazon.com 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="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/GameOn/Esport_Introduction_World_Gearclub_Casestudy_0720._CB471889682_.png?t=true" 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="https://developer.amazon.com/gameon/getting-started" 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="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> <h2>About Eden Games</h2> <p><img alt="Edenlogo-0720.png" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/GameOn/Edenlogo-0720._CB471889477_.png?t=true" style="display:block; height:226px; margin-left:auto; margin-right:auto; width:200px" /><br /> <a href="http://www.edengames.com/" 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="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/AlejandroHitti/Object-introspection-image1-0718._CB473909306_.png?t=true" style="display:block; height:506px; margin-left:auto; margin-right:auto; width:900px" /></p> <p>In<a href="https://developer.amazon.com/blogs/appstore/post/11f78b59-33bf-40cc-b869-78276d728372/object-type-introspection-in-gamemaker-part-1?cmp=US_2017-00_Inf_InfBlogs&amp;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="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/AlejandroHitti/Object-introspection-image1-0718._CB473909306_.png?t=true" style="display:block; height:506px; margin-left:auto; margin-right:auto; width:900px" /></p> <p>In<a href="https://developer.amazon.com/blogs/appstore/post/11f78b59-33bf-40cc-b869-78276d728372/object-type-introspection-in-gamemaker-part-1?cmp=US_2017-00_Inf_InfBlogs&amp;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="https://drive.google.com/open?id=1wzrW5O34dYsi9OSD3v6zX6y-MyCk5vik" 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="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/AlejandroHitti/Object-introspection-image1-0718._CB473909306_.png?t=true" 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="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/AlejandroHitti/object-introspection-image2-0718._CB473909300_.png?t=true" 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="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/AlejandroHitti/object-introspection-image3-0718._CB473909303_.png?t=true" 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="https://drive.google.com/open?id=1wzrW5O34dYsi9OSD3v6zX6y-MyCk5vik" 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="https://marketplace.yoyogames.com/assets/6221/imguigml" 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="https://drive.google.com/open?id=1wzrW5O34dYsi9OSD3v6zX6y-MyCk5vik" 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="https://marketplace.yoyogames.com/assets/6221/imguigml" target="_blank">ImGUIGML extension</a></li> <li><a href="https://developer.amazon.com/blogs/appstore/post/11f78b59-33bf-40cc-b869-78276d728372/object-type-introspection-in-gamemaker-part-1" 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="http://twitter.com/AleHitti" target="_blank">@AleHitti</a>). Thank you for reading. Until next time!</p> <div> <img alt="AlejandroBio.jpg" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/default/AlejandroBio._CB512098171_.jpg?t=true" 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="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/default/blog_post_(2)._CB473911973_.png" 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="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/default/blog_post_(2)._CB473911973_.png" 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="https://m.amazonappservices.com/gameonofficehours" target="_blank"><img alt="" src="https://m.media-amazon.com/images/G/01/DeveloperBlogs/AppstoreBlogs/default/button_gmon._CB473386257_.png" 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="https://developer.amazon.com/gameon/getting-started" 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="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> <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>