"QapLite.h" - простой графический header-движок для C++11, Direct3D9
Страницы:
1 2 Следующая »
"QapLite.h" - простой графический header-движок для C++11, Direct3D9
Особенности:
Для отрисовки используется Direct3D9.
Время компиляции 2-3 секунды.
Нет лишних зависимостей во время компиляции. //(d3dx9,dxut,zlib,bass,glut,sdl etc)
Нет лишних зависимостей во время выполнения. //(d3dx9,dxut,zlib,bass,glut,sdl etc)
Компилируется "из коробки". //ставим MSVC2013; скачиваем "QapLite.h" компилируем и всё работает!
EXE запускается "из коробки". //Скомпилировали exe`шник; отнесли его на "новый комп без драйверов для видео карты". Запустили и всё работает!
Нет текстур.
// Нафиг текстуры для разработки игровой механики?
Нет вывода текста.
// Основной подвох урезанной версии движка. В полной версии то всё есть :)
Нет текстурных атласов.
// Нет текстур - нет текстурных атласов - логично же!
Нет GUI.
// Нафиг GUI для разработки игровой механики?
Нет Spline`ов.
// ок.
Нет систем частиц(particles).
// Нафиг системы частиц для разработки игровой механики? ладно, пофиг, в примерах к движку то они есть!
Есть батчинг! // Это позволяет рисовать много-много-много всего и очень-очень быстро.
Всё в одном H-файле! // Насколько мне известно такая особенностью есть только у моего движка. Это реально круто!
Есть отрисовка прямоугольников/линий/окружностей.
// лол, и чё?
Можно менять цвета примитивов.
// ну круто же!
Нет глобальных переменных. // Уникальная особенностью! Такого больше нигде нет! Правда-правда.
Пример использования:
+ Показать
− Скрыть
#include "QapLite.h"
class TGame:public TD3DGameBoxBuilder{
public:
real ang;
real speed;
public:
TGame(){ang=0;speed=1.50*Pi/180.0;}
public:
void DoMove()
{
if(win.Keyboard.Down[VK_ESCAPE])win.Close();
ang+=speed;
}
void DoDraw()
{
qDev.BindTex(0,nullptr);
QapDev::BatchScope Scope(qDev);
{
qDev.SetColor(0xff000000);
qDev.DrawQuad(vec2i(100,100),50,50,-ang*0.5);
qDev.SetColor(0xff008000);
qDev.DrawQuad(vec2i(-100,-100),100,50,ang);
int n=5;
for(int x=-n;x<=+n;x++)for(int y=-n;y<=+n;y++)
{
qDev.SetColor(0xffffff00);
qDev.DrawQuad(vec2i(x*16*1.5,y*16*1.5)+vec2i(-300,+200),16,16,ang*x*y*0.4);
qDev.SetColor(0xffd08000);
qDev.DrawQuad(vec2i(x*16*1.5,y*16*1.5)+vec2i(-300,+200),12,12,ang*x*y*0.4);
}
qDev.DrawCircle(vec2d(0.5,-0.5),80,0,10,32);
}
}
};
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
GlobalEnv global_env(hInstance,hPrevInstance,lpCmdLine,nCmdShow);
TGame builder;
builder.DoNice();
}
Результат:
Скачать:
QapLiteDemo(2014.06.24)
ЗЫ: Для компиляции использую MS Visual Studio 2010.

Added: Win XP не поддерживается.
− Скрыть
#include "QapLite.h"
static bool CD_CircleAndWall(const vec2d&pos,vec2d&v,const real&r,const vec2d&a,const vec2d&b){
if(abs((pos-a).Rot(b-a).y)>r)return false;
if((pos-a).Rot(b-a).x<0)return false;
if((pos-a).Rot(b-a).x>(b-a).Mag())return false;
if(Sign(v.Rot(b-a).y)==Sign((pos-a).Rot(b-a).y))return false;
v=vec2d(v.Rot(b-a).x,-v.Rot(b-a).y).UnRot(b-a);return true;
}
static bool CD_CircleAndWallCircle(const vec2d&pos,vec2d&v,const real&d,const vec2d&a){
if((pos-a).Mag()>d)return false;
if(v.Rot(pos-a).x>0)return false;
v=vec2d(-v.Rot(pos-a).x,v.Rot(pos-a).y).UnRot(pos-a);
return true;
}
class TGame:public TD3DGameBoxBuilder{
public:
vec2d pos;
vec2d v;
real r;
vec2d a;
vec2d b;
public:
TGame()
{
pos=vec2d(-150,+50);
v=vec2d(0.5,-0.5);
r=32;
a=vec2d(-200,-50);
b=vec2d(+200,+100);
}
public:
void DoMove()
{
if(win.Keyboard.Down[VK_ESCAPE])win.Close();
if(win.Keyboard.OnDown(mbRight)){pos=win.GetMousePos();v=vec2d(1,-1).SetMag(1);}
if(win.Keyboard.OnDown(mbLeft)){v=vec2d(win.GetMousePos()-pos).SetMag(1);}
pos+=v;
CD_CircleAndWall(pos,v,r,a,b);
CD_CircleAndWallCircle(pos,v,r,a);
CD_CircleAndWallCircle(pos,v,r,b);
}
void DoDraw()
{
qDev.BindTex(0,nullptr);
QapDev::BatchScope Scope(qDev);
{
qDev.SetColor(0xff505050);
qDev.DrawQuad((a+b)*0.5,(a-b).Mag(),2,(a-b).GetAng());
qDev.SetColor(0xff505050);
qDev.DrawCircleEx(a,0,4,16,0);
qDev.DrawCircleEx(b,0,4,16,0);
qDev.SetColor(0xffbbbbbb);
qDev.DrawCircleEx(pos,0,r,32,0);
qDev.SetColor(0xff404040);
qDev.DrawCircle(pos,r,0,2,32);
}
}
};
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
GlobalEnv global_env(hInstance,hPrevInstance,lpCmdLine,nCmdShow);
TGame builder;
builder.DoNice();
}
Я старался сделать чтобы код компилировался и работал с первого раза, проверьте пожалуйста.
− Скрыть
#include "QapLite.h"
class TParticle{
public:
vec2d pos;
vec2d v;
real t;
public:
TParticle()
{
pos=vec2d(0,0);
v=vec2d(0,0);
t=0.0;
}
};
class TExplosion{
public:
string name;
bool auto_move;
bool auto_draw;
bool blend_add;
vec2d pos;
int tick;
int max_tick;
real particle_beg_size;
real particle_end_size;
QapColor particle_beg_color;
QapColor particle_end_color;
int particle_life_time;
int particle_per_tick;
real particle_min_speed;
real particle_max_speed;
real particle_pos_dist;
real particle_pos_dist_var;
vec2d particle_grav;
bool undeadable;
vector<TParticle> arr;
public:
TExplosion()
{
name=string();
auto_move=true;
auto_draw=true;
blend_add=true;
pos=vec2d(0,0);
tick=0;
max_tick=64;
particle_beg_size=8;
particle_end_size=1;
particle_beg_color=0xff00ff00;
particle_end_color=0xff000000;
particle_life_time=32;
particle_per_tick=4;
particle_min_speed=100.0/64.0;
particle_max_speed=400.0/64.0;
particle_pos_dist=4;
particle_pos_dist_var=8;
particle_grav=vec2d(0,0);
undeadable=false;
arr=vector<TParticle>();
}
};
class TGame:public TD3DGameBoxBuilder{
public:
vector<TExplosion> explosions;
public:
TGame()
{
vec_add_back(explosions).undeadable=true;
{
auto&back=vec_add_back(explosions);
back.undeadable=true;
back.pos=vec2d(-200,0);
back.particle_beg_color=0xff00aa00;
}
{
auto&back=vec_add_back(explosions);
back.undeadable=true;
back.pos=vec2d(+200,0);
back.particle_beg_color=0xff00aa00;
back.particle_min_speed=40.0/64.0;
back.particle_max_speed=90.0/64.0;
back.particle_per_tick=2;
back.particle_grav=vec2d(0,-0.2);
}
}
public:
void render(TExplosion&ref)
{
if(!ref.auto_draw)return;
QapDev::BatchScope Scope(qDev);
auto&arr=ref.arr;
for(int i=0;i<arr.size();i++)
{
auto&ex=arr[arr.size()-i-1];
real t=1.0-ex.t/real(ref.particle_life_time);
qDev.SetColor(QapColor::Mix(ref.particle_beg_color,ref.particle_end_color,t));
qDev.DrawQuad(ex.pos,vec2d(1,1)*Lerp(ref.particle_beg_size,ref.particle_end_size,t));
}
qDev.SetBlendMode(QapDev::BlendType::BT_SUB);
}
void render(vector<TExplosion>&arr)
{
for(int i=0;i<arr.size();i++)
{
auto&ex=arr[i];
render(ex);
}
}
void update(vector<TExplosion>&arr)
{
clean_if(arr,[](TExplosion&ex){return !ex.undeadable&&(ex.tick>=ex.max_tick)&&ex.arr.empty();});
for(int i=0;i<arr.size();i++)
{
auto&ex=arr[i];
update(ex);
}
}
void update(TExplosion&ref)
{
if(!ref.auto_move)return;
ref.tick++;
auto&arr=ref.arr;
for(int i=0;i<arr.size();i++)
{
auto&ex=arr[i];
ex.pos+=ex.v;
ex.v+=ref.particle_grav;
ex.t--;
}
clean_if(ref.arr,[](TParticle&ex){return ex.t<=0;});
if(!ref.undeadable)if(ref.tick>=ref.max_tick)return;
auto rnd=[]()->real{int n=1024*16;return real(rand()%n)/real(n);};
auto rnd_ang=[&rnd]()->real{return rnd()*Pi2;};
for(int i=0;i<ref.particle_per_tick;i++)
{
auto&back=vec_add_back(ref.arr);
auto dist=ref.particle_pos_dist;
auto dist_var=ref.particle_pos_dist_var;
auto d=dist+dist_var*(-0.5+rnd());
back.pos=ref.pos+Vec2dEx(rnd_ang(),d);
auto ang=rnd_ang();
auto mag=Lerp(ref.particle_min_speed,ref.particle_max_speed,rnd());
back.v=Vec2dEx(ang,mag);
back.t=ref.particle_life_time;
}
}
public:
void DoMove()
{
if(win.Keyboard.Down[VK_ESCAPE])win.Close();
update(explosions);
}
void DoDraw()
{
qDev.BindTex(0,nullptr);
QapDev::BatchScope Scope(qDev);
render(explosions);
}
};
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
GlobalEnv global_env(hInstance,hPrevInstance,lpCmdLine,nCmdShow);
TGame builder;
builder.DoNice();
}
Adler
> Норм?
норм вроде бы=)
Сделал проецирование точки на прямую заданную отрезком вот для этой темы: http://www.gamedev.ru/code/forum/?id=193786
Решение:
vec2d PutAPointOnTheLine(const vec2d&point,const vec2d&a,const vec2d&b){
return a+vec2d((point-a).Rot(b-a).x,0).UnRot(b-a);
}
Скачать:
DemoVec2dRot
Исходный код:
+ Показать
− Скрыть
#include "QapLite.h"
vec2d PutAPointOnTheLine(const vec2d&point,const vec2d&a,const vec2d&b){
return a+vec2d((point-a).Rot(b-a).x,0).UnRot(b-a);
}
class TGame:public TD3DGameBoxBuilder{
public:
vec2d a;
vec2d b;
vec2d point;
vec2d point_on_line;
int point_size;
int point_id;
public:
TGame()
{
a=vec2d(+100,0);
b=vec2d(-100,-20);
point=vec2d(0,200);
point_on_line=PutAPointOnTheLine(point,a,b);
point_size=7;
point_id=-1;
}
public:
static void DrawLine(QapDev&qDev,const vec2d&a,const vec2d&b,real line_size){
qDev.DrawQuad((b+a)*0.5,(b-a).Mag(),line_size,(b-a).GetAng());
}
void DoMove()
{
if(win.Keyboard.Down[VK_ESCAPE])win.Close();
vec2d mpos=win.GetMousePos();
bool down=win.Keyboard.Down[mbLeft];
bool on_down=win.Keyboard.OnDown(mbLeft);
if(down||on_down)
{
int i=0;
#define F(p)if(on_down||point_id>=0)if((p-mpos).Mag()<point_size*2.0){point_id=i;};if(down&&point_id==i){p=mpos;}i++;
F(a)F(b)F(point)
#undef F
}
if(!down)point_id=-1;
point_on_line=PutAPointOnTheLine(point,a,b);
}
void DoDraw()
{
qDev.BindTex(0,nullptr);
qDev.SetColor(0xff000000);
DrawLine(qDev,a-(b-a).SetMag(1024),b-(a-b).SetMag(1024),1);
DrawLine(qDev,a,b,4);
qDev.SetColor(0x40000000);
DrawLine(qDev,point,point_on_line,2);
qDev.SetColor(0xff900000);
qDev.DrawCircleEx(a,0,point_size,16,0);
qDev.SetColor(0xff000090);
qDev.DrawCircleEx(b,0,point_size,16,0);
qDev.SetColor(0xffff8000);
qDev.DrawCircleEx(point,0,point_size,16,0);
qDev.SetColor(0xffffff00);
qDev.DrawCircleEx(point_on_line,0,point_size*0.5,16,0);
}
};
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
GlobalEnv global_env(hInstance,hPrevInstance,lpCmdLine,nCmdShow);
TGame builder;
builder.DoNice();
}

у меня почему то при запуске любого твоего экзешника система уходит в ребут, компилировать сам не пробовал
Операционная система
Microsoft Windows XP Professional
Пакет обновления ОС
Service Pack 3
DirectX
4.09.00.0904 (DirectX 9.0c)
Видеоадаптер
VIA/S3G UniChrome Pro IGP (64 Мб)
Системная память
704 Мб (DDR SDRAM)
gambit_oz
>VIA/S3G UniChrome Pro IGP (64 Мб)
Жесть. Так он же только DirectX 7 держит, нет?
> у меня почему то при запуске любого твоего экзешника система уходит в ребут,
> компилировать сам не пробовал
Я обычно на ноуте кодю с Win8. Но помню года 4 назад когда я только начинал работать с DirectX9 у меня на компе был XP и я решил потестить свою прогу с DX9 и он тоже перезагружался в трёх случаях из трёх. Но я тогда не стал сразу разбираться в чём дело, а потом брат форматнул на компе хард с XP и поставил там линукс. С тех про я уже и забыл про эту проблему.
Надо попробовать скомпилировать и запустить под дебагом в MSVS10 в WinXP и посмотреть воспроизвдёться ли проблемма, только у меня нет WinXP.
А вообще наверно всё дело в DeviceCaps. Я там создаю вершины VertexBuffer и IndexBuffer на 3 миллиона элементов. Наверно на старых видюхах столько не поддерживается.
Я тут по быстрому попробовал пофиксить и теперь учитываю D3DCAPS9::MaxPrimitiveCount при создании буферов:
DemoForWinXp
Ещё проблемма может быть при создании девайса, он может тупо не создаться из-за какой-нибудь не поддерживаемой фигни, но это вроде не должно приводить к ребуту компа. Короче, если фикс выше не поможет, тогда надо логи прикручивать.
Спасибо за инфу.
Добавлено:
Я тут в логах на китайском сайте вот что нашёл для твой видеокарты:
MaxPrimitiveCount : 65535
MaxVertexIndex : 65535
Похоже предположение верно и фикс должен устранить проблему, проверь пажалуйства.
Adler
фикс не помог
доберусь до дома проверю на нормальной машине
странно конечно, я на этой машинке и Opengl приложения часто юзал и DirectX, но такого чтоб прям ребут - еще ни разу не было)) поэтому и написал,
подумал даже по началу, а не вирус ли какой в exe, но каспер с последними базами - молчал
при случае поставлю компилятор - проверю сам, потом отпишусь
видимо и правда с видяхой какой то косяк
bool isRight(const vec2d&prev,const vec2d&o,const vec2d&next){return (next-o).Rot(prev-o).y>0;}
− Скрыть
#include "QapLite.h"
bool isRight(const vec2d&prev,const vec2d&o,const vec2d&next){return (next-o).Rot(prev-o).y>0;}
class TGame:public TD3DGameBoxBuilder{
public:
vec2d prev;
vec2d next;
vec2d o;
int point_size;
int point_id;
public:
TGame()
{
o=vec2d(-100,50);
prev=o+vec2d(-100,-200);
next=o+vec2d(+250,-20);
point_size=12;
point_id=-1;
}
public:
static void DrawLine(QapDev&qDev,const vec2d&a,const vec2d&b,real line_size){
qDev.DrawQuad((b+a)*0.5,(b-a).Mag(),line_size,(b-a).GetAng());
}
void DoMove()
{
if(win.Keyboard.Down[VK_ESCAPE])win.Close();
vec2d mpos=win.GetMousePos();
bool down=win.Keyboard.Down[mbLeft];
bool on_down=win.Keyboard.OnDown(mbLeft);
if(down||on_down)
{
int i=0;
#define F(p)if(on_down||point_id>=0)if((p-mpos).Mag()<point_size*2.0){point_id=i;};if(down&&point_id==i){p=mpos;}i++;
F(prev)F(o)F(next)
#undef F
}
if(!down)point_id=-1;
}
void DoDraw()
{
qDev.BindTex(0,nullptr);
qDev.SetColor(0xff000000);
DrawLine(qDev,prev,o,4);
DrawLine(qDev,next,o,4);
qDev.SetColor(0xff900000);
qDev.DrawCircleEx(prev,0,point_size,16,0);
qDev.SetColor(0xff000090);
qDev.DrawCircleEx(next,0,point_size,16,0);
qDev.SetColor(0xff000000);
qDev.DrawCircleEx(o,0,point_size,16,0);
qDev.SetColor(isRight(prev,o,next)?0xffffff00:0xff00ff00);
qDev.DrawCircleEx(o,0,point_size*0.5,16,0);
}
};
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
GlobalEnv global_env(hInstance,hPrevInstance,lpCmdLine,nCmdShow);
TGame builder;
builder.DoNice();
}

gambit_oz
> фикс не помог
эх... значит надо логи прикручивать чтобы понять в чём дело, но мне лень тебя напрягать, поэтому я пойду просто в начале темы напишу что Win XP не поддерживается и всё :D
спасибо за то что рассказал о проблеме и потестил недофикс.
Делал кубик рубика для вот этой темы: http://www.cyberforum.ru/directx/thread1313280.html

Ещё научился генерировать геометрию для:
кубов
цилиндров
сфер
труб
Ещё научился делать FPS камеру.
Переделал класс vec3f, теперь у него куча перегруженных операторов(прям как у vec2d и QapColor).
Сгенерировал систему координат:

Разбирался куда смотрит камера по дефолту - она смотрит по оси OX из начала координат, OY вверх, OX вправо.
Учусь генерировать линии из труб/цилиндров.
ЗЫ: всё рисуется за один DIP, геометрия генерируется каждый кадр заново, освещения на втором скрине нет, просто я вручную меняю цвета вершин вторым проходом, d3dx9 и прочие либы не используются.
Скачать:
file=102260]
управление: WASD, стерлки, space, shift, control, L, O, F, цифры
>Всё в одном H-файле! // Насколько мне известно такая особенностью есть только у моего движка. Это реально круто!
Круто, то круто, только вот если человек пишет на С++, то ему скорее-всего будет не лень подключить одну lib и h, который подцепит другие заголовки, а вот тебе и другим людям(которые захотят помочь тебе развить сей продукт) будет жутко неудобно работать с кодом в таком виде. даже в 300-500 строчном файле бывает сложно ориентироваться, а тут 3к. Благо есть студия.
задумка хороша, но слишком просто, хотя бы битмап фонты нужны, идеальный вариант это HGE DX11 :)
во многих проектах есть необходимость быстренько вывести дебаг инфу в виде текста или графика, и тут начинается...
Danich
> если человек пишет на С++, то ему скорее-всего будет не лень подключить одну lib и h
Предлагаю подумать о новичках которые только начинаю писать код на С++. // Я считаю, что часть из них скорее забросит С++, чем станет разбираться с lib`ами.
> а вот тебе и другим людям будет жутко неудобно работать с кодом в таком виде
Есть новички которым нужен простой графический header-движок на С++ и Direct3D9 и им пофиг на то, удобно разрабатывать двиг или нет.
> которые захотят помочь тебе развить сей продукт
пусть новички развиваю двиг только в ту сторону которая нужна для их проектов.
baga
> битмап фонты нужны
срочно? :)
baga
> во многих проектах есть необходимость быстренько вывести дебаг инфу в виде
> текста или графика, и тут начинается...
спасибо, я подумаю над этим.