파티클로 부드러운 가장자리 영역을 구현하는 방법


13

내 게임은 Phaser를 사용하여 만들었지 만 질문 자체는 엔진에 구애받지 않습니다.

내 게임에는 플레이어 캐릭터가 움직일 수 있고 영향을받을 수있는 다각형 영역이 있습니다. 예를 들어 얼음, 불, 독 등 '이 영역의 그래픽 요소는 색상으로 채워진 다각형 영역 자체와 적합한 유형의 입자 (이 예에서는 얼음 조각)입니다. 이것이 내가 현재 이것을 구현하는 방법입니다-입자 패턴으로 타일 스프라이트를 덮는 다각형 마스크 :

여기에 이미지 설명을 입력하십시오

딱딱한 가장자리가 나빠 보입니다. 두 가지 작업을 수행하여 개선하고 싶습니다. 1. 다각형 채우기 영역이 부드러운 가장자리를 갖도록 만들고 배경에 혼합합니다. 2. 일부 샤드가 다각형 영역 밖으로 나오도록하여 중간에서 잘리지 않고 직선이 없도록합니다.

예를 들어 (mockup) :

여기에 이미지 설명을 입력하십시오

다각형을 흐리게 처리하면 1을 얻을 수 있다고 생각하지만 2를 사용하는 방법을 잘 모르겠습니다.

이것을 어떻게 구현하겠습니까?


2
대단해 보인다. 게임 으로 연결해 주 시겠습니까? :)
ashes999

@GameAlchemist 여기 타일 이미지가 있습니다 : i.imgur.com/y54CeQ9.png
OpherV

@ ashes999 아직 진행중인 작업입니다. 일단 링크가 올랐다면 여기에 링크를 올릴 것입니다 :)
OpherV

흰색 물체가있는 투명한 PNG입니다. 브라우저에서 사진을 열 때와 같이 흰색 배경으로 볼 경우 아무것도 보이지 않습니다.
OpherV

@OpherV가 좋을 것입니다. 질문을 수정하고 링크를 게시하십시오.이 사이트에서 가장 많이 주제를 다루는 방법 일 것입니다. :)
ashes999

답변:


2

1. 모형에 가까운 것을 원한다면 입자를 사용합니다 (완전히 날려 진 입자 시스템 일 필요는 없습니다).

