정사각형, 삼각형 등과 같은 모양을 형성하는 일련의 확장 된 글 머리 기호 패턴을 만들고 싶습니다. 다음 비디오에서 별을 모을 때 총알이 확장 스타 :
정사각형, 삼각형 등과 같은 모양을 형성하는 일련의 확장 된 글 머리 기호 패턴을 만들고 싶습니다. 다음 비디오에서 별을 모을 때 총알이 확장 스타 :
답변:
가장 쉬운 방법은 먼저 모양을 디자인 한 다음 입자의 움직임을 계산하는 것입니다. 이 답변에서 나는 사각형을 구성 할 것이지만 이것은 모든 모양에 적용됩니다.
원점을 기준으로 상대 위치로 모양을 디자인하여 시작하십시오.
이제 모양이 어떻게 확장되는지 계산해야합니다. 이를 위해 우리 의 위치에서 위치를 빼고 벡터 를 정규화 하여 단순히에서 가리키는 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 이라는이 프로젝트 가 있습니다. 거의 확실하게 코드를 자신의 언어로 이식해야하지만 실제로 놀라운 일을 할 수 있습니다.
예를 들어, 이 보스 는 Unity3D 용 BulletML의 확장 된 (강하게 수정 된) 확장에서 이루어졌습니다 (해당 패턴의 저자는 비디오와 불행이 미친 것뿐만 아니라 1 도 올랐습니다 ). 그것은 적의 가장 어려운 변형이며 BulletML이 아주 잘 할 수있는 것을 보여줍니다 (그리고 Wallmaster 와 같이 Misery의 다른 보스도 확인하십시오 ).
또는이 예제를 보여줄 수 있습니다.이 모드는 친숙하지 않고 단일 문자 AZ 변수 만 사용하는 이전 버전의 시스템을 사용하여 The Last Federation 확장 작업 중에 작성한 패턴입니다 .
그 고리를 만드는 녹색 총알은 고속으로 회전하는 부모 총알에서 생성되지만 스스로 움직이지 않습니다. 그들은 큰 피해를 입히고 플레이어를 더 먼 거리에 유지하여 무기를 낮추고 모바일 방어자가 플레이어를 괴롭히는 것을 허용합니다 (중간에 움직이지 않는 구조가 파괴되면 플레이어가 승리합니다).
이러한 거품을 만드는 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 초 동안 녹색 "곡선 막대"샷을 생성합니다. 데스 폰닝. 내가 생략 한 파란색과 노란색 샷은 훨씬 더 복잡하기 때문에.
확장에서 다른 패턴 ( 포병 포탄 ) 중 하나 는 실제로 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);
}
}
}
}