이런 함수의 목적은 2가지 이다.
좀더 빠른 코드를 만들고 특별한 상황(탄도궤도, 중력, 충돌)을 다루기 위해서다.

-.랜덤 숫자
랜덤 숫자는 로또, AI, 레벨업에의한 파워증가 등 자주 요청된다.

PA_Rand()
u32 num = PA_Rand();
랜덤 숫자를 생성한다. 하지만 중요한 불리한 점이 있는데.. 너무 큰 수를 반환한다는 것이다.

PA_RandMax(max)
0 과 4 사이의 숫자같이 포함되는 것을 원한다면 이 함수를 사용하라

u32 max = 4;
u32 num = PA_RandMax(max);

PA_RandMinMax(min,max)
1~4 사이의 숫자를 원한다면
u32 min = 1;
u32 max = 4;
u32 num = PA_RandMinMax(min,max);

PA_InitRand()
프로그램에서 이것들을 사용하다보면 같은 일련의 숫자가 반환되는 것을 볼수 있을 것이다. 왜 그럴까? 그 이유는 컴퓨터상에서 완벽하게 맞는 랜덤 숫자를 생성할 수는 없기 때문이다. 단지 수학 방법으로 그것을 흉내낼 뿐이다. 이런 현상을 최소화하기 위해서 PA_InitRand() 함수가 유용하다. 게임 메인 루프전 어딘가에 넣고 한번만 실행하면 된다. 그러면 랜덤 함수는 현재 시간과 날짜로 초기화 될 것이다.

-. 고정 소숫점 연산
고정 소숫점 연산을 사용하여 (부동 소숫점이 아닌) 위치를 관리하는 방법은 게임에서 굉장히 빠른 속도를 보인다.
이론
DS(gba나 다른 플랫폼처럼)는 부동소숫점 형식의 변수를 다루려면 매우 느리다. 그러나 예를 들어 프레임당 픽셀보다 더 느리게 sprite를 움직이기를 원할 경우, 0.5 처럼 소수값을 사용할 필요가 있어 보인다.
32bit 변수(s32)를 사용하여, 소수부분과 동일한 마지막 8bit를 예약해 놓을 것이다. 그래서 먼저 8bit는 소수부분이 되고 다음 24bit는 정수부분이 된다.
0~255 값을 가릴수 있는 8bit는 1/256 의 정확도를 가질수 있다는 걸 의미한다. 이것은 대부분의 경우에 대개 충분하다. 24bit는 큰 수를 다루기에 충분한 값이다.
마지막으로 고정 소숫점에서 256 값의 평균은 1이고, 512는 2, 1024는 4가 된다. 그래서 0.5 가 되기 위해서는 128를 사용하면 된다. 196 같은 중간 값을 사용할 수도 있다. 이것은 3/4를 의미한다.

기본 예제
매 프레임마다 한픽셀 이동보다 느리게 sprite를 이동시키기 위한 고정소숫점 연산 사용법을 보여주는 것이다.
s32 speed1 = 256// first speed...0
PA_OutputText(0, 18, 2" 1   pixel/frame");

s32 speed2 = 128;
PA_OutputText(0, 18, 10, "0.5  pixel/frame");

s32 speed3 = 64;
PA_OutputText(0, 18, 18, "0.25 pixel/frame");

PA_LoadSpritePal(0, 0, (void*)sprite0_Pal); // Palette name PA_CreateSprite(0, 0, (void*)vaisseau_Sprite, OBJ_SIZE_32X32, 1, 0, 0, 0);
PA_CreateSprite(0, 1, (void*)vaisseau_Sprite, OBJ_SIZE_32X32, 1, 0, 0, 64);
PA_CreateSprite(0, 2, (void*)vaisseau_Sprite, OBJ_SIZE_32X32, 1, 0, 0, 128);

// all sprites stick to the left
s32 spritex1 = 0; s32 spritex2 = 0; s32 spritex3 = 0;


