GNU의 C에서 함수 혹은 구조체, 변수등에 컴파일러가 코드를 컴파일 할 때 특정 방향으로 컴파일 할 수 있도록 속성을 설정할 수 있는 것이 __attribute__ 이다.
GNU의 C 코드에서 간혹 __attribute__ 라고 써있는 것을 볼 수 있다.
_ 2개를 attribute 끝에 붙여서 사용한다. 그리고 그 뒤에 괄호 두개 사이에 원하는 속성을 넣으면 된다.
예로 이렇게 사용한다.
내가 how2heap의 house of spirit을 분석하다가 마주한 코드이다.
unsigned long long fake_chunks[10] __attribute__ ((aligned (16)));
위와 같이 사용한다.
사용할 수 있는 속성은 굉장히 많다.
예로 든 aligned 속성은 메모리의 정렬 단위를 설정하는 것이다.
해당 내용은 memory alignment를 검색해보면 찾아 볼 수 있다.
간단히 설명하면 메모리에서 입출력을 할 때 가져오는 단위 WORD 로 가져오기 때문에 메모리에 값을 저장할 때 신경을 써야한다.
예를 들어서 좋지 않은 경우를 보겠다.
32비트 컴퓨터라고 하자. 그렇다면 WORD의 단위는 4바이트이다. 그렇다면 메모리에서 4바이트 단위로 값을 가져온다.
여기서 우리가 int 의 값을 저장한다고 하자.( int 는 4바이트(word의 값))
메모리 주소 0번지 부터 저장한다 치면 주소 0,1,2,3 에 우리의 값이 적혀지게 되고
이 값을 부를 때 0번지 주소를 부르게 되면 4바이트 단위로 값을 가져오기 때문에 0,1,2,3 주소의 값을 가져오게 되어 한번의 호출로 우리가 저장한 값을 가져올 수 있다.
하지만 만약 2번지 주소에 저장되었다 치자.
그러면 2,3,4,5 주소에 우리의 int 값이 저장된다. 이 값을 호출 하기위해 메모리 주소를 2번부터 부를 수 있을까? 그렇지 않다. 32비트의 컴퓨터이므로 4바이트 단위로 메모리에서 값을 가져오기 때문에
만약 2번지 주소에 저장되어있다면
0번부터 불러서 0,1,2,3 을 부른 후, 다시 4번부터 또 불러 4,5,6,7 을 가져와서
우리가 저장했던 값을 가져온다. 즉, 메모리 호출을 2번 하게 되는 것이다. 메모리에서 값을 가져오고 쓰는 과정은 굉장히 비싼 작업이다. (시간이 오래걸린다.) 그렇기 때문에 메모리에 값을 저장할 때 신경을 써줘야한다. 보통 이 작업을 컴파일러가 알아서 해준다. 하지만 프로그래머가 특별히 어떠한 단위로 저장을 원할 경우 __attribute__의 aligned 속성을 사용해 지정해 줄 수 있다.
* __attribute__ ((aligned(4))); 를 이용한 해결
위의 경우 2번지에 저장이 되었는데 그 앞에 char 변수 2개가 들어있는 구조체라고 하자.
그렇다면 위의 상황이 나온다. (보통 요즘의 컴파일러들이 알아서 구조체에서 가장 큰 사이즈의 단위로 alignment를 해주지만 안해준다고 치자!)
그렇다면 여기서 우리는 구조체 선언할 때 뒤에 __attribute__ ((aligned(4)));를 붙이므로써 이 문제를 해결할 수 있다.
그렇게 되면 0번지부터 char 변수 2개가 들어가고, 메모리 2,3 주소에 패딩이 들어간다.
패딩이란 메모리 단위를 맞춰주기위한 더미값? 이라고 생각하면된다.
그리고 int값을 쓸 때는 4번지 주소부터 적게 되어 아까 위의 문제가 발생하지 않게 되는 것이다.
전체 글
- __attribute__ 속성 지정 2018.02.20 1
- (게임프로그래밍) 애니메이션, 컨트롤 2018.02.07
- (게임프로그래밍) 간단한 애니메이션 추가 2018.02.07
__attribute__ 속성 지정
(게임프로그래밍) 애니메이션, 컨트롤
이번에는 우주선이 움직이는 것을 표현해 볼 것이다.
오른쪽으로 이동하면서 우주선이 빙글빙글 돌면서 날라간다. 날라가면서 크기도 작아진다. 그리고 화면 밖으로 벗어나게 되면 그 반대에서 다시 나타나서 계속 움직이는 것을 만들 것이다.
(update)
우주선을 회전하게 하는 것을 각도 설정, 크기 설정에서 크기만 넣어주면 된다. 어떻게 작아지는지 어떻게 이미지 생성 위치가 바뀌는지에 대한 것은 애니메이션 그리는 것에서 우리가 다 만들어 놓은 것이다. 우리는 단지 회전각도와 위치만 설정해주면 된다.
(상수)
회전 상수는 180으로 정의 되있어서 초당 180도를 회전한다는 의미이다.
SCALE_RATE 상수는 0.2로 정의 되어있어 초당 100픽셀만큼 움직인다는 의미이다.
SHIP_SCALE 상수는 1.5로 정의되어있는데 우주선이 원래 크기에서 1.5배로 커진다는 의미이다.
(실행 화면)
(update)
(실행화면)
그런데 키를 때면 바로 우주선이 멈춘다.
키를 때도 그 방향으로 계속 움직이게 수정해 줄 것이다.
반대 키를 누르면 그 방향에대한 속도가 줄게 할 것이다. 그러기 위해서는 속도라는 값이 들어가야한다.
키 입력에 따라 속도 값을 수정해주고, 그 속도만큼 움직이게 하면 되는 것이다.
(update)
키를 때었을 때 점차 속도가 줄어들게 하고 싶었다. 그래서 update 아래에 아래 코드를 추가했다.
(추가한 코드)
GRAVITY는 실제 중력값은 아니고 속도가 감소한다는 의미의 상수를 넣었다.
(추가 상수)
(실행 화면)
마지막으로
속도가 좀 느리다는 느낌이 있었다.
그래서 스페이스바를 누르면 부스트 모드로 기존 속도의 2배로 날라가게 만들었다.
(추가한 코드)
스페이스바 입력을 받게 하기 위해 상수로 추가했다.
(스페이스바 추가)
그리고 boost 여부에 따라 2배로 움직이게 만들었다.
(boost 모드)
키 입력을 받아 우주선이 움직이게 하는 것까지 마무리했다.!!
(* 참조 - 2D 게임 프로그래밍, 찰스 켈리)
'Programing > Game Programing' 카테고리의 다른 글
| (게임프로그래밍) - 충돌 ( 화면안에 가두기 ) (0) | 2018.02.23 |
|---|---|
| (게임프로그래밍) 간단한 애니메이션 추가 (0) | 2018.02.07 |
| 스프라이트를 이용하여 이미지 그리기 (0) | 2018.02.05 |
| 게임 엔진 기초 틀 만들기(2) - Input Class (0) | 2018.01.31 |
| 게임 엔진 기초 틀 만들기(1) - Game Class (0) | 2018.01.31 |
(게임프로그래밍) 간단한 애니메이션 추가
우주선을 추가할 것인데, 우주선 주변에 불이 깜빡깜빡하는 아주 간단한 애니메이션을 추가해 볼 것이다.
가장 먼저 해야할 일은 우주선을 추가해주어야하는 일이다.
저번에 이미지를 그렸을 때와 같이 우주선 textureManager와 Image 클래스를 만들어준다.
(우주선 추가)
그 후 초기화 함수에도 추가해준다.
(텍스처 초기화)
(이미지 초기화)
우주선의 화면 위치를 설정해준다. 여기서는 좌측상단에 나타나도록 설정해두었다.
그 애래의 코드들은 우주선 애니메이션과 각도에 관한 설정들이다.
뒤에서 설명하겠다.!
애니메이션을 동작시키기 위해 애니메이션이 있는 이지미를 계속 업데이트해줘야한다.
이 과정은 게임 클래스 안의 update 함수 안에서 해당 이미지의 업데이트를 추가해주므로써 구현한다.
(이미지 update)
예전에 게임엔진 틀을 만들 때 frameTime을 계산해주기 위해 내부 타이머를 이용해 시간을 계산해주는 작업을 한 것이 기억날 것이다. 이런 곳에 사용하기 위해 계산을 해둔 것이다.
이미지클래스의 update를 확인해보자
(update 함수)
먼저 체크하는 것은 애니메이션 동작이 있는 스프라이트인지 체크한다.
애니메이션 동작이 있는 것이라면 먼저 경과 시간을 계산해준다.
우리가 원하는 frameDelay마다 동작하게 하기 위해서이다. 그래서 그 다음으로 frameDelay보다 큰지 확인하고 크면 update를 하고 크지 않으면 다음 루프에서 update를 하게하기 위해서이다.
그 후 애니메이션 타이머에서 frameDelay를 빼준다. (다음 번 update에서 사용하기 위해서)
그리고 현재 프레임수를 1증가시킨다.
그리고 동작하는 것이 setRect() 함수이다.
이제 이 setRect() 함수를 보면 애니메이션이 이해가 갈 것이다.
(setRect() 함수)
이 함수에서는 이미지에서 특정 영역을 설정하는 함수인데, 현재frame을 기준으로 바뀌는 것을 볼 수 있다. 우리가 올린 이미지는 아래와 같다.
(우주선 이미지)
그렇기에 우주선 주위에 불빛이 빤짝거리게 되는 원리이다.
즉, 움직이게 하고 싶은 이미지 마다 위와 같은 과정으로 프레임을 설정해 주는 것이다.
맨 처음에 봤던 우주선 애니메이션활성화 설정을 다시 볼 것이다.
(애니메이션 설정)
setFrames는 처음 프레임과, 마지막 프레임을 설정하는 것이다. 변수의 값은 아래 사진과 같다.
(상수)
프레임은 0에서 3까지 총 4개의 프레임이고 위의 사진에서 보았듯이 4개의 우주선 모양이 있는 것을 확인 할 수 있다. 그리고 setCurrentFrame 함수로 현재 프레임을 우주선의 시작 프레임으로 설정해주는 것이다. (초기화 함수이기 때문에)
(setCurrentFrame 함수)
자! 이제 실행해 볼 것이다!
그 전에! 추가해줘야할 것이 있다. render() 함수에 우주선 이미지 그리는 것을 추가해줘야한다.!
(우주선 그리기)
나는 여기서 빌드 후 실행하고 잘 되는 줄 알았다.
그리고 곧 문제점을 깨달았다.
전체화면으로 바꾸려고 했을 때 되지 않았다.!! 화면이 까매지기만 했다. 디바이스 로스트 상황이었다.
코드를 다시 보다가 이해했다. 디바이스 로스트 때 돌아가는 것 중 우리가 우주선 이미지를 추가하면서 우주선 textureManager를 추가해줬는데 이것도 핸들해줘야하기 때문이다.
(로스트 처리)
이렇게 로스트 처리하게 되면 창전환도 괜찮았다.
(실행 화면)
(* 참조 - 2D 게임 프로그래밍, 찰스 켈리)
'Programing > Game Programing' 카테고리의 다른 글
| (게임프로그래밍) - 충돌 ( 화면안에 가두기 ) (0) | 2018.02.23 |
|---|---|
| (게임프로그래밍) 애니메이션, 컨트롤 (0) | 2018.02.07 |
| 스프라이트를 이용하여 이미지 그리기 (0) | 2018.02.05 |
| 게임 엔진 기초 틀 만들기(2) - Input Class (0) | 2018.01.31 |
| 게임 엔진 기초 틀 만들기(1) - Game Class (0) | 2018.01.31 |