C++ 클론코딩 무작정 따라서 만들어보기 3탄

Junghwan Kim·2023년 5월 26일
0

다음으로 살펴볼 헤더파일은 process.h 이다.
코드는 다음과 같다.




class bike_process
{
     private:

     public:


void load_layer(int x=0 ,int y=0)
{

     apply_surface(bg[0].get_cord_x(),0,back[0],screen);      //Blit the screen;
     apply_surface(bg[1].get_cord_x(),0,back[1],screen);      //Blit the screen;
     apply_surface(0,0,upback,screen);

     for(int i=0;i<SMAX_WALL;i++)
     if(w1[i].get_state())
     apply_surface(w1[i].get_cord_x(),w1[i].get_cord_y(),obs_wall[0],screen);

     for(int i=0;i<BMAX_WALL;i++)
     if(w2[i].get_state())
     apply_surface(w2[i].get_cord_x(),w2[1].get_cord_y(),obs_wall[1],screen);
     apply_surface(bike_x,bike_y,bike,screen);         //bike is blitted..

}

void change_coardinate(int );       //Set the coardinate of the labels..

bool process();

};

bool bike_process::process()
{
     while( SDL_PollEvent(&event) )
     {
          if(event.type==SDL_QUIT)
          return false;
     }

     if( keystate[SDLK_ESCAPE] || game_on==0 || time_gap>=90)
     return false;

     if(keystate[SDLK_SPACE] or keystate[SDLK_UP])                //If space is pressed...
     {
          if(jump_state==0)
          jump_state=36;                       //set the jump or SPACE state in 20*2 steps...

     }
     if( (bike_y <(bike_stand-bike->h)) or jump_state>=16  )    //Condition true untill the MARIO goes upward and downward to surface below it..
     {
          int jump_height;
          jump_height=19-jump_state;         //using the formula n/2*(n+1)...
          bike_y += jump_height;
          jump_state--;
          if(jump_state==0)
          jump_state--;
     }
     else
     {
          bike_y=bike_stand-bike->h;
          jump_state=0; 
     }

     if(keystate[SDLK_RIGHT])
     if(speed<=20)                 //Speed only increase to 10..
     speed++;
     if(keystate[SDLK_LEFT])
     if(speed>0)                    //speed cannot be less than 0..
     speed--;

     if(bike_x < FINISH_BIKE_X)
     bike_x+=speed;
     else
     change_coardinate(-speed/2);
     change_coardinate(0);

     load_layer();
     if(( w2[BMAX_WALL-1].get_cord_x())+w2[BMAX_WALL-1].get_cord_w() < 0)
     {
         apply_surface(100,300,die,screen);
         SDL_Flip(screen);
         SDL_Delay(2000);
         return false;
     }

     std::stringstream time;
     //Convert the timer's time to a string
     time_gap =(SDL_GetTicks() - start_time)/1000;
     int mm=time_gap/60;
     int ss=time_gap%60;
     time << "Timer: " << mm<<":"<<ss;
     times=TTF_RenderText_Solid(font,time.str().c_str(),textColor);
     apply_surface(600,50,times,screen);
     apply_surface(500,55+times->h,time_limit,screen);

     return true;
}

void bike_process::change_coardinate(int n)
{
     if(is_collision())
     {
          game_on=0;
     }
     else if(n!=0)
     {
          bg[0].add_background_x(n);         //add the background caordinate..
          bg[1].add_background_x(n);

          for(int i=0;i<SMAX_WALL;i++)
          w1[i].add_wall_x(n);              //add the wall's coardinte
          for(int i=0;i<BMAX_WALL;i++)
          w2[i].add_wall_x(n);              //add the wall's coardinte
     }
     else
     {
          bg[0].add_background_x(n);
          bg[1].add_background_x(n);
     }
}