while(1) // Infinite loops
{
// Move all the sprites by their corresponding speed
spritex1 += speed1; spritex2 += speed2; spritex3 += speed3;

// Positionne all the sprites, >>8 to return to normal position
PA_SetSpriteX(0, 0, spritex1>>8);
PA_SetSpriteX(0, 1, spritex2>>8);
PA_SetSpriteX(0, 2, spritex3>>8);

PA_WaitForVBL();
}
s32 speed1 = 256; 이것은 고정 소숫점 연산을 사용하는 첫단계로 고정 소숫점 값은 256으로 곱해지는 정규 값이다. 그래서 프레임당 1 픽셀의 속도를 얻을 수 있다.
s32 speed2 = 128; 이것은 128 = 256/2 이므로 128은 프레임당 1/2 픽셀인 0.5 이다.
s32 speed3 = 64; 마찬가지로 1/4, 그래서 0.25/frame
그런데 왜 s32 변수를 사용했을까요? 음수값을 가지므로 s는 부호가 있다는 것이고 32bit가 필요하므로 32 이다. 8bit 같은 경우는 127까지의 값만을 가질수 있다. 이것은 프레임당 1 픽셀을 움직이는데 충분치 않다. 32bit를 사용해야 충분히 유용하다.
고정소숫점에서 sprite 좌표를 변경하는 방법을 보자.
spritex1 += speed1; 이건 고정소숫점과 전혀 관계없고 sprite 위치에 속도를 더하는 것이다.
스크린상에 sprite를 위치시키는 방법에서 진짜 트릭이 존재하는데 그러기 위해서 PA_SetSpriteX를 사용한다.
PA_SetSpriteX(0, 0, spritex1>>8); 여기서 >>8 은 무엇일까? 이것은 256으로 나누는 것을 의미한다. 나누기는 너무 느리므로 제외하고, 반면에 >>8 은 정말 빠르다. 이건 고정소숫점 연산에서 256으로 나누는 것이다. 잘 작동하며 x = 256 위치는 x = 1 를 의미한다.

그래서 끝으로 정규수(0, 0.5, 1, 등등)에서 고정 소숫점으로 가기위해 256을 곱한다.
고정 소숫점에서 정규식(스크린상에 표시할 필요가  있을때)으로 가기 위해 256으로 나눈가.(>>8)

-. 중력사용 ( 점프 등)
수많은 게임에서 사용되는 코드이다. 이것은 간단한 기초에 의존한다. sprite 는 수직 속도를 가진다. 중력은 가속도이다. 다음 세가지를 의미한다.
매 턴마다 속도는 가속도에 따라 변경한다.
매 턴마다 sprite 위치는 속도에 따라 변경한다.
언제든 플레이어가 아래쪽을 터치하면 속도는 null 이 될 것이다.

가속도와 속도는 여러 값을 가질수 있기 때문에 제한을 두지 않고 고정 소숫점 값을 사용할 것이다.
bit 시프트를 사용하는 이유이다.(<<8, >>8) 아래 예제는 작은 셔틀이 올라 갔다가 떨어지는 것이다. 셔틀의 반응 변화를 보기위해 중력과 시작 추진력(점프와 같은)을 바꿀수 있다.
#define FLOOR (160<<8) // Floor y level
 
