ฉันต้องการสร้างชุดของรูปแบบสัญลักษณ์แสดงหัวข้อย่อยที่มีรูปร่างเช่นสี่เหลี่ยมจตุรัสสามเหลี่ยมเป็นต้นตัวอย่างของสิ่งที่ฉันหลังจากสามารถเห็นได้ในวิดีโอต่อไปนี้ซึ่งเมื่อดวงดาวถูกรวบรวมกระสุนระเบิดในรูปของ ดาวฤกษ์ที่กำลังขยายตัว:
ฉันต้องการสร้างชุดของรูปแบบสัญลักษณ์แสดงหัวข้อย่อยที่มีรูปร่างเช่นสี่เหลี่ยมจตุรัสสามเหลี่ยมเป็นต้นตัวอย่างของสิ่งที่ฉันหลังจากสามารถเห็นได้ในวิดีโอต่อไปนี้ซึ่งเมื่อดวงดาวถูกรวบรวมกระสุนระเบิดในรูปของ ดาวฤกษ์ที่กำลังขยายตัว:
คำตอบ:
วิธีที่ง่ายที่สุดในการทำเช่นนี้คือการออกแบบรูปร่างก่อนแล้วคำนวณการเคลื่อนที่ของอนุภาค ในคำตอบนี้ฉันจะสร้างสี่เหลี่ยม แต่สิ่งนี้ใช้ได้กับทุกรูปร่าง
เริ่มต้นด้วยการออกแบบรูปร่างของคุณเป็นตำแหน่งสัมพัทธ์รอบจุดกำเนิดบางจุด
ตอนนี้คุณต้องคำนวณว่ารูปร่างจะขยายได้อย่างไร ในการทำเช่นนี้เราเพียงคำนวณเวกเตอร์ที่ชี้จากoriginไปยังทุก ๆpointด้วยการลบoriginตำแหน่งออกจากตำแหน่งของเราpointจากนั้นปรับเวกเตอร์ให้เป็นมาตรฐาน vector = normalize(point.x - origin.x, point.y - origin.y).
ตอนนี้เราสามารถคำนวณตำแหน่งของจุดได้ทุกเวลาโดยใช้เวกเตอร์นี้ point.position += point.vector * point.velocityคุณคำนวณตำแหน่งต่อไปของจุดโดยการทำ ตัวอย่าง Pseudocode โดยใช้จุดก่อนหน้าของเรา:
// 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 (ผู้เขียนรูปแบบนั้นอัปโหลดวิดีโอและความทุกข์ยากว่าเป็นบ้าและดี1 ) มันเป็นการเปลี่ยนแปลงที่ยากที่สุดของศัตรูตัวนั้นและมันแสดงให้เห็นว่า BulletML นั้นมีความสามารถที่ค่อนข้างดี (และตรวจสอบบอสอื่น ๆ ของ Misery เช่นเดียวกับWallmaster )
หรือฉันสามารถแสดงตัวอย่างนี้ซึ่งเป็นรูปแบบที่ฉันเขียนขณะทำงานเกี่ยวกับการขยายสำหรับThe Last Federationโดยใช้การแก้ไขระบบเก่าที่ไม่ค่อยเป็นมิตรกับ mod และใช้ตัวแปร 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 วินาทีก่อน despawning ภาพสีน้ำเงินและสีเหลืองที่ฉันข้ามไปเนื่องจากมีความซับซ้อนมากขึ้น
หนึ่งในรูปแบบอื่น ๆ ( กระสุนปืนใหญ่ ) ในการขยายตัวถูกเขียนโดย Misery ถึงแม้ว่าฉันจะทำการดัดแปลงบางอย่าง ตอนแรกมันเป็นดาเมจต่ำยิงทะลุทะลวงออกไปในระยะไกลจากนั้นก็ระเบิดออกมาเป็นพลุขนาดใหญ่สร้างความเสียหายมากมาย ระยะสูงสุดนั้นสูงกว่าระดับที่ผู้เล่นสามารถทำได้โดยบังคับให้ผู้เล่นมีส่วนร่วมในระยะสั้นซึ่งเป็นข้อได้เปรียบสำหรับหน่วย NPC ประเภทอื่นเนื่องจากเอฟเฟกต์ของปืนลูกซอง (กระสุนกลุ่มในโซนเล็ก ๆ )
BulletML นั้นใช้งานได้ง่ายโดยทั่วไปและสามารถทำสิ่งมหัศจรรย์ได้ สัญลักษณ์แสดงหัวข้อย่อยสามารถเปลี่ยนทิศทางเปลี่ยนความเร็ววางไข่รูปแบบอื่น ๆ ตายก่อนรวบรวมคำสั่งซ้ำในวงวนใช้ความล่าช้าเปลี่ยนภาพกระสุนสไปรต์ติดตามผู้ปกครองของพวกเขา (หรือไม่) ... และอะไรก็ตามที่คุณไม่สนับสนุนเขียนลงไป
ฉันขอแนะนำอย่างแน่นอนหากคุณกำลังเล่นเกมยิงปืนร้ายแรง คุณยังคงต้องคิดคำนวณพิกัดเพื่อให้ได้รูปร่างที่ต้องการตามที่ Charanor พูดถึงในคำตอบของเขา แต่เครื่องมือกระสุนอย่าง 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);
            }
        }
    }
}