이제 게임안에서 이벤트가 발생할때 어떻게 처리를 해야될것인지에 대한 자세한 구현법이 나와있는 코드이다.
혹시나 코드보면서 모르는 함수들이 나올때마다 아래와 같이 정리해놓았으니 참고하면서 보면 도움이 될것이다.
private:오직 클래스의 다른 멤버만 접근할수 있는 비공개 멤버
public:구조체 또는 클래스 외부에서 접근할 수 있는 구조체 또는 클래스의 공개멤버
get_cord():사용자 정의함수
apply_surface():사용자 정의함수
get_state():사용자 정의함수
SDL_QUIT():종료 요청이 들어온경우 발생되는 이벤트이다.
keystate[SDL_ESCAPE] SDL_LEFT,SDL_RIGHT 각각 이스케이프키 오른쪽 왼쪽 방향키
SDL_Delay:인자로 넘긴 ms만큼 정지해주는 함수
stringstream: C++에서 문자열을 공백과 \n 을 기준으로 int형 string형 float형 등 다양하게 자를 수 있도록 해주는 클래스
SDL_GetTicks():지난 임의의 시간으로부터 지금까지 몇 밀리세컨드(milliseconds)가 지났는지 알려준다.
TTF_RenderText_Solid:Font데이터를 가공하지않고 그대로 출력해준다.
time.str().c_str():문자열 객체에 저장된 문자열들과 같은 내용을 담고 있는 널 종료 문자 배열 을 가리키는 포인터를 리턴한다.
bike_process::process():process()라는 이름의 외부클래스를 정의한다.
bike_process::change_coardinate():change_coardinate라는 이름의 외부클래스를 정의
is_collision:사용자 정의함수

다음으로 살펴볼 헤더파일은 init.h 이다. 저번에 만들어놓은 변수들(variable.h)을 어떻게 초기화 시키고 어떻게 설정값을 줄것인지에 대한 정보가 들어있다.

bool init_all()
{
     if(SDL_Init(SDL_INIT_EVERYTHING)==-1)
     return false;
//SDL is composed of eight subsystems - Audio, CDROM, Event Handling, File I/O, Joystick Handling, Threading, Timers and Video. Before you can use any of these subsystems they must be initialized by calling SDL_Init (or SDL_InitSubSystem). SDL_Init must be called before any other SDL function. It automatically initializes the Event Handling, File I/O and Threading subsystems and it takes a parameter specifying which other subsystems to initialize. So, to initialize the default subsystems and the Video subsystems you would call:

     screen=SDL_SetVideoMode( WIDTH,HEIGHT,BPP,SDL_SWSURFACE );
//
//SDL_SWSURFACE	Create the video surface in system memory
    if(screen==NULL)
    {
        return false;
    }

    if(TTF_Init()==-1)                  //Font Initialization...
    {
        return false;
    }


    SDL_WM_SetCaption("RISING SUN BIKE RACING GAME",NULL);
    return true;
}

//Load a image file on screen and returns the address..
SDL_Surface* load_image(std::string filename,int col1=0xFF,int col2=0xFF , int col3=0xFF )
{
    SDL_Surface *loaded_image=NULL;
    SDL_Surface *optimized_image=NULL;

    loaded_image=IMG_Load(filename.c_str());
    if(loaded_image!=NULL)
    {
        optimized_image=SDL_DisplayFormat(loaded_image);        //Create an optimized image

        SDL_FreeSurface(loaded_image);//        //Free the old image

//Frees the resources used by a previously created SDL_Surface. If the surface was created using SDL_CreateRGBSurfaceFrom then the pixel data is not freed.

//http://lazyfoo.net/SDL_tutorials/lesson05/index.php
        if(optimized_image!=NULL)
        {
            SDL_SetColorKey(optimized_image,SDL_SRCCOLORKEY,SDL_MapRGB(optimized_image->format,col1,col2,col3));
        }
    }
//Then we check if the image was optimized.
/*
If the image was optimized, we have to map the color we want to set as the color key. 
We call SDL_MapRGB() to take the red, green, and blue values and give us the pixel value
 back in the same format as the surface. You can learn more about pixels in article 3.*/
    return optimized_image;     //Return the address of the loaded image...
}