int main(void){
 
PA_Init(); //PAlib inits
PA_InitVBL();

PA_InitText(1, 0);

PA_OutputText(1, 2, 4, "Press A to take off !");
PA_OutputText(1, 2, 5, "Gravity change : Left/Right");
PA_OutputText(1, 2, 7, "Takeoff Speed change : Up/Down");

PA_LoadSpritePal(0, 0, (void*)sprite0_Pal);

PA_CreateSprite(0, 0, (void*)vaisseau_Sprite, OBJ_SIZE_32X32, 1, 0, 50, 50);

 
s32 gravity = 32; // change the gravity and check the result :)
s32 velocity_y = 0;
s32 spritey = FLOOR; // at the bottom
s32 takeoffspeed = 1000; // Takeoff speed...

while(1) // Infinite loops
{

takeoffspeed += (Pad.Held.Up - Pad.Held.Down)*8; // Change takeoff speed...
gravity += (Pad.Held.Right - Pad.Held.Left)*2; // Change gravity speed...
 
PA_OutputText(1, 4, 8, "Takeoff speed : %d   ", takeoffspeed);
PA_OutputText(1, 4, 6, "Gravity       : %d   ", gravity);

if((spritey <= FLOOR) && Pad.Newpress.A)   { // You can jump if not in the air...
velocity_y = -takeoffspeed;  // Change the base speed to see the result...
}

// Moves all the time...
velocity_y += gravity; // Gravity...
spritey += velocity_y; // Speed...

if(spritey >= FLOOR) // Gets to the floor !
{
velocity_y = 0;
spritey = FLOOR;
}

PA_OutputText(1, 0, 0, "Y : %d   \nVY : %d    ", spritey, velocity_y);
 
if (spritey>>8 > -32) PA_SetSpriteY(0, 0, spritey>>8); // show if on screen
else PA_SetSpriteY(0, 0, 192);

PA_WaitForVBL();
}

return 0;
}
#define FLOOR (160<<8) 이것은 바닥 높이이다. 고정 소숫점으로 변경하기위해 <<8 를 사용했다. 160 은 스크린 아래 방향이다.
s32 gravity = 32; 이것은 기본 중력으로 100% 랜덤 값이다. 32 는 256/8 로 1/8 픽셀/프레임 가속도와 같다.
s32 velocity_y = 0; 이것은 우주선 기본 속도이다. ( 위, 아래와 움직이지 않는다)
s32 spritey = FLOOR; 이것은 우주선의 기본 위치로 바닥 높이이다.
s32 takeoffspeed = 1000; 우주선 이륙 속도로 우주선이 가고자 하는 위치까지의 중력과 함께 결정된다.
다음은 중력과 이륙 속도를 변경하는 기본 코드로 특별한 것은 없다.
takeoffspeed += (Pad.Held.Up - Pad.Held.Down)*8; 이륙 속도 변경
gravity += (Pad.Held.Right - Pad.Held.Left)*2; 중력 속도 변경
다음이 진짜 중요한 코드이다.
if((spritey <= FLOOR) && Pad.Newpress.A)   { // You can jump if not in the air...
velocity_y = -takeoffspeed;  // Change the base speed to see the result...
}
바닥 높이(또는 그 밑에)에서 A 버튼을 누르면 이륙하는 것을 의미한다. 이륙하기 위해 수직 속도에 이륙 속도를 더했다. 더 높은 곳으로 가려면 더 낮게 y 값을 지정해야 한다. 그래서 음수 값이 되어야 한다.
그 다음 중력과 위치에 따라 속도를 조정한다. 모든 것은 고정 소숫점에서 진행된다.
velocity_y += gravity; // Gravity...
spritey += velocity_y; // Speed...
중력을 더하는 것으로 속도를 조정한다.(중력은 양수여야 한다.왜냐면 우주전은 하강해야 하기 때문이다. 그래서 이륙과 부호가 반대다.)
그후 새로운 중력에 따라 위치를 조정한다.
먼저 이륙이 일어나도록 음수의 매우 큰 속도를 가지고, 매 프레임마다 중력이 더해져서 이것은 점점 작아질 것이다. 한 시점에서 null 이 될것이고 그때 부호가 바뀌어 양수가 될 것이다. sprite는 떨어 지면서 점점 빨라 질 것이다. 실제 처럼..
이상으로 작동하는데 충분하지만 아래 코드를 추가하는 것을 잊지 않아야 한다.
if(spritey >= FLOOR) // Gets to the floor !
{
velocity_y = 0;
spritey = FLOOR;
}
만일 그렇지 않으면 우주선은 바닥 아래로 떨어질 것이다. 바닥 아래로 가면 속도는 null이 되고 바닥 수준으로 돌아 가야 한다. 그리고 화면상에 sprite를 보여주는 것을 멈춰야 할 것이다.
PA_SetSpriteY(0, 0, spritey>>8); 여기서 >>8 로, 표시하기 위해 고정 소수점에서 정규 정수 위치값으로 전환할 필요가 있다.

