ฉันต้องการสร้างชุดของรูปแบบสัญลักษณ์แสดงหัวข้อย่อยที่มีรูปร่างเช่นสี่เหลี่ยมจตุรัสสามเหลี่ยมเป็นต้นตัวอย่างของสิ่งที่ฉันหลังจากสามารถเห็นได้ในวิดีโอต่อไปนี้ซึ่งเมื่อดวงดาวถูกรวบรวมกระสุนระเบิดในรูปของ ดาวฤกษ์ที่กำลังขยายตัว:
ฉันต้องการสร้างชุดของรูปแบบสัญลักษณ์แสดงหัวข้อย่อยที่มีรูปร่างเช่นสี่เหลี่ยมจตุรัสสามเหลี่ยมเป็นต้นตัวอย่างของสิ่งที่ฉันหลังจากสามารถเห็นได้ในวิดีโอต่อไปนี้ซึ่งเมื่อดวงดาวถูกรวบรวมกระสุนระเบิดในรูปของ ดาวฤกษ์ที่กำลังขยายตัว:
คำตอบ:
วิธีที่ง่ายที่สุดในการทำเช่นนี้คือการออกแบบรูปร่างก่อนแล้วคำนวณการเคลื่อนที่ของอนุภาค ในคำตอบนี้ฉันจะสร้างสี่เหลี่ยม แต่สิ่งนี้ใช้ได้กับทุกรูปร่าง
เริ่มต้นด้วยการออกแบบรูปร่างของคุณเป็นตำแหน่งสัมพัทธ์รอบจุดกำเนิดบางจุด
ตอนนี้คุณต้องคำนวณว่ารูปร่างจะขยายได้อย่างไร ในการทำเช่นนี้เราเพียงคำนวณเวกเตอร์ที่ชี้จาก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);
}
}
}
}