⬆️ ⬇️

Experience developing games for Android. From idea to implementation

Funglish logo



In this article I want to present you the experience of developing a game-simulator of the English language for the Android platform, to tell you what difficulties arose during the development process, as well as what mistakes were made.



Prehistory



Since 2011, I have worked as an Android developer in various companies, including freelancing. During all this time I participated in the development of various projects, but I did not find the time to write my own application. It turns out "shoemaker without shoes" - a programmer who has an account on Google Play and experience of participating in various projects, but no own applications.



Idea



In May 2015, he decided to make a simulator game for memorizing words in English. There are a lot of such games and applications on Google Play, but I wanted to do something different from others. To do this, it was necessary to add some kind of "zest" that would distinguish my game from others. This key difference was the time limit for which the user must have time to translate words. The presence of a timer should add to the game a voltage element.

')

The basic concept of the game is similar to other games - the user translates words, gets for it "asterisks" that allow you to discover new levels of difficulty. For further development it was necessary to carry out a deeper specification of the project.



First of all, I decided to separate the words according to the classic 3 levels of difficulty for games: easy, medium and hard, where in the light are the simplest and most frequently used words in English, and at a difficult level are rarely used words or rare translation options.

After determining the level of difficulty, it was necessary to understand what the game level would be. It was decided that the level will contain 5 words, the translation of which is given for a limited time. Each word is given 4 translation options. To complicate the task, the words to be translated will be chosen either consonant with the Russian translation, or translations of words that are consonant with the original English word. All this is done to ensure that the user is fully focused on the application and carefully (and at the same time quickly) chose the answers.

If the time allotted to the level has ended, or the user has made a mistake with the translation, the level must begin anew, while the user can see the correct answer.



When answering correctly for all 5 words, a rating is set (from 1st to 3 stars, depending on the time spent). When typing a certain number of words should open a new level of complexity, which will be less time for answers.



As a result, we have 3 difficulty levels, each of which has 36 cards of 5 words each. It turns out that with the complete passage of the game, the user will learn 540 English words of various levels of difficulty, if the game passes completely. Not bad for a start.



Naming



The name of the application itself came to mind - a combination of the English words “Fun” and “English”, which describe the whole essence of the game - not a boring study of English words.



Design



For a start, sketches of future application screens were drawn on plain paper with an indication of the sequence of transitions between screens and comments for the designer. It turned out only 10 screens:



This material was transferred to a familiar designer , who set to work. He developed a logo, an icon, chose primary colors, fonts, button sizes, etc. Then he presented a ready-made interface solution, drawn in vector, and a slice. Prepared materials for the release ("thumbnails", promotional images, etc.).



The result of the work can be seen in the screenshots
Splash-screen



Main menu



Level selection



A game



Victory window



Defeat window



Learning window





Development



Highlights


The minimum supported version of Android was selected API 15 (Android 4.0.3).

The application does not need additional permissions (Android Permissions), because There is no advertising or statistics in the application.



There are only 2 Activities in the project: SplashActivity and GameActivity, in the last one the screens are changed by changing various fragments, of which there are only 7:



The database is very simple in its structure, therefore it is made in the traditional way for Android, without using any auxiliary libraries (greenDao or others).

Database structure
public static abstract class BaseTable { public static final String _ID = BaseColumns._ID; } public static class LevelResultTable extends BaseTable { private static final String TABLE_NAME = "LevelResult"; public static final String DIFFICULT = "difficult"; public static final String LEVEL_NUMBER = "level_number"; public static final String STARS = "stars"; private static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + _ID + " INTEGER PRIMARY KEY UNIQUE, " + DIFFICULT + " INTEGER NOT NULL, " + LEVEL_NUMBER + " INTEGER NOT NULL, " + STARS + " INTEGER NOT NULL, " + " UNIQUE (" + DIFFICULT + ", " + LEVEL_NUMBER + ")" + ") ;"; } public static class WordTable extends BaseTable { private static final String TABLE_NAME = "Word"; public static final String ORIGINAL = "original"; public static final String DIFFICULT = "difficult"; public static final String LEVEL = "level"; public static final String ANSWER = "answer"; public static final String TRANSLATE1 = "translate1"; public static final String TRANSLATE2 = "translate2"; public static final String TRANSLATE3 = "translate3"; public static final String TRANSLATE4 = "translate4"; public static final String TRANSLATE5 = "translate5"; private static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + _ID + " INTEGER PRIMARY KEY UNIQUE, " + DIFFICULT + " INTEGER NOT NULL, " + LEVEL + " INTEGER NOT NULL, " + ORIGINAL + " TEXT UNIQUE NOT NULL, " + ANSWER + " TEXT NOT NULL, " + TRANSLATE1 + " TEXT NOT NULL, " + TRANSLATE2 + " TEXT NOT NULL, " + TRANSLATE3 + " TEXT NOT NULL, " + TRANSLATE4 + " TEXT NOT NULL, " + TRANSLATE5 + " TEXT NOT NULL " + ");"; } 


