ps:本文适用于和我一样刚刚入门egret的同学们,大佬看到这里可以忙别的去了。
之前用egret引擎设计了一款双人设计小游戏-《疯狂大乱斗》,算是初步了解了引擎的使用,这次打算开发一款基于最短路径算法的h5小游戏,思路参考自前段时间很火的《围住神经猫》,这次教程我会尽可能描叙详细,并且附上代码。
先奉上游戏封面镇楼:
--------------------------------------------------------------------------------------游戏封面.jpg
第一步:
算法设计:
《猫猫大作战》的核心算法是最短路径算法(迪杰斯特拉算法–dijkstra算法)
先用C++语言实现一遍:
实现代码:
#include
using namespace std;
//-------------------最短路径 dijkstra算法 狄克斯特拉算法 dijkstra
//图的模板基类
const int DefaultVerticles = 30 ; //默认最大顶点数
//enum bool {false,true}; //为不支持bool类型的编译器设置的,也是为了存储0和1
template <class T,class E>
//用邻接矩阵表示图
class Gragh{
public:
const static E maxWeight=10000;//代表无穷的值
Gragh(int sz=DefaultVerticles);//构造函数
bool GraphEmpty()const{//判断图空
if(numEdges==0) return true;
return false;
}
bool GraphFull()const{//判断图满
if((numVertices==maxVertices)||(numEdges==maxVertices*(maxVertices-1)/2))return true;
return false;
}
int NumberOfVertices(){
return numVertices;//返回顶点数
}
int NumberOfEdges(){
return numEdges;//返回边数
}
bool insertVertex(const T& vertex){//插入顶点vertex
if(numVertices==maxVertices) return false;
VerticesList[numVertices++]=vertex;
cout<<"插入了顶点,下标是"<<numVertices<<endl;
cout<<"值"<<VerticesList[numVertices-1]<<endl;
}
bool insertEdge(int v1,int v2,E cost){
//插入边(v1,v2) 权值为cost
cout<<"v1 v2的值"<<v1<<v2<<endl;
if(v1>-1&&v1<numVertices&&v2>-1&&v2<numVertices&&Edge[v1][v2]==maxWeight)
{
cout<<"插入一条记录"<<endl;
Edge[v1][v2]=cost;
cout<<"插入"<<v1<<" "<<v2<<"权值"<<cost<<endl;
Edge[v2][v1]=cost;
cout<<"插入"<<v2<<" "<<v1<<"权值"<<cost<<endl;
numEdges++;
return true;
}
else return false;
}
int getVertexPos(T vertex){//给出顶点vertex在图中的位置
for(int i=0;i<numVertices;i++)
if(VerticesList[i]==vertex) return i;
return -1;
}
T getValue(int i)
{
//cout<<"getvalue的参数i是"<
return i>=0&&i<=numVertices?VerticesList[i]:NULL;
}
E getWeight(int v1,int v2)
{
return v1!=-1&&v2!=-1?Edge[v1][v2]:0;
}
//protected:
int maxVertices;//最大顶点数
int numEdges;//边数
int numVertices;//顶点数
T * VerticesList;//顶点表
E ** Edge;//邻接矩阵
};
//构造函数
template <class T,class E>
Gragh<T,E>::Gragh(int sz){
maxVertices=sz;
numVertices=0;
numEdges=0;
int i,j;
VerticesList=new T[maxVertices];//创建顶点表数组
Edge=(E**)new E *[maxVertices];//创建邻接矩阵
for(i=0;i<maxVertices;i++)
{
Edge[i]=new E [maxVertices];//创建邻接矩阵
}
for(i=0;i<maxVertices;i++) //邻接矩阵初始化
for(j=0;j<maxVertices;j++)
Edge[i][j]=(i==j)?0:maxWeight;
}
//基于邻接矩阵的图输入/输出的友元重载函数
template <class T,class E>
istream & operator >> (istream& in,Gragh<T,E>& G){
int i,j,k,m,n;
T e1,e2;
E weight;
cout<<"请输入顶点和边数";
in>>n>>m;
cout<<"请输入"<<n<<"个顶点";
for(i=0;i<n;i++){
in>>e1;
G.insertVertex(e1);
}
i=0;
cout<<"请输入"<<m<<"个边的两个端点和权重";
while(i<m){
in>>e1>>e2>>weight;//输入端点信息
j=G.getVertexPos(e1);
k=G.getVertexPos(e2);//查顶点号
if(j==-1||k==-1)
cout<<"信息有误"<<endl;
else
G.insertEdge(j,k,weight); i++;
cout<<"i的值为 "<<i<<endl;
}
return in;
}
//基于邻接矩阵的图输入/输出的友元重载函数
template <class T,class E>
ostream & operator << (ostream& out,Gragh<T,E>& G){
int i,j,m,n;
T e1,e2;
E w;
n=G.NumberOfVertices();
cout<<"顶点数"<<n<<endl;
m=G.NumberOfEdges();
cout<<"边数"<<m<<endl;
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
{
w=G.getWeight(i,j);//取边上权值
cout<<"w的值"<<w<<endl;
if(w>0&&w< 10000)
{
e1=G.getValue(i);
e2=G.getValue(j);//输出
out<<"("<<e1<<","<<e2<<","<<w<<")"<<endl;
}
}
return out;
}
template <class T,class E>
void ShortestPath(Gragh<T,E>& G,T v,E dist[],int path[])
{
int maxValue=G.maxWeight;
int n=G.NumberOfVertices();
bool * S =new bool[n];//最短路径顶点集
int i,j,k;
E w,min;
for(i=0;i<n;i++)
{
dist[i]=G.getWeight(v,i);//数组初始化
S[i]=false;
if(i!=v&&dist[i]<maxValue) path[i]=v;
else path[i]=-1;
}
S[v]=true; dist[v]=0;//顶点v加入集合
for(i=0;i<n-1;i++)
{
min=maxValue;
int u=v;
for(j=0;j<n;j++)
{
if(S[j]==false&&dist[j]<min)
{
u=j;
min=dist[j];
}
}
S[u]=true;
for(k=0;k<n;k++)
{
w=G.getWeight(u,k);
if(S[k]==false&&w<maxValue&&dist[u]+w<dist[k])
{
dist[k]=dist[u]+w;
path[k]=u;
}
}
}
};
template <class T,class E>
void printShortestPath(Gragh<T,E>& G,T v,E dist[],int path[])
{
cout<<"从顶点"<<G.getValue(v)<<"到达其他顶点的最短路径为"<<endl;
int i,j,k;
int n=G.NumberOfVertices();
int *d=new int [n];
for(int i=0;i<n;i++)
{
if(i!=v){
j=i;k=0;
while(j!=v)
{
d[k++]=j;j=path[j];
}
cout<<"顶点"<<G.getValue(i)<<"的最短路径为"<<G.getValue(v);
while(k>0)
{
cout<<"->"<<G.getValue(d[--k])<<" ";
}
cout<<"最短路径长度为"<<dist[i]<<endl;
}
}
delete []d;
}
int main()
{
int *path=new int[1000];
Gragh <int,int>G(30);
cin>>G;
cout<<G;
ShortestPath(G,0,G.Edge[0],path);
printShortestPath(G,0,G.Edge[0],path);
return 0;
}
运行截图:
第二步:基于egret引擎制作游戏封面
封面效果.jpg
修改egret引擎给我们提供的默认舞台大小:
修改位置在index.html中
<div style="margin: auto;width: 100%;height: 100%;" class="egret-player"
data-entry-class="Main"
data-orientation="auto"
data-scale-mode="showAll"
data-frame-rate="30"
data-content-width="1800"//这是修改宽度
data-content-height="1200"//这里修改高度
data-multi-fingered="2"
data-show-fps="false" data-show-log="false"
data-show-fps-style="x:0,y:0,size:12,textColor:0xffffff,bgAlpha:0.9"
>
</div>
这里修改完之后舞台大小就变成封面所示的大小了
接下来修改网页背景图片
<style>
html, body {
-ms-touch-action: none;
background: #888888;
padding: 0;
border: 0;
margin: 0;
height: 100%;
background-image: url(https://i.loli.net/2020/01/21/FpStr29dabmIXQH.jpg);
background-repeat: no-repeat;
background-size: 100%
}
p{
font-weight: bold;
}
</style>
这里说一下,对于游戏素材的问题,网上都可以很轻松的找到相应的资源,如果有需要游戏中的素材的话,欢迎在下方留言。
好了,到现在为止游戏框架已经完成,接下来是封面的制作:
egret引擎的运行的第一个ts文件就是Main.ts文件,我们找到他
找到createGameScene()方法 此方法用来创建场景界面
将游戏背景添加进去(用自己的背景就行)
let sky = this.createBitmapByName("bg1_jpg");
this.addChild(sky);
let stageW = this.stage.stageWidth;
let stageH = this.stage.stageHeight;
sky.width = stageW;
sky.height = stageH;
把小猫添加进去
let icon: egret.Bitmap = this.createBitmapByName("Cat1_png");
this.addChild(icon);
icon.x = 1400;
icon.y = 600;
开一个定时器,实现小猫的移动
var car_move_timer=setInterval(function(){
icon.x-=5;
if(icon.x<0)
icon.x=1600;
},50);
到此为止,游戏封面制作完成。
几个注意的地方(大佬主动忽略):
1.关于图片素材的命名问题,将图片文件上传到resource文件下的assets文件夹下,egret会自动在json文件中添加快速访问名称,例如: bg.img 会变成 bg_img
使用时用bg_img进行访问。
2. 关于gif图片,egret是不支持gif的,添加gif之后图片是不会动的,解决办法是自己制作动画来实现。
3. 其他注意问题,我会在后续教程中持续添加。
接下来的制作,欢迎持续关注–egret开发HTML5小游戏-《猫猫大作战》(二)