Friday, January 25, 2013

Building a Game Library: steps, design decisions, sacrifices. Part 2



This is the second and final part of the series. If you missed the first part you should read it here.

Here I continue to define the phases I went through while re-writing my game library RaptorGL and the tools I added to ease the development and deploy/build your RaptorGL game.

Phase 5: Give some TLC to Sprite. Sprite was pretty dumb in previous implementation. It required the dev to add pretty much any feature to it besides drawing and moving. I realized that this not a very nice thing so Sprite can now rotate itself based on anchor points between 0-1, the default being 0.5 which is the center. It can also scale now too using the same anchor points used for rotating. I may separate them in future versions. Also the new Sprite.moveBy() and Sprite.moveTo() does not create a new object every time.  Instead it stores the values in a private variable of the Sprite object.

Phase 6: Throw away label and write new one. Label was well, not my proudest piece of code lol. So when it came to a re-write I just deleted the module all together, being very careful not even seeing a line of code in there. So the new label is a totally new implementation which I'm very happy with right now. I decided to stay away from inheritance hell, so I did not inherit from Sprite even though they share many common features. This turned out to be an awesome decision. Label has scale, rotate, align left, right, center, and of course it can move.

Phase 7: Simplify assets loading. Now each class handles the loading of the proper assets and notifies the object when the loading is done. This includes Textures, SpriteSheets, Sounds, and soon custom Fonts. When RaptorGL boots up it asks all these classes to start loading their resources. After they are done RaptorGL removes the loading screen and calls the game's main function.

Phase 8: Write a simple module loading system. This one was very fun to work on. Implementation is super simple and it also allows the RaptorGL build tool to combine all your modules into one JS file and even compress it for you. The way I got around adding all those extra functions, and with it all the extra function calls, was to introduce the includes.js file into the project. This file gets run before your main.js file and imports all the modules that are defined in there. Syntax is very simple: you write rgl.include('gam-module.js'); That's all, now your module files are not polluted with all the require and import statements and it also enforces you to think about your code layout. I'm planning on adding module folder support as well.

Phase 9: Development Server. I noticed right away the it can be a pain to run the game using the "file:///" url in the browser, especially when using webworkers. Also I want to test on my iPad and iPhone so I needed a lan IP for that. It helps debugging to see which resources are getting requested etc.. So I opened up my Python editor and with only about 70 lines of code (which includes comments) I got an awesome small dev server. It can accept 3 arguments for IP, Port, Directory.  Now one can fire it up from the command line and test your game from anywhere on your network.
I even found another cool use of the server. Since you can define any directory to be the root directory you can start the server with your home directory and others can read and download files from your computer. Pretty snazzy ;)

Phase 10: Build tools. Now if you've done any development you know that there is a difference between your dev and build versions. Since RaptorGL implements the module import in such a straight forward way it was a natural choice to provide a build tool to get rid of those rgl.include(); calls and just combine the files into the main.js file in the same order as the includes. So just like with the Server I opened up my Python editor and with 174 lines of code I wrote an awesome build tool. I say Awesome because it not just combines your JS files, it also creates a build directory in your project and copies all other assets and RaptorGL itself. But wait! There is "One More Thing..." :)
RaptorGL build tool also can compress your main game file using the Google Closure Compiler
It supports all three compressions: Whitespace, Simple, and Advance. It creates a new file with the .min extension so your packaged JS file will not be overwritten.

Phase 11: Sacrifice platform. This one was Hard.  I realized that many parts of the library were being updated, adjusted, and expanded just to support Mobile Browsers... But Why?! RaptorGL already has hosts for desktops, why not just create hosts for iOS, Android, and Windows 8 Phone as well? Since I'm much more familiar with iOS I decided to tackle it first. It only took me about 2 hours to get a host up and running. RaptorGL was running an average 50FPS with over 800 sprites. Thats perfect! I can live with that, since I know there is a lot of room for optimization. So I dropped the Mobile Browser support... for now. But since I already have the orientation support with dynamic viewport/scene/layer resize and full touch support including multi touch you can bet that "It Will Be Back" :) 

