예전부터 의문을 가지고있던 질문입니다
글쓴이: zooloo / 작성시간: 목, 2017/03/16 - 4:21오후
스타크래프트를 예를들면
일꾼하나를 다른곳에 보내면 일꾼이 그쪽으로 이동합니다
다른유닛을 아무곳에나 보내면 그 역시도 이동시킨곳으로 이동합니다
순간이동하는게 아니라 점진적으로 이동합니다
동시에 다른유닛을 또 다른곳에 보내면 아까보낸 유닛이랑 또 별개로 이동합니다
파이썬의 터틀그래픽같은경우도 즉시 그려지는게 아니라 선이 점점 길어지면서
그려지는데 이런것들이 프로그래밍적으로 어떻게 구현하는건지 정말 궁굼합니다
제가 생각해본건 유닉별로 thread를 각각 만들고 주기적으로 sleep()를 호출하면
가능할거 같긴 하지만 자원을 너무 비효율적으로 사용하는것 같고 코드역시 어마무시하게
복잡해 질것 같습니다
뭐로 뭘 어떻게 하면 저런걸 만들수 있는 건가요?
Forums:
혹시 이런 방법은 아닐까요?
혹시 이런 방법은 아닐까요?
각 유닛의 좌표값이 담겨있는 배열이 있고 그것만 계속 갱신해서 그려주는 방식으로 통합관리?
배열이든 리스트든 값을 갱신할때 딜레이를 어떻게
배열이든 리스트든 값을 갱신할때 딜레이를 어떻게 줘야할까요? 딜레이없이 그냥 갱신하면 순간이동이랑 똑같아질텐데요..
이동거리 = 속도 * 시간
이동거리 = 속도 * 시간
아시는분 없나요?
아시는분 없나요?
이미 댓글들에 답이 나왔는데요? 약간 더 부연
이미 댓글들에 답이 나왔는데요? 약간 더 부연 설명하자면 버퍼(도화지라고 생각하세요)에 배경과 유닛들을 그리고 화면에 출력합니다. 잠시 기다렸다가 다시 각 유닛들의 위치를 속도에 맞춰서 계산해서 버퍼에 그리고 화면에 출력합니다. 이것을 반복하는 것이지요. 유닛별로 쓰레드를 사용할 이유는 전혀 없습니다. 그냥 셀 애니메이션과 다를 것이 전혀 없지요.
"잠시 기다렸다가 다시" 여기에서
"잠시 기다렸다가 다시" 여기에서
유닛별로 잠시 기다리는걸 어떻게 구현해야 할까요?
제가 궁굼한게 다른게 아니라 어떤식으로 딜레이를 줘야 하느냐입니다
대체 답이 어디에 나와있다는말인가요
유닛이 별개로 행동하는 것이 아니고, 전체 아이템들
유닛이 별개로 행동하는 것이 아니고, 전체 아이템들 중의 일부로 행동하므로 sleep 같은 것을 쓰면 안 되겠죠. 기다리는 것은 그냥 제 자리에 계속 그려주면 되요.
각 유닛에 대해 thread를 쓸 수도 있지만, 어차피 그려지는 시점에서 모든 신을 다시 갱신해서 그려야 하므로 인스턴스로 처리하는 것이 좋을 것입니다.
음 ..
그냥 간단히 고전적인 방식으로 풀어 보자면..
A 는 (x, y) 에서 (x, y+30) 으로 이동하고, B 는 (x+30, y) 에서 (x, y) 로 이동하고..
속도는 초속 30 pixel 에.. 초당 30 프레임으로 화면을 찍어 낸다고 가정해 보면..
1/30 초 후의 위치는 A(x, y+1), B(x+29, y) 가 되겠죠.
그 다음 1/30 초 후의 위치는 A(x, y+2), B(x+28, y) 가 되겠죠.
한 쪽에서는 매 1/30 초 후에 있을 모든 유닛의 좌표를 계산해서 버퍼에 그리고..
다른 쪽에서 매 1/30 초 마다, 버퍼의 내용을 그대로 화면에 뿌린다면..
자연스럽게 A 와 B 가 원하는 목적지로 이동하는 것처럼 보일겁니다.
매 정해진 시간 간격마다 뭔가를 하는 거라면 타이머 같은 거 쓰면 되겠구요.
되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』
일반적으로는 FPS가 고정되어 있지 않고 가능한 한
일반적으로는 FPS가 고정되어 있지 않고 가능한 한 많은 프레임을 그립니다.
저 사양에서는 초 당 30프레임이 안 나올 수도 있습니다.
따라서 이전 프레임과의 시간 차이를 이용하여 계산을 하게 됩니다.
답변.
질문자 분이 그래픽 환경에서 개발을 해보지 않은 사람임을 가정하고 설명하는 점 양해바랍니다.
아마 다른 분들도 이걸 다 설명하는 게 지나치게 길어서 그냥 넘기신 것 같아요.
보통 프로그래밍 언어 입문서를 뗄 때쯤엔 언어의 문법은 어느 정도 알지만,
실제로 그래픽 환경에서 이것이 어떻게 적용되는지에 대한 개념은 없는 경우가 많습니다.
간단하게 설명하면, 무한히 루프를 도는 겁니다. 기본은 다음 방식입니다.
이 꼴이 게임에 적용되면 이런 모양이 됩니다.
1. 유니티 개발자라 C# 기준으로 작성했어요.
2. 별도로 정의되지 않은 메서드는 알아서 잘 정의되어있다고 가정하세요.
만약 특정 개체의 속도를 바꾸는 ChangeVelocity() 메서드를 작성하고 싶다면, 이렇게 하면 됩니다.
키를 누를 때마다 X, Y축 속도가 1씩 증가하는 개체 StrangeUnit이 있다면 이렇게 하겠죠.
이것이 어떻게 돌아가는지를 설명하면 이렇습니다.
1. GameManager가 루프를 돌고 있습니다.
2. Update의 루프가 수행되면서, GameManager에 등록된 GameObject의 Update()가 모두 호출됩니다.
3. Draw의 루프가 수행되면서, GameManager에 등록된 GameObject의 Draw()가 모두 호출됩니다.
4. 1로 복귀
따라서 우리는 GameObject의 Update 메서드만 오버라이드해주면,
StrangeUnit의 위치 이동은 자동으로 이루어지는 것입니다.
당연한 거라고 생각하실 수가 있는데 전혀 그렇지 않아요. 이건 아주 정교한 설계 패턴입니다.
질문에 나온, "잠깐 기다렸다가 다시"는 결국 이렇게 구현됩니다.
한 번에 이해하긴 힘들 거라고 생각하고, Unity 등의 게임 개발 도구를 직접 익히는 것을 추천합니다.
저는 이렇게 생각했습니다.
답변 추가.
중요한 부분을 말하지 않아서 정리합니다.
유닛이 병렬적으로 움직여야 한다고 해서 각 유닛 별로 thread를 생성하지 않습니다. 그냥 다음을 반복하면 됩니다.
저는 이렇게 생각했습니다.
고맙습니다.
고맙습니다.
덕분에 어떤방식으로 만드는지 이해가 되었습니다.
파이썬에 관련하여
파이썬으로 그래픽쪽을 다뤄본적이 없기 때문에, 거북이라 말씀하신걸 찾아 보니
파이썬 거북이 그래픽 (Python Turtle Graphics) 모듈을 말씀하시는거라면, 기본적으로
질문자께서 GDI/GDI+ 나 BITMAP을 화면에 뿌리는 방식같은 것을 모르시는거라 판단이 되네요.
해당 모듈은 그저 API에 따라서 이동해서 자체적 Thread 처리로 이미지를 그리는 것 같군요.
쉽게 말해서 그래픽 API들이 A를 (x,y) 지점 까지 1000ms 로 이동해가 아니라
A를 x,y 지점으로 1 pixel/s 로 이동을 원하는 경우
1. 화면을 뿌릴 메모리에 이미지를 지운다.
2. 메모리에 배경을 그린다.
3. 현재 시점의 A의 좌표를 계산한다.(큰 프로그램일 경우 이부분은 다른 부분에서 처리하겠죠. 그럴땐 그저 현재 있어야될 위치만 읽어오면 되겠죠)
4. 3에서 계사된 A의 좌표에 A의 오브젝트를 그린다.
5. 나머지 모든 오브젝트를 그린다.
6. 다 그린 이미지를 화면에 뿌린다.
이런 순서로 진행됩니다. 또한 모든 이미지를 메모리 한곳에다가 그린다음 화면을 갱신시키는것을
더블버퍼링이라 합니다.
질문자께서 화면을 그리는 방법을 더 잘알고 싶다면 아마도 파이썬은 그것에 약한 언어일 수도 있다고 생각이 됩니다.
C# 까진 C++ GDI/GDI+를 랩핑하여 사용하는듯 해서 성능이 크게 나쁘지 않지만, 파이썬으로는 GUI도 만들어 본적이 없기에, 해당 언어에 대해서 자세한 설명을 해드리긴 어렵겠군요.
아무튼 질문이 해결되셨다면, 다행이시고 만약에 이해가 안되는 부분이 있다면 리플을 달아 주시거나 직접 다른 언어들이 어떻게 화면을 그리는지 한번 찾아보시면 될 것 같군요.
댓글 달기