Взрыв — это не что иное, как группа частиц (будь то пиксели, маленькие фигуры или изображения), разбросанных по экрану и возникающих из одной точки. Не все время, но в основном и для простоты будем считать, что все частицы происходят из одной точки.
Просто подумай о фейерверке. Крошечная маленькая ракета взлетает и взрывается в сотни сверкающих маленьких звездочек, которые исчезают при падении. Происходит то, что огромная сила в центре ракеты разрывает тело на части (создавая таким образом частицы) и случайным образом рассеивает их вокруг точки взрыва.
Для простоты мы создадим несколько частиц, поместим их в одно место (начало координат) и дадим им случайные силы. Сила — это векторная величина. Это означает, что оно имеет величину и направление. Величина будет определять его скорость, а направление будет указывать частице, в какую сторону двигаться.
Частица
Файл класса:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
public class Particle { public static final int STATE_ALIVE = 0 ; // particle is alive public static final int STATE_DEAD = 1 ; // particle is dead public static final int DEFAULT_LIFETIME = 200 ; // play with this public static final int MAX_DIMENSION = 5 ; // the maximum width or height public static final int MAX_SPEED = 10 ; // maximum speed (per update) private int state; // particle is alive or dead private float width; // width of the particle private float height; // height of the particle private float x, y; // horizontal and vertical position private double xv, yv; // vertical and horizontal velocity private int age; // current age of the particle private int lifetime; // particle dies when it reaches this value private int color; // the color of the particle private Paint paint; // internal use to avoid instantiation } |
Частица — это всего лишь маленький прямоугольник (это может быть изображение, круг или любая другая фигура, но в нашем случае мы используем прямоугольник) с несколькими свойствами.
У него есть состояние . Это указывает, является ли частица живой или мертвой. Частица жива, когда ее цвет не черный (она не исчезла) и ее возраст не достиг своего времени жизни . Подробнее об этом чуть позже.
У него есть позиция . Его положение в 2D системе координат представлено двумя точками: x и y .
У этого также есть скорость и направление. Как вы помните, скорость — это вектор, поэтому она имеет 2 компонента в 2D. В 3D он также будет иметь компонент z, но пока мы остаемся в 2D. Для простоты теперь добавим два свойства для этого. VX и VY
Возраст частицы в начале равен 0 и увеличивается с каждым обновлением.
Время жизни — это максимальный возраст, который может достичь частица, прежде чем она умрет.
Остальные цвета и краски . Это только для рисования.
Если вы помните предыдущие записи, обновление игры — это не что иное, как вызов методов обновления всех сущностей в игре и их отображение. Метод обновления частицы довольно прост.
Но сначала нам нужно создать частицу:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
public Particle( int x, int y) { this .x = x; this .y = y; this .state = Particle.STATE_ALIVE; this .widht = rndInt( 1 , MAX_DIMENSION); this .height = this .widht; this .lifetime = DEFAULT_LIFETIME; this .age = 0 ; this .xv = (rndDbl( 0 , MAX_SPEED * 2 ) - MAX_SPEED); this .yv = (rndDbl( 0 , MAX_SPEED * 2 ) - MAX_SPEED); // smoothing out the diagonal speed if (xv * xv + yv * yv > MAX_SPEED * MAX_SPEED) { xv *= 0.7 ; yv *= 0.7 ; } this .color = Color.argb( 255 , rndInt( 0 , 255 ), rndInt( 0 , 255 ), rndInt( 0 , 255 )); this .paint = new Paint( this .color); } |
Проверьте создание частицы, и она должна быть прямой.
Вы заметите, что частица создана в позиции x , y .
Государство установлено живым .
Мы хотим рандомизировать размер прямоугольников, потому что взрыв создает частицы разных размеров и форм, но мы просто рандомизируем размер и цвет.
Я написал несколько вспомогательных методов, которые дают мне случайные числа, для этого проверьте полный исходный код.
Далее устанавливается время жизни . Каждая частица будет иметь одинаковое время жизни.
Конечно, возраст равен 0, так как частица только что родилась.
Далее интересный момент. Это очень любительское. Чтобы установить скорость, я использовал 2 случайных числа для 2 компонентов вектора скорости ( vx и vy ). Сглаживание необходимо, потому что, если оба компонента близки к максимальному значению, результирующая величина будет выше максимальной скорости. Вместо этого вы можете использовать простые тригонометрические функции со случайной степенью.
Последнее, что нужно установить, это цвет, который снова является случайным.
Там у вас есть это.
Метод update () для частицы.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
public void update() { if ( this .state != STATE_DEAD) { this .x += this .xv; this .y += this .yv; // extract alpha int a = this .color >>> 24 ; a -= 2 ; // fade by 2 if (a <= 0 ) { // if reached transparency kill the particle this .state = STATE_DEAD; } else { this .color = ( this .color & 0x00ffffff ) + (a << 24 ); // set the new alpha this .paint.setAlpha(a); this .age++; // increase the age of the particle } if ( this .age >= this .lifetime) { // reached the end if its life this .state = STATE_DEAD; } } } |
Это довольно просто. При каждом обновлении позиция устанавливается в соответствии со скоростью, а альфа-компонент цвета частицы уменьшается. Другими словами, частица исчезает.
Если возраст превысил время жизни или непрозрачность равна 0 (это означает, что она полностью прозрачна), частица объявляется мертвой.
Если вас интересует магия с цветами, это довольно просто, если вы получите побитовые операторы. Не волнуйтесь, я тоже мусор, просто убедитесь, что вы знаете, где искать. Вот хорошее объяснение компонентов цвета и как использовать побитовые операторы для управления ими: http://lab.polygonal.de/2007/05/10/bitwise-gems-fast-integer-math/ . Это быстрее, чем использование объектов, но вы также можете безопасно использовать методы Android.
Просто как примечание к цветам
Вы можете указать цвета в Android как int. Если вы знакомы с rgb и argb, это здорово.
rgb — это 24-битный цвет, а argb — 32-битный. У этого также есть альфа-компонент, который является прозрачностью / непрозрачностью.Значения непрозрачности: 0 = прозрачный, 255 = полностью непрозрачный.
Для представления целого числа в шестнадцатеричном виде вы просто ставите перед ним префикс 0x . Цвет в шестнадцатеричном формате прост: например, 0x00FF00 — зеленый. Шаблон: 0xRRGGBB (красный, зеленый, синий). Теперь, чтобы добавить альфа, вы добавите его в начало. 0xAARRGGBB .
Поскольку это в шестнадцатеричном, значения между 00 и FF. 0 — 0, а FF — 255 в десятичном виде.
Когда вы создаете цвет из таких компонентов, как цвет (a, r, g, b) (например, новый цвет (125, 255, 0, 0) создает полупрозрачный красный), вы можете просто создать его с целым числом, выраженным в шестнадцатеричном виде вот так: новый цвет (0x80FF0000);Вот как вы должны извлечь компоненты цвета argb.
12345int
color =
0xff336699
;
int
alpha = color >>>
24
;
int
red = color >>>
16
&
0xFF
;
int
green = color >>>
8
&
0xFF
;
int
blue = color &
0xFF
;
Метод draw () снова прост.
1
2
3
4
|
public void draw(Canvas canvas) { paint.setColor( this .color); canvas.drawRect( this .x, this .y, this .x + this .widht, this .y + this .height, paint); } |
На этом этапе попробуйте создать несколько частиц на игровой панели и посмотреть, что произойдет.
Взрыв
Взрыв — это не что иное, как сотни частиц, происходящих из одного места, источника.
На изображении выше вы видите первые 4 обновления простого взрыва. Все частицы имеют одинаковую скорость, но они распространяются в разных направлениях. Каждый круг — это одно обновление.
Основными свойствами взрыва являются:
01
02
03
04
05
06
07
08
09
10
|
public class Explosion { public static final int STATE_ALIVE = 0 ; // at least 1 particle is alive public static final int STATE_DEAD = 1 ; // all particles are dead private Particle[] particles; // particles in the explosion private int x, y; // the explosion's origin private int size; // number of particles private int state; // whether it's still active or not } |
Он содержит массив частиц. Размер — это количество частиц. Взрыв жив, если в нем есть хотя бы одна частица.
Обновление предельно просто. Он перебирает все частицы и вызывает метод update () для каждой частицы. Ничья () тоже самое.
В нашем приложении мы будем создавать взрывы на экране, где мы его касаемся.
Конструктор очень прост:
01
02
03
04
05
06
07
08
09
10
|
public Explosion( int particleNr, int x, int y) { Log.d(TAG, "Explosion created at " + x + "," + y); this .state = STATE_ALIVE; this .particles = new Particle[particleNr]; for ( int i = 0 ; i < this .particles.length; i++) { Particle p = new Particle(x, y); this .particles[i] = p; } this .size = particleNr; } |
Массив частиц заполняется в позиции касания.
В нашем приложении мы допустим до 10 взрывов. Поэтому в MainGamePanel мы объявляем массив взрывов.
1
|
private Explosion[] explosions; |
В методе surfaceCreated мы создаем экземпляр массива и заполняем его нулем .
1
2
3
4
|
explosions = new Explosion[ 10 ]; for ( int i = 0 ; i < explosions.length; i++) { explosions[i] = null ; } |
На onTouchEvent мы создаем взрывы.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { // check if explosion is null or if it is still active int currentExplosion = 0 ; Explosion explosion = explosions[currentExplosion]; while (explosion != null && explosion.isAlive() && currentExplosion < explosions.length) { currentExplosion++; explosion = explosions[currentExplosion]; } if (explosion == null || explosion.isDead()) { explosion = new Explosion(EXPLOSION_SIZE, ( int )event.getX(), ( int )event.getY()); explosions[currentExplosion] = explosion; } } return true ; } |
Что мы делаем, так это перебираем взрывы, и когда мы находим первый ноль (это означает, что мы никогда не использовали его для экземпляра) или первый мертвый взрыв, мы создаем новый в позиции касания.
Методы обновления и рендеринга просты. Выполните итерацию по взрывам, и если они не равны NULL и живы, то вызовите их методы update и draw соответственно
В последнем коде я добавил границу для экрана в качестве стены и добавил базовое обнаружение столкновений для частиц, чтобы они отражались от стен. Стена передается как ссылка, и метод обновления проверяет ее на предмет столкновения. Используйте это как упражнение, удалите столкновение и попробуйте прикрепить изображение к частице, а не быть прямоугольником. Для создания взрывов просто нажмите на экран.
Это должно выглядеть так:
Изучите код и получайте удовольствие.
Загрузите его здесь ( android.particles.tgz ).
Ссылка: Particle Explosion с Android от нашего партнера JCG Тамаса Яно из блога « Против зерна ».
- Введение в разработку игр для Android Введение
- Разработка игр для Android — Идея игры
- Разработка игр для Android — Создать проект
- Разработка игр для Android — базовая игровая архитектура
- Разработка игр для Android — основной игровой цикл
- Разработка игр для Android — Отображение изображений с Android
- Разработка игр для Android — перемещение изображений на экране
- Разработка игр для Android — The Game Loop
- Разработка игр для Android — Измерение FPS
- Разработка игр для Android — Sprite Animation
- Разработка игр для Android — Дизайн игровых объектов — Стратегия
- Разработка игр для Android — Использование растровых шрифтов
- Разработка игр для Android — переход с Canvas на OpenGL ES
- Разработка игр для Android — отображение графических элементов (примитивов) с помощью OpenGL ES
- Разработка игр для Android — OpenGL Texture Mapping
- Разработка игр для Android — Дизайн игровых сущностей — Государственный паттерн
- Серия игр для Android