반응형

EX01_읽기 엑세스 위반

 

 

 

원인 : 배열의 인덱스를 벗어난 주소를 찾아서, 금지된 영역에(kernal 영역) 엑세스 하려고 했기 때문에

 

해결 : 배열이 충분히 사이즈가 크게 만들던지, 배열을 가져오는 함수에서 제한 범위를 벗어나지 않게 해야 한다

반응형
반응형

맵의 끝(흰색별)에 도달하면 맵의 처음(검은별)이 보인다

 

 

 

 

 

맵을 렌더링 할때 발생한 것으로 보임

 

 

렌더링 코드를 살펴보면

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
void CStage::Render()
{
    /*
    맵은 스크톨 처리하여, 현재 플레이어가 이동한 위치로부터 맵을 출력해줌
    출력 크기는 세로 4칸 가로 10칸으로 해줌
    0 : 벽
    1 : 길
    2 : 시작점
    3 : 도착점
    4 : 코인
    */
    CPlayer* pPlayer = CObjectManager::GetInst()->GetPlayer();
 
    int player_Coin = pPlayer->GetCoin();
 
    //플레이어의 x,y 좌표를 얻어온다
    int player_iX = pPlayer->GetX();
    int player_iY = pPlayer->GetY();
 
    // 맵의 출력은 플레이어의 위치를 중심으로 출력
    // 세로는 플레이어 2칸위부터 한칸 아래까지 출력
    // 총 4줄이 출력되는것이다
    // 가로는 플레이어 위치부터 오른쪽 10칸 까지 출력함
    constexpr int iClientPadding_left        = 0;
    constexpr int iClientPadding_Top        = -2;
    constexpr int iClientPadding_Right        = 9;
    constexpr int iClientPadding_Bottom        = 1;
 
    int iClientHeight_start = player_iY + iClientPadding_Top;
    int iClientHeight_end = player_iY + iClientPadding_Bottom;
    int iClientWidth_start = player_iX + iClientPadding_left;
    int iClientWidth_end = player_iX + iClientPadding_Right;
 
    for (int i = iClientHeight_start; i <= iClientHeight_end; ++i)
    {
        for (int j = iClientWidth_start; j < iClientWidth_end; ++j)
        {
            if (i == player_iY  && j == player_iX)
            {
                std::cout << "§";
            }
            else if (m_cStage[i][j] == SBT_WALL)
            {
                std::cout << "■";
            }
            else if (m_cStage[i][j] == SBT_ROAD)
            {
                std::cout << "  ";
            }
            else if (m_cStage[i][j] == SBT_START)
            {
                std::cout << "☆";
            }
            else if (m_cStage[i][j] == SBT_END)
            {
                std::cout << "★";
            }
            else if (m_cStage[i][j] == SBT_COIN)
            {
                std::cout << "◎";
            }
        }
        std::cout << std::endl;
    }
    std::cout << "coin : "<< player_Coin << std::endl;
    std::cout << "Left : ← " << " Right : → " << std::endl;
    std::cout << "Jump : space bar "<< std::endl;
}
 
cs

31,32라인에 있는 iClientWidth, iClientHeight 가 곧 게임 클라이언트 화면의 가로 세로를 나타낸다

실제 맵 사이즈는 g_iMapWidth = 50, g_iMapHeight = 10 이며

iClientWidth_start , iClientWidth_end 는 각각, 맵에서 실제로 보여줄 가로 시작지점과 가로 끝점을 나타내고

iClientHeight_start, iClientHeight_end 는 각각, 맵에서 실제로 보여줄 세로 시작지점과 세로 끝점을 나타낸다

 

즉 그림으로 보면 아래와 같다

 

 

위에 버그는 iClientWidth_start 값과 iClientWidth_end 값이 일정 범위 안으로(맵의 끝에 도달하려고 했을때) 들어가면 

고정된값들이 되야 하는데, 그러지 않고 맵의 처음(0)부터 다시 출력 하게 되서 버그가 발생한듯함

