Genişleyen mermi desen şekilleri nasıl yapabilirim?


12

Kareler, üçgenler, vb. genişleyen yıldız:

https://youtu.be/7JGcuTWYdvU?t=2m41s


2
Oh, bu iyi bir soru. Belirli bir cevabım yok, ancak bir sprite veya basit bir şekil olan bir 2D nesne kullanabileceğinizi ve mermi kenar boyunca ortaya çıkarabileceğinizi hayal ediyorum. Tabii ki, hile onlara doğru hız veriyor, hem şekline göre dışa doğru hem de böyle bir kaydıraç yapıyorsanız, ekranla ilerlemelerini sağlamak. Burada herhangi bir cevap görmek çok ilgi.
Jesse Williams

1
Bu tür etki için popüler bir isim "parçacık efektleridir". Bu arama terimi size yardımcı olabilir!
Cort Ammon

1
Teşekkürler, XNA ve libGDX'te bir süredir parçacık efektleri kullanıyorum, ancak bu belirli etki tarzını nasıl kullanacağımdan emin değildim.
lepton

1
Bunun inanılmaz derecede güçlü, ancak programlanması çok karmaşık olan başka bir cevabı var. Ve yazmak için gerçek bir klavyeye ihtiyaç var. Daha sonra açıklama için yer işareti koyma.
Draco18s artık SE

İlginç - Böyle bir şey için asla parçacık efektleri yapmazdım. Veya bu sadece Birlik'teki bir tariftir. Parçacık efektleri çarpıştırıcılara sahip olabilse de (böylece bir nesneye zarar verir), bunun basitçe nesne kopyalarını başlatmaktan çok daha fazla yük oluşturduğu görülüyor.
Jesse Williams

Yanıtlar:


11

Bunu yapmanın en kolay yolu önce şekli tasarlamak sonra parçacıkların hareketini hesaplamak olacaktır. Bu cevapta bir kare inşa edeceğim, ancak bu herhangi bir şekil için geçerlidir.

Şeklinizi bir başlangıç ​​noktası etrafındaki göreli konumlar olarak tasarlayarak başlayın.

Meydan

Şimdi şeklin nasıl genişleyeceğini hesaplamanız gerekiyor. Bunu yapmak için biz sadece gelen vektör işaret hesaplamak originher üzere pointçıkarılarak originbizim dan pozisyon pointardından 'ın pozisyonuna normale vektör. vector = normalize(point.x - origin.x, point.y - origin.y).

vektör

Artık bu vektörü kullanarak noktaların konumunu herhangi bir zamanda hesaplayabiliriz. Noktaların bir sonraki konumunu yaparak hesaplarsınız point.position += point.vector * point.velocity. Önceki noktamızı kullanarak sözde kod örneği:

// 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)

Bunu yaptığınızda tüm noktalar her karede 3 birimde dışa doğru hareket edecektir.


notlar

  • Bazı basit vektör matematiğini burada okuyabilirsiniz .
  • Tüm pozisyonlar bir başlangıç ​​noktasına göre olduğu sürece konum herhangi bir şey olabilir.
  • Tekdüze hareket sağlamak için tüm noktaların hızı aynı olmalıdır, ancak farklı hızlara sahip olmak size ilginç sonuçlar verebilir.
  • Hareket kapalı görünüyorsa başlangıç ​​noktasını kontrol etmelisiniz. Şeklin tam ortasında değilse, şekil garip bir şekilde genişleyebilir.

9
Sadece belirtmek isterim ki, her parçacığın hızı ilk karedeki başlangıç ​​noktasından olan uzaklığa orantılı olmalıdır (yani her kare başına yalnızca bir kez hesapla). Alternatif olarak, yön vektörünü normalleştiremezsiniz. Bunu yapmazsanız, şekil doğrusal olarak ölçeklenmez, daha ziyade bir daire olmaya doğru hareket eder (tüm hızlar aynı ise)
Aaron

@Charanor Açıklama için çok teşekkürler. Aslında üniversitede ayrık matematik okudum ama çok uzun zaman önceydi. Bugün bir şeyler yapmaya çalışacağım.
lepton

2

Yani, orada karmaşık parçacık / mermi kalıpları oluşturmak için bir biçimlendirme dili olan BulletML adlı bir proje var . Kodu kesinlikle kendi dilinize taşımanız gerekecek, ancak gerçekten şaşırtıcı şeyler yapabilir.