Conclusion: Well, there you have it. Looking at all that, now you can see writing a game library is not a walk in the park, but it's so worth it! Very challenging and rewarding at the same time.
Stay tuned to read all about the native hosts for RaptorGL, which even includes the same dev tools you are used to in Safari and Chrome.

If you have any questions leave a comment or ping me on twitter @LZAntal

Thursday, January 24, 2013

Building a Game Library: steps, design decisions, sacrifices. Part 1

Re-writing RaptorGL was a real eye opening experience. Even though everything went great at the beginning, somewhere in the back of my mind I knew it was too good to be true. Boy was I right.
But thats the end of the post so lets start at the beginning.

After playing around with WebGL back in late 2012 and reading this awesome book I knew that if I could use WebGL as a drawing backend to RaptorGL it would be a huge performance boost. I actually have been following one of the author's blog about WebGL @Tojiro. His demos are amazing. It's inspiring to see how far we can push the current state of WebGL. So I went ahead and wrote a very simple "click to destroy" style game which btw will be my January game for OneGameAMonth :))
Once it was working I realized that I needed a mouse position converter from World coordinates to Window coordinates. It was much simpler than I thought so now I could properly detect where the mouse was down.

Next came the Layer class... it was a total failure. But a good one! It showed me that the current implementation of RaptorGL using the Canvas didn't have a nice concise API that I could follow. Also, if the user's browser does not support WebGL I need to fall back to canvas.

There came the idea of a re-write with a properly defined internal API so I can hook WebGL in when it's available, and have the engine auto switch the TouchMgr and Layer classes to use the proper implementation... be it Canvas or WebGL.

But before I can run I need to learn to walk. 
It was time to seriously commit to RaptorGL and bring it up from "Pet Project" to "Project". This also meant that I had to downgrade my current obsession with MOAI and my TrexGL library to "Pet Project" but it is a sacrifice well worth making as you'll find out in an other post. Hint: RaptorGL now has it's very own native host so it runs as a standalone game without a browser for Win, Mac, Linux :))

With all that in place I embarked on the journey to re-write the Canvas implementation of RaptorGL, keeping in mind the implementation has to be able to work with WebGL... my main goal.

I structured the re-write into phases. So far there are 11, described below. I'm sure there will be more as I continue to use it for my games and share it with beta testers.

Phase 1: Remove 3rd party library dependency. Write everything in pure javascript. This was the best decision ever. Removing jQuery alone brought the size down by almost 100KB. Then came the really overused and over-recommended RequireJS library. Running my simple prototype was a breath of fresh air. Now I had full power and control over every aspect of the code. Love it!

Phase 2: Clean up the classes, class implementation. I used @Jeresig implementation of JavaScript inheritance. This design helps keep the overhead low and at the same time allows proper inheritance while still keeping the code simple. What I like most about this implementation is that it allows calling the super/parent classes method when you overwrite it in your own implementation. This will help devs create their own version of Sprite, Layer etc.. but still have the option to call the super/parent method from within their method.

Phase 3: Combine mouse and touch controls. Since I already had this done in TrexGL it was a matter of converting my Lua implementation to JavaScript... yeah right! See the game runs in the browser so everything in there is laid out using the DOM. So guess what, there are a lot of browser differences I needed to take into consideration, oh and did I tell you about resizing the browser window changes all the off sets? I decided to use a callback system instead of keeping the positions in globally accessible variables. I got the inspiration from Futile an awesome unity 2D framework written by @MattRix. If I ever decide to do 2D this is the tool I'll use. Although it works great now I can actually foresee adding the global variable option as well. Maybe my prototypes are just too simple and the overhead of a loop and function call bothers me. Time will tell.

Phase 4: Fix Scene and Layer implementation. These two were arguing all the time in the previous implementations. Scene was trying to be like Layer and Layer was trying to be like Scene. So it was time to put an end to this. Now Scene behaves nice and manages the drawing and updating of the Layers. Scene is also the main entry point in RaptorGL to start a game and RaptorGL uses it to dispatch draw and update calls. Layers can care less now about their surroundings and obey the Scene. Layer also holds all the Sprites and Labels. Layer can ask the Scene to call it every frame to update with the deltatime.

