총알 패턴 모양을 확장하려면 어떻게해야합니까?


12

정사각형, 삼각형 등과 같은 모양을 형성하는 일련의 확장 된 글 머리 기호 패턴을 만들고 싶습니다. 다음 비디오에서 별을 모을 때 총알이 확장 스타 :

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


2
오 좋은 질문입니다. 구체적인 답변이 없지만 스프라이트 또는 간단한 모양의 2D 객체를 사용하고 가장자리를 따라 총알을 생성 할 수 있다고 상상합니다. 물론, 그 속임수는 모양과 바깥 쪽 모두에 적절한 속도를 제공하고 스크롤러를 만드는 경우 화면과 함께 앞으로 나아갈 수 있도록합니다. 여기에 대한 답변을 보는 데 매우 관심이 있습니다.
Jesse Williams

1
이러한 종류의 효과에 대한 일반적인 이름은 "입자 효과"입니다. 그 검색어는 당신을 도울 수 있습니다!
Cort Ammon

1
고마워, 나는 XNA와 libGDX에서 파티클 이펙트를 꽤 오랫동안 사용해 왔지만,이 특정 스타일의 이펙트를 어떻게 다룰 지 확신하지 못했습니다.
lepton

1
이것에 대한 또 다른 대답이 있습니다. 엄청나게 강력하지만 프로그램하기에는 매우 복잡합니다. 그리고 입력하려면 실제 키보드가 필요합니다. 나중에 설명하기 위해 이것을 즐겨 찾기에 추가하십시오.
Draco18s는 더 이상

흥미 롭습니다. 저는 이런 식으로 파티클 이펙트를 사용한 적이 없었습니다. 아니면 Unity의 묘사 일뿐입니다. 입자 효과에는 충돌체가있을 수 있지만 (따라서 객체가 손상됨) 단순히 객체 사본을 인스턴스화하는 것보다 훨씬 많은 오버 헤드가 발생하는 것처럼 보입니다.
Jesse Williams

답변:


11

가장 쉬운 방법은 먼저 모양을 디자인 한 다음 입자의 움직임을 계산하는 것입니다. 이 답변에서 나는 사각형을 구성 할 것이지만 이것은 모든 모양에 적용됩니다.

원점을 기준으로 상대 위치로 모양을 디자인하여 시작하십시오.

광장

이제 모양이 어떻게 확장되는지 계산해야합니다. 이를 위해 우리 의 위치에서 위치를 빼고 벡터 를 정규화 하여 단순히에서 가리키는 origin모든 벡터를 계산합니다 . .pointoriginpointvector = 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 단위 씩 바깥쪽으로 이동합니다.


노트

  • 여기에서 간단한 벡터 수학을 읽을 수 있습니다 .
  • 모든 위치가 일부 원점을 기준으로하는 한 위치는 무엇이든 될 수 있습니다.
  • 균일 한 움직임을 보장하기 위해 모든 점의 속도는 동일해야하지만 속도가 다르면 흥미로운 결과를 얻을 수 있습니다.
  • 움직임이 보이지 않으면 원점을 확인해야합니다. 모양의 정확한 중앙에 있지 않으면 모양이 이상한 방식으로 확장 될 수 있습니다.

9
각 입자의 속도는 첫 번째 프레임의 원점과의 거리에 비례해야합니다 (프레임 당 한 번만 계산 됨). 또는 단순히 방향 벡터를 정규화 할 수 없습니다. 이 작업을 수행하지 않으면 모양이 선형으로 확장되지 않고 원이되도록 이동합니다 (모든 속도가 동일한 경우)
Aaron

@Charanor 설명해 주셔서 감사합니다. 나는 실제로 대학에서 이산 수학을 공부했지만 지금은 꽤 오래되었습니다. 오늘 무언가를 시도하고 구현하려고합니다.
lepton

2

복잡한 입자 / 탄환 패턴을 만들기위한 마크 업 언어 인 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과 같은 불릿 엔진은 훨씬 더 많은 유연성을 제공하여 알아내는 것보다 새로운 패턴을 디자인하는 데 더 많은 시간을 할애 할 수 있습니다 코딩 방법

  1. Misery가 얼마나 좋은지 설명하기 위해이 비디오는 장비 , 소모품 및 기본 완두콩 사수 와 같은 시작 장비를 갖춘 바닥 보스에 대한 비디오 입니다. 그리고 xe는 싸움의 연장 된 특성에도 불구하고 단 한 번의 타격 만받습니다. 좋아, Centrifuge에 9 번의 타격을가한다. (플레이어가 업그레이드 한 후 3 층까지는 나타나지 않지만, 최소한 2 배의 데미지를 입힌다).

고맙게도, BulletML이 잠시 동안 있었기 때문에 모호하게 알고 있었지만 때로는 단순한 총알에 덤벼 들며 총알이 저격수가 아닙니다.
lepton

@lepton 완전히 이해할 수 있습니다. 그것은 당신이 내리기로 한 결정이지만, 다른 사람에게는 "최고의"답변이 될 수 있습니다. 나는 TLF에서 일하고 나 자신의 저격수를 만들기 시작한 후에 얼마나 강력하고 사용하기 쉽기 때문에 그것을 사용하고 싶다는 것을 알고 있습니다. :)
Draco18s는 더 이상 SE

1

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

예를 들어 주셔서 감사합니다. 오늘 오후에 확인하여 실행할 수 있는지 확인하겠습니다.
lepton
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.