C# WPF实战-TankWar开发随笔

复习多线程

Thread childThread1 = new Thread(new ThreadStart(ChildThreadMethod));//创建子线程

childThread1.Start();//开启子线程

GDI绘制图片、线段和文字

#region 绘制线和字符串、和图片
		    Graphics g = this.CreateGraphics(); //画布初始化

			g.DrawString("www.baidu.com", new Font("宋体", 20),
				new SolidBrush(Color.Red), new Point(100, 100));//绘制字符串

			// RGB red green blue

			Pen p = new Pen(Color.Black);

            g.DrawLine(p, new Point(50, 50), new Point(100, 100));//画线段

			//g.DrawString("www.4399.com",
			//    new Font("隶书", 20),
			//    new SolidBrush(Color.Red),
			//    new Point(100, 100));

			Image image = Properties.Resources.Boss;

			g.DrawImage(image, 200, 200); //绘制图片,调用resource图片资源
#endregion

开发流程

编写游戏逻辑

主线程(确定帧率)

编写生命周期 Start( ) --> Update( )

update( )更新每一帧需要的游戏逻辑

        private static void GameMainThread() //绘制游戏主线程【确定帧率】
        {

            //GameFramework

            GameFramework.Start();

            int sleepTime = 1000 / 60;//1000ms除以60,1/60秒

            //60
            while (true)
            {
                GameFramework.g.Clear(Color.Black);//使用黑色背景

                GameFramework.Update();// 60帧(每秒运行60次update)

                windowG.DrawImage(tempBmp, 0, 0);

                Thread.Sleep(sleepTime);//休息1/60s
            }

        }

 private void Form1_FormClosed(object sender, FormClosedEventArgs e) //线程关闭
        {
            t.Abort();
        }

下面给出gameobject的业务逻辑

tank_war_gameobject.drawio.png
GameObject.cs

abstract class GameObject
 {

		//private int x;
		//public int x {
		//    get
		//    { 
		//        return x;
		//    }
		//    set
		//    {
		//        value = x;
		//    } 
		//}
		public int X { get; set; } //绘制时期的x,y坐标
		public int Y { get; set; }

        public int Width { get; set; }
        public int Height { get; set; }

        protected abstract Image GetImage();

        public virtual void DrawSelf() //得到画布,通用图像绘制
        {
            Graphics g = GameFramework.g;

            g.DrawImage(GetImage(),X,Y);//绘制时期需要用到初始坐标和图片
        }


       public virtual void Update()
        {
            DrawSelf();
        }
        public Rectangle GetRectangle()
        {
            Rectangle rectangle = new Rectangle(X, Y, Width, Height);
            return rectangle;
        }
}

添加游戏元素(静态【墙面】)
GameObjectManager.cs

//创建环境方法
private static void CreateWall(int x,int y,int count,Image img, List<NotMovething> wallList)
        {
            int xPosition = x * 30;
            int yPosition = y * 30;
            for(int i = yPosition; i < yPosition + count * 30; i += 15)
            {
                // i xPosition     i xPosition+15
                NotMovething wall1 = new NotMovething(xPosition, i, img);
                NotMovething wall2 = new NotMovething(xPosition+15, i, img);
                wallList.Add(wall1);
                wallList.Add(wall2);
            }
        }
public void static CreateMap(){
   CreateWall(1, 1, 5, Resources.wall ,wallList);//从1,1起竖排创建5个砖块墙   
}
 

在GameFramework.cs中添加
CreateMap 加入 start()
CreateWall 加入update()

解决生成墙面闪烁的问题,原因:墙面和黑色背景是交替出现的

重点:画布的粉刷工作(清空工作)
游戏元素是update()实时更新在新的位置上的,通过粉刷画布实现。

解决闪烁的方法:
每帧创建新的画布,然后铺上图片,然后一次性覆盖窗体初始化画布。

添加Moving类对象(tank)

添加鼠标操作、事件流

   //事件  消息  事件消息
        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            GameObjectManager.KeyDown(e);
        }

        private void Form1_KeyUp(object sender, KeyEventArgs e)
        {
            GameObjectManager.KeyUp(e);
        }

mytank.cs

        public void KeyDown(KeyEventArgs args)
        {
            switch (args.KeyCode)
            {
                case Keys.W:
                    Dir = Direction.Up;
                    IsMoving = true;
                    break;
                case Keys.S:
                    Dir = Direction.Down;
                    IsMoving = true;
                    break;
                case Keys.A:
                    Dir = Direction.Left;
                    IsMoving = true;
                    break;
                case Keys.D:
                    Dir = Direction.Right;
                    IsMoving = true;
                    break;
                case Keys.Space:
                    Attack();
                    break;
            }
        }
        public void KeyUp(KeyEventArgs args)
        {
            switch (args.KeyCode)
            {
                case Keys.W:
                    IsMoving = false;
                    break;
                case Keys.S:
                    IsMoving = false;
                    break;
                case Keys.A:
                    IsMoving = false;
                    break;
                case Keys.D:
                    IsMoving = false;
                    break;
            }
        }

玩家坦克移动

  private void Move()
        {
            if (IsMoving == false) return;

            switch (Dir)
            {
                case Direction.Up:
                    Y -= Speed;
                    break;
                case Direction.Down:
                    Y += Speed;
                    break;
                case Direction.Left:
                    X -= Speed;
                    break;
                case Direction.Right:
                    X += Speed;
                    break;
            }
        }

碰撞检测

  • 是否超出边界
            #region 检查有没有超过窗体边界
            if (Dir == Direction.Up)
            {
                if (Y - Speed < 0)
                {
                    IsMoving = false; return;
                }
            }
            else if (Dir == Direction.Down)
            {
                if (Y + Speed + Height > 450)
                {
                    IsMoving = false; return;
                }
            }
            else if (Dir == Direction.Left)
            {
                if (X - Speed < 0)
                {
                    IsMoving = false; return;
                }
            }
            else if (Dir == Direction.Right)
            {
                if (X + Speed + Width > 450)
                {
                    IsMoving = false; return;
                }
            }
            #endregion

  • 是否发生碰撞墙体
Rectangle rect = GetRectangle();

            switch (Dir)
            {
                case Direction.Up:
                    rect.Y -= Speed;
                    break;
                case Direction.Down:
                    rect.Y += Speed;
                    break;
                case Direction.Left:
                    rect.X -= Speed;
                    break;
                case Direction.Right:
                    rect.X += Speed;
                    break;
            }

            if (GameObjectManager.IsCollidedWall(rect) != null)
            {
                IsMoving = false; return;
            }
            if (GameObjectManager.IsCollidedSteel(rect) != null)
            {
                IsMoving = false; return;
            }
            if (GameObjectManager.IsCollidedBoss(rect))
            {
                IsMoving = false; return;
            }

tank转向(切图片)

 protected override Image GetImage()
        {
            Bitmap bitmap = null;
            switch (Dir)
            {
                case Direction.Up:
                    bitmap = BitmapUp;
                    break;
                case Direction.Down:
                    bitmap =  BitmapDown;
                    break;
                case Direction.Left:
                    bitmap = BitmapLeft;
                    break;
                case Direction.Right:
                    bitmap = BitmapRight;
                    break;
            }
            bitmap.MakeTransparent(Color.Black);

            return bitmap;
        }

实机演示画面
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值