You may notice that in the WordTable table there is a answer field and translate1, translate2, translate3, translate4, translate5 fields, which in total gives 6 response options, although only 4 are displayed on the screen. Re-passing the level saw partially other answers.





When developing the first version, they focused only on phones, so a line was added to AndroidManifest
 <supports-screens android:xlargeScreens="false"/> 
to limit the list of supported devices.



Content


The popularity of any application (if you do not take into account any utilities or specialized professional applications) depends on the quality of its content.



As mentioned above, in annex 3 levels of difficulty. Words for each level were selected manually, and the complexity was estimated subjectively. To further complicate the game, when trying to find words, I tried to use words that are congruent and similar in spelling or meaning, for example, if the original word is “Something”, then the translation options would be:





Blur


When at the end of the level a result window appears (“defeat” or “success”), the background becomes “blurred”. The blur effect is implemented in the classical way: save the Bitmap of the game Layout, process it and put it in the background in the result window.



Image processing was implemented using the Mario Klingemann code (mario@quasimondo.com), which was found by reference . Image processing is a very long process, therefore, to speed up processing, the image is pre-reduced. As it often happens, losing in quality we gain in time. In this case, quality loss is not critical.



Method code for creating a screenshot
 public class ScreenShot { public static Bitmap getScaledScreenshot(View v, float scaleFactor) { Bitmap b = Bitmap.createBitmap((int) (v.getWidth() / scaleFactor), (int) (v.getHeight() / scaleFactor), Bitmap.Config.RGB_565); Canvas c = new Canvas(b); c.scale(1.f / scaleFactor, 1.f / scaleFactor); v.draw(c); return b; } } 




Class code to reduce the image
 public class Resize { private static Paint sPaint = new Paint(Paint.FILTER_BITMAP_FLAG); public static Bitmap scale(Bitmap bmp, float scaleFactor, boolean recycleOriginalBmp) { Bitmap overlay = Bitmap.createBitmap((int) (bmp.getWidth()/scaleFactor), (int) (bmp.getHeight()/scaleFactor), Bitmap.Config.RGB_565); Canvas canvas = new Canvas(overlay); canvas.scale(1 / scaleFactor, 1 / scaleFactor); Paint paint = new Paint(); paint.setFlags(Paint.FILTER_BITMAP_FLAG); canvas.drawBitmap(bmp, 0, 0, paint); if(recycleOriginalBmp) { bmp.recycle(); bmp = null; } return overlay; } } 




Customview


To improve performance and to improve the display of some screens, several of their own View and ViewGroup were written, for example, the answer button for a question.



The text of buttons with words must be as large as possible, but at the same time the number of letters in a word may differ from the word to the word. Therefore, an automatic adjustment was made to the size of the text if it exceeds a certain width (the width of the View minus the indent).



