我的弹幕系统是一个预设的指针数组(暂定300个 通过这个方式限制最大弹幕数量)
然后新生成的弹幕就把其地址放到这个数组里面并且记录新的总弹幕数量
每一帧里从0到总数-1 每个弹幕分别跑自己的移动函数
基于这个原因 所以一开始函数指针设计考虑的就是让每个子弹自理自己的移动 弹幕的生成函数只负责创建新的弹幕以及给新生成的弹幕配备相应的移动函数
当然以上内容因为效率太难看已经给否了
说起来这个总体设计是否可取?还是干脆移动不交给全局的函数来管理 而交给不同的stage或者chapter一类的函数来负责? Delta67 发表于 2015-6-9 10:44 static/image/common/back.gif
现在的情况是这样
我的弹幕系统是一个预设的指针数组(暂定300个 通过这个方式限制最大弹幕数量)
然后新 ...
std::list试过没。。。
我用vector都没那么慢
而且每个弹幕自己一个函数也并不影响效率。。 借串问下要如何有效率的决定Sprite的绘制顺序?
我把Sprite指针存在vector内然后每帧绘制前依Z值->Y值->X值来排序,但是上千Sprite就有掉帧的感觉了。 效率问题你是用VS的话可以用vs的性能分析工具跑一下,不是的话就用VTune吧。 刚花了点时间写了个弹幕的基础类,等会发上来。。。
这附件大小真鬼畜。。。 #include "mdl.h"
#include "mdl_Sprite.h"
#include "windows.h"
#include "cmath"
#include "ctime"
#include <VECTOR>
#include <iostream>
#include <functional>
mdl_sprite* gs;
struct spritedes
{
spritedes::spritedes(DWORD SH)
{
sprite_handle = SH;
}
BOOL rS = 1;
XMFLOAT2 position;
float rotation=0;
DWORD sprite_handle;
};
class globalttime
{
public:
globalttime::globalttime()
{
startTime = clock();
lastTime = startTime;
currentTime = lastTime;
}
void update()
{
lastTime = currentTime;
currentTime = clock();
interval = currentTime - lastTime;
}
long getInter()
{
return interval;
}
long getCurrent()
{
return currentTime;
}
long getPassed()
{
return currentTime - startTime;
}
private:
clock_t startTime;
clock_t lastTime;
clock_t currentTime;
long interval;
}*gt;
class msprite
{
public:
msprite::msprite(){};
msprite::msprite(char* filename)
{
teH = gs->load_texture(filename);
spH = gs->init_sprite(teH);
big = gs->spritemap.big;
}
virtual void update()
{
}
virtual void draw()
{
std::list < spritedes >::iterator iter = list.begin();
for (unsigned int i = 0; i < list.size(); i++, iter++)
{
int j = gs->RenList.size();
gs->add2RenList(spH);
gs->RenList.position = iter->position;
gs->RenList.rotation = iter->rotation;
}
}
protected:
XMFLOAT2 big;
DWORD teH;
DWORD spH;
std::list < spritedes >list;
};
struct __polar
{
float r = 0;
float ra = 0;
float rv = 0;
float o = 0;
float oa = 0;
float ov = 0;
};
struct __rect
{
XMFLOAT2 pos = { 0, 0 };
XMFLOAT2 v = { 0, 0 };
};
class __coord
{
public:
__coord::__coord(XMFLOAT2 __centre, std::function<void(__coord* lp)> __proc)
{
isRect = 0;
centre = __centre;
position = { 0, 0 };
proc = __proc;
}
XMFLOAT2* getCentre()
{
return ¢re;
}
__polar* getLppolar()
{
return &polar;
}
__rect* getLprect()
{
return &rectC;
}
XMFLOAT2 getPos()
{
return position;
}
float getO()
{
return polar.o;
}
void changeCoordMode()
{
}
void update()
{
proc(this);
polar.ov += polar.oa * gt->getInter()/1000.0f;
polar.o += polar.ov* gt->getInter() / 1000.0f;
polar.rv += polar.ra* gt->getInter() / 1000.0f;
polar.r += polar.rv* gt->getInter() / 1000.0f;
while (polar.o >= XM_2PI)
{
polar.o -= XM_2PI;
}
while (polar.o <= -XM_2PI)
{
polar.o += XM_2PI;
}
position = { centre.x + polar.r * cosf(polar.o), centre.y + polar.r * sinf(polar.o) };
}
private:
bool isRect;
XMFLOAT2 centre;
XMFLOAT2 position;
__polar polar;
__rect rectC;
std::function<void(__coord* lp)> proc;
};
class danmu:public msprite
{
public:
danmu::danmu(char* filename)
{
teH = gs->load_texture(filename);
spH = gs->init_sprite(teH);
big = gs->spritemap.big;
}
danmu::~danmu()
{
std::list<__coord*>::iterator iter = danmuLst.begin();
for (unsigned int i = 0; i < danmuLst.size(); i++, iter++)
{
delete *iter;
}
danmuLst.~list();
}
void initADanmu(__polar _polar,std::function<void(__coord* lp)> __proc, XMFLOAT2 __centre = XMFLOAT2(w_width / 2.0f, w_height / 2.0f))
{
__coord* lpCoord = new __coord(__centre, __proc);
__polar* lpPolar = lpCoord->getLppolar();
memcpy(lpPolar, &_polar, sizeof(__polar));
danmuLst.push_back(lpCoord);
}
void update()
{
std::list<__coord*>::iterator iter = danmuLst.begin();
for (unsigned int i = 0; i < danmuLst.size(); i++, iter++)
{
(*iter)->update();
}
}
void draw()
{
std::list<__coord*>::iterator iter = danmuLst.begin();
for (unsigned int i = 0; i < danmuLst.size(); i++, iter++)
{
int j = gs->RenList.size();
gs->add2RenList(spH);
gs->RenList.position = (*iter)->getPos();
gs->RenList.rotation = (*iter)->getO() - XM_2PI / 4.0f;
}
}
DWORD size()
{
return danmuLst.size();
}
private:
std::list<__coord*> danmuLst;
};
std::vector<msprite*> spriteLst;
#define installdProc __polar* polar = lp->getLppolar();\
__rect* rectC = lp->getLprect();\
XMFLOAT2* centre = lp->getCentre();\
float time = gt->getInter();
void dProc(__coord* lp)
{
installdProc;
if (polar->rv < 0)
{
polar->ra = 0;
polar->rv = 0;
}
}
int Render(int state, WORD reflect)
{
static BOOL inited = FALSE;
static danmu*id;
if (!inited)
{
gs = new mdl_sprite;
gt = new globalttime;
id = new danmu("DT\\bullet.png");
spriteLst.push_back(id);
inited = true;
}
gt->update();
static long timeProc = 0;
if (gt->getPassed() -timeProc >=300)
{
timeProc = gt->getPassed();
const float d = 6.0;
for (float i = 0; i < d; i++)
{
float o = XM_2PI / d*i;
__polar p;
p.o = o - XM_2PI / d /2.0f;
p.ov = XM_2PI / 360.0 * 30;
p.rv = 250.0;
p.ra = -100;
id->initADanmu(p, dProc);
p.o = o ;
p.ov = XM_2PI / 360.0 * 45;
id->initADanmu(p, dProc);
}
}
for (int i = 0; i < spriteLst.size(); i++)
{
spriteLst->update();
spriteLst->draw();
}
char danmuNum = { 0 };
sprintf_s(danmuNum,"%u", id->size());
SetWindowTextA(g_hWnd, danmuNum);
gs->spriteRender();
MDL_RenderPresent();
gs->RenList.clear();
MDL_clear();
return state;
}
所有代码都在这了,,,这大概是我的算法吧,,,比较low。
本意是实现一个发射器函数,一个弹幕处理函数,,但是还只封装了一个,坐标现在也只能处理极坐标。 谢谢各位的回复 因为我周五有一场考试所以这两天得复习 过两天再来看 再次感谢 应该是哪写的有问题,dx hge1.8.1老台机跑上万子弹都不会卡,台机弹幕通常差不多5w不卡比较正常,dx9可以参考下hge,虽然很多人说效率不好,但我感觉其实还挺好。
例子可以参考上古物marisa-ex,大概需要跳墙
https://marisa-ex.googlecode.com/svn/trunk/
页:
1
[2]