Thats all for the first post. Stay tuned for the second/final post of this series where you can read the other 6 Phases, two of which are tools to ease development and deploy/build your RaptorGL game.
Next post comes out this Saturday,

Part 2 available here, read on to learn about the tools and the other 6 Phases. :)

If you have any questions leave a comment or ping me on twitter @LZAntal

Monday, January 7, 2013

Found an HTML5 canvas shortcoming: Rotation

As I was working on the RaptorGL.com re-write I found the first noticeable shortcoming of the html5 canvas: rotation

To rotate a sprite on the canvas first we have to call context.save() then translate to the center point of the sprite or any other anchor point. After all this finally we can rotate the entire canvas... in radians. Not a big deal. We can easily convert angles into radians, but here comes the tricky part... what do you think the 0,0 (top,left) position of the canvas is now? If you said it's the center of the sprite then you're right. It took me a few tries to realize that it got moved around. Well now we have two options: call another context.translate or just use the context.drawImage and specify it there to save a function call. I chose the latter, and finally I can call context.restore(). As you can see that is a lot of extra function calls and steps just to rotate one sprite. 

Performance gets hit around 1000 sprites all rotating around at every frame. In the old implementation of RatorGL.com I had every sprite on its very own canvas and that canvas was drawn to the layer canvas. It sounds like a lot of work but it was all done in the background and only costs a little extra time at startup. That design could work in this case to eliminate many of the function calls if an object rotates once every second or so. I can see some optimizations there like group draw calls together for all the sprites that have the same rotation etc...

Since I'm set on entering into the Mozilla Game On Challenge with RaptorGL and also use it to write many of the games for the awesome One Game A Month Challenge I'm ok with FPS to drop to around 56 when rotating over 1000 sprites every frame
It’s not time for optimization yet :)

Thursday, January 3, 2013

One Game A Month Has Begun


As you all probably already know OneGameAMonth is a game developer challenge to build 1 game a month every month in 2013.
It started out as a dozen or so tweets back and forth with Christer aka @McFunkyPants and he took initiative (for which I'm utterly grateful) and started 1GAM challenge. Since then over 2800 gamedevs joined in. Amazing!
If you haven't already, go and watch the keynote on OneGameAMonth.com It will give you a clear picture on what 1GAM is and what it's not. Also read his blog post on how he made 12 games in 2012.

Rules

There aren't any! It is all about “You”, this challenge is here to help you start, boost or re-ignite your game developer career. As you heard in the keynote, if at the end of all this it just helps a few developers it's a WIN!

Why?

This challenge can help you build a nice portfolio. Think about it, by the end of 2013 you'll have 12 games to showcase. Not just that but you'll gain huge experience in the process. It will also show great on your resume that you committed to a year long challenge and you followed through, shows huge commitment.

How to get started

Come and signup at OneGameAMonth.com website using your twitter account. Complete your profile. Join us on Reddit.com/r/OneGameAMonth and on IRC at freenode #1GAM.
Follow @OneGameAMonth, @McFunkyPants, and @LZAntal on twitter. I also created and am going to make more as people signup Twitter lists List1, List2, List3, List4. Unfortunately I had to split them into separate lists because of twitter's 500 member limit per list.

Start writing the games you always wanted! Anytime you get stuck just come and ask questions. 1GAM is a very welcoming and helping community.

What's coming

Working on a resource list for new game developers but I'm sure there will be plenty of good stuff for seasoned devs as well. It will include everything from tutorials on gamedev, level design, AI, math for games, free game art, game art websites, game art howtos.
Wrote a short blog post coming in a couple of days to help you write your first game, if I have time I'll implement it using RaptorGL.com

I'm also thinking of live streaming some game dev using RaptorGL.com and maybe MOAI if there is any interest for it. All my games will be very simple so even new comers should be able to follow along. Tweet me @LZAntal if its something that interests you.

Hope you join in the fun, I look forward to playing your games! :))