C#

2020.07.14 (화) - C# review & 게임만들기

J_Bin 2020. 7. 14. 10:01

1-1-1. 윈폼 크기 조절

namespace _2020._07._13_005
{
    public partial class Form1 : Form
    {
        public Form1()
        {	
            InitializeComponent();
            // 윈폼크기조절
            ClientSize = new Size(550, 550);
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Image image = new Bitmap(Properties.Resources.Image1);
            e.Graphics.DrawImage(image, 120, 0);

        }
    }
}

1-1-2. 캐릭터 만들기

그림판을 이용해 게임에 사용할 캐릭터를 앞 옆 뒷모습을 만들었다. 

2-1-1. Class

-추상화 : 상상하는 것

-캡슐화 : 데이터의 '은닉' 개념, 필요한 것만 보여주고 필요없는 것은 가린다.

-모듈화 : 조각조각 내는 것 , 생산성 향상

-계층성 : 유지보수가 편리함

 

-객체를 분석해서 클래스(문서화)를 만든다.

-객체는 실제 존재

-속성은 변수, 행위는 메서드

-변수와 메서드를 모아놓은 것을 클래스

-프로그램 빌딩 할 때 클래스 단위로 만들어야 한다.

 

2-1-2. 상속

-단일 상속 : 하나의 클래스를 상속 받아 하나의 클래스를 만든다. (C#)

-다중 상속 : 여러 개의 클래스를 상속 받아 클래스를 만든다.

둘 다 복잡하다!

 

2-1-3. Car class 만들기

객체지향적 프로그래밍을 만들 때 속성과 행위로 일단 나누어 생각해보자.

 

컴퓨터의 메모리 partion

-Code: 메서드, 상수(변하지 않는 수) / ReadOnly

-Data

-Bss

-Heap: 객체

-Stack: 지역변수(메서드 내부의 변수)

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


class Auto 
{
    static void Main1(string[] args)
    {
        //// Car클래스를 지칭하는 aCar생성
        //Car aCar;
        //// 객체를 생성할 때는 new를 사용
        //aCar = new Car();
        //// Car클래스 내부의 Run메서드 호출
        //aCar.Run();
        //aCar.Speed = 0;
        //// 표현방법
        ////Console.WriteLine($"aCar의 속도는 {aCar.Speed}입니다.");          // C#만
        //Console.WriteLine("aCar의 속도는 {0}입니다.", aCar.Speed);          // C, C++, C# (이게 좀 더 좋은거같다?)
        ////Console.WriteLine("aCar의 속도는 " +  aCar.Speed + "입니다.");    // 객체지향프로그램들
    }

    static void Main(string[] args)
    {
        Car aCar = new Car();
        aCar.Accel();
        aCar.Accel();
        aCar.Accel();
        aCar.Accel();

        aCar.Break();
        aCar.Break();
        aCar.Break();
        aCar.Break();
        aCar.Break();

    }

}
// Car 클래스
class Car
{
    // 속성(attribute)은 변수로 표현
    // 상수 설정(이것만 고치면 메서드안에 있는 것들 전부 한번에 고칠 수 있다.) 한개로 통합한다는 의미
    // private : 외부에서접근불가
    private const int SpeedValue = 10;
    private const int SpeedLimit = 200;
    // 속도 : 숫자 => int
    private int Speed;


    // 행위(behavior)는 메서드로 표현
    public void Run ()
    {
        Console.WriteLine("달립니다.");
    }

    public void Accel()
    {
        Speed = Speed + SpeedValue;

        if (Speed > SpeedLimit)
        {
            Speed = SpeedLimit;
        }
        Console.WriteLine("현재속도는 {0}입니다.", Speed);
    }

    public void Break()
    {
        Speed = Speed - SpeedValue;

        if (0 > Speed)
        {
            Speed = 0;
        }
        Console.WriteLine("현재속도는 {0}입니다.", Speed);
    }
}

 

 

 

3-1-1. 생성자 in Car Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _2020._07._14_002
{
    class Program
    {   // inner 클래스
        class Car
        {
            string color;
            string vender;
            string name;

            /* 생성자
             * 1. 메서드
             * 2. 클래스와 이름이 동일
             * 3. 반환 타입이 존재하지 않는다.(void가 필요x)
             * */

            // 생성자(public이어야 다른곳에서 생성자를 불러올 수 있다.)
            public Car()    // 디폴트 생성자 (인자가 없는 생성자)
            {
                Console.WriteLine("Car 디폴트 생성자 호출");

            }

            public Car(string name) // 생성자 오버로딩(생성자 이름이 같다!)
            {
                Console.WriteLine("Car 생성자 호출");

            }

            /* Car 생성자의 소멸자, 생성자가 소멸할 때 해야할 일들을 여기 적는다.
             * 얘는 Main에서 호출하지 않아도 자동으로 호출된다.
             * 소멸자는 맨 마지막에 호출된다.*/
            ~Car()
            {
                Console.WriteLine("Car 소멸자 호출");

            }

          
        }

        static void Main(string[] args)
        {
            Console.WriteLine("1=======================");
            // 생성자 호출(생성자는 객체가 만들어질 때 딱 1번만 만들어진다.)
            Car aCar = new Car("비앰다블유");   // 생성자 1번 호출
            new Car();              // 생성자 2번 호출
            Console.WriteLine("2=======================");

        }
    }
}

4-1-1. 게임 만들기(캐릭터 움직이기)

배경 만들기

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

namespace _2020._07._13_005
{
    public partial class Form1 : Form
    {   // 앞모습, 왼쪽, 오른쪽, 뒷모습
        Image Human;
        Image HumanF;
        Image HumanL;
        Image HumanR;
        Image HumanB;
        Image Box;
        Image Wall;
        Image Dot;
        Image Road;
        int   WTile;
        int   HTile;
        const int WTileSize = 16;
        const int HTIleSize = 9;

        string[] Map;

        int XHuman;
        int YHuman;

        public Form1()
        {
            InitializeComponent();

            HumanF = new Bitmap(Properties.Resources.HumanF);
            WTile = HumanF.Width;       // 가로크기(48)
            HTile = HumanF.Height;     // 세로크기(48)
            ClientSize = new Size(WTileSize * WTile, HTIleSize * HTile);


            HumanL = new Bitmap(Properties.Resources.HumanL);
            HumanR = new Bitmap(Properties.Resources.HumanR);
            HumanB = new Bitmap(Properties.Resources.HumanB);
            Human = HumanF;

            Box = new Bitmap(Properties.Resources.Box);
            Wall = new Bitmap(Properties.Resources.Wall);
            Dot = new Bitmap(Properties.Resources.Dot);
            Road = new Bitmap(Properties.Resources.Road);

            XHuman = 0;
            YHuman = 0;
            //////////////////////1234567890123456///////////
            string[] TempMap = { "################",
                                 "#       BB     #",
                                 "#### # B  #  ###",
                                 "#    #B#  #B####",
                                 "##  B#      ####",
                                 "##  #   #  #####",
                                 "##   #B    ...##",
                                 "#    ## B  ...##",
                                 "################"
                                };
            // TempMap 배열을 만들어 Map에 대입
            Map = TempMap;
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {	// 이중 for문
            for (int j = 0; j < HTIleSize; ++j)
            {
                for (int i = 0; i < WTileSize; ++i)
                {	// '#'은 Wall
                    if ('#' == Map[j][i])
                    {
                        e.Graphics.DrawImage(Wall, WTile * i, HTile * j);
                    }	// 'B'는 Box
                    else if ('B' == Map[j][i])
                    {
                        e.Graphics.DrawImage(Box, WTile * i, HTile * j);
                    }
                }
            }
            e.Graphics.DrawImage(Human, XHuman, YHuman);

        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            // 왼쪽방향키를 눌렀을 때 HumanB 생성   내가 처음만든 코드
            /*if(e.KeyCode == Keys.Left)
            {   //Graphics 객체생성
                XHuman = XHuman - 10;
                Refresh();
            }
            else if (e.KeyCode == Keys.Right)
            {
                XHuman = XHuman + 10;
                Refresh();
            }
            else if (e.KeyCode == Keys.Up)
            {
                YHuman = YHuman - 10;
                Refresh();
            }
            else if (e.KeyCode == Keys.Down)
            {
                YHuman = YHuman + 10;
                Refresh();
            }*/


            // switch case문은 그 값만 불러오기 때문에 if > else if 보다 좀 더 효율적이다.
            switch (e.KeyCode)
            {
                case Keys.Left:
                    XHuman = XHuman - 10;
                    Human = HumanL;
                    break;
                case Keys.Right:
                    XHuman = XHuman + 10;
                    Human = HumanR;
                    break;
                case Keys.Up:
                    YHuman = YHuman - 10;
                    Human = HumanF;
                    break;
                case Keys.Down:
                    YHuman = YHuman + 10;
                    Human = HumanB;
                    break;
                default:
                    return;
            }
            Refresh();

            /* 최적화
             * 1. else if 사용하기
             * 2. swich case문으로 변경
             * 3. Refresh()를 밖으로 뺌 */
             
        }
    }
}