-. 탄도 궤도와 각도
이 영역은 3가지 부분으로 나뉜다.
먼저 PAlib의 특별한 각도 보는 법과 Cos, Sin 함수 이론, 마지막으로 이것을 게임에 적용하는 방법의 구체적인 예제를 보는 것이다.
PAlib 에서 각도
PAlib에서 각도는 일반적인 범위의 각도를 사용하지 않는다. 하지만 DS에 사용하기에 적합하다.
범위는 0 (오른쪽) 에서 511이며 시계 반대 방향이다. 그래서 각도가 0 이면 3시 방향이고 128은 12시 방향이며 256은 9시 방향이다. sprite에서의 회전과 같다.

GetAngle 코드(Math/GetAngle/)에서 각도의 효과적인 사용을 볼수 있다. 간단한 예제이지만 터치 스크린을 사용한다면 매우 유용할 것이다.
PA_OutputText(1, 5, 10, "Angle : %d ", PA_GetAngle(128, 96, Stylus.X, Stylus.Y));
매우 중요한 코드로 PA_GetAngle(x1, y1, x2, y2) 는 2개의 주어진 위치와 수평선에 의해 만들어진 각도를 반환한다. 대부분 위치값의 하나로 Stylus.X 와 Stylus.Y를 사용하길 원할 것이다. 이 예제에서 스크린 중앙과 스타일러스 위치사이의 각도를 얻는 방법을 볼수 있다.

Sin, Cos 기초
PA_Sin, PA_Cos 함수들은 -1~1 사이값을 반환하지 않는다. -256~256 값을 반환한다. 이유는 고정소수점 작업을 위해 더 낫기 때문이다.

위에 그림처럼 각도가 주어진다. 원상의 수평 좌표 위치가 Cos 이고 수직 좌표가 Sin 이다. 그래서 PA_Cos, PA_Sin을 사용하여 주어진 각도에 따라 sprite를 움직일수 있는 것이다. up/down, left/right 로 직접 제어하는 대신에 주어진 궤도에 따라 움직이게 할 수 있는 방법이다.

궤도 예제
PAlibExamples/Math/AngleSinCos 예제 코드로 화면 중앙에 우주선을 표시한다. 누르는 키방향대로 방향을 튼다.
PA_InitText(1,0); // On the top screen
 
PA_LoadSpritePal(0, 0, (void*)sprite0_Pal);
 
PA_CreateSprite(0, 0,(void*)vaisseau_Sprite, OBJ_SIZE_32X32,1, 0, 128-16, 96-16); // Create the ship in the center...
PA_SetSpriteRotEnable(0,0,0);// Enable rotations and use Rotset 0...

s32 x = (128-16) << 8; // ship x position in 8bit fixed point
s32 y = (96-16) << 8; // Y
u16 angle = 0; // direction in which to move !
 
while(1)
{
angle += Pad.Held.Left - Pad.Held.Right;
PA_SetRotsetNoZoom(0, 0, angle); // Turn the ship in the correct direction

if (Pad.Held.Up){ // Move forward
x += PA_Cos(angle);
y -= PA_Sin(angle);
}
if (Pad.Held.Down){ // Move backwards
x += -PA_Cos(angle);
y -= -PA_Sin(angle);
}

PA_OutputText(1, 5, 10, "Angle : %d  ", angle);

PA_SetSpriteXY(0, 0, x>>8, y>>8); // Sprite position converted to normal...

PA_WaitForVBL();
}
먼저 sprite를 만들고 회전가능하게 만든다. 그리고 필요한 변수를 초기화한다. 위치를 위해 x, y 와 각도를 위해 angle 변수가 필요하다. ship.x 같은 것을 위해 스트럭쳐를 사용할수 있다.
s32 x = (128-16) << 8; // ship x position in 8bit fixed point
s32 y = (96-16) << 8; // Y
u16 angle = 0; // direction in which to move !
보는 것처럼 각도는 특별한게 없다. x, y는 고정 소수점을 사용하고 있다.
우주선 방향을 틀게 하는 것은 꽤 간단하다.
angle += Pad.Held.Left - Pad.Held.Right;
PA_SetRotsetNoZoom(0, 0, angle); // Turn the ship in the correct direction
먼저 키 누르는 것에 따라 각도가 변한다. 자주 본 것처럼, 우주선이 턴하는 것을 더 빠르게 하고 싶으면 주어진 회전 속도를 증가 시키면 된다.( 1은 정상 속도, 2는 두배 빠르기 등등)
여기서는 줌은 사용하지 않았고 일반적인 회전 함수에 따라 각도에 따라 우주선은 턴할 것이다.
다음이 중요한 부분이다.
if (Pad.Held.Up){ // Move forward
 
x += PA_Cos(angle);
y -= PA_Sin(angle);
}
이것이 up 키를 눌렀을때 우주선이 위로 나아가게 만든다.
x 위치를 위해서 PA_Cos(angle) 를 더한다. PA_Cos, PA_Sin 은 8bit 연산에 적합하다. 그래서 -256~256 값을 반환한다.
y에 대해서 음수 부호를 가진다. 이유는 일반적인 Sin 함수는 위로 움직일때 Sin은 양수이다. DS 화면상에서 화면의 상단은 y=0 값이다. 그래서 일반적인 Sin에서 반대 값이 되어야 한다. 이것을 균형잡기 위해 음수 부호를 더한 것이다.
앞에 예제에서 PA_GetAngle 로 각도를 바꾸고 Pad.Held.Up 를 Stylus.Held로 바꾸면 우주선은 스크린상에 터치할때 스타일러스 방향으로 움직일 것이다.

