|
Basic game development library? |
gnolam
Member #2,030
March 2002
|
(Starting a new thread since that other one's gone all off-topic and this is a slightly different question anyway)
</li> SDL fails the last condition. SFML seems to have a godawful text API, but appears nice otherwise. Do you have any other suggestions on libraries to try out? -- |
Evert
Member #794
November 2000
|
Quote: Do you have any other suggestions on libraries to try out? Sure. Allegro. Allegro 4.9 current svn that is (to be Allegro 5). |
gnolam
Member #2,030
March 2002
|
Updated the list. [EDIT] -- |
Evert
Member #794
November 2000
|
As I said, it's usable right now, but installation may be a bit rough and the API is not in feature freeze yet. It's probably at least worth a quick look. |
StevenVI
Member #562
July 2000
|
Use Fudgefont. It loads TTF files as Allegro fonts and they look quite beautiful when rendered with alpha blending. It loads them with Freetype. It looks like the sourceforge page for it isn't functioning, so I've attached my modified version of the source and header file. When you say "basic justification support" do you mean similar to Allegro's left/right/centre functions? A5 also does TTF loading quite well. I have some tutorials linked in my signature, but they have a critical flaw in the timer code, so disregard that portion of them if you decide to take a look. __________________________________________________ |
Peter Wang
Member #23
April 2000
|
[potential thread derailment; deleted]
|
Thomas Harte
Member #33
April 2000
|
Quote: Using just FreeType and writing the rest myself seems like too much work It's actually a lot less work than you think. FreeType passes you vectors that describe the edges of arbitrarily-shaped polygons, and GLU has code to turn that sort of polygon into triangles. All you really need to do is write glue code with a tiny bit to turn Beziers into line segments, assuming you're happy with doing your fonts as geometry rather than textures. I'm at work, so can't excise the relevant bits from my code, but check out my old Ice Field Frenzy (ChristmasHack '07 entry) code, or wait for me to post later. [My site] [Tetrominoes] |
OICW
Member #4,069
November 2003
|
Quote: A license that isn't (L)GPL.
Quote: SDL fails the last condition. I see, but their page states: Quote: SDL is distributed under GNU LGPL version 2. This license allows you to use SDL freely in commercial programs as long as you link with the dynamic library. That leads me to a conlusion that as long as you link dynamic version of the library you cat have closed code. Can you elaborate your problem? [My website][CppReference][Pixelate][Allegators worldwide][Who's online] |
MiquelFire
Member #3,110
January 2003
|
I think it's the open code that it becomes a problem. The (L)GPL is a bit viral. --- |
gnolam
Member #2,030
March 2002
|
Harry Carey: thanks, but as far as I can see that only does the TTF loading bit - it still goes through AllegroGL's horribly broken font and text handling. OICW said: Can you elaborate your problem?
A lesser evil is still evil. -- |
Mokkan
Member #4,355
February 2004
|
ClanLib, maybe? It claims to have a BSD style license.
|
OICW
Member #4,069
November 2003
|
Quote:
A lesser evil is still evil. Allright, fair enough. Quote: I think it's the open code that it becomes a problem. The (L)GPL is a bit viral. I'm not sure I'm following your chain of thoughts. I know that when you actually use GPL'ed code you have to GPL the whole source of yours, however when you link dynamically the library it's ok. [My website][CppReference][Pixelate][Allegators worldwide][Who's online] |
SiegeLord
Member #7,827
October 2006
|
Quote: I'm not sure I'm following your chain of thoughts. It is generally hard to follow thoughts of reactionary zealots. Even harder than those of the normal ones. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
ImLeftFooted
Member #3,935
October 2003
|
How does A5 stack up against SDL? |
Thomas Fjellstrom
Member #476
June 2000
|
Quote: I know that when you actually use GPL'ed code you have to GPL the whole source of yours, however when you link dynamically the library it's ok. That only qualifies for LGPL. While I'm not sure this point has actually been tested in court (which is the only way to know if something is legal or illegal in the us), the GPL actually effects any linked code, dynamic or static. Since your code does directly use it, which makes it a derivative, which makes it subject to the GPL. -- |
OICW
Member #4,069
November 2003
|
Quote: That only qualifies for LGPL. While I'm not sure this point has actually been tested in court (which is the only way to know if something is legal or illegal in the us), the GPL actually effects any linked code, dynamic or static. Since your code does directly use it, which makes it a derivative, which makes it subject to the GPL. All right. SDL seems to be LGPL. But anyway, it hasn't been tested. By the way, has it been tested with GPL? [My website][CppReference][Pixelate][Allegators worldwide][Who's online] |
gnolam
Member #2,030
March 2002
|
I said: A lesser evil is still evil. To expand a little bit more: ensuring LGPL compliance isn't as straightforward as you think it is. Can we get back on topic now, please? -- |
OICW
Member #4,069
November 2003
|
Quote: To expand a little bit more: ensuring LGPL compliance isn't as straightforward as you think it is. Can we get back on topic now, please? Fair enough. Sure, sorry for this little debate. I just digged out of my memory that Richard Phipps was working with PTK. Looks like it can be used for free. Maybe it can be worthwile to look at. [My website][CppReference][Pixelate][Allegators worldwide][Who's online] |
Thomas Harte
Member #33
April 2000
|
How does A5 stack up against SDL?In license terms, Allegro is more liberal as discussed above. In ideological terms, SDL is lower level but has much more mature OpenGL support and as a result of both of those facts, it supports a much wider array of platforms. In terms of being in the process of an API refresh, both are equal. Except that now I'd say that Allegro's is more likely to arrive. Back to my real promise, code to do TTF in OpenGL. There's much more to it than I thought, because of the way I've chosen to optimise it. Much of it is unnecessary fluff. And some of it probably just replicates the STL, I don't know. Code it relies on includes my DataCollector template. It exists only to aggregate things it is given one at a time into C-style arrays and is the main thing I think STL can probably do for you. Here: template
There are also my VertexArray and DrawElements handlers, which are their own separate classes so that they can opt to use VBOs if available. If you don't care about VBOs then they're an unnecessary complication.
ebgf_DrawElements.h (don't worry about CResource — it's the mechanism I use to maintain objects that are otherwise lost when I destroy and create contexts, e.g. when switching to fullscreen mode or, because of the way SDL is set up, when the user resizes the window):
class CDrawElements: public CResource
{
public:
CDrawElements(GLenum mode, GLsizei count, GLenum type, GLvoid *pointer, bool copy = true);
~CDrawElements();
void Draw();
virtual void Backup();
virtual bool Restore();
private:
GLenum mode;
GLsizei count;
GLenum type;
GLvoid *ptr;
GLuint buffer;
int DataSize;
};
And .cpp:
#include "ebgf_GLExts.h"
CDrawElements::CDrawElements(GLenum mode, GLsizei count, GLenum type, GLvoid *pointer, bool copy)
{
this->mode = mode;
this->count = count;
this->type = type;
int basesize;
switch(type)
{
case GL_UNSIGNED_BYTE: basesize = sizeof(GLubyte); break;
case GL_UNSIGNED_SHORT: basesize = sizeof(GLushort); break;
case GL_UNSIGNED_INT: basesize = sizeof(GLuint); break;
}
DataSize = basesize*count;
if(copy)
{
ptr = new unsigned char[DataSize];
memcpy(ptr, pointer, DataSize);
}
else
ptr = pointer;
Restore();
Filename = new char[50];
sprintf(Filename, "DrawElements::%016x", (const unsigned int)this);
__EBGF_StoreHash(this);
}
CDrawElements::~CDrawElements()
{
Backup();
delete[] (unsigned char *)ptr;
EBGF_ReturnResource(this, false);
}
void CDrawElements::Backup()
{
if(AvailableGLExtensions&GLEXT_VBO)
glDeleteBuffersARB(1, &buffer);
}
bool CDrawElements::Restore()
{
buffer = 0;
if(AvailableGLExtensions&GLEXT_VBO)
{
//VBO extension supported, upload
glGenBuffersARB(1, &buffer);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, DataSize, ptr, GL_STATIC_DRAW_ARB);
}
return true;
}
void CDrawElements::Draw()
{
if(!buffer)
glDrawElements(mode, count, type, ptr);
else
{
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer);
glDrawElements(mode, count, type, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
}
}
And VertexArray, which is almost a copy'n'paste job of DrawElements (I've reduced code redundancy in another version of my code, I just can't find it right now):
class CVertexArray: public CResource
{
public:
CVertexArray(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer, int number);
~CVertexArray();
void Enable();
void Disable();
virtual void Backup();
virtual bool Restore();
private:
GLint size;
GLenum type;
GLsizei stride;
GLvoid *ptr;
GLuint buffer;
int DataSize;
};
#include "ebgf_GLExts.h"
CVertexArray::CVertexArray(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer, int number)
{
ptr = NULL;
this->size = size;
this->type = type;
this->stride = stride;
int basesize;
switch(type)
{
case GL_SHORT: basesize = sizeof(GLshort); break;
case GL_INT: basesize = sizeof(GLint); break;
case GL_FLOAT: basesize = sizeof(GLfloat); break;
case GL_DOUBLE: basesize = sizeof(GLdouble); break;
}
DataSize = (basesize*size + stride) * number;
ptr = malloc(DataSize);
memcpy(ptr, pointer, DataSize);
Restore();
Filename = new char[50];
sprintf(Filename, "VArray::%016x", (unsigned int)this);
__EBGF_StoreHash(this);
}
CVertexArray::~CVertexArray()
{
Backup();
free(ptr);
EBGF_ReturnResource(this, false);
}
void CVertexArray::Backup()
{
if(buffer)
glDeleteBuffersARB(1, &buffer);
buffer = 0;
}
bool CVertexArray::Restore()
{
buffer = 0;
if(AvailableGLExtensions&GLEXT_VBO)
{
//VBO extension supported, try to upload
glGenBuffersARB(1, &buffer);
if(1)//glIsBufferARB(buffer))
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, DataSize, ptr, GL_STATIC_DRAW_ARB);
}
else
buffer = 0;
}
return true;
}
void CVertexArray::Enable()
{
glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
if(!buffer)
glVertexPointer(size, type, stride, ptr);
else
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer);
glVertexPointer(size, type, stride, NULL);
}
}
void CVertexArray::Disable()
{
if(buffer)
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glPopClientAttrib();
}
So, up to here, mostly dull dry support stuff that adds a useful thing or two but creates complexity. You don't need an equivalent of my VertexArray or DrawElements holders, they're just the mechanism I use for utilising VBOs in a transparent fashion.
The first class that is actually really helpful for TTF is my Polygon class. You feed it a sequence of vertices and then later you can ask it to draw the resulting polygon. Really it's just a thin layer on top of the GLU tesselator, utilising my pet classes for VBOs.
#ifndef WIN32
#define __stdcall
#endif
class CPolygon
{
public:
CPolygon();
~CPolygon();
void Draw();
void AddVert(GLfloat x, GLfloat y);
void NewContour();
void Finish();
private:
static void __stdcall Begin(GLenum type);
static void __stdcall End(void);
static void __stdcall Combine(GLdouble coords[3], void *vertex_data[4], GLfloat weight[4], void **outData);
static void __stdcall Vertex(void *Data);
static int StoreVert(GLfloat x, GLfloat y);
CVertexArray *Array;
struct Plate
{
Plate() {Elements = NULL; Next = NULL;}
~Plate() {delete Elements;}
CDrawElements *Elements;
Plate *Next;
} *PlateList;
static Plate *PlateWorker;
static DataCollector
DataCollector
Which just leaves my tiny bit of code for turning a TTF glyph into a polygon. I'm going to have to cut things a bit here since I've lazily just used a 7bit ASCII glyph table and that isn't what you want. Just imagine you are set up so that the Glyphs struct is large enough to hold a continuous array spanning every glyph you may want to use. That'd be a really bad unicode implementation decision, but I don't really expect you to use my code verbatim anyway.
#include
#define GLYPH_MULTIPLIER 128
bool CFont::Open(const char *name)
{
if(FT_New_Face(__ebgf_TTFLibrary, name, 0, &face)) return false;
FT_Set_Char_Size(face, GLYPH_MULTIPLIER << 6, GLYPH_MULTIPLIER << 6, 72, 72); // default size is 1x1, with 72dpi
And these are called just once, when the program is first loaded and before it is shut:
FT_Library __ebgf_TTFLibrary = NULL;
void __EBGF_FreeFontLibrary()
{
FT_Done_FreeType(__ebgf_TTFLibrary);
}
void __EBGF_SetupFontLibrary()
{
FT_Init_FreeType(&__ebgf_TTFLibrary);
atexit(__EBGF_FreeFontLibrary);
}
In my 7bit ASCII world, I have the following print function, which does the obvious stuff + pair kerning:
void CFont::Print(const char *fmt, ...)
{
char String[2048];
va_list varlist;
va_start(varlist, fmt);
// vsnprintf(String, 2048, fmt, varlist);
vsprintf(String, fmt, varlist);
va_end(varlist);
glPushAttrib(GL_ENABLE_BIT);
glDisable(GL_CULL_FACE);
fmt = String;
glPushMatrix();
glScalef(1.0f / (64.0f * GLYPH_MULTIPLIER), 1.0f / (64.0f * GLYPH_MULTIPLIER), 1.0f / (64.0f * GLYPH_MULTIPLIER));
while(*fmt)
{
int idx = (*fmt)&127;
if(Glyphs[idx].Graphic) Glyphs[idx].Graphic->Draw();
glTranslatef(Glyphs[idx].Width, 0, 0);
int glyph_index1;
int glyph_index2;
FT_Vector kerning;
glyph_index1 = FT_Get_Char_Index(face, (FT_ULong)fmt[0]);
glyph_index2 = FT_Get_Char_Index(face, (FT_ULong)fmt[1]);
FT_Get_Kerning(face, glyph_index1, glyph_index2, FT_KERNING_UNFITTED, &kerning);
glTranslatef((GLfloat)kerning.x, 0, 0);
fmt++;
}
glPopMatrix();
glPopAttrib();
}
So, yes, a lot of my code is a mess and I don't expect you to use it verbatim. But it hopefully shows that linking FreeType to GLU is really quite easy. [My site] [Tetrominoes] |
SiegeLord
Member #7,827
October 2006
|
Quote: How does A5 stack up against SDL? And if it does so unfavourably in some way, you can always make a suggestion and affect how the yet unfinished A5 will stack up to SDL as the former is under active development... "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Thomas Fjellstrom
Member #476
June 2000
|
Quote: you can always make a suggestion and affect how the yet unfinished A5 will stack up to SDL as the former is under active development... And I intend to keep it that way even if I don't get anywhere near as much actual work done on it myself as I want to (especially in a reasonable amount of time, fshooks could have been done last year) -- |
Elias
Member #358
May 2000
|
Quote: So, yes, a lot of my code is a mess and I don't expect you to use it verbatim. But it hopefully shows that linking FreeType to GLU is really quite easy. Someone want to add that to A5's ttf addon? Or as a new addon? -- |
Thomas Harte
Member #33
April 2000
|
I think it'll need to wait until either SiegeLord's primitive stuff is in the library, giving implicit access to VBOs and suchlike from on top of Allegro with no regard whatsoever for which particular driver is in use, or — if it is planned at all — until it's clear how and to what extent Allegro will expose OpenGL (specifically, how the user will keep track of resources that are tied to specific rendering context if there are some operations that cause Allegro to destroy the current context and create a new one). FreeType obviously isn't OpenGL specific, and GLU actually isn't either. You can link against and use GLU without linking against or using the main body of OpenGL, so probably waiting to see what SiegeLord comes up with is smartest. He's already assured me that it'll be set up to allow vertex data to be left on the GPU. Then we can have a nice TTF-as-geometry library that's platform agnostic. [My site] [Tetrominoes] |
axilmar
Member #1,204
April 2001
|
SFML seems very good. Very nice tutorials, nicely organized homepage, nice APIs. I will give it a try. |
|