Я хочу зробити серію розширюваних шарів кулі, що утворюють такі фігури, як квадрати, трикутники і т. Д. Приклад того, що я хочу побачити на наступному відео, де при зібранні зірок кулі вибухають у формі зірка, що розширюється:
Я хочу зробити серію розширюваних шарів кулі, що утворюють такі фігури, як квадрати, трикутники і т. Д. Приклад того, що я хочу побачити на наступному відео, де при зібранні зірок кулі вибухають у формі зірка, що розширюється:
Відповіді:
Найпростіший спосіб зробити це було б спочатку спроектувати форму, а потім обчислити рух частинок. У цій відповіді я буду будувати квадрат, але це стосується будь-якої форми.
Почніть з проектування своєї форми як відносної позиції навколо якоїсь точки початку.
Тепер потрібно порахувати, як буде розширюватися форма. Для цього ми просто обчислюємо вектор, що вказує від точки origin
до кожного point
, віднімаючи origin
позицію з позиції нашого point
, а потім нормалізуючи вектор. vector = normalize(point.x - origin.x, point.y - origin.y)
.
Тепер ми можемо обчислити положення точок у будь-який момент за допомогою цього вектора. Ви обчислюєте наступне положення очок, виконуючи point.position += point.vector * point.velocity
. Приклад псевдокоду, використовуючи попередній пункт:
// When you start your program you set these values.
point.position = (-3, 3); // Start position. Can be anything.
point.vector = normalize(-3, 3); // Normalized vector.
point.velocity = 3; // Can be anything.
// You do this calculation every frame.
point.position += point.vector * point.velocity;
// point.vector * point.velocity = (-3, 3)
// point.position is now (-6, 6) since (-3, 3) + (-3, 3) = (-6, 6)
Це перемістить всі точки назовні на 3 одиниці кожного кадру.
Примітки
Отже, існує цей проект під назвою BulletML, який є мовою розмітки для створення складних шаблонів частинок / куль. Вам майже напевно потрібно буде перенести код на свою власну мову, але це може зробити справді дивовижні речі.
Наприклад, цей начальник був зроблений у (сильно модифікованому) розширенні BulletML для Unity3D (автор цього шаблону завантажив, що відео та Misery є божевільним, а також хорошим 1 ). Це найскладніший варіант цього ворога, і він показує, на що BulletML здатний цілком добре (і перевірити деяких інших босів Місі , теж, як Wallmaster ).
Або я можу показати цей приклад, який є закономірністю, яку я написав під час роботи над розширенням для The Last Federation , використовуючи старішу версію системи, яка менш зручна для моди та використовує лише однозначні змінні AZ:
Зелені кулі, які роблять ці кільця там, породжені з батьківської кулі, яка обертається з великою швидкістю, але самі не мають руху. Вони завдають великої шкоди, утримуючи гравця на більшій відстані, обмежуючи знижуючи зброю і дозволяючи мобільним захисникам домагатися гравця (гравець виграв, якщо руйнувана структура посередині була зруйнована).
Ось частина синтаксису XML, яка створює ці бульбашки:
<bullet_pattern name="Barrier">
$WallShotAngle B=.3 A=90
$WallShotAngle B=.3 A=-90
$WallShotAngle B=.3 A=0
$WallShotAngle B=.375 A=180
</bullet_pattern>
<var name="WallShotAngle">
<bullet angle="[A]" speed="4000" interval_mult=".01" dumbfire="1" shot_type="GravityWavePurple">
<wait time="[B]" />
<change angle="0" speed="1000" time=".0001" />
<spawn>
<bullet_pattern>
<bullet angle="[A]" speed="0" shot_type="CurveBarGreen" damage_mult="8">
<wait time="12" />
<die />
</bullet>
</bullet_pattern>
</spawn>
<die />
</bullet>
</var>
На скріншоті ви можете побачити кілька фіолетових знімків "хвилі гравітації", які майже миттєво прямують від джерела (який обертається) до краю бульбашки, після чого він породжує зелений кадр "зігнутої смуги", який сидить там за 12 секунд до відпадання. Сині та жовті кадри я опустив, оскільки вони набагато складніші.
Один з інших шаблонів ( артилерійський снаряд ) у розширенні насправді був написаний Мізері, хоча я вносив до нього деякі модифікації. Спочатку це малопошкоджений проникаючий постріл, який вилітає на далекі відстані, а потім вибухає у величезний феєрверк, наносячи тонни збитків. Максимальний діапазон був набагато більшим, ніж гравцеві вдалося досягти, по суті змушуючи гравця брати участь на невеликій відстані, що було вигідно для інших типів одиниць NPC завдяки ефекту дробовика (більше куль купилося в невеликій зоні).
Працювати з BulletML, як правило, легко і можна робити дивовижні речі. Кулі можуть змінювати напрямок, змінювати швидкість, нерестувати інші шаблони, рано вмирати, повторювати збір команд у циклі, використовувати затримки, змінювати спрайтове зображення кулі, слідувати за своїм батьківським (чи ні) ... І все, що це не підтримує, ви могли б запишіть його.
Я б точно рекомендував це, якщо ви робите серйозну гру в стрілянину. Вам все одно знадобиться опрацювати математику координат, щоб отримати бажані форми, про що Харанор говорить у своїй відповіді, але кульовий двигун, як BulletML, дасть вам набагато більше гнучкості, що ви витратите більше часу на розробку нових шаблонів, ніж з'ясування як їх кодувати.
Як вказував Charanor, ви можете використовувати масив точок, щоб визначити свою форму, а потім оновити їх положення з часом. Нижче наводиться робочий приклад того, як реалізувати форму зірки чи власну форму за допомогою точок:
package com.mygdx.gtest;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
public class Test extends ApplicationAdapter{
public SpriteBatch sb;
private StarShape ss, ssBig;
@Override
public void create() {
sb = new SpriteBatch();
Pixmap pmap = new Pixmap(2, 2,Format.RGBA8888);
pmap.setColor(Color.WHITE);
pmap.fill();
ss = new StarShape(50,50,new Texture(pmap), 10, true);
ssBig = new StarShape(250,250,new Texture(pmap), 50, false);
pmap.dispose();
}
@Override
public void render() {
super.render();
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
ss.update(Gdx.graphics.getDeltaTime());
ssBig.update(Gdx.graphics.getDeltaTime());
sb.begin();
ss.draw(sb);
ssBig.draw(sb);
sb.end();
}
@Override
public void dispose() {
super.dispose();
}
private class StarShape{
public float progress = 1f;
public Texture bulletTex;
public Array<Vector2> points = new Array<Vector2>();
public Vector2 center;
public StarShape(float x, float y, Texture tex, float initialSize, boolean mathWay){
center = new Vector2(x,y);
bulletTex = tex;
if(mathWay){
// define star shape with maths
float alpha = (float)(2 * Math.PI) / 10;
float radius = initialSize;
for(int i = 11; i != 0; i--){
float r = radius*(i % 2 + 1)/2;
float omega = alpha * i;
points.add(
new Vector2(
(float)(r * Math.sin(omega)),
(float)(r * Math.cos(omega))
)
);
}
}else{
// or define star shape manually (better for non geometric shapes etc
//define circle
points.add(new Vector2(-3f,0f));
points.add(new Vector2(-2.8f,1f));
points.add(new Vector2(-2.2f,2.2f));
points.add(new Vector2(-1f,2.8f));
points.add(new Vector2(0f,3f));
points.add(new Vector2(1f,2.8f));
points.add(new Vector2(2.2f,2.2f));
points.add(new Vector2(2.8f,1f));
points.add(new Vector2(3f,0f));
points.add(new Vector2(2.8f,-1f));
points.add(new Vector2(2.2f,-2.2f));
points.add(new Vector2(1f,-2.8f));
points.add(new Vector2(0f,-3f));
points.add(new Vector2(-1f,-2.8f));
points.add(new Vector2(-2.2f,-2.2f));
points.add(new Vector2(-2.8f,-1f));
// mouth
points.add(new Vector2(-2,-1));
points.add(new Vector2(-1,-1));
points.add(new Vector2(0,-1));
points.add(new Vector2(1,-1));
points.add(new Vector2(2,-1));
points.add(new Vector2(-1.5f,-1.1f));
points.add(new Vector2(-1,-2));
points.add(new Vector2(0,-2.2f));
points.add(new Vector2(1,-2));
points.add(new Vector2(1.5f,-1.1f));
points.add(new Vector2(-1.5f,1.5f));
points.add(new Vector2(1.5f,1.5f));
}
}
public void update(float deltaTime){
this.progress+= deltaTime;
}
public void draw(SpriteBatch sb){
Vector2 temp = new Vector2(0,0);
for(Vector2 point: points){
temp.x = (point.x);
temp.y = (point.y);
temp.scl(progress);
sb.draw(bulletTex,temp.x + center.x,temp.y +center.y);
}
}
}
}