Sprite 충돌
sprite 충돌의 2 종류를 볼 것이다. 둥근 sprite와 (정)사각 sprite 이다.
둥근 sprite
원의 충돌이론
둥근 sprite 를 고려해보면 정확하게 그것들이 충돌하게 하는 것은 정말 쉽다.

보는 것처럼 원이 충돌할때 서로의 거리는 얼마나 될까? 그것들의 중앙에서 정확한 거리는 r1 + r2 이다. 그래서 원 중앙에서 거리를 계산하여 r1 + r2 보다 작은 거리는 충돌한 것이다.

원의 충돌 코드
이 코드는 Math/CollisionRound/ 예제에서 볼수 있다.
똑같은 2개의 둥근 sprite가 있다. 서로 크기가 다르더라도 원중 하나는 고정되어 있다. 다른 하나는 스타일러스로 움직일수 있다. 만일 충돌한다면 상단 화면에 보여준다.
// This'll be the movable sprite...
PA_CreateSprite(0, 0,(void*)circle_Sprite, OBJ_SIZE_32X32,1, 0, 0, 0);
s32 x = 16; s32 y = 16; // Sprite's center position

// This will be the fixed circle
PA_CreateSprite(0, 1,(void*)circle_Sprite, OBJ_SIZE_32X32,1, 0, 128-16, 96-16);

while(1)
{
if (PA_MoveSprite(0)){
x = PA_MovedSprite.X;
y = PA_MovedSprite.Y;
}

// Collision ?
if (PA_Distance(x, y, 128, 96) < 32*32) PA_OutputText(1, 2, 10, "Collision !!");
else PA_OutputText(1, 2, 10, "            ");
 
PA_WaitForVBL();
}
처음에 0, 1 로 2개의 sprite를 생성한다.
if (PA_MoveSprite(0)){
x = PA_MovedSprite.X;
y = PA_MovedSprite.Y;
}
sprite 0 이 움직이면 그 중앙의 X, Y 좌표를 기억할 것이다. 이것은 2 sprite 사이의 거리를 계산하는데 사용될 것이다.
if (PA_Distance(x, y, 128, 96) < 32*32) PA_OutputText(1, 2, 10, "Collision !!");
PA_Distance(x1, y1, x2, y2) 는 사각형 거리를 반환하는 간단한 함수다. 왜 실제 거리가 아닐까? 이유는 사각형 루트 사용이 요구되기 때문이다. 사각형은 거리를 측정하는데 충분하다. 정확한 거리가 필요하지 않다. 하지만 비교해 볼 필요는 있다.
32*32와 왜 비교할까? 32는 2 원의 충돌 제한 값이다. 이 둘은 16픽셀의 반지름을 가진다. 그래서 16 + 16 = 32 가 된다. 사각형 거리가 필요하므로 32 를 곱하는 것이다. 이것은 거리의 사각형 루트를 구하는 것보다 빠르다.
만일 거리가 제한값보다 작다면, 2개의 sprite 는 충돌하는 것이고 상단 화면에 표시 될 것이다.