RenderTexture에서 입자를 다각형 형태로 렌더링합니다. 입자에 첨가제 혼합을 사용하십시오. 다각형 내부의 입자는 서로 부드럽게 혼합되며 외부의 입자는 원하는 부드러운 가장자리를 제공합니다. (이 유튜브 비디오에서 효과의 예를 볼 수 있습니다 : Additive Particles Video 이제 RenderTexture를 기본 화면에 렌더링하면 완료됩니다. RenderTexture는 입자가 배경과 혼합되지 않도록해야합니다.

삼각형을 입자 질감에 직접 넣고 어떻게 작동하는지 확인할 수 있습니다. 그렇지 않으면 "입자 수프"위에 별도의 레이어로 렌더링하십시오.

업데이트 된 jsfiddle에서 다음과 같은 빠른 모형을 만들었습니다. 여기데모 에서 업데이트 된 데모를 찾을 수 있습니다.

2. 각 입자에는 속도와 원점이 있습니다. 플레이어가 다각형에 닿으면 플레이어 속도에 비례하여 각 입자 속도가 변경됩니다. 입자가 플레이어에서 멀어 질수록 플레이어 속도의 영향을 덜받습니다.

입자 속도를 계산하는 공식은 다음과 같습니다.

//player.velocity and particle.velocity are vectors 
//k is a factor to enhance or weaken the influence of players velocity
var distanceToPlayer = (player.position - particle.position).length();
particle.velocity = particle.velocity + ((k * player.velocity) + particle.velocity) * (1/distanceToPlayer);

입자의 위치를 ​​계산하려면 이것을 업데이트 방법에 넣으십시오.

var speedY = -(springConstant * (particle.position.y - particle.origin.y)) - (dampingFactor * particle.velocity.y);
var speedX = -(springConstant * (particle.position.x - particle.origin.x)) - (dampingFactor * particle.velocity.x);

particle.position.y = particle.position.y + speedY;
particle.position.x = particle.position.x + speedX;

particle.velocity.x = particle.velocity.x + speedX;
particle.velocity.y = particle.velocity.y + speedY;

이것은 플레이어가 유체를 교반 할 때 각 입자가 원점을 중심으로 스윙하는 "유체"를 제공해야합니다. 스프링 상수는 파티클이 원점에서 얼마나 멀리 스윙하는지와 dampingFactor가 파티클이 얼마나 빨리 정지되는지를 변경합니다. 게임에서 사용하는 1d 시뮬레이션의 수정 된 버전이므로 코드를 조정해야 할 수도 있습니다.

이제 데모로 : 데모 유체가 원하는대로 동작 할 때까지 상단에있는 3 개의 상수를 조정하십시오.


# 1을 해결하는 것은 정말 흥미로운 아이디어입니다! 나는 그것을 좋아한다. 삼각형 이동 / 간격 구현을 어떻게 제안 하시겠습니까?
OpherV

1
질문 # 2에 답하기 위해 원본 게시물을 편집했습니다.
zilluss

입자 효과의 작은 데모를 추가했습니다. 약간의 조정만으로 원하는 효과를 얻을 수 있다고 생각합니다.
zilluss

나는 당신의 솔루션을 사용하여 끝내고, 내가 달성하고자했던 효과에 가장 가깝습니다. 감사! 하나의 질문-어떻게 당신의 예제에서 탄력을 어떻게 고정시킬 수 있습니까? 그래서 실제로 약간의 움직임으로 인해 입자가 그렇게 큰 거리를 뛰어 넘지 않을 것입니까?
OpherV

dampingFactor와 springConstant로 놀 수 있습니다. 댐핑이 높으면 입자가 더 빨리 정지됩니다. 스프링 상수가 낮을수록 입자의 속도가 느려집니다. 불행하게도, 두 값 모두 입자 수프가 더 점성을 느끼게한다. 따라서 플레이어가 파티클에 닿을 때 플레이어가 파티클에 추가하는 최대 속도를 다음과 같이 고정 할 수 있습니다. particle.velocity.x = clamp (maxVelocity, -maxVelocity, particle.velocity.x + ((playerInfluenceFactor * deltaVelocityX ) + particle.velocity.x) * (1 / distanceToPlayer)); 클램프에 대한 참조 : stackoverflow.com/a/11409944
zilluss

4

이 두 가지 점에 대한 나의 생각 :

  1. 쉐이더 블러를 사용할 수 있지만 비용이 많이 듭니다. 대신, "흐림"을 시뮬레이션하기 위해 중앙의 반투명에서 가장자리의 투명으로 희미 해지는 삼각형의 경계를 추가로 그렸습니다. 나는 내 게임에서 그것을했고 꽤 잘 작동합니다. 내 게임에서 무지개 같은 승압기의 두 스크린 샷이 있습니다.

    여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오

    바깥 쪽 테두리에는 그라디언트가 있습니다. 내 상황에서 테두리는 내부와 같은 불투명도로 시작하지 않지만 이러한 불투명도를 동일하게 설정하면 멋진 페이드가 생깁니다.

  2. 파티클 시스템을 프로그래밍하고 파티클이 다각형을 따르도록합니다. 이렇게하면 가장자리에서 어떤 일이 발생할지 걱정할 필요가 없습니다. 파티클 시스템의 역학은 파티클이 다각형 내부에 고르게 분포되어 있는지 확인합니다. 가장 가까운 입자가 서로 밀리도록 시도 할 수 있지만 많은 "질량"로 만들어서 관성이 있고 부드러워 보입니다. 이 일을 빨리하기 위해서는 몇 가지 가능성이 있지만, 큰 문제는 서로를 밀어 붙이는 시간의 복잡성입니다. 각 파티클이 다른 파티클을 밀게하면 O (n ^ 2)가되는데, 예를 들어 시스템에 100 개의 파티클이 있다면 좋지 않습니다. 이것을 최적화 할 수있는 방법에 대한 좋은 설명은 PixelJunk의 프레젠테이션입니다.http://fumufumu.q-games.com/gdc2010/shooterGDC.pdf

    보다 간단한 방법은 입자 시스템을 구성 할 때 각 입자를 3 개 또는 4 개의 다른 입자에 연결하는 것입니다. 이제 모든 파티클은 연결된 네 개의 다른 파티클 만 밀어야합니다. 그러나이 방법은 파티클 시스템의 난기류를 불가능하게합니다. 그러나 현재 상황이 정적 텍스처를 사용하기 때문에 이것은 문제가되지 않는 것 같습니다. 이 접근법은 O (n)이 될 것입니다.


감사! 1. 이것을 시각화하는 데 어려움을 겪고 있습니다. 게임에서 어떻게 보이는지에 대한 모형을 게시 할 수 있습니까? 2. 흥미 롭다!
그것에

이미지 주셔서 감사합니다. 튜브 또는 선 기반 모양에서 어떻게 작동하는지 볼 수 있지만 다각형에서는 어떻게 작동합니까? 각면에서 투사 된 삼각형의 그라디언트가 잘 정렬되지 않습니까?
OpherV

잘 맞도록 만드세요. 그것이 아이디어입니다. 여기에는 수학 및 계산 교차점 등이 포함됩니다. 경계를 세분화하고 매끄럽게 만들 수도 있습니다. 가능성의 톤.
Martijn Courteaux

3

게시물을 읽을 때 내가 가진 아이디어는 다음과 같습니다.
• 해당 지역에 사용할 타일 세트를 만듭니다.
• 타일 해상도에서 작은 임시 캔버스에 영역 다각형을 렌더링합니다 (예 : 타일이 16X16 인 경우 (16X, 16X) 낮은 해상도로 렌더링).
• 임시 캔버스를 사용하여 기본 캔버스에 타일을 렌더링할지 여부를 결정합니다.
저해상도 캔버스에 점이 설정되어 있으면 기본 캔버스 에 '임의'타일을 그립니다. 점이 설정 점의 인접 항목 인 경우 기본 캔버스에서 불투명도를 낮추고 (전환을 위해) '랜덤'타일을 그립니다.

해상도를 낮추면 블록 효과가 생길 까봐 두려웠지만 20X20 타일에서도 상당히 좋아 보입니다.

여기에 이미지 설명을 입력하십시오

이를위한 단계는 다음과 같습니다. 다각형을 가져옵니다.
여기에 이미지 설명을 입력하십시오

타일 ​​해상도에서 다각형을 여기에 이미지 설명을 입력하십시오그립니다 : (!! 예, 쇼핑몰 빨간색 일입니다).

그런 다음 저해상도 캔버스의 imageData를 사용하여 타일 또는 노트를 그릴 지 결정합니다.
저해상도 캔버스에 픽셀이 설정되어 있으면 타일을 그려야합니다. '무작위'타일 색인을 선택하여 그릴 타일을 선택합니다. 임의의 인덱스는 주어진 영역 / 타일에 대해 항상 동일해야합니다.
점이 비어 있지만 채워진 점 옆에 있으면 반투명도의 타일을 그립니다.

여기에 이미지 설명을 입력하십시오

타일을 그려 봅시다 :

여기에 이미지 설명을 입력하십시오

다각형의 경우 다각형을 여러 번 그려 다각형을 축소하고 각 그리기에서 불투명도를 높입니다 (globalCompositeOperation 'lighter'도 사용할 수 있음).

여기에 이미지 설명을 입력하십시오

모든 것을 추가하면 다음과 같은 결과가 나타납니다.

여기에 이미지 설명을 입력하십시오

바이올린은 여기 있습니다 :

http://jsfiddle.net/gamealchemist/T7b4Y/

이것이 도움이되는지 알려주십시오.


솔루션을 정교하게 작성하고 코드를 제공해 주셔서 감사합니다! "그런 다음 저해상도 캔버스의 imageData를 사용하여 타일 또는 노트를 그릴 지 여부를 결정하십시오"는 무슨 뜻입니까? 작은 이미지 데이터를 어떻게 사용하여 큰 이미지를 그릴 위치 / 방법을 결정합니까? 그리고이 방법을 사용하여 삼각형의 겹침을 피할 수 있으므로 모형과 비슷한 간격을 유지할 수 있습니까?
OpherV

완전한 부울 테스트라는 것을 의미합니다.이 타일을 채워야합니까? , true 또는 false는 imageData [(x + y * width) * 4]! = 0에 대한 저해상도 테스트에 의해 제공됩니다. 즉, == '저는 하단 캔버스에 무언가를 그렸습니까? 그 타일 장소? '. 그렇다면 예를 들어 정교한 소수로 채워진 수식 (getRandomNumber)을 사용하여 (x, y)에서 항상 주어진 영역 + (x, y)에 대해 동일한 숫자를 제공하는 '랜덤'타일 인덱스로 이동하십시오. 다각형을 올바르게 정의하면 두 번째 질문을 얻지 못하면 어떻게 겹칠 수 있는지 알 수 없습니다.
GameAlchemist

1

그냥 아이디어 :

타일에서 "피스"는 최대 약 80 픽셀입니다. 두 가지 영역을 만드는 것이 좋습니다. 원래 다각형을 그리고 각 가장자리에서 약 80 픽셀의 모형을 만듭니다. 그런 다음 타일을 더 큰 다각형으로 그립니다.

그런 다음 내부 다각형 외부에 픽셀이 있고 내부 다각형과 교차하지 않는 모든 "조각"을 투명하게 채울 수 있습니다.

이것은 매우 높은 수준이지만 나는 당신과 그것을 공유 할 것이라고 생각했습니다. 여기서 결정해야 할 세부 사항이 많이 있습니다.

설명하기위한 조잡한 이미지 :

여기에 이미지 설명을 입력하십시오

내부 검은 색 다각형이 원본 인 경우 모든 다각형을 빨간색 점으로 지 웁니다.


내부 다각형과 타일 이미지에 포함 된 조각의 교차점을 어떻게 확인합니까?
OpherV

@OpherV 음, 점 X가 다각형에 있는지 확인할 수 있습니까? 외부 다각형의 모든 픽셀을 반복하고 각 흰색 픽셀에 대해 모든 픽셀을 플러드 검사하고 내부 / 외부에 있는지 확인하십시오. 이것은 특히 효율적으로 들리지 않지만, 일단 당신이 무언가를 최적화하는 방법을 생각할 수 있습니까?
user46560

그것은 CPU에서 수행되는 사후 처리입니다. 그 자체로는 최적화 할 수 없습니다. 내부 다각형과 외부가 삼각형 스트립으로 연결되어 있으면 아이디어가 잘 작동 할 수 있습니다. OP는 정점 속성 정보를 추가하고 각 정점을 내부 또는 외부로 태그 할 수 있습니다. 그런 다음 정점 셰이더에서 불투명도 / 알파를 덜 투명한 값에서 완전한 불투명 값으로 선형 보간 할 수 있습니다.
teodron

@teodron 이것이 대답을하려고 한 요점입니다. 높은 수준의 아이디어이며 실제로 게임 개발자는 아닙니다. 방금 아이디어가있었습니다.
user46560

@ user46560 예, 그러나 이런 식으로 당신은 어떤 다각형간에 픽셀을 계산할 필요가 없습니다. GPU 나 CPU에서도 마찬가지입니다. 당신이 말하는대로 게임 개발 방법에 익숙하지 않기 때문에, 당신은 당신의 아이디어에 +1을받을 가치가 있습니다 :).
teodron
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.