疫情期间无聊,用C#写了个游戏《坦克大战》。
1.概述
程序主要包括地图部分,坦克部分,和碰撞检测部分。本章只写地图部分。
2.地图系统
地图包括底图和上面的地形元素,比如草地(减缓速度),土墙(容易击破),河流(能通过子弹但阻碍坦克)等。而且允许自定义各种地形。
3.重点
地图系统的重要功能是绘图,并保存地图元素,以便主程序进行碰撞判断。
1.可以加载图片当作底图,也可以随机生成。
2.绘制元素,或擦除元素并恢复原来的地图内容。
3.需要保存工具,下次打开程序还能继续使用。
4.需要自动生成地图,并保存到本地。
4.代码
首先要一个静态类,保存地图的各种信息,以便主程序随时调用。
namespace tank
{
/// <summary>
/// 需要保存到本地的信息
/// </summary>
[Serializable]
public class savemap
{
public List<Seritoolitempar> xtoolitems;//保存的地形工具列表
public List<tlandformType> tlandforms; //地形参数列表
public byte[,] mask=new byte[ctankpar.PANSIZEY + cmap.OFFET * 2, ctankpar.PANSIZEX + cmap.OFFET * 2] ;
public Bitmap dstimg, srcimg; //底图
}
/// <summary>
/// 地图系统的信息
/// </summary>
public static class map
{
static public int[,] mapHps ; //保存当前地形HP
static public List<toolitem> toolitems = new List<toolitem>(); //保存地形工具
static public List<toolitem> toolitemsbk = new List<toolitem>(); //保存地形工具
static public List<tlandformType> tlandforms = new List<tlandformType>(); //保存地形选项参数
static public List<ttankinfo> tkinfos; //所有坦克信息
static public byte[,] mask ,maskbk; //地形掩膜,以及其备份
static public Image srcimg; //底图原画,用于恢复
static public Image mainimg ; //主图
//更新当前地形HP
static public bool updatamapHps()
{
if (toolitems.Count == 0)
{ return false; }
mapHps = null;
mapHps = new int[ctankpar.PANSIZEX / ctankpar.TANKSIZEX, ctankpar.PANSIZEY / ctankpar.TANKSIZEY];
int xsize = ctankpar.PANSIZEX / ctankpar.TANKSIZEX;
int ysize = ctankpar.PANSIZEY / ctankpar.TANKSIZEY;
for (int y = 0; y < ysize; y++)
{
for (int x = 0; x < xsize; x++)
{
int it=mask[x*ctankpar.TANKSIZEX,y*ctankpar.TANKSIZEY];
mapHps[x, y] = toolitems[it].lft.hp;
}
}
return true;
}
//跟新地形参数
static public void updatatlandforms()
{
tlandforms.Clear();
foreach (var x in toolitemsbk)
{
tlandforms.Add(x.lft);
}
}
//坦克链表初始化
static public void tksinit()
{
tkinfos = null;
tkinfos = new List<ttankinfo>();
}
//初始化mask
static public void maskinit(ref byte[,] dst)
{
mask = null;
mask = new byte[ctankpar.PANSIZEY + cmap.OFFET * 2, ctankpar.PANSIZEX + cmap.OFFET * 2];
for (int i = 0; i < ctankpar.PANSIZEY + cmap.OFFET * 2; i++)
{
for (int j = 0; j < ctankpar.PANSIZEX + cmap.OFFET * 2; j++)
{
if (i < cmap.OFFET || i > ctankpar.PANSIZEY + cmap.OFFET || j < cmap.OFFET || j > ctankpar.PANSIZEX + cmap.OFFET)
dst[i, j] = clandform.IRONWALL;
else
dst[i, j] = 0;
}
}
}
static public void maskinit()
{
mask = null;
mask = new byte[ctankpar.PANSIZEY + cmap.OFFET * 2, ctankpar.PANSIZEX + cmap.OFFET * 2];
for (int i = 0; i < ctankpar.PANSIZEY + cmap.OFFET * 2; i++)
{
for (int j = 0; j < ctankpar.PANSIZEX + cmap.OFFET * 2; j++)
{
if (i < cmap.OFFET || i > ctankpar.PANSIZEY + cmap.OFFET || j < cmap.OFFET || j > ctankpar.PANSIZEX + cmap.OFFET)
mask[i, j] = clandform.IRONWALL;
else
mask[i, j] = 0;
}
}
}
static public void maskbkinit()
{
maskbk = null;
maskbk = new byte[ctankpar.PANSIZEY + cmap.OFFET * 2, ctankpar.PANSIZEX + cmap.OFFET * 2];
for (int i = 0; i < ctankpar.PANSIZEY + cmap.OFFET * 2; i++)
{
for (int j = 0; j < ctankpar.PANSIZEX + cmap.OFFET * 2; j++)
{
if (i < cmap.OFFET || i > ctankpar.PANSIZEY + cmap.OFFET || j < cmap.OFFET || j > ctankpar.PANSIZEX + cmap.OFFET)
maskbk[i, j] = clandform.IRONWALL;
else
maskbk[i, j] = 0;
}
}
}
//复制
static public void maskcopy(ref byte[,] dst ,byte[,] src )
{
//if (dst == null || src == null) return;
for (int i = 0; i < ctankpar.PANSIZEY + cmap.OFFET * 2; i++)
{
for (int j = 0; j < ctankpar.PANSIZEX + cmap.OFFET * 2; j++)
{
if (i < cmap.OFFET || i > ctankpar.PANSIZEY + cmap.OFFET || j < cmap.OFFET || j > ctankpar.PANSIZEX + cmap.OFFET)
dst[i, j] = clandform.IRONWALL; //超出部分等于钢墙,不可击破
else
dst[i, j] = src[i, j] ;
}
}
}
}
}
在vs设计界面拖动一些控件,菜单等
代码太多,不一一贴了,需要的朋友可以到第三篇文章下载。