원의 충돌은 게임에 적용하기에 적합하지 않다고 생각할수 있다. 실제로는 자주 사용된다. 쏘아 올리는 첫 예제에서, 무기뿐 아니라 우주선도 원과 일치시킬수 있다.그래서 만일 2개 원사이의 충돌을 체크하는 것처럼 체크한다면 빠르고 효과적일 것이다. 게임의 대부분은 픽셀단위의 완벽한 충돌을 볼수 없을 정도로 빠르다.

-. 사각형 Sprite
사각형 충돌 이론
사각형 충돌은 원형 충돌과 같은 방법으로 작동하지 않는다.

그림에서 보는 것처럼 2개의 다른 사각형을 가지고 있다. 각각은 넓이와 높이가 정의되어 있다.(w1와 h1, w2와 h2) 어떻게 이것들이 사용될 수 있는지 다음에서 볼수 있다.

적색 사각형이 청색 사각형과 충돌할 수 있는 4면을 보여준다. 충돌할때 적색 사각형의 중앙을 고려하면 청색 사각형 주위에 완벽한 사각형을 표현할 수 있을 것이다. 그래서 이 점선의 새로운 사각형의 넓이와 높이를 알 필요가 있다. 새로운 사각형은 w1+w2의 넓이와 h1+h2의 높이를 가진다. 청색 사각형의 중앙이 이것의 중앙이 된다.

그래서 만일 x1, y1, x2, y2가  각각의 사각형 중앙에 더해지면, 충돌에 대해 다음과 같은 공식이 생긴다. 넓이에 대해 (x2 >= x1 - (w1 + w2)/2) 와 (x2 ⇐ x1 + (w1 + w2)/2), 높이에 대해 (y2 >= y1 - (h1 + h2)/2) 와 (y2 ⇐ y1 + (h1 + h2)/2) 이것은 충돌할때 계산하기에 충분하다.

사각형 충돌 코드
// This'll be the movable sprite...
PA_CreateSprite(0, 0,(void*)rect_Sprite, OBJ_SIZE_32X16,1, 0, 0, 0);
s32 x1 = 16; s32 y1 = 8; // Sprite's center position
s8 w1 = 32; s8 h1 = 16; // width and height...

// This will be the fixed circle
PA_CreateSprite(0, 1,(void*)rect_Sprite, OBJ_SIZE_16X32,1, 0, 128-8, 96- 16);
s32 x2 = 128; s32 y2 = 96; // Sprite's center position
s8 w2 = 16;  s8 h2 = 32; // width and height...

while(1)
{
if (PA_MoveSprite(0)){
x1 = PA_MovedSprite.X;
y1 = PA_MovedSprite.Y;
}

// Collision ?
if ((x2 >= x1 - (w1 + w2)/2) && (x2 <= x1 + (w1 + w2)/2) && (y2 >= y1 - (h1 + h2)/2) && (y2 <= y1 + (h1 + h2)/2)) PA_OutputText(1, 2, 10, "Collision !!");
else PA_OutputText(1, 2, 10, "            ");
 
PA_WaitForVBL();
}
먼저 32x16의 사각형을 생성하고 변수에 위치, 넓이, 높이를 입력한다.
PA_CreateSprite(0, 0,(void*)rect_Sprite, OBJ_SIZE_32X16,1, 0, 0, 0);
s32 x1 = 16; s32 y1 = 8; // Sprite's center position
s8 w1 = 32; s8 h1 = 16; // width and height...

원형 충돌 사용을 원하지 않는 곳 어디든지 사각형 충돌을 사용할수 있다.
(x2 >= x1 - (w1 + w2)/2) && (x2 ⇐ x1 + (w1 + w2)/2) && (y2 >= y1 - (h1 + h2)/2) && (y2 ⇐ y1 + (h1 + h2)/2)
이 방정식을 다음과 같이 바꿀수 있다.
(x2 >= x1 - (w1 + w2)»1) && (x2 ⇐ x1 + (w1 + w2)»1) && (y2 >= y1 - (h1 + h2)»1) && (y2 ⇐ y1 + (h1 + h2)»1)
나누기가 없기때문에 좀더 빠르게 작동할 것이다.