즉 아래와 같은 코드가 들어가야 한다

 

     //맵 끝에 거의 도달했을때 가로 스크롤 멈춤

    //클라이언트 시작 지점이 최대 시작지점(맵 가로길이 - 클라이언트 오른쪽 여백) 보다 크거나 같을때

    //클라이언트 시작 지점 = 최대 시작지점(맵 가로길이 - 클라이언트 오른쪽 여백)

    if (iClientWidth_start >= g_iMAP_WIDTH - iClientPadding_Right)

    {

        iClientWidth_start = g_iMAP_WIDTH - iClientPadding_Right;

    }

   

     //클라이언트 끝 지점이 최대 끝지점 (맵의 길이)보다 클때

     //클라이언트 끝 지점 = 최대 끝 지점(맵의 가로길이)  

    if (iClientWidth_end > g_iMAP_WIDTH)

    {

        iClientWidth_end = g_iMAP_WIDTH;

    }

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
void CStage::Render()
{
    /*
    맵은 스크톨 처리하여, 현재 플레이어가 이동한 위치로부터 맵을 출력해줌
    출력 크기는 세로 4칸 가로 10칸으로 해줌
    0 : 벽
    1 : 길
    2 : 시작점
    3 : 도착점
    4 : 코인
    */
    CPlayer* pPlayer = CObjectManager::GetInst()->GetPlayer();
 
    int player_Coin = pPlayer->GetCoin();
 
    //플레이어의 x,y 좌표를 얻어온다
    int player_iX = pPlayer->GetX();
    int player_iY = pPlayer->GetY();
 
    // 맵의 출력은 플레이어의 위치를 중심으로 출력
    // 세로는 플레이어 2칸위부터 한칸 아래까지 출력
    // 총 4줄이 출력되는것이다
    // 가로는 플레이어 위치부터 오른쪽 10칸 까지 출력함
    constexpr int iClientPadding_left        = 0;
    constexpr int iClientPadding_Top        = -2;
    constexpr int iClientPadding_Right        = 9;
    constexpr int iClientPadding_Bottom        = 1;
 
    int iClientHeight_start = player_iY + iClientPadding_Top;
    int iClientHeight_end = player_iY + iClientPadding_Bottom;
    int iClientWidth_start = player_iX + iClientPadding_left;
    int iClientWidth_end = player_iX + iClientPadding_Right;
 
    //맵 끝에 거의 도달했을때 가로 스크롤 멈춤
    if (iClientWidth_start >= g_iMAP_WIDTH - iClientPadding_Right)
    {
        iClientWidth_start = g_iMAP_WIDTH - iClientPadding_Right;
    }
 
    if (iClientWidth_end > g_iMAP_WIDTH)
    {
        iClientWidth_end = g_iMAP_WIDTH;
    }
 
    for (int i = iClientHeight_start; i <= iClientHeight_end; ++i)
    {
        for (int j = iClientWidth_start; j < iClientWidth_end; ++j)
        {
            if (i == player_iY  && j == player_iX)
            {
                std::cout << "§";
            }
            else if (m_cStage[i][j] == SBT_WALL)
            {
                std::cout << "■";
            }
            else if (m_cStage[i][j] == SBT_ROAD)
            {
                std::cout << "  ";
            }
            else if (m_cStage[i][j] == SBT_START)
            {
                std::cout << "☆";
            }
            else if (m_cStage[i][j] == SBT_END)
            {
                std::cout << "★";
            }
            else if (m_cStage[i][j] == SBT_COIN)
            {
                std::cout << "◎";
            }
        }
        std::cout << std::endl;
    }
    std::cout << "coin : "<< player_Coin << std::endl;
    std::cout << "Left : ← " << " Right : → " << std::endl;
    std::cout << "Jump : space bar "<< std::endl;
}
 
cs

 

 

버그 해결 완료

더이상 맵의 시작지점이 보이지 않고, 횡스크롤은 정지되있다

반응형

'develop-note > MarioGame' 카테고리의 다른 글

MarioGame 최근 업데이트 2020_03_07  (0) 2020.03.07
MarioGame UML  (0) 2020.03.03
반응형

Singleton Pattern (싱글톤 패턴)

프로그램안에서 어떤 클래스의 인스턴스가 1개만 존재 하도록, 폐쇄적으로 클래스를 디자인 하는것

 

 

구현방법

1.생성자는 private 으로 막는다, 외부에서 new 를 통한 instance 생성을 할 수 없게 만든다.

 

 

 

 

2.인스턴스 하나를 담을 수 있는 포인터변수를 선언, static 으로 설정해서, 오직하나만 존재할 수 있게 만든다

 

 

 

 

 

 

3. m_pInst를 가져오거나(get), 메모리 해제(Destroy)할 수 있는 멤버 함수들을 선언, static 변수에 접근할 수 있어야 하고

외부에서 해당 함수들을 쓸 수 있어야 하므로 public 으로 지정

 

 

 

 

 

 

 

MySingletonClass.cpp

 

4. m_pInst를 초기화 해주기 위해서는 static 멤버 변수 이므로, 생성자가 아닌 클래스 외부에서 

MySingletonClass* MySingletonClass::m_pInst = nullptr; //이런식으로 초기화를 해준다

 

 

5.GetInst() 함수를 구현한다, m_pInst 가 nullptr 이라면, 새로 생성하여 instance를 초기화 해준뒤

앞으로도 호출될때마다 이미 생성된 instance를 return 하도록 한다

 

 

6.DestroyInst() 함수를 구현한다, GetInst() 함수와 유사한 구조를 가지고 있다 차이점은

delete와 nullptr, 초기화 가 return 대신에 들어간다

 

 

 

최종코드

MySingletonClass.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#pragma once
class MySingletonClass
{
private:
    MySingletonClass();
    ~MySingletonClass();
 
private:
    static MySingletonClass* m_pInst;
 
public:
    static MySingletonClass* GetInst();
    static void DestroyInst();
 
};
 
cs

 

MySingletonClass.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include "MySingletonClass.h"
 
MySingletonClass* MySingletonClass::m_pInst = nullptr;
 
MySingletonClass::MySingletonClass()
{
}
 
MySingletonClass::~MySingletonClass()
{
}
 
MySingletonClass* MySingletonClass::GetInst()
{
    if (!m_pInst)
    {
        m_pInst = new MySingletonClass;
    }
    return m_pInst;
}
 
void MySingletonClass::DestroyInst()
{
    if (!m_pInst)
    {
        return;
    }
    delete m_pInst;
    m_pInst = nullptr;
 
}
 
cs
반응형

+ Recent posts