Ich habe jetzt endlich auch das ultimative NIH-Projekt angefangen, in dem ich mal alle möglichen Sachen, die ich für meine restlichen Spiele-Projekte so entwickelt habe, sammle:
xqlib
Das Ganze ist eine wilde Sammlung von C++17-Code mit einigen Komponenten, unter anderem:
- xstd: Generische Helferklassen wie unique_id (nicht-arithmetischer Integer-Typ mit Type-Tag-Template für Typsicherheit) und dynamic_array (non-resizable Vector)
- xlog: Einfacher logger nach stdout mit versch. log levels und ANSI-Einfärbung
- xio: Handling für binäre Datenströme mit einfachen read/write-Funktionen.
- xapp: grundlegende Anwendungsinitialisierung und Update mit SDL 2. Stellt Init-Code für OpenGL sowie SDL_Renderer bereit
- xgl: OpenGL-Wrapper im RAII-Stil. Benötigt zwingendermaßen Direct State Access
- xcs:Ein einfaches Entity-Component-System
- xgraphics: Grafik-Klassen aufbauend auf xgl, im Moment debug_draw, shader_compiler, sprite_batch, texture_loader. Implementiert primär Helferklassen für Grafikprogrammierung, die die übliche Arbeit abnehmen.
- xnet: POSIX-Socket-Abstraktion sowie ein einfacher HTTP-Server
Das ganze Projekt ist im Moment primär für mich als Basis-Framework gedacht, wenn sich aber zwei, drei Leute melden, wäre ich auch gewillt, in Teamwork das ganze zu optimieren und zu dokumentieren...
Ansonsten darf man sich natürlich auch gerne die Implementierung mopsen und für eigenen Kram verwenden!
Grüße
Felix
PS.: Beispielcode ist ja nie verkehrt, von daher ein paar Beispiele:
xapp:
Code: Alles auswählen
#include <xgl/all>
#include <xapp>
int main()
{
if(not xapp::init(xapp::opengl)) // opengl oder sdl
return 1;
while(xapp::update())
{
xapp::clear();
// custom render logic here
xapp::present();
}
return xapp::quit();
}
Code: Alles auswählen
// OpenGL-Buffer anlegen und mit Daten füllen leicht gemacht:
xgl::buffer vertexBuffer;
vertexBuffer.data({
glm::vec3(1.0, 0.0, 0.0),
glm::vec3(0.0, 1.0, 0.0),
glm::vec3(0.0, 0.0, 1.0),
});
Code: Alles auswählen
// HTTP-Server:
int main()
{
xnet::http::server server;
if(not server.bind(xnet::parse_ipv4("0.0.0.0", 8080)))
return 1;
std::cout << "ready.\n";
while(true)
{
auto [ request, response ] = server.get_context();
response.status_code = 200;
auto stream = response.get_stream();
stream.write_line("URL: " + request.url);
stream.write_line("Method: " + request.method);
stream.write_line();
stream.write_line("Headers:");
for(auto const & header : request.headers)
{
stream.write_line(header.first + ": " + header.second);
}
}
return 0;
}
Code: Alles auswählen
// tcp echo server
int main()
{
xnet::socket server(AF_INET, SOCK_STREAM);
if(not server.bind(xnet::parse_ipv4("127.0.0.1", 8080)))
return 1;
if(not server.listen())
return 2;
while(true)
{
auto [ client, addr ] = *server.accept();
std::cout << "connection from " << xnet::to_string(addr) << "!" << std::endl;
while(true)
{
std::array<char, 128> data;
auto const len = client.read(data.data(), data.size());
if(len == 0)
break;
if(len < 0)
return 3;
client.write(data.data(), len);
}
std::cout << "client disconnected!" << std::endl;
}
}
Code: Alles auswählen
#include <xcs>
struct SomeComponent
{
int a, b;
};
// erlaubt Erstellung der Komponente über Namen, zudem wird so verhindert, dass wild jeglicher Datentyp als Komponente verwendet werden kann.
XCS_REGISTER_COMPONENT(SomeComponent)
int main()
{
xcs::universe scene;
SomeSystem system(scene);
xcs::entity ent = scene.create_entity();
auto & c = xcs::add_component<SomeComponent>(ent);
c.a = 10;
c.b = 20;
// Loop über alle Entitäten + Komponenten eines Komponententyps:
for(auto [ entity, component ]: xcs::get_components<SomeComponent>(universe))
{
std::cout << entity.id << ", " << component.a << ", " << component.b << std::endl;
}
return 0;
}