所有游戏对象的父类代码
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 推箱子
{
enum Direction //上下左右和无方向
{
Up,
Down,
Left,
Right
}
/// <summary>
/// 定义所有游戏对象的父类
/// </summary>
abstract class GameObject
{
#region X,Y坐标 高宽 方向
public int X
{
set;
get;
}
public int Y
{
set;
get;
}
public int Width
{
set;
get;
}
public int Height
{
set;
get;
}
public Direction Dir
{
get;
set;
}
#endregion
public GameObject(int x,int y,int height,int width,Direction dir)
{
this.X = x;
this.Y = y;
this.Height = height;
this.Width = width;
this.Dir = dir;
}
public abstract void Draw(Graphics g);
public virtual void Move()
{
switch (Dir)
{
case Direction.Up:
this.Y -= 35;
break;
case Direction.Down:
this.Y += 35;
break;
case Direction.Left:
this.X -= 35;
break;
case Direction.Right:
this.X += 35;
break;
default:
break;
}
}
/// <summary>
/// 获取该游戏对象的矩形范围
/// </summary>
/// <returns></returns>
public virtual Rectangle GetRectangle()
{
return new Rectangle(this.X, this.Y, this.Width, this.Height);
}
public Rectangle GetNextRe()
{
switch (Dir)
{
case Direction.Right:
return new Rectangle(this.X + this.Width, this.Y + this.Height / 2, 1, 1);
case Direction.Left:
return new Rectangle(this.X - 1, this.Y + this.Height / 2, 1, 1);
case Direction.Up:
return new Rectangle(this.X + this.Width / 2, this.Y - 1, 1, 1);
case Direction.Down:
return new Rectangle(this.X + this.Width / 2, this.Y + this.Height, 1, 1);
}
return new Rectangle(this.X, this.Y, this.Width, this.Height);
}
}
}
玩家类代码
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 推箱子.Properties;
namespace 推箱子
{
/// <summary>
/// 玩家类
/// </summary>
class Player:GameObject
{
//玩家图片
private static Image imgPlayer=Resources.player;
/// <summary>
/// 初始化父类的属性并缩小图片尺寸
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="dir"></param>
public Player(int x,int y,Direction dir):base(x,y,35,35,dir)
{ }
/// <summary>
/// 绘制当前人物并按照当前的朝向
/// </summary>
/// <param name="g"></param>
public override void Draw(Graphics g)
{
switch (Dir)
{
case Direction.Right:
imgPlayer = Resources.player;
break;
case Direction.Down:
imgPlayer = Resources.player;
RotateFlipType type = RotateFlipType.Rotate90FlipNone;
imgPlayer.RotateFlip(type);
break;
case Direction.Left:
imgPlayer = Resources.player;
type = RotateFlipType.Rotate180FlipY;
imgPlayer.RotateFlip(type);
break;
case Direction.Up:
imgPlayer = Resources.player;
type = RotateFlipType.Rotate270FlipNone;
imgPlayer.RotateFlip(type);
break;
}
g.DrawImage(imgPlayer, this.X,this.Y,this.Width,this.Height);
Pen p = new Pen(Color.Blue, 2);//定义了一个蓝色,宽度为的画笔
g.DrawRectangle(p, this.X, this.Y, this.Width, this.Height);
}
public int clikcnt = 0;
public override void Move()
{
if (clikcnt == 2)
{
base.Move();
clikcnt = 0;
}
}
}
}
奖品类代码(被箱子盖住的)
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 推箱子.Properties;
namespace 推箱子
{
class Reward:GameObject
{
public static Image imgRew=Resources.reward;
public Reward(int x, int y) : base(x, y, 35, 35, Direction.Down)
{ }
public bool IsOver
{
set;
get;
} = false;
public override void Draw(Graphics g)
{
g.DrawImage(imgRew,this.X, this.Y, this.Width, this.Height);
}
}
}
箱子类代码
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 推箱子.Properties;
namespace 推箱子
{
class Box : GameObject
{
public static Image imgBox=Resources.box;
public Box(int x, int y) : base(x, y, 35, 35, Direction.Up)
{}
public bool ismove = false;
public override void Draw(Graphics g)
{
g.DrawImage(imgBox,this.X, this.Y,this.Width,this.Height);
}
}
}
墙类代码
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 推箱子.Properties;
namespace 推箱子
{
class Wall:GameObject
{
public static Image imgWall = Resources.wall;
public Wall(int x, int y) : base(x, y, 35, 35, Direction.Down)
{ }
public override void Draw(Graphics g)
{
g.DrawImage(imgWall, this.X, this.Y, this.Width, this.Height);
}
}
}
单例设计模式的单例类代码
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 推箱子
{
class SingleObject
{
//单例设计模式
//1、构造函数私有化
private SingleObject()
{ }
//2、声明全局唯一的对象
private static SingleObject _single = null;
//3、提供一个静态函数用于返回一个唯一的对象
public static SingleObject GetSingle()
{
if (_single == null)
{
_single = new SingleObject();
}
return _single;
}
#region 游戏所有对象的声明
public Player P1
{
get;
set;
}
public List<Box> listBox = new List<Box>();
public List<Wall> listWall = new List<Wall>();
public List<Reward> listRew = new List<Reward>();
#endregion
//声明地图数组
static int[,] map = new int[10, 10]
{
{0 ,0 ,0 ,1 ,1 ,1 ,1 ,0 ,0 ,0 },
{0 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,0 },
{1 ,1 ,1 ,1 ,0 ,0 ,1 ,0 ,0 ,0 },
{1 ,0 ,0 ,0 ,0 ,0 ,1 ,0 ,0 ,0 },
{1 ,0 ,2 ,2 ,0 ,0 ,1 ,0 ,0 ,0 },
{1 ,0 ,0 ,0 ,0 ,0 ,1 ,0 ,0 ,0 },
{1 ,0 ,0 ,0 ,0 ,0 ,1 ,1 ,1 ,1 },
{1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,3 ,1 },
{1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,3 ,1 },
{1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 }
};
/// <summary>
/// 按照map数组创建地图,1为墙 2为箱子 3为奖励
/// </summary>
public void CreatMap()
{
for(int i=0;i<10;i++)
for(int j=0;j<10;j++)
{
if (map[i, j] == 1) SingleObject.GetSingle().AddGameObject(new Wall(j * 35, i * 35));
if (map[i, j] == 2) SingleObject.GetSingle().AddGameObject(new Box(j * 35, i * 35));
if (map[i, j] == 3) SingleObject.GetSingle().AddGameObject(new Reward(j * 35, i * 35));
}
}
/// <summary>
/// 添加游戏对象的实例存入list
/// </summary>
/// <param name="go"></param>
public void AddGameObject(GameObject go)
{
if (go is Player)
{
this.P1= go as Player;
}
if(go is Box)
{
listBox.Add(go as Box);
}
if (go is Wall)
{
listWall.Add(go as Wall);
}
if(go is Reward)
{
listRew.Add(go as Reward);
}
}
/// <summary>
/// 绘出所有游戏对象
/// </summary>
/// <param name="g"></param>
public void Draw(Graphics g)
{
//绘画顺序不同 就会产生不同的覆盖效果,越最后画优先级越高,优先级越高就不会被覆盖
for (int i = 0; i < listRew.Count; i++)
{
listRew[i].Draw(g);
}
this.P1.Draw(g);
for (int i=0;i<listBox.Count;i++)
{
listBox[i].Draw(g);
}
for (int i = 0; i < listWall.Count; i++)
{
listWall[i].Draw(g);
}
if(SingleObject.GetSingle().IsPass())
g.DrawString("顺利通关", new Font("宋体", 20, FontStyle.Bold), Brushes.Red, new Point(0, 0));
}
/// <summary>
/// 检测人物当前朝向是否发生碰撞
/// </summary>
/// <returns></returns>
public bool CheckP1()
{
for (int i = 0; i < listBox.Count; i++)
{
if (listBox[i].ismove) continue;
if (listBox[i].GetRectangle().IntersectsWith(P1.GetNextRe()))
{
return true;
}
}
for (int i = 0; i < listWall.Count; i++)
{
if (listWall[i].GetRectangle().IntersectsWith(P1.GetNextRe()))
{
return true;
}
}
return false;
}
/// <summary>
/// 检测箱子与墙,人物与箱子是否发生碰撞,
/// </summary>
public void CheckPZ()
{
//判断箱子
for (int i = 0; i < listBox.Count; i++)
{
//判断奖励是否全部被挡住
for (int j = 0; j < listRew.Count; j++)
{
//如果有一个奖励没有被挡住
if (listRew[j].GetRectangle().IntersectsWith(listBox[i].GetRectangle()))
listRew[j].IsOver = true;
}
//判断人物朝向是否有箱子存在,如果有就将箱子朝向=人物朝向
if (listBox[i].GetRectangle().IntersectsWith(P1.GetNextRe())) listBox[i].Dir = P1.Dir;
//判断当前箱子朝向有无墙壁,是否可以继续移动 true:可以 false:不可以
for (int j = 0; j < listWall.Count; j++)
{
if (listBox[i].GetNextRe().IntersectsWith(listWall[j].GetRectangle()))
{
//只要有一个墙与箱子朝向相接就不能移动,直接跳出循坏
listBox[i].ismove = false;
break;
}
else
{
listBox[i].ismove = true;
}
}
//如果当前箱子朝向不能移动,跳出循环判断下一个箱子
if (!listBox[i].ismove) continue;
//判断当前箱子朝向有无其他箱子,是否可以继续移动 true:可以 false:不可以
for (int j = 0; j < listBox.Count; j++)
{
if (j == i) continue;//如果是箱子本身与本身进行判断则continue
if (listBox[i].GetNextRe().IntersectsWith(listBox[j].GetRectangle()))
{
//只要朝向有一个箱子相接就不能移动,直接跳出循坏
listBox[i].ismove = false;
break;
}
else
{
listBox[i].ismove = true;
}
}
//如果当前箱子朝向不能移动,跳出循环判断下一个箱子
if (!listBox[i].ismove) continue;
//这时箱子是可以移动的,当人物前进时箱子会同向移动
if (listBox[i].GetRectangle().IntersectsWith(P1.GetRectangle()))
{
listBox[i].Dir = P1.Dir;
listBox[i].Move();
listBox[i].ismove = false;//防止检测意外,人物出现移动bug(冲进箱子里)
}
}
}
/// <summary>
/// 用于检测所有奖励是否被箱子盖住
/// </summary>
/// <returns></returns>
public bool IsPass()
{
for(int i=0;i<listRew.Count;i++)
{
if (!listRew[i].IsOver) return false;
}
return true;
}
}
}
窗口界面事件代码
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 推箱子
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
InitialGame();
}
private void Form1_Load(object sender, EventArgs e)
{
//在窗体加载的时候 解决窗体闪烁问题
//将图像绘制到缓冲区减少闪烁
this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint, true);
}
public void InitialGame()
{
SingleObject.GetSingle().AddGameObject(new Player(105, 105, Direction.Up));
SingleObject.GetSingle().CreatMap();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
SingleObject.GetSingle().Draw(e.Graphics);
}
/// <summary>
/// 控制人物上下左右移动
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Up)
{
//实现二次按压才会移动,第一次按键只会改变人物的朝向,当clickcnt为2时 才会move()
SingleObject.GetSingle().P1.clikcnt = 0;
if (SingleObject.GetSingle().P1.Dir == Direction.Up) SingleObject.GetSingle().P1.clikcnt = 1;
SingleObject.GetSingle().P1.Dir = Direction.Up;
SingleObject.GetSingle().P1.clikcnt++;
//检测当前到朝向是否有不可移动的障碍物,发生碰撞时不能继续向前
if (SingleObject.GetSingle().CheckP1())
{
if (SingleObject.GetSingle().P1.Dir == Direction.Up) return;
}
SingleObject.GetSingle().P1.Move();
}
if (e.KeyCode == Keys.Down)
{
//实现二次按压才会移动,第一次按键只会改变人物的朝向,当clickcnt为2时 才会move()
SingleObject.GetSingle().P1.clikcnt = 0;
if (SingleObject.GetSingle().P1.Dir == Direction.Down) SingleObject.GetSingle().P1.clikcnt = 1;
SingleObject.GetSingle().P1.Dir = Direction.Down;
SingleObject.GetSingle().P1.clikcnt++;
//检测当前到朝向是否有不可移动的障碍物,发生碰撞时不能继续向前
if (SingleObject.GetSingle().CheckP1())
{
if (SingleObject.GetSingle().P1.Dir == Direction.Down) return;
}
SingleObject.GetSingle().P1.Move();
}
if (e.KeyCode == Keys.Left)
{
SingleObject.GetSingle().P1.clikcnt = 0;
if (SingleObject.GetSingle().P1.Dir == Direction.Left) SingleObject.GetSingle().P1.clikcnt = 1;
SingleObject.GetSingle().P1.Dir = Direction.Left;
SingleObject.GetSingle().P1.clikcnt++;
if (SingleObject.GetSingle().CheckP1())
{
if (SingleObject.GetSingle().P1.Dir == Direction.Left) return;
}
SingleObject.GetSingle().P1.Move();
}
if (e.KeyCode == Keys.Right)
{
SingleObject.GetSingle().P1.clikcnt = 0;
if (SingleObject.GetSingle().P1.Dir == Direction.Right) SingleObject.GetSingle().P1.clikcnt = 1;
SingleObject.GetSingle().P1.Dir = Direction.Right;
SingleObject.GetSingle().P1.clikcnt++;
if (SingleObject.GetSingle().CheckP1())
{
if (SingleObject.GetSingle().P1.Dir == Direction.Right) return;
}
SingleObject.GetSingle().P1.Move();
}
}
private void Timer1_Tick_1(object sender, EventArgs e)
{
this.Invalidate();
SingleObject.GetSingle().CheckPZ();
}
}
}