-. 가능한한 % 대신에 & 사용
%연산자는 a%b 와 같이 2 수로 작동한다. 이것은 a/b 의 나머지를 반환한다. 만일 2%4 면 2를 얻을수 있고 4%4 는 0, 5%4는 1를 반환한다. 이 연산은 나누기를 사용하므로 매우 느리다.
어떤 조건에서는 2진 연산을(사용하기에 매우 빠른) 사용할수 있다. 단 요구사항은 2의 제곱이 되는 b (a&b 에서)이다. 그래서 x%2, x%4, x%8 등은 교체 가능하다. 단 &를 사용할때 b를 쓰지 않고 b-1를 사용해야 한다.
x%2;   ->   x&1;
x%16;  ->   x&15;

-. bit 시프트 사용 (<< 와 >>)
bit 시프트는 나누가와 2제곱을 곱할때 효과적이다.
2제곱으로 나누기위해 오른쪽으로 bit 시프트한다.
8»1 = 4 (8/2^1 = 8/2 = 4)
8»3 = 1 (8/2^3 = 8/8 = 1)
2제곱으로 곱하기위해 왼쪽으로 bit 시프트한다.
2«1 = 4 (2*2^1 = 2*2 = 4)
2«3 = 16 (2*2^3 = 2*8 = 16)

-.if/else 최적화
if/else 문은 비경제적이다. 그래서 사소한 경우에는 사용을 줄일 필요가 있다. 다행이도 논리문장을 악용할 수 있다. 예를 들어 다음과 같은 코드를 대신하여
(if levelup==true)
x++;  //add one to x
다음과 같은 코드를 사용하라.
x+=(levelup==true);
이것은 x= x+(levelup==true) 와 같다.

-. FPS 얻기
다음 코드는 게임루프 매초마다 얼마나 많이 실행되는지 추적한다. DS의 비디오 화면은 60Hz로 갱신한다. 그래서 게임루프안에서 코드가 실행하는데 16.7ms 보다 더 걸리지 않으면 60 fps가 될 것이다.
#include <PA9.h> //Include PA Lib
 
s8 fps = 0; //Our FPS
s8 time = 0;
s8 lastTime = 0;

int main(void)
{
   PA_Init();   //Initialize the main library
   PA_InitVBL(); // Initialize Vertical Blanking
   
   PA_InitText(1,2); //Init the text on both screens
   PA_InitText(0,2);
   PA_OutputText(1,0,0,"Starting...");
  
   lastTime = PA_RTC.Seconds;
  
   //We may start halfway into a second
   //let's wait until the clock starts the next second
   while(PA_RTC.Seconds == lastTime)
   {
      PA_WaitForVBL();
   }
   lastTime = PA_RTC.Seconds;
  
   while(1)
   {
      PA_WaitForVBL();   //Wait for Video Blank

      fps +=1//up the fps every time the code runs through

      time = PA_RTC.Seconds//Grab the time
     
      //If the second has changed we are done counting frames
      if(time != lastTime)
      {
         lastTime = time;  //Start looking for end of next second
 
         PA_ClearTextBg(0); //Clear the text so we don't get text mishaps
         PA_ClearTextBg(1);
         PA_OutputText(1,0,0,"Fps %d /60",fps)

         fps = 0; //Start counting back at zero
      }  
   }
}
Posted by 버들피리불며

BLOG main image
닌텐도 DS 관련해서 Palib를 소개하고 제가 개발한 홈브류와 다른 개발자의 홈브류를 소개하고자 합니다. NDS 자체 제작(Homebrew)에 관심있는 다른 분들의 길잡이가 되고 싶습니다. by 버들피리불며

공지사항

카테고리

분류 전체보기 (39)
따라하기 (5)
PA_lib 소개 (10)
Homebrew 소개 (7)
나의 Homebrew (15)
기부하기(Donate) (1)
Wii (1)
Total : 117,195
Today : 1 Yesterday : 1