📆 2023.01.19 ~ 2023.01.28
⬆️ w: 전진
⬅️ A: 좌로 이동
⬇️ S: 후진
➡️ D: 우로 이동
🖱️ Mouse: 시점 변환
⌨️ Keyboard 방향키 좌우: 시점 변환
학부 강좌에 그래픽스 강좌가 없어서 강의를 따라하며 간략한 게임을 만들어보고
3D 프로그래밍에 대한 기초적인 개념을 파악한다.
1️⃣ 3D Game을 Java로 만들어본다.
2️⃣ 3D Programming에 대한 기본적인 개념을 알아보도록 한다.
3️⃣ 그래픽 렌더링에 대한 대략적인 이해를 할 수 있도록 한다.
1️⃣ 강의를 듣고 예제를 구현한다.
2️⃣ 주차별 강의에 대한 스터디 내용 정리와 후기를 남긴다.
✅ 3D Game Programming - Episode 1 - Window
Java Swing을 사용하기에 꽤나 익숙하게 시작할 수 있다.
(이전에 Swing을 써봐서 꽤 익숙한 내용이다.)
✅ 3D Game Programming - Episode 2 - Game Loop
게임 루프를 만들기 위해 thread를 응용한다. 별로 어려운 내용은 없다.
그냥 thread start하는 내용들이 있다.
✅ 3D Game Programming - Episode 3 - Arrays
pixel value를 Array안에 저장하겠다는 내용이다.
✅ 3D Game Programming - Episode 4 - Drawing Pixels!
랜덤한 값의 pixel Array를 화면에 쏴준다. 이 부분에서 이전에 본 적 없는 API가 사용된다.
아래의 코드 조각들이 등장하는데 모르고 지나치기엔 꽤 중요한 부분이다.
픽셀 연산과는 상관없지만 직접 화면에 쏘는 바로 그 과정이 이 부분이다.
/*
BufferedImage img
pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData()
BufferStrategy
createBufferStrategy(3)
Graphics g = bs.getDrawGraphics();
g.drawImage(img, 0, 0, WIDTH, HEIGHT, null);
g.dispose();
bs.show();
*/
✅ 3D Game Programming - Episode 4.5 - How Rendering Works
렌더링과 관련된 간략한 설명이다.
✅ 3D Game Programming - Episode 5 - Playing with Pixels!
sin과 cos의 수학적인 기법을 사용하여 화면에 다양한 연출을 보여준다.
-> 참고로 출력문은 절대 연산과정에 삽입하지 말자. 속도가 지나치게 느려진다.
✅️ 3D Game Programming - Episode 6 - Performance Boosting
리팩토링하는 과정이다. 렌더링하지 않아도될 픽셀은 그냥 continue해도 된다.
그 외의 테크닉이 소개된다. 이건 다른 분야에서도 유용하게 써먹을 수 있는 내용이다.
for문을 더 적게 돌 수 있는 방법이 소개된다.
✅ 3D Game Programming - Episode 7 - FPS Counter
FPS Counter를 만드는 공식이 어떻게 되는지 이해가 가지 않을 수 있다.
특정 시간에 한해 렌더링이 일어나는 수를 측정하고 그 두 가지 수 사이의 계산이 진행된다.
아마 프레임 율에 관한 이해가 있어야지 이해되는 부분이라고 생각된다.
✅ 3D Game Programming - Episode 8 - Alpha Suppport and More
픽셀 연산에 관여되는 수를 바꿈으로써 다양한 연출이 가능하다.
✅ 3D Game Programming - Episode 9 - Beginning 3D
3D에 대한 가장 기본적인 구현이 나온다. 정면에 보이는 간단한 바닥과 천장을 보여준다.
나오는 공식이 이해가 안될텐데 관련된 설명 중 가장 근접한 설명은 아래 설명인 것 같다.
사실 공식을 봐도 모르겠고 설명도 잘 이해가 안간다. 아마 실제 3D 좌표계와 화면 상의
차이를 공식으로 연결짓는 내용인데 난이도가 꽤 있다.
/*
Comment below:
From what I can tell, he basically derived the rendering mechanism from the following perspective equations,
sx = x / z tan(fov / 2)
sy = y / z tan(fov / 2)
Where sx, sy are normalized screen coords and x, y, z are 3d space coords
You can exclude the tan to get an fov of 90 degrees
Then since already know sx, sy and y(the floor/ceiling distance/height) you loop through the y coordinate of the screen and for each row solve for z:
z = 1 / sy * y
Then you have a z distance for every horizontal row of pixels
Next, for every horizontal row you loop through all the pixels based on the distance of the row from the camera,
x = sx * z
Now you have top down 2d coords x and z which you can directly translate to texture coordinates
Am i on the right track? I'm very tired
*/
✅ 3D Game Programming - Episode 10 - Floors and Animation
floor 생성에 관한 내용이다.
✅ 3D Game Programming - Episode 11 - Rotation
floor 상에서 대각선, 전진, 후진, 우회전, 좌회전 등을 가능하게함. 이때 rotation
의 경우 회전 동작인데 회전을 하려면 원을 그릴 수 있어야함. 원을 그리기 위해서 sin과 cos을 활용한다.
✅ 3D Game Programming - Episode 12 - User Input
우리가 게임을 조작하는 것처럼 W A S D키를 사용해서 앞,뒤,좌,우 움직임을 실행할 수 있도록 한다.
Key Event를 받아서 해당 키에 대한 조작을 실행한다.
✅ 3D Game Programming - Episode 13 - Render Distance Limiter!
floor에서 먼 거리까지 렌더링을 하기 때문에 보기 좋지 않은 부분이 있다.
이걸 gradient까지 넣어서 자연스럽게 거리표현까지 하면서도 먼 거리를 표현할 수 있을까?
그에 대해 다룬다.
✅ 3D Game Programming - Episode 14 - Basic Mouse Movement
마우스 커서를 추가한다. 마우스 커서가 밖으로 나가면 더 이상 회전하지 않는 이슈가 있다.
해당 이슈는 이후 강좌에서 추가적으로 수정될 예정임. 마우스의 현재 위치를 알아낸 뒤 해당 위치가
다음 위치와 다른지, 더 큰지, 작은지를 비교해서 좌우로 회전할 방향을 정한다. 히전은 이전에 Episode 11의 rotation에서
다룬 기능을 그대로 사용한다.
✅ 3D Game Programming - Episode 15 - Textures + More!
텍스쳐 적용을 구현한다. 텍스쳐 이미지의 int array데이터를 얻어와서 그걸 pixels인 array에
넣어주면 된다.
이슈:
텍스쳐를 적용하기 위해서는 8비트x8비트 짜리 원하는 이미지를 생성하고 그 이미지의
경로를 지정해줘서 이미지를 읽어와야하는데 이때 사용하는 Texture.class.getResource(fileName)에 이슈가 있다.
java.lang.IllegalArgumentException: input == null! 이라는 Exception이 발생하는데 이건
경로를 제대로 지정해줘도 문제가 발생한다. 그래서 이 기능 대신에 FileInputStream을 사용해서 경로를 넘기면
제대로된 데이터를 얻을 수 있다. 아래 링크를 참조하면 된다.
해결방법:
https://stackoverflow.com/questions/15424834/java-lang-illegalargumentexception-input-null-when-using-imageio-read-to-lo
✅ 3D Game Programming - Episode 16 - Walking, Crouching, Sprinting + More
게임을 run하고나서 따로 클릭을 하지 않고도 게임창에 자동으로 Focus가 맞춰져있도록 수정함.
crouch모드에서는 즉 앉아서 걸을때는 걷기 속도를 감소시킨다.
✅ 3D Game Programming - Episode 16.5 - Exporting Runnable Jars
jar 파일 export 하는 내용
✅ 3D Game Programming - Episode 17 - Small Adjustments + Birthday!
코드 최적화 및 걷기 효과 수정
✅ 3D Game Programming - Episode 17.5 - Creating an Applet
web browser 에서 돌릴 수 있도록 applet으로 만들어보자.
applet은 JAR File로 export 하면 된다. runnable jar file이 아니라 그냥 JAR File이다.
.html파일에 applet 태그를 선언해주면 applet사용이 가능함.
✅ 3D Game Programming - Episode 18 - The Beginning of Walls
z 축에 근거한 벽 생성. z축 즉 깊이가 얕으면 화면과 가까운 벽 생성, 깊으면 화면과 멀리 떨어진 벽 생성.
✅ 3D Game Programming - Episode 18.1 - A Few More Things
리팩토링. Episode 18에서 wall을 생성하게 되면 wall에도 render distance가 적용되서 벽의 중간이 어둡게 보인다.
이걸 해결하기 위해 Screen class에서 렌더를 돌릴때 render distance 를 돌리고 난 이후에 벽 생성을 진행하는 방식으로 수정한다.
✅ 3D Game Programming - Episode 18.5 - Creating an EXE File in Java
jar파일을 EXE파일로 생성하기, Launch4j를 활용함.
✅ 3D Game Programming - Episode 19 - Rendering Walls
rotation에 따라 sreen에 생성한 wall도 자연스러운 방향으로 렌더될 수 있도록 수정.
✅ 3D Game Programming - Episode 20 - Continuing Walls, Fixing Bugs, and Managing Crashes
벽 생성을 하고 나서 벽을 보고 걷게 되면 벽에도 마찬가지로 걷기 효과가 적용된다.
그래서 벽이 위아래로 bounce하는 연출이 나온다. 벽 or object 걷기 효과가 적용되면 안되기 떄문에 이와 관련된
리팩토링을 진행한다.
✅ 3D Game Programming - Episode 21 - Texturing Walls, Fixing Clipping, and Fixing the Mouse
생성된 wall에 texture 를 입힌다. 텍스쳐를 하나의 이미지 파일로 간주하고 텍스쳐 하나하나는 해당 이미지에서
일종의 섹터로 구분해서 읽어들인다. 마인크래프트에서 텍스쳐를 관리하는 방식과 비슷한 방식이다.
✅ 3D Game Programming - Episode 22 - Random Level Generator + Properly Fixing Clipping
랜덤 벽을 생성해서 미로를 연출해본다. 벽이 겹쳐 보이는 Clipping을 해결하기 위한 리팩토링이 진행된다.
아직 벽과의 충돌은 구현되지 않아서 벽이 통과되는 버그가 있음.
✅ 3D Game Programming - Episode 23 - Graphical User Interface(GUI) Launcher
Launcher를 만들어본다. 스크린 사이즈를 조정하고 간단한 play 준비 화면을 제공한다.
기본적인 GUI프로그래밍과 관련된 내용임.
✅ 3D Game Programming - Episode 24 - Making Our Launcher Work
전편에 이어지는 기본적인 GUI프로그래밍과 관련된 내용.
✅ 3D Game Programming - Episode 25 - Writing and Reading Files
resolution 정보 즉 화면 크기 정보를 파일로 저장하고 쓰고 읽을 수 있게 구현함.
이전 설정 정보를 XML파일에 저장한다. Properties를 활용한다. file IO 기능을 활용한다.
✅ 3D Game Programming - Episode 26 - Custom Resolutions
Resolution을 직접 설정할 수 있도록 JTextField를 활용함.
✅ 3D Game Programming - Episode 27 - Decorating the Launcher
GUI Launcher에 Background 이미지를 삽입한다. 다만 정적인 이미지가 아닌 graphics를 활용해서 삽입한다.
이 과정에서 문제가 발생. 리팩토링 및 수정은 다음 에피소드에서 진행됨.
✅ 3D Game Programming - Episode 28 - Continuing our Custom Launcher!
Launcher에서 이미지를 사용해서 메뉴를 구성한다. 또한 런쳐가 드래그될 수 있도록 커스텀한다.
반투명 이미지 생성 링크: https://pixlr.com/kr/remove-background/
✅ 3D Game Programming - Episode 29 - Launching The Game
싱글톤 패턴을 Launcher에 적용한다. Display의 getInstance를 통해 항상 같은 Launcher를 받아올 수 있다.
추가적인 리팩토링이 진행됨.
이슈:
런쳐를 드래그해서 이동하는 movement가 깨지는 현상이 있었음.
해결방법:
updateFrame의 getLocation을 반드시 Jframe에서 호출해야 한다.
Canvas에서 호출할 경우 Canvas의 getLocation을 호출하기 때문에 드래그가 깨지게 됨.
✅ 3D Game Programming - Episode 30 - Colour Processing In-Depth
새로운 프로젝트 진행. 2D movement 구현 및 충돌 처리 구현. 다른 리포에 구현함.
레벨 디자인에 대해 알아본다. 게임의 맵을 구성할 수 있는 표현 방식.
✅ 3D Game Programming - Episode 31 - Sprites!
Sprite를 추가한다. 벽을 제외한 평면 공간에 새로운 오브젝트를 표현한다.
✅ 3D Game Programming - Episode 32 - Sprite Mapping
Sprite에 텍스쳐를 적용한다.
Sprite에 투명 효과를 적용하고 랜덤으로 생성될 수 있도록 한다.
(Sprite의 특정 RGB를 렌더링하지 않는 방식으로 투명 효과를 적용한다.)
✅ 3D Game Programming - Episode 33 - High Resolution Rendering
Texture를 32x32사이즈 텍스쳐맵으로 관리함. 천장과 바닥을 분리해서 렌더링할 수 있음.
텍스쳐를 커스텀하고 파라미터값 조정을 통해서 원하는 텍스쳐를 사용할 수 있음.
✅ 3D Game Programming - Episode 34 - Entities
전반적인 리팩토링을 진행한다. Player 클래스와 Entity, Mob클래스를 새롭게 생성한다.