Devlog

애벌레 게임(Moving Bug)

1. 프로젝트 개요

이번 프로젝트인 애벌레 게임의 기본 베이스는 1970년대에 출시 된 게임으로 영어로는 Snake game, 일본어로는  ヘビゲーム이라 부른다.

플레이어는 화면에 있는 뱀 (우리 프로그램에서는 애벌레)을 방향키로 조작하여 상하좌우로 움직일 수 있다.

이때 타이머로 AUTO key를 조절하며 1P는 (↑, ↓, ←, → )로, 2P는 ( W, S, A, D )로 방향을 조절 할 수 있다.

애벌레가 먹이를 먹을 때 마다 꼬리의 개수가 증가하며 머리와 꼬리가 부딪혔을 때 Game Over! 창이 출력되면서 게임이 종료된다.  

 

 

2. 설계작품 개요

2.1. 프로그램 기획

  • 애벌레 게임의 기본 베이스는 1970년대에 출시 된 게임으로 영어로는 Snake game, 일본어로는 ヘビゲーム(뱀 게임)라고 부른다.
  • 플레이어는 화면에 있는 뱀(처럼 생긴 길쭉한 막대)(우리 프로그램에서는 애벌레)을 방향 키로 조작해서 상하좌우로 움직일 수 있다.
  • 애벌레의 머리가 꼬리에 닿으면 죽으면서 게임이 종료된다.

2.2 기본 프로그램 기능

  • 방향키
  • 1P는 (↑, ↓, ←, →)로 방향 조절한다.
  • 2P는 (W, S, A, D)로 방향 조절한다.
  • 타이머로 AUTO로 Key 조절한다.
  • 먹이를 먹을 때 마다 꼬리의 개수가 증가한다.
  • 머리와 꼬리가 부딪혔을 때 Game Over! 창이 출력되고 게임이 종료된다.

 

3. 설계작품 일정

  • 5/24: 애벌레 코드 분석 및 조건 내용 파악
  • 5/27 ~ 6/13: 조건에 맞춘 애벌레 게임 프로그램 구현
  • 6/13: 최종 보고서 작성 및 제출
  • 6/18: 최종 보고서 및 발표

 

4. 설계 구성요소

4.1. 목표설정(Objective Establishment)

  • 경기장은 33*33 크기로 변경, 먹이도 30개로 변경한다.
  • 시작하면 애벌레 두 마리(왼쪽 상단에 하나, 오른쪽 하단에 하나) 출력한다.
  • 오른쪽 애벌레는 방향키로 이동한다.
  • 왼쪽 애벌레는 A(<-) S(위쪽) D(->) W(아래쪽) 으로 이동한다.
  • 먹이를 먹으면 먹이는 사라지고 애벌레 꼬리가 생긴다.
  • 타이머가 작동하면 애벌레는 계속 움직인다.
  • 벽은 통과 못한다.
  • 애벌레의 자기 꼬리는 통과 못한다.
  • 이동시 벌레끼리 서로 통과 못하며, 서로 못 먹는다.

4.2. 합성(Synthesis)

  • 자기 꼬리를 통과 못한다

애벌레 프로그램의 기본 베이스인 뱀 게임에서 아이디어를 얻었으며 애벌레의 머리가 꼬리에 부딪혔을 때 애벌레가 죽으면서 게임을 종료한다. 종료시 Game Over! 창이 뜨도록 한다.

 

