среда, 13 июля 2011 г.

Flow

Addictive, fun and simple. This is the snake game everyone is talking about!
Flow is an Android version of the snake game.
Control the snake with your finger tips.
Game Features:
- 3 difficulty levels
- Classic Mode & Time Mode


понедельник, 4 июля 2011 г.

Neon Physics:разработка

Всем людям свойственно лениться, и я не являюсь исключением. До этого момента я с мобильными технологиями никогда не работал. Собрав всю волю в кулак, я решил освоить java и android sdk, написать более менее серьёзное приложение и разместить его на android market. Я решил сделать игрушку с физической составляющей.

За пару часов было составлено техническое задание и правила игры. Правила оказались очень простыми. В игре есть 16 уровней. Пройдя уровень, открывается следующий. На каждом уровне есть различные объекты, некоторые можно передвигать, некоторые зафиксированы. Так же на игровом уровне присутствует генератор, который создает шарики, и объект-цель, куда эти шарики должны попасть. На шары действует гравитация. Чтобы выиграть шарик должен попасть в цель. Игру решил назвать Neon Physics.

Прочитав некоторое количество литературы на различных сайтах, в том числе о hello world, я понял, что писать с нуля нет смысла. За основу я взял готовый движок andengine для рендера opengl + box2d для расчета физики. Что бы их подключить нужно заглянуть на этот сайт. Там есть детальное видео, как сделать так, что бы все заработало в три клика. Так же целый список примеров можно посмотреть тут.

Дальше я расскажу как, использовав пример ниже, я написал простенькую игрушку. Пример находиться тут. Если вы сделали все так как было показано в видео, то вы сможете скомпилировать данный пример.

<code>

public class PhysicsExample extends BaseExample implements IAccelerometerListener, IOnSceneTouchListener {

//Размеры изображения для рендеринга
private static final int CAMERA_WIDTH = 720;
private static final int CAMERA_HEIGHT = 480;

//Переменная отвечающая за физические характеристики объекта
private static final FixtureDef FIXTURE_DEF = PhysicsFactory.createFixtureDef(1, 0.5f, 0.5f);

//Текстура
private Texture mTexture;

//4 изображения анимированных изображения
private TiledTextureRegion mBoxFaceTextureRegion;
...

//Переменная отвечающая за физический движок
private PhysicsWorld mPhysicsWorld;

//Количество объектов
private int mFaceCount = 0;

//Событие, которое срабатывает, когда сцена загрузилась
@Override
public Engine onLoadEngine() {
//Вывод сообщения "Touch the screen to add objects."
Toast.makeText(this, "Touch the screen to add objects.", Toast.LENGTH_LONG).show();

//Создание камеры для сцены
final Camera camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
final EngineOptions engineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);

//Устанавливаем флаг true для работы в отдельном потоке обработки прикосновений
engineOptions.getTouchOptions().setRunOnUpdateThread(true);

//Создаем Engine с заданными параметрами
return new Engine(engineOptions);
}

//Событие, которое срабатывает, когда грузятся ресурсы
@Override
public void onLoadResources() {
//Создание текстуры с альфа каналом
//Размеры текстуры в opengl должны быть степенью двойки
this.mTexture = new Texture(64, 128, TextureOptions.BILINEAR_PREMULTIPLYALPHA);

//Устанавливаем папку, откуда грузить ресурсы
TextureRegionFactory.setAssetBasePath("gfx/");

//Загрузка 4 спрайтов
//Последние четыре числа:положение на текстуре по x и y, количество кадров по x и y
this.mBoxFaceTextureRegion = TextureRegionFactory.createTiledFromAsset(this.mTexture, this, "face_box_tiled.png", 0, 0, 2, 1); // 64x32
...

this.mEngine.getTextureManager().loadTexture(this.mTexture);

//Включаем работу G-sensor
this.enableAccelerometerSensor(this);
}

