Взрыв — это не что иное, как группа частиц (будь то пиксели, маленькие фигуры или изображения), разбросанных по экрану и возникающих из одной точки. Не все время, но в основном и для простоты будем считать, что все частицы происходят из одной точки.
Просто подумай о фейерверке. Крошечная маленькая ракета взлетает и взрывается в сотни сверкающих маленьких звездочек, которые исчезают при падении. Происходит то, что огромная сила в центре ракеты разрывает тело на части (создавая таким образом частицы) и случайным образом рассеивает их вокруг точки взрыва.
Для простоты мы создадим несколько частиц, поместим их в одно место (начало координат) и дадим им случайные силы. Сила — это векторная величина. Это означает, что оно имеет величину и направление. Величина будет определять его скорость, а направление будет указывать частице, в какую сторону двигаться.
  Частица 
 
 
Файл класса:
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 | publicclassParticle {    publicstaticfinalintSTATE_ALIVE = 0;    // particle is alive    publicstaticfinalintSTATE_DEAD = 1;     // particle is dead    publicstaticfinalintDEFAULT_LIFETIME    = 200;  // play with this    publicstaticfinalintMAX_DIMENSION       = 5;    // the maximum width or height    publicstaticfinalintMAX_SPEED           = 10;   // maximum speed (per update)    privateintstate;          // particle is alive or dead    privatefloatwidth;        // width of the particle    privatefloatheight;       // height of the particle    privatefloatx, y;         // horizontal and vertical position    privatedoublexv, yv;      // vertical and horizontal velocity    privateintage;            // current age of the particle    privateintlifetime;       // particle dies when it reaches this value    privateintcolor;          // the color of the particle    privatePaint 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 | publicParticle(intx, inty) {    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 = newPaint(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 | publicvoidupdate() {    if(this.state != STATE_DEAD) {        this.x += this.xv;        this.y += this.yv;        // extract alpha        inta = 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.
intcolor =0xff336699;intalpha = color >>>24;intred = color >>>16&0xFF;intgreen = color >>>8&0xFF;intblue = color &0xFF;
Метод draw () снова прост.
| 1 2 3 4 | publicvoiddraw(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 | publicclassExplosion {    publicstaticfinalintSTATE_ALIVE     = 0;    // at least 1 particle is alive    publicstaticfinalintSTATE_DEAD      = 1;    // all particles are dead    privateParticle[] particles;           // particles in the explosion    privateintx, y;                       // the explosion's origin    privateintsize;                       // number of particles    privateintstate;                      // whether it's still active or not} | 
Он содержит массив частиц. Размер — это количество частиц. Взрыв жив, если в нем есть хотя бы одна частица.
Обновление предельно просто. Он перебирает все частицы и вызывает метод update () для каждой частицы. Ничья () тоже самое.
  В нашем приложении мы будем создавать взрывы на экране, где мы его касаемся. 
  Конструктор очень прост: 
| 01 02 03 04 05 06 07 08 09 10 | publicExplosion(intparticleNr, intx, inty) {    Log.d(TAG, "Explosion created at "+ x + ","+ y);    this.state = STATE_ALIVE;    this.particles = newParticle[particleNr];    for(inti = 0; i < this.particles.length; i++) {        Particle p = newParticle(x, y);        this.particles[i] = p;    }    this.size = particleNr;} | 
Массив частиц заполняется в позиции касания.
В нашем приложении мы допустим до 10 взрывов. Поэтому в MainGamePanel мы объявляем массив взрывов.
| 1 | privateExplosion[] explosions; | 
В методе surfaceCreated мы создаем экземпляр массива и заполняем его нулем .
| 1 2 3 4 | explosions = newExplosion[10];for(inti = 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 | publicbooleanonTouchEvent(MotionEvent event) {    if(event.getAction() == MotionEvent.ACTION_DOWN) {        // check if explosion is null or if it is still active        intcurrentExplosion = 0;        Explosion explosion = explosions[currentExplosion];        while(explosion != null&& explosion.isAlive() && currentExplosion < explosions.length) {            currentExplosion++;            explosion = explosions[currentExplosion];        }        if(explosion == null|| explosion.isDead()) {            explosion = newExplosion(EXPLOSION_SIZE, (int)event.getX(), (int)event.getY());            explosions[currentExplosion] = explosion;        }    }    returntrue;} | 
Что мы делаем, так это перебираем взрывы, и когда мы находим первый ноль (это означает, что мы никогда не использовали его для экземпляра) или первый мертвый взрыв, мы создаем новый в позиции касания.
Методы обновления и рендеринга просты. Выполните итерацию по взрывам, и если они не равны 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





