A星算法经常会用在寻径算法中,是一种典型的启发式搜索算法,属于人工智能算法的一种,能够让物体在游戏中活动起来。今天刚好看到了A星算法这一块,对于其中涉及的原理和实际的运用做了一定的研究,介于自己第一次接触这块算法,文中借用了一些网上看见的知识介绍和模块,并结合自己的实际使用和结合,最后再cocos2d-x中实现A星算法的简单运用。
先来说说A星算法,作为一种寻径算法,使用递归或者循环的方式进行运算。
启发式算法就是在状态空间图中对每个搜索的位置进行评估,得到评估值最优的位置点,逐个对位置点评估直到目标。
文中采用的A星搜索是一种迭代的有序搜索。维护一个状态空间的开发集合。每次使用一个评价函数F(n)评价集合中各个邻接点的状态,选择最小的代价,直到达到终点为止。
其中定义
F(N) = G(n) + H(n)
G(n) :从初始点到第N个点的最短路径
H(n):从第N个点到目标点的估算代价,一般不是一个真实值,而是一个估计值。
F(N):到目前的迭代阶段从初始点经过第N个点到目的点的预计值。
A星算法思考过程如下:
1,首先把整个地图,划分为若干个小块,通常最简单的小块,全部都是正方形,这些小块,有些是障碍,有些是通道。我们把小块都称为节点。
2,在A型算法中有下面几个比较重要的量:
①自己的横坐标
②自己的纵坐标
③自己离起点的距离
④自己离终点的距离
⑤父节点的横坐标
⑥父节点的纵坐标
⑦F值,这个F值,就是属性③和属性④相加得到的和,因为可以计算,所以我们暂时不作为一个单独的属性来记录,而是作为描述使用
①②属性很好理解,不解释了;
③属性也很简单,代表的是从起点进过多少步到达此节点;
④属性,由于在获取到完整的路径之前,你并不知道需要经过多少步会达到终点,所以这个属性实际上是一个估算值,估算的方法也有很多,对整个A星的计算效率也会有影响,我们暂时使用一个较为简单的估算方法:采用所在点在最后终点的横纵坐标差的和来计算,体现在最后的代码getH()函数中,如下所示。
int Astar::getH(int col,int row)
{
//获得该点的h值
return abs(aimCol - col) * 10 + abs(aimRow - row) * 10;
}
⑤⑥属性解释下,这2个坐标是指的你从哪一个节点到达的当前节点,也就是对应的上一个节点。这2个属性可以确保在最终你能找到最短路径。
3、寻路过程中我们会用到3个列表,这3个表,通常被设计为一维数组
开放列表。我们在寻路过程中,认为可能符合要求的点,就添加到开放列表中,下面的例子中为open列表;
探索列表。我们对开放列表里面所有的节点进行判断,符合要求的,放到这个表中,下面的例子中文close列表;
路径列表。从探索列表里面所有符合要求的节点中,找出的最短路径的节点,下面的例子中文path列表;
4、寻路的步骤
a)将起点放入探索列表,定义为当前节点。
b)检测当前节点周围的节点(本例中进行4方向检测),这些周围的点,称为临时节点。如果该临时节点是通道,那么将其加入开放列表。
将 c 和 d这2步,作为循环来处理
c)从开放列表中,选取一个F值最小的节点(就是属性③和属性④相加最小,代表着这个节点在当前看来是符合最短路径的要求的),将它从开放列表中去掉,加入到探索列表中。如果开放列表中,有多个节点的F是相等的,那么我们选取属性③比较小的节点(因为距离起点的值是可靠的,而距离终点的值是估算的),如果属性③仍然相等,那么我们选取最新加入到开放列表的那个节点(这一步在大地图的时候,会增加速度)。
d)将这个选出来的点,再次作为当前节点,开始检测它周围的4个临时节点,从这个时候开始,如果临时节点是障碍,我们就舍弃;而如果是通道,我们也不能像第 b)步 那样直接把这个临时节点加入到开放列表。我们还需要判断:第一,该临时节点是否已经被加入了探索列表?如果是,那么舍弃它;第二,该临时节点是否已经在开放列表中?如果是,那么代表这个临时节点和保存在开放列表中的节点,属性①②相同,但属性③⑤⑥必定不完全相同(因为是经由不同的父节点进行检测,这一点需要理解),于是我们对临时节点和保存在开放列表中的节点(属性①②相同的这2个节点)进行属性③的对比(这2个点的属性④是相同的),如果临时节点的属性③比较小,那么我们就将临时节点的信息,替换掉已经保存在开放列表中那个节点的所有信息,否则我们就舍弃这个临时节点;第三,该临时节点是个通道,没有保存在探索列表中,也没有在开放列表中,那么我们把这个临时节点加入到开放列表。
进行 c-d 的循环
e)循环在何时结束?很简单,当终点也被加入到了探索列表中,代表着我们的探索已经完成,这个时候跳出循环
f)循环结束之后,我们获得了一个比较庞大的探索列表,里面包含了我们所有探索过的节点,其中,第一个是起点,最后一个是终点。于是我们从终点开始,检测其父节点的坐标,然后再检测父节点的父节点,最终我们得到了一条从终点指向起点的最短路径。
理论清楚以后,下面开始具体的cocos2d-x的实现;
首先是A星算法相关节点信息的定义,如下所示:
#pragma once
#include "cocos2d.h"
using namespace cocos2d;
class AstarItem:public CCNode
{
public:
AstarItem(void);
~AstarItem(void);
void setpos(int col,int row);
int getcol(){return id_col;};
int getrow(){return id_row;};
void setg(int g);
int getg(){return id_g;};
void seth(int h);
int geth(){return id_h;};
void setfid(int fid);
int getfid(){return id_fid;};
void setf(int f);
int getf(){return id_f;};
private:
int id_col;//列
int id_row;//行
int id_g;// 实际代价
int id_h;// 估计代价
int id_fid;// 父节点id
int id_f;// 估价函数f = g + h
};
接着是相关的实现文件,以简单的存取为内容
#include "Astaritem.h"
AstarItem::AstarItem(void)
{
}
AstarItem::~AstarItem(void)
{
}
void AstarItem::setpos(int col,int row)
{
id_col = col;
id_row = row;
}
void AstarItem::setg(int g)
{
id_g = g;
}
void AstarItem::seth(int h)
{
id_h = h;
}
void AstarItem::setfid(int fid)
{
id_fid = fid;
}
void AstarItem::setf(int f)
{
id_f = f;
}
接着是A星算法的相关头文件定义
#pragma once
#include "cocos2d.h"
#include "AstarItem.h"
using namespace cocos2d;
class Astar
{
private:
int curCol, curRow, aimCol, aimRow;
int AimX, AimY, AimW, AimH;
CCTMXTiledMap* map;
CCArray *open;
CCArray *close;
CCArray *path;
public:
Astar(void);
~Astar(void);
int getG(int col,int row,int id);
int getH(int col,int row);
void fromopentoclose();
void removefromopen();
void getpath();
void starseach(int fid);
void resetSort(int last);
bool checkclose(int col,int row);
void addtoopen(int col,int row,int id);
bool checkmap(int col,int row);
bool checkOpen(int col,int row,int id);
CCArray *findPath(int curX, int curY, int aimX, int aimY, CCTMXTiledMap* passmap);
};
接着是相关的实现文件,算法设计了迭代,最小堆的排序,循环等众多的内容,在具体的实现中,我在代码中加了相关的注释进行说明:
#include "Astar.h"
#include "Astaritem.h"
Astar::Astar(void)
{
}
Astar::~Astar(void)
{
open->removeAllObjects();
close->removeAllObjects();
path->removeAllObjects();
}
CCArray *Astar::findPath(int curX, int curY, int aimX, int aimY, CCTMXTiledMap* passmap)
{
//参数以及记录路径数组初始化
curCol = curX;
curRow = curY;
aimCol = aimX;
aimRow = aimY;
map = passmap;
<span style="background-color: rgb(51, 255, 51);">path = new CCArray(); </span>
open = new CCArray();
AstarItem * temp = new AstarItem();
<span style="background-color: rgb(51, 255, 51);">open->addObject(temp); //加入一个空白元素到open列表中是因为头元素设置为空,方便以后的堆排序计算。</span>
AstarItem * temp1 = new AstarItem();
temp1->setpos(curCol,curRow);
temp1->setg(0);
int ag = getH(curCol,curRow);
temp1->seth(ag);
temp1->setfid(0);
temp1->setf(ag);
<span style="background-color: rgb(51, 255, 51);">open->addObject(temp1); //将第一个起点放如open列表</span>
close = new CCArray();
//遍历寻找路径
while(open->count() > 1){
<span style="background-color: rgb(255, 255, 0);">fromopentoclose();//open和close列表管理</span>
<span style="background-color: rgb(51, 255, 51);"> int fatherid = close->count() - 1; </span>
if(abs(aimCol - ((AstarItem *)close->objectAtIndex(fatherid))->getcol()) <= 1 && abs(aimRow - ((AstarItem *)close->objectAtIndex(fatherid))->getrow()) <= 1){
getpath();
break;
}else{
//搜索
starseach(fatherid);
}
}
open->removeAllObjects();
close->removeAllObjects();
//获得路径
if(path->count() == 0){
return NULL;
}else{
if(((AstarItem *)path->lastObject())->getcol() != aimCol || ((AstarItem *)path->lastObject())->getrow() != aimRow){
AstarItem * temp = new AstarItem();
temp->setpos(aimCol,aimRow);
path->addObject(temp);
}
return path;
}
}
void Astar::starseach(int fid)
{
int col = ((AstarItem *)close->objectAtIndex(fid))->getcol();
int row = ((AstarItem *)close->objectAtIndex(fid))->getrow();
//搜索目前点的上下左右四个方向
int mycol = col;
int myrow = row - 1;
if(myrow >= 0 && checkmap(mycol,myrow)){
if(checkOpen(mycol,myrow,fid) && checkclose(mycol,myrow)){
addtoopen(mycol,myrow,fid);
}
}
mycol = col - 1;
myrow = row;
if(mycol >= 0 && checkmap(mycol,myrow)){
if(checkOpen(mycol,myrow,fid) && checkclose(mycol,myrow)){
addtoopen(mycol,myrow,fid);
}
}
mycol = col;
myrow = row + 1;
if(myrow < map->getMapSize().width && checkmap(mycol,myrow)){
if(checkOpen(mycol,myrow,fid) && checkclose(mycol,myrow)){
addtoopen(mycol,myrow,fid);
}
}
mycol = col + 1;
myrow = row;
if(mycol < map->getMapSize().height && checkmap(mycol,myrow)){
if(checkOpen(mycol,myrow,fid) && checkclose(mycol,myrow)){
addtoopen(mycol,myrow,fid);
}
}
}
void Astar::addtoopen(int col,int row,int id)
{
//向open列表中加入点
AstarItem * temp = new AstarItem();
temp->setpos(col,row);
temp->setfid(id);
int g = getG(col, row, id);
int h = getH(col, row);
temp->setg(g);
temp->seth(h);
temp->setf(g + h);
open->addObject(temp);
resetSort(open->count() - 1);
}
bool Astar::checkclose(int col,int row)
{
//检查close列表
for(int i = close->count() - 1;i > 0;i --){
if(((AstarItem *)close->objectAtIndex(i))->getcol() == col && ((AstarItem *)close->objectAtIndex(i))->getrow() == row){
return false;
}
}
return true;
}
bool Astar::checkOpen(int col,int row,int id)
{
//检查open列表中是否有更小的步长,并排序
for(int i = open->count() - 1;i > 0;i --){
if(((AstarItem *)open->objectAtIndex(i))->getcol() == col && ((AstarItem *)open->objectAtIndex(i))->getrow() == row){
int tempG = getG(col,row,id);
if(tempG < ((AstarItem *)open->objectAtIndex(i))->getg()){
((AstarItem *)open->objectAtIndex(i))->setg(tempG);
((AstarItem *)open->objectAtIndex(i))->setfid(id);
((AstarItem *)open->objectAtIndex(i))->setf(tempG + ((AstarItem *)open->objectAtIndex(i))->geth());
resetSort(i);
}
return false;
}
}
return true;
}
bool Astar::checkmap(int col,int row)
{
//检查地图中是否有碰撞
if(abs(aimCol - col) > 1 || abs(aimRow - row) > 1){
CCTMXLayer* layer = map->layerNamed("grass");
int tilegid = layer->tileGIDAt(ccp(col,row));
CCDictionary *tiledic = map->propertiesForGID(tilegid);
CCString *mvalue = (CCString *)tiledic->objectForKey("conflict");
int mv = mvalue->intValue();
if(mv == 1){
return false;
}
}
return true;
}
void Astar::getpath()
{
//从整个close数组中找出路径
if(path->count() == 0){
path->addObject(close->objectAtIndex(close->count() - 1));
}else{
path->insertObject(close->objectAtIndex(close->count() - 1),path->count() - 1);
}
while(true){
if(((AstarItem *)path->objectAtIndex(0))->getg() == 0){
break;
}
path->insertObject(close->objectAtIndex(((AstarItem *)path->objectAtIndex(0))->getfid()),0);
}
curCol = aimCol;
curRow = aimRow;
}
void Astar::fromopentoclose()
{
//<span style="background-color: rgb(255, 255, 102);">把open列表中的点放到close列表中</span>
AstarItem * temp = (AstarItem *)open->objectAtIndex(1);
close->addObject(temp);
removefromopen();
}
void Astar::removefromopen()
{
int last = open->count() - 1;
open->replaceObjectAtIndex(1,open->lastObject(),true);
open->removeLastObject();
last = open->count() - 1;
<span style="color:#330033;background-color: rgb(51, 255, 51);"><span style="white-space:pre"> </span>//堆排序
<span style="white-space:pre"> </span>/*int head = 1;
<span style="white-space:pre"> </span>while( ( head*2) <= last){
<span style="white-space:pre"> </span>int child1 = head * 2;
<span style="white-space:pre"> </span>int childe = head*2 + 1;
<span style="white-space:pre"> </span>int childmin;
<span style="white-space:pre"> </span>if ((head*2 + 1) < last )<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>childmin = (((AstarItem *)open->objectAtIndex(child1))->getf() <( ((AstarItem *)open->objectAtIndex(childe))->getf()) ? child1:childe);
<span style="white-space:pre"> </span>else
<span style="white-space:pre"> </span>childmin = child1;
<span style="white-space:pre"> </span>if ( ((AstarItem *)open->objectAtIndex(head))->getf() <(((AstarItem *)open->objectAtIndex(childmin))->getf()))
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>break;
<span style="white-space:pre"> </span>head = childmin;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>AstarItem *temp = (AstarItem *)open->objectAtIndex(childmin);
<span style="white-space:pre"> </span>open->replaceObjectAtIndex(childmin, open->objectAtIndex(head), false);
<span style="white-space:pre"> </span>open->replaceObjectAtIndex(head, temp, true);
<span style="white-space:pre"> </span>temp->release();
<span style="white-space:pre"> </span>head = childmin;
<span style="white-space:pre"> </span>}*/ 内容属于对open中的节点进行相关的堆排序,但实现后出现程序编译通过,运行报堆栈错误,希望有遇见的朋友可以一起解决,不加入这部分的话能够实现,但是人物运动有问题,非常的不智能。属于重点讨论部分</span>
}
void Astar::resetSort(int last)
{
//根据步长排序,堆排序
while(last > 1){
int half = last / 2;
if(((AstarItem *)open->objectAtIndex(half))->getf() >= ((AstarItem *)open->objectAtIndex(last))->getf())
break;
open->exchangeObjectAtIndex(half,last);
last = half;
}
}
int Astar::getG(int col,int row,int id)
{
//获得该点的g函数值
int fx = ((AstarItem *)close->objectAtIndex(id))->getcol();
int fy = ((AstarItem *)close->objectAtIndex(id))->getrow();
int fg = ((AstarItem *)close->objectAtIndex(id))->getg();
if(fx - col != 0 && fy - row != 0){
return fg + 14;
}else{
return fg + 10;
}
}
int Astar::getH(int col,int row)
{
//获得该点的h值
return abs(aimCol - col) * 10 + abs(aimRow - row) * 10;
}
接着是相关的场景文件
#ifndef __MAPSCENE_H__
#define __MAPSCENE_H__
#define LAYER_CREATE_FUNC(layer) static layer* create() { layer *pRet = new layer(); if (pRet && pRet->init()) { pRet->autorelease(); return pRet; } else { delete pRet; pRet = NULL; return NULL; } }
#include "cocos2d.h"
#include "SimpleAudioEngine.h"
#include "Astar.h"
#include "AstarItem.h"
using namespace cocos2d;
class MapScene :public CCLayer
{
private:
CCArray * path;
int stepindex;
int smallstepindex;
public:
int vmove;
int hmove;
Astar * myastar;
CCSprite* m_tamara;
virtual bool init();
void update(float dt);
//void MapScene::update1(ccTime dt);
static cocos2d::CCScene* scene();
CCPoint convertto2d(float x,float y);
virtual void menuCloseCallback(CCObject* pSender);
virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);
LAYER_CREATE_FUNC(MapScene);
};
#endif
和实现文件
#include "MapScene.h"
#include "Astar.h"
#include "AstarItem.h"
#include <math.h>
using namespace cocos2d;
enum
{
kTagTileMap = 1,
};
CCScene* MapScene::scene()
{
CCScene *scene = CCScene::create();
MapScene *layer = MapScene::create();
scene->addChild(layer);
return scene;
}
// on "init" you need to initialize your instance
bool MapScene::init()
{
if ( !CCLayer::init() )
{
return false;
}
//初始化地图
CCTMXTiledMap *map = CCTMXTiledMap::create("iso-test-zorder.tmx");
addChild(map, 0, kTagTileMap);
CCSize s = map->getContentSize();
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
----UXLOG("ContentSize: %f, %f", s.width,s.height);
map->setPosition(ccp(-s.width/2 + winSize.width/2,0));
//初始化人物
m_tamara = CCSprite::create("grossinis_sister1.png");
map->addChild(m_tamara, map->getChildren()->count() );
m_tamara->retain();
int mapWidth = map->getMapSize().width * map->getTileSize().width;
int mapHeight = map->getMapSize().height * map->getTileSize().height;
m_tamara->setPosition(ccp( mapWidth/2,112));
m_tamara->setAnchorPoint(ccp(0.5f,0));
setTouchEnabled(true);
scheduleUpdate();
vmove = -1;
hmove = -1;
stepindex = -1;
myastar = new Astar();
return true;
}
//坐标与地图位置的转换
CCPoint MapScene::convertto2d(float x,float y){
CCTMXTiledMap* map = (CCTMXTiledMap*) getChildByTag(kTagTileMap);
int mapWidth = map->getMapSize().width * map->getTileSize().width;
int mapHeight = map->getMapSize().height * map->getTileSize().height;
double distanse;
double sin1;
double sin11;
double sin22;
double cos11;
double cos1;
int d2x;
int d2y;
double mystatic5 = sqrt(5.0);//«Û∏˘∫≈5
double mystatic = 16 * mystatic5;//–°ÕºøÈ¿‚≥§
//char mch[256];
if(x > mapWidth/2){
distanse = sqrt((x - mapWidth/2) * (x - mapWidth/2) + (mapHeight - y) * (mapHeight - y));
sin1 = (mapHeight - y)/distanse;
cos1 = (x - mapWidth/2)/distanse;
sin11 = (sin1 * 2 - cos1) / mystatic5;
cos11 = (sin1 + cos1 * 2) / mystatic5;
d2y = distanse * 5 / 4 * sin11 / mystatic;
sin22 = (2 * sin1 + cos1) / mystatic5;
d2x = distanse * 5 / 4 * sin22 / mystatic;
return ccp(d2x,d2y);
}else{
distanse = sqrt((mapWidth/2 - x) * (mapWidth/2 - x) + (mapHeight - y) * (mapHeight - y));
sin1 = (mapHeight - y)/distanse;
cos1 = (mapWidth/2 - x)/distanse;
sin11 = (sin1 * 2 - cos1) / mystatic5;
cos11 = (sin1 + cos1 * 2) / mystatic5;
d2x = distanse * 5 / 4 * sin11 / mystatic;
//sin22 = 4.0 * cos11 / 5 + 3.0 * sin11 / 5;
sin22 = (2 * sin1 + cos1) / mystatic5;
d2y = distanse * 5 / 4 * sin22 / mystatic;
return ccp(d2x,d2y);
}
}
void MapScene::update(float dt)
{
CCPoint herop = m_tamara->getPosition();
CCPoint mapindex = convertto2d(herop.x,herop.y);
//根据路径移动
if(stepindex >= 1){
if(smallstepindex == 0){
int ncol = ((AstarItem *)path->objectAtIndex(stepindex))->getcol();
int nrow = ((AstarItem *)path->objectAtIndex(stepindex))->getrow();
int pcol = ((AstarItem *)path->objectAtIndex(stepindex - 1))->getcol();
int prow = ((AstarItem *)path->objectAtIndex(stepindex - 1))->getrow();
if(pcol == ncol){
if(prow > nrow){
vmove = 2;
}else if(prow < nrow){
vmove = 3;
}else{
vmove = -1;
}
}else if(prow == nrow){
if(pcol > ncol){
vmove = 1;
}else if(pcol < ncol){
vmove = 0;
}else{
vmove = -1;
}
}else{
vmove = -1;
}
}
if(vmove == 0){
herop.x += 1;
herop.y -= 0.5;
}else if(vmove == 1){
herop.x -= 1;
herop.y += 0.5;
}else if(vmove == 2){
herop.x += 1;
herop.y += 0.5;
}else if(vmove == 3){
herop.x -= 1;
herop.y -= 0.5;
}else if(vmove == 4){
herop.x += 1;
}else if(vmove == 5){
herop.x -= 1;
}else if(vmove == 6){
herop.y += 0.5;
}else if(vmove == 7){
herop.y -= 0.5;
}
smallstepindex ++;
if(smallstepindex >= 32){
smallstepindex = 0;
if(stepindex >= path->count() - 1){
stepindex = -1;
vmove = -1;
}else{
stepindex ++;
vmove = -1;
}
}
}
m_tamara->setPosition(herop);
//地图随主角移动
CCTMXTiledMap* map = (CCTMXTiledMap*) getChildByTag(kTagTileMap);
CCSize s = map->getContentSize();
int mapWidth = map->getMapSize().width * map->getTileSize().width;
int mapHeight = map->getMapSize().height * map->getTileSize().height;
float deltax = herop.x - mapWidth/2;
float deltay = herop.y - 112;
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
map->setPosition(ccp(-s.width/2 + winSize.width/2 - deltax,-deltay));
}
void MapScene::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)
{
CCSetIterator it = pTouches->begin();
CCTouch* touch = (CCTouch*)(*it);
CCPoint m_tBeginPos = touch->locationInView();
m_tBeginPos = CCDirector::sharedDirector()->convertToGL( m_tBeginPos );
char mch[256];
CCTMXTiledMap* map = (CCTMXTiledMap*) getChildByTag(kTagTileMap);
CCPoint mapp = map->getPosition();
//获得触摸点位置在地图上的索引(行列)
CCPoint aimmapindex = convertto2d(m_tBeginPos.x - mapp.x,m_tBeginPos.y - mapp.y);
if(aimmapindex.x < 0 || aimmapindex.y < 0 || aimmapindex.x >= map->getMapSize().width || aimmapindex.y >= map->getMapSize().height)
{
return;
}
CCPoint herop = m_tamara->getPosition();
CCPoint mapindex = convertto2d(herop.x,herop.y);
CCTMXLayer* layer = map->layerNamed("grass");
int tilegid = layer->tileGIDAt(ccp(aimmapindex.x,aimmapindex.y));
CCDictionary *tiledic = map->propertiesForGID(tilegid);
CCString *mvalue = (CCString *)tiledic->objectForKey("conflict");
int mv = mvalue->intValue();
if(mv == 1){
return;
}
//A星搜索
path = myastar->findPath(mapindex.x,mapindex.y,aimmapindex.x,aimmapindex.y,map);
stepindex = 1;
smallstepindex = 0;
}
void MapScene::menuCloseCallback(CCObject* pSender)
{
// "close" menu item clicked
CCDirector::sharedDirector()->end();
}
最后注意在AppDelegat文件中做相关的场景替换
CCScene *pScene = MapScene::scene();
我在实现中把屏幕放大为960*640尺寸,便于观察实际的效果。
AppDelegate app;
CCEGLView* eglView = CCEGLView::sharedOpenGLView();
<span style="color:#ff6666;"><span style="background-color: rgb(255, 204, 204);"> eglView->setFrameSize(960, 640);</span>
</span>
int ret = CCApplication::sharedApplication()->run();
最后的实现效果如图所示:
由于在Sstar::remevefromopen方法中有堆排序部分的确实,造成效果比较差,实现后由会出现堆栈错误的问题,目前正在解决。这几天研究下看看问题所在。