bool load_files()
{
     for(int i=0;i<3;i++)
     {
          back[i]=load_image("image/bg2.png");         //Loads the background image..
          if(back[i]==NULL)
          return false;
     }
     bg[0]=background(0,0,back[0]->w,back[0]->h);
     bg[0]=background(WIDTH,0,back[1]->w,back[1]->h);

     upback=load_image("image/bg1.png");     //Loads the uper side of the  background image..
     if(upback==NULL)
     return false;

     bike=load_image("image/bike.PNG");      //Loads the image of bike..
     if(bike==NULL)
     return false;
     bike_y=LAYER_Y-bike->h;

     obs_wall[0]=load_image("image/wall.JPG");
     obs_wall[1]=load_image("image/wall1.JPG");
     if(obs_wall==NULL || obs_wall[1]==NULL)
     return false;

     w1[0]=wall(WIDTH+50,LAYER_Y-obs_wall[0]->h,obs_wall[0]->w,obs_wall[0]->h);
     w1[1]=wall(WIDTH+1350,LAYER_Y-obs_wall[0]->h,obs_wall[0]->w,obs_wall[0]->h);
     w1[2]=wall(WIDTH+3350,LAYER_Y-obs_wall[0]->h,obs_wall[0]->w,obs_wall[0]->h);
     w1[3]=wall(WIDTH+5050,LAYER_Y-obs_wall[0]->h,obs_wall[0]->w,obs_wall[0]->h);
     w1[4]=wall(WIDTH+7100,LAYER_Y-obs_wall[0]->h,obs_wall[0]->w,obs_wall[0]->h);

     w2[0]=wall(WIDTH+2050,LAYER_Y-obs_wall[1]->h,obs_wall[1]->w,obs_wall[1]->h);
     w2[1]=wall(WIDTH+4350,LAYER_Y-obs_wall[1]->h,obs_wall[1]->w,obs_wall[1]->h);
     w2[2]=wall(WIDTH+6050,LAYER_Y-obs_wall[1]->h,obs_wall[1]->w,obs_wall[1]->h);
     w2[3]=wall(WIDTH+7800,LAYER_Y-obs_wall[1]->h,obs_wall[1]->w,obs_wall[1]->h);


     font=TTF_OpenFont("times.ttf",20);      //Font file is loaded....

     time_limit=TTF_RenderText_Solid(font,"Time limit is 1:30 minute",textColor);
     die=TTF_RenderText_Solid(font,"GAME OVER",textColor);

    menu_pic=load_image("image/menu.jpg");
    play_menu=load_image("image/menu_play.jpg");
    instruction_menu=load_image("image/menu_instruction.jpg");
    quit_menu=load_image("image/menu_exit.jpg");
    if(menu_pic==NULL || play_menu==NULL || instruction_menu==NULL || quit_menu==NULL)
    return false;

     return true;
}

sdl_init:sdl에서 특정한 뭔가를 초기화를 시킬때 쓰이는 함수
sdl_init_everything:서브시스템에 있는 모든것들
sdl_setvideomode:비디오 모드를 특정 높이 너비와 픽셀당비트수로 설정해준다.
ttf_init:SDL_ttf 라이브러리를 초기화
sdl_wm_setcaption:SDL의 제목표시변경을 해줄때 사용됨
IMG_load:소프트웨어 서페이스 안으로 특정파일 경로에 있는 이미지를 로드할때 사용됨
SDL_Displayformat:서페이스를 디스플레이 포멧으로 변환시켜줄때 사용됨
sdl_freesurface:sdl_surface를 삭제할때 사용됨
sdl_setcolorkey:color key를 설정한다 bittable surface와 RLE acceleration에서 쓰이는
sdl_maprgb:색상을 집어넣고 싶을때 사용되는 함수
ttf_openfont:TTF 폰트파일을 열때 사용되는 함수
마찬가지로 코드를 읽으면서 모르는 함수들 형식들이 나올때마다 따로 정리해서 코드를 이해하는데에 수월하게끔 하였다.

해외 개발자분이 주석으로 중간중간 코드에 대한 설명을 달아놓으셔서 코드를 이해하는데에 한층더 도움이 되었다. 대충 분석을 해본결과 이러하였다. 게임이 시작되고 그과정에서 여러 이미지들이 로드 되어지고 배경화면들이 나타나면서 게임이 시작되고 시간 제한이 있어서 그 시간 제한을 넘어서면 다시 초기화면 이미지들을 불러와서 초기화면으로 돌아가게끔 설계된 코드임을 알수있었다.

다음으로 살펴볼 헤더파일은 function.h 이다.
코드는 다음과 같다.

void apply_surface(int x,int y,SDL_Surface *source,SDL_Surface *distination,SDL_Rect *clip=NULL)
{
    SDL_Rect offset;
    offset.x=x;
    offset.y=y;
    SDL_BlitSurface(source,clip,distination,&offset);       //Load image to the display screen i.e. on the screen..
}

드디어 모두가 궁금해하던 apply_surface()의 정체가 공개되어지는 순간이다..!
SDL_Rect:화면에 사각형 영역을 정의한다.
offset:아마 사용자 정의 변수인듯
SDL_BlitsSurface:소스 표면에서 목적지 표면으로 복사를 한다.
모르는 함수들 변수들은 따로 모아서 이렇게 정리를 하는 습관을 들이고난후 코드분석에 들어간다.
매개변수에 들어간 값에 따라서 디스플레이 화면에 이미지를 로드시켜주는 함수인듯 하다. 사각형 형태로

참고한 사이트:https://lazyfoo.net/tutorials/SDL/index.php

profile
안녕하세요~

0개의 댓글