Pull to refresh

Самая Сложная Игра

Reading time 4 min
Views 21K

Оправдание


Размышлял, стоит ли писать на сам Хабр! о такой Android-поделке. В итоге решил, что кому интересно — прочтут, а кому нет — пролистают мимо. И плохо в итоге никому не будет. Я специально почти весь пост спрятал под кат, чтобы тем, кому это не интересно, еще больше казалось, что этого поста здесь нет.
Игру я делал еще пару недель назад (написал за 1 выходной день), но сейчас появилось свободное время довести ее до ума и выложить в Play Market.
Все повествование разделено на описание игры, описание реализации и описание нюансов, непосредственно к игре не относящихся.

1. Суть игры



Это логическая головоломка, с помощью поворотов окружностей и смещения фишек в пустую ячейку необходимо выставить фишки одного цвета в один ряд. Есть возможность выбирать разное количество цветов и разное количество окружностей, чем больше — тем сложнее. С увеличением сложности решаемой головоломки увеличивается множитель очков. Итоговые очки зависят от сложности головоломки и количества сделанных ходов.

2. Некоторые технические моменты


2.1 Графика

Игра реализована на чистом Canvas'e, без использования движков и даже без использования bitmap'ов.
Архитектурно это CustomView, который содержит в себе список всех фишек. Так же он содержит список окружностей, каждая из которых ссылается на те фишки, которые рисуются на ней. CustomView ловит все события нажатия и передает их вниз по иерархии (окружностям и фишкам).
Вся отрисовка довольно банальная, кроме разве что поворотов окружностей — здесь пришлось через arctg выяснять необходимый угол поворота.
И все таки она вертится!


2.2 Сохранение

Сохранение игры так же максимально быстро было реализовано с помощью настроек (тех, которые Prefferences). Понятно, что можно было использовать БД или файловый кеш, но так как сделано — действительно быстрее. Решение без гугла пишется за минут 5 по памяти. Вот кстати оно:
Java code
public class PrefsManager {
	private static final String PREFS_TAG = "prefs_tag";
	
	public static void save(Context c, String tag, String val) {
		SharedPreferences p = c.getSharedPreferences(PREFS_TAG, Context.MODE_PRIVATE);
		Editor e = p.edit();
		e.putString(tag, val);
		e.apply();
	}
	
	public static String get(Context c, String tag, String defVal) {
		SharedPreferences p = c.getSharedPreferences(PREFS_TAG, Context.MODE_PRIVATE);
		return p.getString(tag, defVal);
	}
	
	public static void delete(Context c, String tag) {
		SharedPreferences p = c.getSharedPreferences(PREFS_TAG, Context.MODE_PRIVATE);
		Editor e = p.edit();
		e.remove(tag);
		e.apply();
	}
}


2.3 Диалог рейтинг поднимающий

Небольшая хитрость, правда давно уже используемая. При энном запуске приложения появляется диалог, отображающий RatingBar (он представляет собой 5 звезд) и просьба пользователя оценить приложение. И дальше есть 2 варианта:
  • Пользователь выбрал 5 — отображаем диалог с просьбой повторить это в Play Market'e.
  • Пользователь выбрал 4 или меньше — просим пользователя написать на email саппорта в чем, собственно, дело.

Количество запусков приложения хранится все в тех же Preferens'ах, для отправки пользователя в Market || Email используются просто intent'ы.

3. Интересности


Т.к. сама реализация приложения довольно простая, я решил воспользоваться двумя новыми технологиями:
  • Playhaven;
  • Scoreloop.

Т.к. игра не потребила должного количества человеко-часов, то и встраивать в нее рекламу было бы неправильно. Тоже самое, ествественно, относится и к платной версии в еще большей степени. Именно поэтому я решил смотреть в сторону альтернативных видов монетизации и нашел Playhaven. Они кроме стандартной рекламы предлагают установить виджет More games. Пользователь, видя эту кнопку, с большой вероятностью не воспримет ее за рекламу, а, следовательно, и настроение у всех останется замечательным.
Интеграция данной рекламной партнерки вообще очень замечательная в плане количества кода, но я не сразу пример этого кода нашел, если честно.
Вот пример кода отображения More Games Widget'a
	/*
	 * Вызывается заранее, в onCreate или в onResume, чтобы при нажатии на кнопку не было задержки.
	 */
	private void prepareMoreGamesRequest() {
		moreGamesRequest = new PHPublisherContentRequest(this, MORE_GAMES_PLACEMENT);
		moreGamesRequest.preload();
	}

		/*
		 * Вешаем событие, которое отображает список и сразу же готовит новый, если пользователь захочет нажать на кнопку второй раз.
		 */
		findViewById(R.id.moreGames).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				moreGamesRequest.send();
				prepareMoreGamesRequest();
			}
		});


В общем и целом всем эта площадка радует, разве что в плане дохода оценить пока что никак — приложение с самого начала оказалось в таком низу, что установили его только я да я, да вся моя семья.

Scoreloop порадовал меня не так сильно. С одной стороны — они предоставляют бесплатный сервер с БД. С другой — я хотел бы интегрировать что-то более готовое, комплексное. Поясню. Раньше я часто наблюдал приложения со Scoreloop, которые выглядели следующим образом:

Т.е. это довольно стандартизированный вид. И в интернете еще остались примеры реализации Leaderboards Activity. Всего лишь один вызов intent'a и в Вашем приложении есть комплексная доска рекордов. Но в новом SDK этой Activity нет. Как итог, приходится городить свой собственный ListView, писать запросы, показывать ProgressBar'ы и т. д. и т. п. Совершенно не понимаю, зачем было это делать. Но наверное немцам виднее.
Что еще не понравилось в Scoreloop — чтобы отобразить нормальный список пользователей с набранными очками и позицией в рейтинге — необходимо сделать 2 запроса. В одном получить список пользователей, а в другом получить Rank (позицию в рейтинге) для какого-то одного из пользователей. После того, как я таким образом реализовал Leaderboard:

Мне стало вдвойне не понятно, зачем было убирать из SDK готовую Activity. Но… немцам виднее.

P. S.


Если вдруг кому-то интересны еще какие-то детали реализации — спрашивайте. Не просто же так я все это тут затеял.
Tags:
Hubs:
0
Comments 9
Comments Comments 9

Articles