Örneğin, bu patron , BulletML for Unity3D'nin (yoğun şekilde değiştirilmiş) bir uzantısında yapıldı (bu kalıbın yazarı bu videoyu yükledi ve Misery çılgınca ve iyi 1 ). Bu düşmanın en zor varyasyonu ve BulletML'nin neyi iyi yapabileceğini gösteriyor (ve Misery'nin diğer patronlarına da bak, Wallmaster gibi ).

Ya da, The Last Federation için bir genişletme üzerinde çalışırken yazdığım bir desen olan, daha az mod dostu olan ve yalnızca tek karakterli AZ değişkenleri kullanan sistemin eski bir revizyonunu kullanarak bu örneği gösterebilirim :

Madde işareti örneği örneği

Bu halkaları yapan yeşil mermiler, yüksek hızda dönen bir ana mermiden çıkarılır, ancak kendilerinin hiçbir hareketi yoktur. Oyuncuyu daha uzun bir menzilde tutarak, hasar silahlarını düşürmelerini kısıtlayarak ve mobil savunucuların oyuncuyu taciz etmelerine izin veren büyük hasar verir (oyuncu, ortadaki hareketsiz yapı tahrip edildiğinde kazandı).

XML sözdiziminin bu balonları oluşturan kısmı:

<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>

Ekran görüntüsünde, kaynaktan (dönen) hemen balonun kenarına doğru giden mor "yerçekimi dalgası" çekimlerinden bazılarını görebilirsiniz. despawning. Çok daha karmaşık oldukları için mavi ve sarı çekimleri atladım.

Genişlemedeki diğer kalıplardan biri ( topçu kabuğu ) aslında Misery tarafından yazılmıştır, ancak bazı değişiklikler yaptım. Başlangıçta, uzun menzilli uçan ve ardından tonlarca hasar veren büyük bir havai fişek gösterisine patlayan düşük hasarlı, delici bir atış. Maksimum menzili, oyuncunun başarabileceğinden çok daha yüksekti, esas olarak oyuncuyu kısa menzilde çalışmaya zorladı, bu da av tüfeği etkisi nedeniyle (küçük bir bölgede kümelenmiş daha fazla mermi) diğer NPC birimleri için avantajlıydı.

BulletML ile çalışmak genellikle kolaydır ve şaşırtıcı şeyler yapabilir. Mermiler yön değiştirebilir, hızı değiştirebilir, diğer modelleri ortaya çıkarabilir, erken ölebilir, bir döngüdeki komut koleksiyonunu tekrarlayabilir, gecikmeleri kullanabilir, mermi hareketli görüntüsünü değiştirebilir, ebeveynlerini takip edebilir (ya da değil) ... Ve destekleyemediği her şey içine yazın.

Ciddi bir ateş em up oyunu yapıyorsanız kesinlikle tavsiye ederim. Charanor cevabında bahsedildiği gibi, istenen şekilleri elde etmek için koordinat matematiğini çalıştırmanız gerekecek, ancak BulletML gibi bir mermi motoru size çok daha fazla esneklik kazandıracak ve yeni desenler tasarlamaktan daha fazla zaman harcayacaksınız. nasıl kodlanır.

  1. Misery'in ne kadar iyi olduğunu açıklamak için, bu videolar başlangıç ​​ekipmanı olan yer patronlarına karşıdır : modül yok, sarf malzemesi yok ve temel bezelye atıcı. Ve xe dövüşün uzatılmış doğasına rağmen sadece bir vuruş yapar. Tamam, Santrifüj'e karşı 9 vuruş (oyuncudan sonra üçüncü kata kadar görünmeyen kesinlikle yükseltmeler olacak ve nispeten en az iki kez hasar verecek).

Teşekkürler, bir süredir olduğu için BulletML'nin belirsiz bir şekilde farkındaydım, ancak sadece zaman zaman mermi cehenneminde duran ve kendi başına bir kurşun cehennemi atıcı olmayan basit oyunum için kesinlikle abartılıydı.
lepton

@lepton Tamamen anlaşılabilir. Bu sizin vermeniz gereken bir karardır, ancak cevap başkası için "en iyi" olabilir. TLF üzerinde çalıştıktan sonra kendi atıcımı yapmaya başladıktan sonra, bununla çalışmanın ne kadar güçlü ve kolay olduğu için kullanmak istediğimi biliyorum. :)
Draco18s artık SE

1

Charanor'un işaret ettiği gibi, şeklinizi tanımlamak ve daha sonra zaman içinde konumlarını güncellemek için bir dizi nokta kullanabilirsiniz. Aşağıda, noktaları kullanarak bir yıldız şeklinin veya özel bir şeklin nasıl uygulanacağının çalışan bir örneği verilmiştir:

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);
            }
        }
    }
}

Örnek için çok teşekkürler, bu öğleden sonra bakıp çalıştırabileceğimi kontrol edeceğim.
lepton
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.