//Событие, которое срабатывает, когда грузятся сцена
@Override
public Scene onLoadScene() {
//Подключаем FPSLogger
this.mEngine.registerUpdateHandler(new FPSLogger());

//Создаем сцену с двумя слоями, слои нужны, что бы не перекрывать объекты
final Scene scene = new Scene(2);

//Устанавливаем задний фон
scene.setBackground(new ColorBackground(0, 0, 0));

//Включаем обработку прикосновений
scene.setOnSceneTouchListener(this);

//Создаем mPhysicsWorld, box2d
//Устанавливаем гравитацию в зависимости от G-sensor
this.mPhysicsWorld = new PhysicsWorld(new Vector2(0, SensorManager.GRAVITY_EARTH), false);

//Создаем четыре объекты-стенки, которые будут ограничивать наш физический движок по краям, что бы объекты не улетали за границу экрана
final Shape ground = new Rectangle(0, CAMERA_HEIGHT - 2, CAMERA_WIDTH, 2);
...

//Переменная отвечающая за физические характеристики объекта
final FixtureDef wallFixtureDef = PhysicsFactory.createFixtureDef(0, 0.5f, 0.5f);

//Создаем физическое представление четырех объектов, которые были описаны выше
PhysicsFactory.createBoxBody(this.mPhysicsWorld, ground, BodyType.StaticBody, wallFixtureDef);
...

//Добавляем наши объекты в сцену
scene.getFirstChild().attachChild(ground);
....

//включаем mPhysicsWorld
scene.registerUpdateHandler(this.mPhysicsWorld);

return scene;
}

...

//Обработка нажатия на экран
//При нажатии добавляем новый объект
@Override
public boolean onSceneTouchEvent(final Scene pScene, final TouchEvent pSceneTouchEvent) {
if(this.mPhysicsWorld != null) {
if(pSceneTouchEvent.isActionDown()) {
this.addFace(pSceneTouchEvent.getX(), pSceneTouchEvent.getY());
return true;
}
}
return false;
}

...

//Процедура добавления объекта
//В зависимости от количества объектов добавляет один из четырех объектов
private void addFace(final float pX, final float pY) {
//получение текущей Scene
final Scene scene = this.mEngine.getScene();

//увеличиваем счетчик количества объектов
this.mFaceCount++;

//Переменная визуального представления
final AnimatedSprite face;
//Переменная физического представления
final Body body;

//В зависимости от mFaceCount % 4 создаем объект
//Визуальное представление + физическое представление
if(this.mFaceCount % 4 == 0) {
face = new AnimatedSprite(pX, pY, this.mBoxFaceTextureRegion);
body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, face, BodyType.DynamicBody, FIXTURE_DEF);
} else
...

//Включаем смену кадров с задержкой в 200 мс
face.animate(200);

//Добавляем в рендер список объект
scene.getLastChild().attachChild(face);

//Добавляем в список на обработку физики
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(face, body, true, true));
}

//В стандартной поставке box2d есть только геометрия для прямоугольного и круглого объекта. Нам надо задать произвольную геометрию для треугольного и гексагонального объекта

...
}
</code>

На основе этого примера я сделал свое первое приложение для android и поместил его на market. Справедливости ради надо сказать, что на разработку я потратил около недели в свободное время. Много времени было потрачено на дизайн и оформление. Художник из меня очень плохой.

В течение первых дней его скачало около ста человек. Приложение является бесплатным. Для монетизации приложения добавил admob, но <s>больших</s> денег он мне не принес. Для себя считаю это небольшим успехом, так как получил новый опыт в разработке. Ссылка на android marke.

четверг, 26 мая 2011 г.

Alterlife

This game is about 4 fractions of bacteria. You control one of the colonies. For victory to become the largest colony. To do this, eat white foods and attack the bacteria colonies of different colors. Touch the screen to the right place to give orders. The game has three types of difficulties. You can play with 1, 2 and 3 computer players.



среда, 18 мая 2011 г.

Чина сегодня прислало письмо по поводу размещения моего приложения на ихнем маркете. Я не доволен, так как они провели реверс и вырезали рекламу. Сейчас идет переписка.