Button code
 public class AnswerButton extends View { //private final static String TAG = AnswerButton.class.getSimpleName(); public final static int STATE_NORMAL = 0; public final static int STATE_SUCCESS = 1; public final static int STATE_FAILED = 2; public final static int STATE_PRESSED = 3; private Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private static Bitmap sBackgroundBitmap, sPressedBitmap, sSuccessBitmap, sFailedBitmap; private int mState = STATE_NORMAL; private int mWidth; private int mHeight; private float mTextLeftX, mTextTopY; private float mLeftRightPadding; private Rect mBackgroundRect = new Rect(), mTextBounds = new Rect(); private float mTextSize; private String mText; public AnswerButton(Context context) { super(context); init(); } public AnswerButton(Context context, AttributeSet attrs) { super(context, attrs); init(); } public AnswerButton(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { if(sBackgroundBitmap == null) { sBackgroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.btn_answer_normal); } if(sSuccessBitmap == null) { sSuccessBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.btn_answer_success); } if(sFailedBitmap == null) { sFailedBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.btn_answer_failed); } if(sPressedBitmap == null) { sPressedBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.btn_answer_pressed); } setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction() & MotionEvent.ACTION_MASK; if(action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE) { if(mState == STATE_PRESSED) { return false; } mState = STATE_PRESSED; invalidate(); } else { if(mState != STATE_PRESSED) { return false; } mState = STATE_NORMAL; invalidate(); } return false; } }); mLeftRightPadding = getResources().getDimension(R.dimen.view_answer_button_left_right_padding); mTextSize = getResources().getDimension(R.dimen.answer_button_text_size); mTextPaint.setTextSize(mTextSize); mTextPaint.setColor(getResources().getColor(R.color.answer_button_text_color)); mTextPaint.setTypeface(FontManager.VDS_COMPENSATED_LIGHT); } public void setText(String text) { setState(STATE_NORMAL); mText = text; recalculate(); invalidate(); } public String getText() { return mText; } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mWidth = w; mHeight = h; mBackgroundRect.left = 0; mBackgroundRect.top = 0; mBackgroundRect.right = w; mBackgroundRect.bottom = h; recalculate(); invalidate(); } public void setState(int state) { mState = state; invalidate(); } private void recalculate() { mTextPaint.setTextSize(mTextSize); mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBounds); if(mWidth != 0) { while (mTextBounds.width() >= mWidth - mLeftRightPadding * 2) { mTextPaint.setTextSize(mTextPaint.getTextSize() - 2); mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBounds); } } mTextLeftX = (mWidth - mTextBounds.width()) / 2 - mTextBounds.left; mTextTopY = (mHeight - mTextBounds.height()) / 2 - mTextBounds.top; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if(mState == STATE_NORMAL) { canvas.drawBitmap(sBackgroundBitmap, null, mBackgroundRect, mBackgroundPaint); } else if(mState == STATE_PRESSED) { canvas.drawBitmap(sPressedBitmap, null, mBackgroundRect, mBackgroundPaint); } else if(mState == STATE_SUCCESS) { canvas.drawBitmap(sSuccessBitmap, null, mBackgroundRect, mBackgroundPaint); } else { canvas.drawBitmap(sFailedBitmap, null, mBackgroundRect, mBackgroundPaint); } canvas.drawText(mText, mTextLeftX, mTextTopY, mTextPaint); } } 




Animation


Static Splash-screen looked boring. Therefore, we decided to add animation to it, namely the rotating British flag in the letter g of the logo. It was possible to make the usual gif-animation, but we are not looking for easy ways, so everything is implemented in the code.



The animation was implemented quite simply: in the markup, the first layer is the image of the British flag, aligned centrally with the container, the next layer is the image of the word funglish, also aligned in the center. When you open the Activity, an animation is launched that performs 2 turns of the image of the British flag. The standard animation interpolator was also changed to AccelerateDecelerateInterpolator so that the rotation is non-linearly accelerated and slowed down.



The animation turned out quite nice and memorable and was liked by all the people surveyed.



Tutorial


Most of the articles and books about the development and promotion of applications in one voice say that one of the most important points is to educate the user how to use the product. For learning, a Tutorial screen was created, in which on 3 pages the user is briefly told the key points of the game. This screen appears once before the first start of the game.



Screenshot
Tutorial



Publication



The publication of the application was made on August 7. I think it makes no sense to describe the process of obtaining the key and putting the application on the Play Market.



The application is available for download only in a few countries where you can meet a large number of Russian-speaking population, this, of course, Russia and Belarus, Bulgaria, Kazakhstan and Ukraine. As you already understood, the application has support for only the Russian language.



Testing



When most of the game was made, the content was found, and the game was already preparing for release, testing was conducted. For this, volunteers were found who agreed to play the alpha version of the game.



The expectations were met - users liked the concept of guessing words for a while. According to them, the constantly updated timer keeps me in suspense, and similar translations of words are confusing.



In this case, the effect of “Flappy Bird” was discovered, when the user does not have time to respond to words before the end of the timer or answers incorrectly at the last moment — he is very angry. Emotions, even in this case, they are negative, have a positive effect. The user cannot calm down until he passes the level, which means that he will learn the unfamiliar word.



Spread



For some reason, I did not have the opportunity to come to grips with the distribution of the application. The only thing that was done on the first day - laying out a link in the social. VKontakte network, and the story to friends asking to download the application. The first day brought 17 downloads. Then the number of downloads dropped to 1 per day.



On August 20, a topic was created on the forum site w3bsit3-dns.com, where a description of the application was posted and a link to the Play Market. To date, more than 700 people have viewed this topic. A little later, the site r-android.ru pleasantly surprised and wrote a review of the game on its website. These days the number of downloads has risen to 30.

Download statistics
Download statistics



It should be noted that w3bsit3-dns.com has brought a large audience of users. And, most likely, the authors of the site r-android.ru learned from there about the game and wrote a review on it.



Conclusion



Looking back, it can be understood that a lot has been done wrong or not in time. For example, it was possible to better think up the concept of the application, so that in the middle of the design development not to redo half the work of the designer.



Testing of the UX can and should have been done primarily on a quickly assembled concept to test the idea. But this was done before the release.



Due to lack of time, I did not add Flurry statistics, although now it would give a lot of useful and necessary information about using the application.



I also wanted to add AdMob ads to see what income it can bring and whether it will bring. But again there was not enough time.

I was not ready for the release either: no press releases, no articles, nothing. If it were a better approach to this issue, on the day the application was laid out, it would be possible to spread messages on subject forums, make an application page on social networks, send out articles to various sites. All this could, in theory, bring a large number of downloads, which would have a positive impact on the position of the application in the Play Market rating.



The topic of learning English is very relevant, so now I have a choice: make a small update (update content), make a conceptual update (add new types of levels, such as audio translation), or make a package of applications for learning English (tenses, irregular verbs and etc.).



They say, "the first pancake is a lump." But I think that this does not apply to Funglish. The development of this game is an invaluable experience. The game has good ratings, people write reviews, ask to add some new features. It's nice to know that someone really likes your application. It is inspiring to make new games and applications.

Source: https://habr.com/ru/post/265793/



All Articles