namespace BrickGameFinal
{
internal class BALLDATA
{
public int nReady;
public int nDirect;
public int nX, nY;
}
}
namespace BrickGameFinal
{
internal class Ball
{
BALLDATA m_tBall = new BALLDATA();
//C# 공의 방향 배열 정의
int[,] g_WallCollision = new int[4, 6]
{
{ 3 , 2,-1,-1,-1, 4},
{ -1 ,-1,-1,-1, 2, 1},
{ -1 , 5, 4,-1,-1,-1},
{ -1 ,-1, 1, 0, 5,-1},
};
Bar m_pBar;
Block m_pBlock;
//바 클래스도 가져와야 할 거 같다. 값만 가져온다.
public void SetBar(Bar bar) { m_pBar = bar; }
//벽돌 클래스도 가져와야 할 거 같다. ref로 가져와서 값을 변환해줄 수 있다.
//참조해야한다 블럭의 Life값을 설정해주기 위해서
public void SetBlock(ref Block pBlock) { m_pBlock = pBlock; }
//그려줄 함수
public void ScreenWall()
{
Program.gotoxy(0, 0);
Console.Write("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓");
Program.gotoxy(0, 1);
Console.Write("┃ ┃");
Program.gotoxy(0, 2);
Console.Write("┃ ┃");
Program.gotoxy(0, 3);
Console.Write("┃ ┃");
Program.gotoxy(0, 4);
Console.Write("┃ ┃");
Program.gotoxy(0, 5);
Console.Write("┃ ┃");
Program.gotoxy(0, 6);
Console.Write("┃ ┃");
Program.gotoxy(0, 7);
Console.Write("┃ ┃");
Program.gotoxy(0, 8);
Console.Write("┃ ┃");
Program.gotoxy(0, 9);
Console.Write("┃ ┃");
Program.gotoxy(0, 10);
Console.Write("┃ ┃");
Program.gotoxy(0, 11);
Console.Write("┃ ┃");
Program.gotoxy(0, 12);
Console.Write("┃ ┃");
Program.gotoxy(0, 13);
Console.Write("┃ ┃");
Program.gotoxy(0, 14);
Console.Write("┃ ┃");
Program.gotoxy(0, 15);
Console.Write("┃ ┃");
Program.gotoxy(0, 16);
Console.Write("┃ ┃");
Program.gotoxy(0, 17);
Console.Write("┃ ┃");
Program.gotoxy(0, 18);
Console.Write("┃ ┃");
Program.gotoxy(0, 19);
Console.Write("┃ ┃");
Program.gotoxy(0, 20);
Console.Write("┃ ┃");
Program.gotoxy(0, 21);
Console.Write("┃ ┃");
Program.gotoxy(0, 22);
Console.Write("┃ ┃");
Program.gotoxy(0, 23);
Console.Write("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛");
}
//충돌 처리
public int Collision(int x, int y)
{
// 벽충돌
if (y == 0)
{
m_tBall.nDirect = g_WallCollision[0, m_tBall.nDirect];
return 1; //공의 방향이 바뀌면 1을 리턴
}
if (x == 1)
{
m_tBall.nDirect = g_WallCollision[1, m_tBall.nDirect];
return 1;
}
if (x == 77)
{
m_tBall.nDirect = g_WallCollision[2, m_tBall.nDirect];
return 1;
}
if (y == 23)
{
m_tBall.nDirect = g_WallCollision[3, m_tBall.nDirect];
return 1;
}
// Bar충돌처리 ->바 윗면 아랫면 체크 Y + 1(아래충돌) Y - 1 (윗충돌)
if(x >= m_pBar.m_tBar.nX[0] && x <= m_pBar.m_tBar.nX[2] + 1 && y == (m_pBar.m_tBar.nY)) // 바위 충돌
{
//공의 방향 정의
if (m_tBall.nDirect == 1)
m_tBall.nDirect = 2;
else if (m_tBall.nDirect == 2)
m_tBall.nDirect = 1;
else if (m_tBall.nDirect == 5)
m_tBall.nDirect = 4;
else if (m_tBall.nDirect == 4)
m_tBall.nDirect = 5;
//방향이 바뀐다
return 1;
}
// 위충돌
if (x >= m_pBar.m_tBar.nX[0] && x <= m_pBar.m_tBar.nX[2] + 1 && y == (m_pBar.m_tBar.nY +1)) // 바위 충돌
{
if (m_tBall.nDirect == 1)
m_tBall.nDirect = 2;
else if (m_tBall.nDirect == 2)
m_tBall.nDirect = 1;
else if (m_tBall.nDirect == 5)
m_tBall.nDirect = 4;
else if (m_tBall.nDirect == 4)
m_tBall.nDirect = 5;
//방향이 바뀐다
return 1;
}
//벽돌 충돌
for(int i = 0; i < 20; i++)
{
if (m_pBlock.tBlock[i].nLife == 1) //살아있을때
{
if(x >= m_pBlock.tBlock[i].nX && x <= m_pBlock.tBlock[i].nX+1 && y == m_pBlock.tBlock[i].nY) //충돌 하면
{
if (m_tBall.nDirect == 1)
m_tBall.nDirect = 2;
else if (m_tBall.nDirect == 2)
m_tBall.nDirect = 1;
else if (m_tBall.nDirect == 5)
m_tBall.nDirect = 4;
else if (m_tBall.nDirect == 4)
m_tBall.nDirect = 5;
//벽돌은 숨겨야 한다.
m_pBlock.tBlock[i].nLife = 0;
//방향이 바뀐다
return 1;
}
}
if (m_pBlock.tBlock[i].nLife == 1) //살아있을때
{
if (x >= m_pBlock.tBlock[i].nX && x <= m_pBlock.tBlock[i].nX + 1 && y == m_pBlock.tBlock[i].nY+1) //충돌 하면
{
if (m_tBall.nDirect == 1)
m_tBall.nDirect = 2;
else if (m_tBall.nDirect == 2)
m_tBall.nDirect = 1;
else if (m_tBall.nDirect == 5)
m_tBall.nDirect = 4;
else if (m_tBall.nDirect == 4)
m_tBall.nDirect = 5;
//벽돌은 숨겨야 한다.
m_pBlock.tBlock[i].nLife = 0;
//방향이 바뀐다
return 1;
}
}
}
return 0;
}
//볼 데이터 값
public BALLDATA GetBall() { return m_tBall; }
//바에서 움직이는 값
public void SetX(int x) { m_tBall.nX += x; }
public void SetY(int y) { m_tBall.nY += y; }
//볼 데이터 넣기
public void SetBall(BALLDATA tBall) { m_tBall = tBall; }
//레디 할 것인지.
public void SetReady(int Ready) { m_tBall.nReady = Ready; }
public void Initialize()
{
// 이동을 위한
m_tBall.nReady = 0; //공안움직임 1 움직임 0
m_tBall.nDirect = 1;
m_tBall.nX = 30;
m_tBall.nY = 10;
//커서 안보이게 하기
Console.CursorVisible = false;
}
public void Progress()
{
if (m_tBall.nReady == 0)
{
//공의 방향에따른 스위치문
switch (m_tBall.nDirect)
{
case 0: //위
if (Collision(m_tBall.nX, m_tBall.nY - 1) == 0)
m_tBall.nY--;
break;
case 1: //오른쪽 위
if (Collision(m_tBall.nX + 1, m_tBall.nY - 1) == 0)
{
m_tBall.nX++;
m_tBall.nY--;
}
break;
case 2: //오른쪽 아래
if (Collision(m_tBall.nX + 1, m_tBall.nY + 1) == 0)
{
m_tBall.nX++;
m_tBall.nY++;
}
break;
case 3: //아래
if (Collision(m_tBall.nX, m_tBall.nY + 1) == 0)
m_tBall.nY++;
break;
case 4: //왼쪽 아래
if (Collision(m_tBall.nX - 1, m_tBall.nY + 1) == 0)
{
m_tBall.nX--;
m_tBall.nY++;
}
break;
case 5://왼쪽 위
if (Collision(m_tBall.nX - 1, m_tBall.nY - 1) == 0)
{
m_tBall.nX--;
m_tBall.nY--;
}
break;
}
}
}
public void Render()
{
ScreenWall();
Program.gotoxy(m_tBall.nX, m_tBall.nY);
Console.Write("●");
}
public void Releas()
{
}
}
}
namespace BrickGameFinal
{
internal class BARDATA
{
public int[] nX = new int[3];
public int nY;
}
}
namespace BrickGameFinal
{
internal class Bar
{
//퍼블릭으로 변경 바와 공의 충돌 처리를 위해
public BARDATA m_tBar = new BARDATA();
int m_nCatch; //공을 잡았는지 체크
const int LEFTKEY = 75; //상수로 만들어준다. 변수에 값 대입 x
const int RIGHTKEY = 77; //상수로 만들어준다. 변수에 값 대입 x
public void Initialize()
{
m_nCatch = 0;
m_tBar.nY = 18;
m_tBar.nX[0] = 12;
m_tBar.nX[1] = 14;
m_tBar.nX[2] = 16;
}
//공의 객체를 가지고와서 잡았는지 판단 및 움직임도 줘야함
//ref로 인자값 전달 참조
public void Progress(ref Ball pBall)
{
int nKey = 0;
if (Console.KeyAvailable)
{
nKey = Program._getch(); // 키 눌림 값
switch (nKey)
{
case LEFTKEY: //왼쪽
m_tBar.nX[0]--;
m_tBar.nX[1]--;
m_tBar.nX[2]--;
if (pBall.GetBall().nReady == 1 && m_nCatch == 1)
{
//공이 잡힌상태
pBall.SetX(-1); //공왼쪽으로 움직이게 값주기
}
break;
case RIGHTKEY: //오른쪽
m_tBar.nX[0]++;
m_tBar.nX[1]++;
m_tBar.nX[2]++;
if (pBall.GetBall().nReady == 1 && m_nCatch == 1)
{
//공이 잡힌상태
pBall.SetX(1); //공 오른쪽으로 움직이게 값주기
}
break;
case 'a':
pBall.SetReady(0);
//초기화 -> 떠나보내기로 변경
/*BALLDATA tBall = new BALLDATA();
tBall.nReady = 0;
tBall.nX = 20;
tBall.nY = 1;
pBall.SetBall(tBall);
m_nCatch = 0;*/
break;
case 's':
if (pBall.GetBall().nX >= m_tBar.nX[0] && pBall.GetBall().nX <= m_tBar.nX[2] + 1 && pBall.GetBall().nY == (m_tBar.nY - 1))
{
pBall.SetReady(1);
m_nCatch = 1;
}
break;
}
}
}
public void Render()
{
for (int i = 0; i < 3; i++)
{
Program.gotoxy(m_tBar.nX[i], m_tBar.nY);
Console.Write("▥");
}
}
public void Release()
{
}
}
}
namespace BrickGameFinal
{
internal class BLOCKDATA
{
public int nLife;
public int nX, nY;
}
}
namespace BrickGameFinal
{
internal class Block
{
//벽돌이 여러개 -> 충돌 처리를 위해 public 으로 변경
public BLOCKDATA[] tBlock = new BLOCKDATA[50]; //배열
public Block() //생성자
{
//벽돌초기화
for (int i = 0; i < tBlock.Length; i++)
{
tBlock[i] = new BLOCKDATA();
tBlock[i].nLife = 0;
tBlock[i].nX = 0;
tBlock[i].nY = 0;
}
}
//Search함수 주어진 좌표가 현재 설정된 블록 배열 중에 중복된 것이 있는지를
//검색해주는 함수이다.
//현재 최대 블록 50개 설정가능
//매번 50개의 블록을 전부 검색할 필요없이 스테이지마다 할당된 블록
//안에서만 검색
//Search함수는 첫번째 인자의 nEnd변수는 블로그이 범위가 된다.
//이 함수는 SetBlock함수에서 호출이 된다.
public int Search(int nEnd, int nX, int nY)
{
for (int i = 0; i < nEnd; i++)
{
if (tBlock[i].nY == nY) //Y좌표가 같고
{
if (tBlock[i].nX == nX || (tBlock[i].nX + 1) == 1) //특수문자여서
return 1; //같으면 1을 반환
}
}
return 0; //같지 않으면 0을 반환
}
//범위 안에서 블록의 중복 검사를 하는 이유
public void SetBlock(int nBlockCount)
{
int nX, nY;
Random r = new Random();
for (int i = 0; i < nBlockCount; i++)
{
tBlock[i].nLife = 1;
while (true) //중복찾기
{
nX = r.Next(2, 66); //2~65범위 안에서
nY = r.Next(2, 16); //2~15범위 안에서
if (Search(i, nX, nY) == 0)
{
//중복이 아님
tBlock[i].nX = nX;
tBlock[i].nY = nY;
break; //한개를 만들고 for문 탈출
}
}
}
}
//필요 함수들
public void Initialize()
{
SetBlock(20);
}
public void Progress()
{
}
public void Render()
{
for (int i = 0; i < 20; i++)
{
if (tBlock[i].nLife == 1) //살아있는 벽돌만 그리기
{
Console.SetCursorPosition(tBlock[i].nX, tBlock[i].nY);
Console.Write("■");
}
}
}
public void Release()
{
}
}
}
namespace BrickGameFinal
{
internal class GameManager
{
Ball m_pBall = null;
Block m_pBlock = null;
Bar m_pBar = null;
//초기화
public void Initialize()
{
//하나만 생성하고 싶음
if(m_pBall == null)
{
m_pBall = new Ball();
m_pBall.Initialize();
}
//바
if(m_pBlock == null)
{
m_pBlock = new Block();
m_pBlock.Initialize();
}
//벽돌
if(m_pBar == null)
{
m_pBar = new Bar();
m_pBar.Initialize();
}
//볼에서 바와 벽돌을 사용해야할 거 같다. -> 이제 충돌처리를 할 수 있는 상태임
m_pBall.SetBar(m_pBar);
m_pBall.SetBlock(ref m_pBlock);
}
public void Progress()
{
m_pBall.Progress();
m_pBar.Progress(ref m_pBall);
m_pBlock.Progress();
}
public void Render()
{
//지우고 전체를 그려줌
Console.Clear();
m_pBall.Render();
m_pBar.Render();
m_pBlock.Render();
}
//c#자체에 있는 함수인가봄. 나중에 바꿔주던지 해야함.
public void Release()
{
m_pBall.Releas();
m_pBar.Release();
m_pBlock.Release();
}
}
}
namespace BrickGameFinal
{
internal class Program
{
[DllImport("msvcrt.dll")]
public static extern int _getch(); //c언어 함수 가져옴
public static void gotoxy(int x, int y)
{
Console.SetCursorPosition(x, y);
}
static void Main(string[] args)
{
GameManager gm = new GameManager();
//초기화
gm.Initialize();
//현재시간
int Curr = Environment.TickCount;
while(true)
{
if(Curr + 50 < Environment.TickCount)
{
Curr = Environment.TickCount;
gm.Progress();
gm.Render();
}
}
gm.Release();
}
}
}
728x90
'프로그래밍 > 콘솔프로젝트' 카테고리의 다른 글
공 튕기기 (0) | 2023.07.12 |
---|---|
벽돌 중복없이 만들기 (0) | 2023.07.12 |
Ball Bar로 잡기 (0) | 2023.07.11 |
공의 이동 (0) | 2023.07.11 |
공 벽 튕기기 (0) | 2023.07.11 |