Wednesday, January 6, 2010
Cấu hình gửi mail cho joomla sử dụng gmail
Mailer: SMTP Server Mail from: email@mydomain.com
From Name: Nguyễn Minh Tân
Sendmail Path: /usr/sbin/sendmail
SMTP Authentication: Yes
SMTP Security: None
SMTP Port: 25
SMTP Username: email@mydomain.com
SMTP Password: **
SMTP Host: ssl://smtp.gmail.com:465
Light Racer 2.0 - Days 3 and 4 - New Design Completion
Much like the first two days of work, days 3 and 4 involved mostly refactoring the existing code to bring it all in to the new architecture. The end of the fourth day was much more exciting than the rest because nearly 100% of the design was completed and I was able to work on new code again. I implemented 2D coordinate interpolation for the racer physics and AI, which I had a few problems with but overcame. I also implemented visual AI debugging which is key in developing better AI.
Before I started modifying the game or adding anything, I was almost purely refactoring. This approach has paid off because now I have a great new design that will allow me to add all of the new features and the game is still in a 100% usable state. In fact, I could still package it up and put it on the market with little effort. I keep pushing this idea because I believe it's very fundamental to a successful developer. Notice how through the days of refactoring, I was able to keep the game working exactly as it had before. That's the big difference between refactoring and rewriting. Call it semantics if you wish, but I have not lost a single piece of functionality and I've been able to test it several times every day and verify that everything is still working exactly the way it was when I started the project.
The great thing about what I'm doing is that I'm so confident the entire way. I'm not scared that I'm going to make a huge mess that will be a major headache to clean up. It's one thing at a time and by dealing with only one small issue at a time as I go, I'm able to tackle every issue that comes up. In software, it's simply overwhelming to deal with tons of issues all in one go. Slow and steady wins the race here, no pun intended. At the end of the refactoring, the new design was fully implemented and the game was still working exactly as I left it. Now it all works and I'll be able to add in all of the new features I want. How cool is that?
Day 3: What was completed?
The LightRacerWorld is now used consistently and several things were added to the world. It has game state information, the pixel size of the game area of the screen, all of the players, the last, current and delta tick time, the level and the current movement rate (game speed). This was important because the world is the part that is passed into GameObject update() methods, which in turn will run AI algorithms. All of these things are needed for AI to process and for physics to interpolate.
I moved SoundManager into resources. This made it so that GameObjects can trigger and control their own sounds.
I combined AI and player physics updates into a single update. This improved the interface from the main game class to the players. Now the main loop just iterates through players and calls update(world) on each. Before it had some logic to determine if the player was AI and what to do.
I moved path updates into Player. This is just to further simplify the main game loop. The more simple, the better. Here's some game testing from the end of Day 3, just to confirm that the core game was still working correctly.
Day 4: What was completed?
Player now controls all of its own sounds. This wasn't complete before but now is 100%.
Player has one update() method. It was many updates before but all of that logic exists only in the Player class and the main loop has a very easy interface to update the Players.
Changed Receiver to PlayerInputSource. I renamed that class because I think that it is more appropriate this way. The PlayerInputSource is fundamental because it is either a network client, network host, human player or AI player. It is the keystone that will allow for different kinds of AI and network configurations.
LightRacerAI now implements PlayerInputSource. It's official. The AI is now a PlayerInputSource.
Created HumanInputSource. This was to finish implementing that part of the design.
Renamed PlayerPhysics to Collisions. All that was in the class was a method to check for collisions. I made that public and static, so it's really just a utility class now. I don't normally do that but it was needed by a few different classes and didn't fit well into the hierarchy.
GameObject created but can't standardize draw methods because of layering. I have a GameObject now but because this game is 2D, I can't have one draw method. Drawing order must occur like this: Background, light paths, racers, explosions, text. If I were to do one player at a time instead of one layer at a time for all players, you would end up with paths and racers on top of explosions, which would not look good at all. I don't have a good solution for this yet but it's not the worst thing ever to have one custom interface and everything else is looking very good.
Refactoring is complete! Now for the fun stuff...
Implementing Interpolation in a 2D World
I changed the physics of the game to use time distance interpolation instead of moving a set number of pixels per tic. The idea is that the game will run the exact same speed but at different FPS depending on how much load is already on the device. I found that for different phones with different numbers of services running, the game would run faster or slower and I wanted it to be consistent.
The interpolation works really well. It's really straight forward to write interpolation for a 3D coordinate system because you can actually move a floating point number away but in 2D land there are a set number of pixels and so you must move a nice round number. This was problematic at first because when I set the movement rate to 100 pixels per second, I ended up getting about 80. Why do you think that is?
I almost knew immediately what the problem was. Interpolation is calculated by using the the last known location of the object, the direction the object is moving in, the rate of movement and the last tic time and the current tick time. If you have that information, you simply take the difference in time, multiply that against the rate of movement and then move the object that far from the last position in the direction it is moving. The formula could be expressed as newPosition = oldPosition + (tickDelta * movementRate * direction).
Here is an example that also shows the problem:
Movement Rate = 100 pixels per second
Racer is located at (x,y) (100,100) and is facing North.
The last tic time was at 1000
The current tic time is 1078
Where should he be now?
The math looks like this: 78 (tick delta in ms) * movementRate (in seconds) / 1000 (to convert seconds to milliseconds) = 7 pixels.
So we should move 7 pixels in the north direction (subtract from Y axis) so that would put our racer at 100, 93. That works, but with a tic delta of 78, how did we end up with 7 pixels? What happened to the other .8 pixels? In a floating point world, we would have moved the racer 7.8 pixels. Since we can't do that we can either discard the remainder, which is what I was doing and was causing the game to run slower than it should have, or we can use a trick that I came up with.
Since there is usually a remainder, I changed the code so that it works like this:
movement = (tickDelta * movementRate + carryOver) / 1000
carryOver = (tickDelta * movementRate + carryOver) % 1000
carryOver must be an instance field on the GameObject you are interpolating, because it will need to be the remainder from the last physics update. This worked, because now that .8 pixels from the example is carried to the next update, and if that next update has a remainder that is at least .2 pixels, then an entire pixel will be added to the movement, thus making the movements add up to 100 pixels per second.
This worked ok but I was able to see the little jumps sometimes if there were small remainders for a few updates and then they finally added up to 1000 to add a pixel. I realized that only rounding down wasn't the most even way of approaching the movement and remainder problem so I also implemented a negative carry over for remainders over 500. Now the carry over value will, instead of being 0 to 900, be -400 to 500. This worked to smooth out the 2D interpolation. Here's some physics code from the game:
int pixelsToMove = (int) (targetMovementAmount / 1000);
movementCarryOver = (int) (targetMovementAmount % 1000);
if (movementCarryOver > 500) {
// round up and carry over a debt.
movementCarryOver = movementCarryOver - 1000;
pixelsToMove++;
}
All said and done, the game runs really well now. It's much smoother than before and it doesn't feel like there's any lag even when the phone slows down for a brief second.
Making AI work consistently in a variable update-time environment
After I added the interpolation to the Player physics, I got rid of the old cap I had placed on updates. Now the game will update as fast as the SurfaceView will allow for draws, so 60FPS. My emulator runs at around 45FPS so that's not too bad. I haven't tried it on the phone yet with my FPS text turned on but I'll have more on performance later in the book. For now, a new problem has come up. I used to run the game at a set 30 updates per second (or slower) and my AI was designed to run at that speed. The new AI has to be able to also interpolate or it runs totally different on one system to the next and also it takes up far more CPU cycles than are necessary. AI doesn't actually need to recalculate 45 times per second. 10 will do just fine. Is it even fair to play a computer player that can process everything faster than your eye registers motion?
I updated the AI to use interpolation similar to that of the Player. All the AI really needs to know is "How far will the racer move until I get to make another decision?" For that I decided to combine that with an AI update limit of 10 updates per second. This made the math simple: If the AI updates every 100 milliseconds, then the furthest the racers could go before getting to make another decision is 1/10th of the current movement rate. This doesn't take into account if the game runs slower than 10FPS, in which case there will be a problem here but I'm assuming that it is unplayable at that speed anyway. It works this way because the AI needs to be able to make sure that it's not going to run into a wall before getting to decide to turn again. That number is how many pixels it will go so it can pipe that through the collision detection code and see if there is something in the way.
Limiting the AI to 10FPS is a great thing because it works well and now I have some extra CPU cycles to use for even better AI. My Medium and Hard AI are going to be far more CPU intensive than the current Easy implementation. I knew I was going to need a better way to debug the algorithms so I added in a visual AI debugging feature. The PlayerAI interface has a drawDebug(canvas) method which is called by the main loop when the AI debugging is turned on. I implemented a little bit of it for the EasyAI to make sure it was all working. The EasyAI sometimes decides to "come after" a human opponent. Each time it makes this decision, I had it draw a "targeting" line that you can see in red in this screenshot.
Light Racer Easy AI debugging
It looks really cool to watch it make the decisions real-time, which is in the video below.
That's it for today. There have been so many changes and I'm getting really excited about adding all of the new features.
Tuesday, January 5, 2010
Light Racer 2.0 - Days 1 and 2 - Refactoring
What changed?
I first started by creating two new activites: One for the game and one for the instructions. Before it was just one activity that had a hacked up layout. That hacked layout had all 3 different layouts all layered on top of each other and the activity would switch which ones were visible depending on the state of the whole game. This was very hard to manage and work on and certainly wouldn't have worked out well to add in the new multiplayer menus. Now there are three distinct Activities. One for the main menu, one for the instructions and one for the game itself. In the future there will be more to handle more of the new functionality.
My next goal was to break out the existing AI code so that I could make it more modular. What I wanted to do was be able to just pop a new instance of a MediumAI and be able to set that on any player. Here's the idea:
Player p1 = new Player();
p1.isHuman = true;
Player p2 = new Player();
p2.setAI(new EasyAI());
Player p3 = new Player();
p3.setAI(new MediumAI());
startGame();
}
Sounds easy enough, right? Well that interface is in place now so I can have code that works almost exactly like that, but the hard part was working it out so that the AI code could work correctly on its own, which means working without access to all of the fields of the game. This was achieved by doing two things. First, I created a "World" class that contains everything that matters to the game. I moved all of the Players and state info into the World. Then I took the old updateAI() method which used to exist in the big monolithic game class and moved it into the AI interface, which all AI implementations implement, and added it as a parameter, so that every time the AI is updated, it has access to the entire world. To translate - the AI code is handed the positions of every player and game object as well as the paths of light, just like you see on the screen. This is necessary because those things are all used in the calculations for the AI to determine where to move its player to next. The most used method in that calculation is collision detection, which is some code that simply checks to see if the racer is going to hit a wall. That collision detection code is needed by AI and by the update() method in the Player class so I took a standard OO approach and created a base class called PlayerPhysics and made EasyAI and Player both extend it, thus allowing for them to share that common collision detection code.
Does this sound like a big jumble? It's actually really clean now. Here's how it looks:
public void update(LightRacerWorld world);
}
public abstract class PlayerPhysics {
public boolean checkCollision(LightRacerWorld world, int fromX, int fromY, int toX, int toY) {
... collision detection code
}
}
public class EasyAI implements AI extends PlayerPhysics {
public void update(LightRacerWorld world) {
... all the old AI code is in here now
}
}
public class Player extends PlayerPhysics {
... tons of fields for position, next move, animation, color, etc
public void setAI(AI ai) {
this.ai = ai;
}
public void updateAI(LightRacerWorld world) {
ai.update(world);
}
}
Since a good, safe refactoring job moves things in small steps and doesn't break anything, this should be considered a few steps taken but not a finished job. The design in the architecture document uses Receivers, which we don't have implemented yet. For now, this is an improvement and takes steps to get there.
The other thing that was done is that resources were moved into their own class, also following the architecture document. This was necessary to allow for GameObjects to be able to draw themselves, which was an ability they did not previously possess. Did I mention I added GameObjects?
So far so good on the development. Here are screenshots of where the game is at now. Much of this work won't have any visible artifact but soon we'll get there. In fact, all that has changed aesthetically is that the game is now full screen and there are placeholders up on top for the game difficulty and level.
Main Menu Dev Shot | Light Racer 2.0 Dev Shot Game 4-7-2009 |
Light Racer's New Game Architecture
Version 1.0 of Light Racer didn't have much to say for architecture. There was a single Activity which dealt with the buttons, showed instructions and displayed the main game View. I'll cover the way the menus are going to work in a different article but suffice to say for now that having a single Activity deal with multiple different things is not a good idea at all in Android. The main View was a SurfaceView and simply started up the main game thread. The Thread class was the main game and besides the Sound Manager and a very light Player class which held the state, path and animation information for any given player, there wasn't a whole lot to it. This made it easy to develop but the new requirements are to have NPCs (Non Player Characters), network multi-player, different 2D and 3D displays and more. How does one tackle such a problem? With a better design, of course.
The new design is much more organized and also more abstract. The following slides will show how I am changing the design to delegate far more responsibility into the Game Objects and Receivers and away from the main class. The main class's job will be simply to initialize the environment, load resources, initialize and configure the world, run the game and watch for changes to the Android environment.
The environment consists of the world (everything a game cares about and will display to the user), various managers like sound and notification managers, any object pools (because Android gets slow if you are creating and GCing lots of objects) and hooks into the Android environment.
Resources are things like graphics, sounds, fonts, and colors. Many parts of the game need to access the resource pools so it's always a good idea to have them managed by one object and pass that one object to anything requiring resources. For example, all GameObjects are responsible for drawing themselves so they will need to get their bitmaps from the resource manager. The main game class will have the resource manager release its resources when it's time to clean the game environment up.
Main Class, World and Resources
The next diagram is a bit more concrete and recognizable. Player is the only Game Object on here but you can imagine that there might be others, such as a barrier or a power-up item. All of these things are Game Objects and are responsible for drawing and animating themselves. The Player will be doing collision detection on itself to check for a crash. If I end up adding power-ups, it will also check to see if it has touched or passed over an item. A Player maintains its own position in the world. It also maintains it's state so it knows if it's still alive or crashed. The path is the trail of light. Animation means which frame of what kind of animation is currently being drawn.
Game Objects, Players, Receivers and AI
The big key element in this new design is the Receiver. I couldn't think of a better name at the time and this may be renamed when I do, but a Receiver is responsible for determining the next direction of the player. In LR 1.0, the Android button hooks were tied directly to a field that held the next direction of movement until the physics update could pick it up. It also had the AI code in the same big game class and assumed that any player that was not Player 1 was AI. That won't work for the new requirements so I'm designing this to make 2 policies: 1) The Receiver is entirely responsible for setting the next direction of a Player. 2) If there is no Receiver, the Player shall always continue (interpolate) on its trajectory.
Does policy 2 make sense? When would we not want a Receiver? Wouldn't that player always end up in the wall if it started North and continued without change?
Let me start by answering that there are several types of Receivers. The Player Receiver is directly tied to the buttons and touch. When a player hits up, that receiver sets the next direction to North. Simple enough. The AI Receiver is abstract and so there can be several different AI implementations. I'm doing 3, which are Easy, Medium and Hard. The different implementations may be better at playing than one another but they all end up outputting only one thing: The next direction for their Player. The network receivers are the most confusing. I'll explain the way multi-player games will work and then get back to them.
In Light Racer, you will be able to host a game or join a game. There can be up to 3 players for the regular game and 4 players for LR3D. The clients each "estimate" what is happening but the host is the real authority. One could say that the actual, authoritative game runs on the host. This means that when the host decides there was a crash, there was a crash. This is an easy strategy to follow because the rule is that the host's world always overrides anything on the client.
Let's discuss the following example:
In this example, there are 3 players. One player is the host of the game, the second is a client and the third is an AI player. The configurations are different in that the host uses a Human Receiver for the person playing, a NetHost Receiver to pick up the input from the remote player and an AI Receiver to control the AI. Every time it ticks and updates the world, it packages the world up and sends it to the client. The client unpackages the world and overwrites its current world. This is because the host is always the authority. The client then processes input from its one Receiver, which is a NetClient Receiver. The NetClient Receiver is dual-purpose. It has a Human Receiver so it can take button presses and touch events from the real player and that will set the next direction, but then it also immediately sends that over to the host via the network connection.
If you can imagine that happening around 30 times per second, you can see why the Client World does not need Receivers. Its World is always being updated by the host and the Players in that world are located and on the trajectory that the World dictates. This means that the client simply tells the host what it would like to do and draws what it thinks is happening. The host processes this and tells the client what actually happened. So long as the updates are fast and consistent, this will work. Even if there are small stutters, the interpolation code will take care of it and things will still look mostly smooth.
Getting Started in Android Game Development
Android is a Java-based environment. This is nice for new developers as Java is widely accepted as a much easier language to get started in than C++, which is the norm for mobile development. Google has also done an excellent job with documenting the API and providing examples to use. There is an example to show functionality for almost 100% of the API, called API Demos. If you're familiar with Java and have already used Eclipse, getting your first app working should be fairly simple. If you've never coded anything in your life before, you will have a lot to absorb as you move forward, but don't get discouraged.
Get the SDK
The first step in getting started with the Android platform is to get the Android SDK (Software Development Kit). The SDK has the core libraries, an emulator, tools and sample code. I highly recommend using Eclipse and the android eclipse plugin. Eclipse IDE for Java Developers is fine if you are just doing Android. If this is your first Java development project, you will want to download the full Java SE Development Kit (JDK) as it contains tools you will need for signing and deploying your application.
Learn the application architecture
As tempting as it may seem to just dive right in, it's very important to understand the android application architecture. If you don't learn it, you may design things in such a way that will make it very difficult to fix problems with your game down the line. You will want to understand Applications, Activities, Intents and how they are all related to each other. Google has provided good information on the architecture here. The really important thing is to understand why your game may need to consist of more than one Activity and what that means to designing a game with good user experience. This is where things tie in to the Activity lifecycle.
Learn the activity lifecycle
The activity lifecycle is managed by the Android OS. Your activity will be created, resumed, paused and destroyed as the OS dictates. Handling these events correctly is very important to having an application that behaves well and does what the user perceives as correct. It's very good to know how all of this works before you start designing your game because you will save yourself debugging time and costly redesign time later on. For most applications, the default settings will work but for games, you may want to consider turning the SingleInstance flag on. When set as default, android will create new instances of the activity as it sees fit. For a game, you may only want to have 1 instance of the game activity. This has some implications for how you need to manage the state of things but for me it solved some resource management issues and it should be considered.
The main loop
Depending on what type of game you are writing, you may or may not have a main loop. If your game is not time-dependent or if it only responds to what the user does and will wait forever for user input without making any kind of visual changes, you may not need a main loop. If you are writing an action game or a game that has animations, timers or any kind of automation, you should seriously consider using a main loop.
The main loop of a game is the part that "ticks" sub systems in a specific order and usually as many times per second as possible. Your main loop will need to run on its own thread. The reason for this is that Android has a main UI thread and if you don't run your own thread, the UI thread will be blocked by your game which will cause the Android OS to not be able to handle any of its normal update tasks. The order of execution is usually as follows: State, Input, AI, Physics, Animation, Sound and Video.
Updating State means to manage state transitions, such as a game over, character select or next level. Often times you will want to wait a few seconds on a state and the State management is the part that should handle this delay and setting the next state after the time has passed.
Input is any key, scroll or touch from the user. It's important to handle this before processing Physics because often times input will affect the physics so processing input first will make the game more responsive. In Android, the input events come in from the main UI thread and so you must code to buffer the input so that your main loop can pick it up when the time comes. This is not a difficult task. Defining a field for the next user input and having the onKeyPressed or onTouchEvent set the next user action into that field is all that will be required. All the Input update needs to do at that point is determine if it is valid input given the state of the game and let the Physics side handle responding to it.
The AI update is analagous to a user deciding what they are going to "press" next. Learning how to write AI is out of the scope of this article but the general idea is that the AI will press buttons just like the user does. This will also be picked up and responded to by the Physics update.
The Physics update may or may not be actual physics. For action games, the point of it is to take into account the last time it was updated, the current time it is being updated at, the user input and the AI input and determine where everything needs to be and whether any collisions have occured. For a game where you visually grab pieces and slide them around, it will be the part that is sliding the piece or letting it drop into place. For a trivia game, it would be the part deciding if the answer is right or wrong. You may name yours something else, but every game has a part that is the red meat of the game engine and for this article, I'm referring to it as Physics.
Animations aren't as simple as just putting an animated gif into your game. You will need to have the game draw each frame at the right time. It's not as difficult as it sounds. Keeping state fields like isDancing, danceFrame and lastDanceFrameTime allows for the Animation update to determine if its time to switch to the next frame. That's all the animation update really does. Actually displaying the change of animation is handled by the video update.
The Sound update handles triggering sounds, stopping sounds, changing volumes and changing the pitch of sounds. Normally when writing a game, the sound update would actually produce a stream of bytes to be delivered to the sound buffer but Android manages its own sounds so your options for games are to use SoundPool or MediaPlayer. They are both a little sensitive but know that because of some low level implementation details, small, low bitrate OGGs will yield the best performance results and the best stability.
The Video update takes into account the state of the game, the positions of players, scores, statuses, etc and draws everything to screen. If using a main loop, you will want to use the SurfaceView and do a "push" draw. With other views, the view itself will call the draw operation and the main loop won't have to do it. SurfaceView gives the highest frames per second and is the most appropriate for games with animation or moving parts on screen. All the video update should do is take the state of the game and draw it for this instance in time. Any other automation is better handled by a different update task.
What's this code look like? Here's an example.
while (isRunning) {
while (isPaused && isRunning) {
sleep(100);
}
update();
}
}
private void update() {
updateState();
updateInput();
updateAI();
updatePhysics();
updateAnimations();
updateSound();
updateVideo();
}
3D or 2D?
Before you start on your game, you need to decide if you're going to go 3D or 2D. 2D games have a much lower learning curve and generally are easier to get good performance on. 3D games require much more in-depth math skills and may have performance issues if you are not very careful. They also require the ability to use modeling tools like 3D Studio and Maya if you intend to have shapes more complex than Boxes and Circles. Android supports OpenGL for 3D programming and there are many good tutorials on OpenGL that one can find to learn it.
Build simple, high quality methods
When getting started, make sure that you avoid writing one big long monolithic method that is "the game." If you follow the main loop pattern that I described above, this should be fairly easy. Each method you write should accomplish one very specific task and it should do so error-free. For example, if you need to shuffle a deck of cards, you should have a method called "shuffleCards" and that should be all it does.
This is a coding practice that applies to all software development but it's particularly important in game development. Debugging can get very difficult in a stateful, real-time system. Keep your methods small and the general rule of thumb is that each method should have 1 and only 1 purpose. If you're going to programatically draw a background for a scene, you may want a method called "drawBackground." Things like that will make it so that you develop your game in terms of building blocks and you will continue to be able to add what you need without making it too complex to understand.
It's all about efficiency!
Performance is a major issue for any game. The goal is to make the game as responsive as possible and to also look as smooth as possible. Certain methods like Canvas.drawLine are going to be slow. Also drawing an entire screen-sized bitmap onto the main canvas every frame will also be costly. Balancing things like that is necessary to achieve the best performance. Make sure to manage your resources well and use tricks to use the least amount of CPU to achieve your task. Even the best game will not be very fun if it can't perform well. People in general have little tolerance for choppiness or poor response.
Tips and Tricks
Take a look at the example for LunarLander in the SDK. It uses a SurfaceView and that would be the appropriate view to use for a game that needs the highest number of frames per second possible. If you're going 3D, there is a GLView in the examples that handles a lot of initialization required to get a 3D display. For LightRacer, I had to optimize the way I have everything drawn or else the framerate would be drastically lower. I drew the background to a Bitmap only once which was when the view is initialized. The light trails are in their own bitmap which gets updated as the racers move. Those two bitmaps are drawn to the main canvas every frame with the racers drawn on top and then finally an explosion. This technique made the game run at a playable rate.
It's also a good practice to have your bitmaps be the exact size you intend to draw them on screen, if applicable. This makes it so that no scaling is needed and will save some CPU.
Use a consistent Bitmap Configuration (like RGBA8888) throughout the game. This will save the graphics library CPU in having to translate the different formats.
If you're determined to develop a 3D game but have no 3D knowledge, you will want to pick up a book or two on 3D game programming and study up on linear algebra. At a bare minimum, you must understand dot products, cross products, vectors, unit vectors, normals, matrixes and translation. The best book I have come across for this math is called Mathematics for 3D Game Programming and Computer Graphics.
Keep the sound small and at a low bitrate. The less there is to load, the faster loading times will be and the less memory the game will use.
Use OGGs for sound, PNGs for graphics.
Make sure to release all media players and null out all of your resources when the activity is destroyed. This will ensure that the garbage collector gets to everything and that you don't have any memory leaks between launches of the game.
Join the Android Google group and find community support. There will be people that can help you along the way.
Above all, spend time testing and retesting and making sure that every little thing works exactly the way you would expect it to. Polishing the game up is the longest and hardest part of development. If you rush it out to market, you will probably have a disappointed crowd and you may feel that all your hard work is wasted. It's not possible to have 100% of people love what you write but you should at least try to put out the highest quality work that you can.
Google has excellent documentation for getting started here.