4.3. 분석(Analysis) 및 구현(Build)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CCProject_20172804_20172829
{
    public partial class Form1 : Form
    {
        const int BAB_NUM = 30;
        int[,] game_pan = new int[33, 33];
        int len, len_2;
        int[] bugX = new int[90];
        int[] bugY = new int[90];
        int[] oldbugX = new int[90];
        int[] oldbugY = new int[90];
        int xDir, yDir, xDir_2, yDir_2;
        int[] babx = new int[30];
        int[] baby = new int[30];
        int[] bugX_2 = new int[90];//두 번째 애벌레 머리랑 꼬리 저장
        int[] bugY_2 = new int[90];
        int[] oldbugX_2 = new int[90];
        int[] oldbugY_2 = new int[90];
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            GamePanInit();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            DrawGamePan(e.Graphics);
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            CursorControl(e.KeyCode);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            Invalidate();
            MovingBug();
        }

        void babGenerator()
        {
            int i, x, y;
            Random rand = new Random();

            for (i = 0; i < BAB_NUM; i++)
            {
                x = rand.Next() % 30 + 1;
                y = rand.Next() % 30 + 1;
                babx[i] = x;
                baby[i] = y;
                if (game_pan[y, x] == 0)
                    game_pan[y, x] = 2;
                else
                {
                    i = i - 1;
                    continue;
                }
            }
            return;
        }

        void GamePanInit()
        {
            int i;
            for (i = 0; i < 33; i++)
            {
                game_pan[i, 0] = -1;
                game_pan[i, 32] = -1;
                game_pan[0, i] = -1;
                game_pan[32, i] = -1;
            }
            bugX[0] = 2; bugY[0] = 1;
            bugX[1] = 1; bugY[1] = 1;
            game_pan[bugY[0], bugX[0]] = 3;
            game_pan[bugY[1], bugX[1]] = 3;

            bugX_2[0] = 30; bugY_2[0] = 31;
            bugX_2[1] = 31; bugY_2[1] = 31;

            babGenerator();

            len = 2;
            len_2 = 2;
            xDir = 1; yDir = 0;
            xDir_2 = 1; yDir_2 = 0;
        }

        void DrawGamePan(Graphics g)
        {
            int x, y, i;

            Pen blackPen = new Pen(Color.Black);
            Pen redPen = new Pen(Color.Red);
            Pen bluePen = new Pen(Color.Blue);

            for (y = 0; y < 33; y++)
            {
                for (x = 0; x < 33; x++)
                {
                    switch (game_pan[y, x])
                    {
                        case -1:
                            g.DrawRectangle(blackPen, x * 20, y * 20, 20, 20);
                            break;
                        case 2:
                            SolidBrush blackBrush = new SolidBrush(Color.Black);
                            g.FillEllipse(blackBrush, x * 20, y * 20, 20, 20);
                            break;
                    }
                }
            }

            g.DrawEllipse(redPen, bugX[0] * 20, bugY[0] * 20, 20, 20);
            g.DrawEllipse(redPen, bugX_2[0] * 20, bugY_2[0] * 20, 20, 20);
            for (i = 1; i < len; i++)
                g.DrawEllipse(bluePen, bugX[i] * 20, bugY[i] * 20, 20, 20);
            for (i = 1; i < len_2; i++)
                g.DrawEllipse(bluePen, bugX_2[i] * 20, bugY_2[i] * 20, 20, 20);
        }

        void CursorControl(Keys DirectKey)
        {
            //1p
            switch (DirectKey)
            {
                case Keys.Left:
                    if (xDir == 1)
                        break;
                    if (game_pan[bugY[0], bugX[0] - 1] != -1)
                    {
                        xDir = -1;
                        yDir = 0;
                    }
                    break;
                case Keys.Right:
                    if (xDir == -1)
                        break;
                    if (game_pan[bugY[0], bugX[0] + 1] != -1)
                    {
                        xDir = 1;
                        yDir = 0;
                    }
                    break;
                case Keys.Up:
                    if (yDir == 1)
                        break;
                    if (game_pan[bugY[0] - 1, bugX[0]] != -1)
                    {
                        xDir = 0;
                        yDir = -1;
                    }
                    break;
                case Keys.Down:
                    if (yDir == -1)
                        break;
                    if (game_pan[bugY[0] + 1, bugX[0]] != -1)
                    {
                        xDir = 0;
                        yDir = 1;
                    }
                    break;
            }

            //2p (머리방향이 다르기 때문에 1p와 부호 반대)
            switch (DirectKey)
            {
                case Keys.A:
                    if (xDir_2 == -1)
                        break;
                    if (game_pan[bugY_2[0], bugX_2[0] - 1] != -1)
                    {
                        xDir_2 = 1;
                        yDir_2 = 0;
                    }
                    break;
                case Keys.D:
                    if (xDir_2 == 1)
                        break;
                    if (game_pan[bugY_2[0], bugX_2[0] + 1] != -1)
                    {
                        xDir_2 = -1;
                        yDir_2 = 0;
                    }
                    break;
                case Keys.W:
                    if (yDir_2 == -1)
                        break;
                    if (game_pan[bugY_2[0] - 1, bugX_2[0]] != -1)
                    {
                        xDir_2 = 0;
                        yDir_2 = 1;
                    }
                    break;
                case Keys.S:
                    if (yDir_2 == 1)
                        break;
                    if (game_pan[bugY_2[0] + 1, bugX_2[0]] != -1)
                    {
                        xDir_2 = 0;
                        yDir_2 = -1;
                    }
                    break;
            }
            MovingBug();
            Invalidate();
        }

        void MovingBug()
        {

            //1p 머리 따라 꼬리 움직이기
            if (xDir != 0 || yDir != 0)
            {
                for (int i = 0; i < len; i++) // 머리랑 몸통 위치 저장
                {
                    oldbugX[i] = bugX[i];
                    oldbugY[i] = bugY[i];
                }

                bugX[0] += xDir; //위치값 받아서 움직이기
                bugY[0] += yDir;

                for (int i = 0; i < len; i++) // 저장된 머리랑 몸통 위치 전달
                {
                    bugX[i + 1] = oldbugX[i];
                    bugY[i + 1] = oldbugY[i];
                }
            }
            //1p 먹이 먹으면 꼬리 늘어남
            for (int i = 0; i < BAB_NUM; i++)
            {
                if (bugX[0] == babx[i] && bugY[0] == baby[i])
                {
                    game_pan[bugY[0], bugX[0]] = 1; // 먹이 사라지게
                    len++; // 꼬리 늘어남
                }
            }

            //2p 머리 따라 꼬리 움직이기
            if (xDir_2 != 0 || yDir_2 != 0)
            {
                for (int j = 0; j < len_2; j++) // 머리랑 몸통 위치 저장
                {
                    oldbugX_2[j] = bugX_2[j];
                    oldbugY_2[j] = bugY_2[j];
                }

                bugX_2[0] -= xDir_2;//위치값 받아서 움직이기, 2p는 머리 방향이 다르기 때문에 1p와 반대 부호
                bugY_2[0] -= yDir_2;

                for (int j = 0; j < len_2; j++)// 저장된 머리랑 몸통 위치 전달
                {
                    bugX_2[j + 1] = oldbugX_2[j];
                    bugY_2[j + 1] = oldbugY_2[j];
                }
            }
            //2p 먹이 먹으면 꼬리 늘어남
            for (int i = 0; i < BAB_NUM; i++)
            {
                if (bugX_2[0] == babx[i] && bugY_2[0] == baby[i])
                {
                    game_pan[bugY_2[0], bugX_2[0]] = 1;// 먹이 사라지게
                    len_2++;// 꼬리 늘어남
                }
            }

            //1p 벽 막기
            for (int y = 0; y < 33; y++)
            {
                for (int x = 0; x < 33; x++)
                {
                    if (bugX[0] == 31 && game_pan[y, x] == -1)//오른쪽
                    {
                        xDir = 0;
                    }
                    if (bugX[0] == 1 && game_pan[y, x] == -1)//왼쪽
                    {
                        xDir = 0;
                    }
                    if (bugY[0] == 31 && game_pan[y, x] == -1)//아래쪽
                    {
                        yDir = 0;
                    }
                    if (bugY[0] == 1 && game_pan[y, x] == -1)//위쪽
                    {
                        yDir = 0;
                    }

                }
            }
            //2p 벽 막기
            for (int y = 0; y < 33; y++)
            {
                for (int x = 0; x < 33; x++)
                {
                    if (bugX_2[0] == 31 && game_pan[y, x] == -1)//오른쪽
                    {
                        xDir_2 = 0;
                    }
                    if (bugX_2[0] == 1 && game_pan[y, x] == -1)//왼쪽
                    {
                        xDir_2 = 0;
                    }
                    if (bugY_2[0] == 1 && game_pan[y, x] == -1)//아래쪽
                    {
                        yDir_2 = 0;
                    }
                    if (bugY_2[0] == 31 && game_pan[y, x] == -1)//위쪽
                    {
                        yDir_2 = 0;
                    }
                }
            }
            //1p 자신의 몸 통과 못하기, 몸끼리 부딪히면 게임 끝!
            for (int i = 1; i < len; i++)
            {
                if (bugY[0] + yDir == bugY[i] && bugX[0] + xDir == bugX[i])
                {
                    xDir = 0; //몸 부딪히면 못 움직이게
                    yDir = 0;
                    MessageBox.Show("Game Over!");
                }
            }
            //2p 자신의 몸 통과 못하기, 몸끼리 부딪히면 게임 끝!
            for (int i = 1; i < len_2; i++)
            {
                if (bugY_2[0] - yDir_2 == bugY_2[i] && bugX_2[0] - xDir_2 == bugX_2[i])
                {
                    xDir_2 = 0; //몸 부딪히면 못 움직이게
                    yDir_2 = 0;
                    MessageBox.Show("Game Over!");
                }
            }
        }
    }
}

 

profile

Devlog

@덩이

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그