Jump to content

  • Log In with Google      Sign In   
  • Create Account

Solid_Spy

Member Since 26 Nov 2012
Offline Last Active Today, 06:01 PM

Topics I've Started

How to compile libraries for C++ MinGW with MSYS on Windows - for indie game developers

16 December 2014 - 03:28 PM

Compiling libraries is something that a lot of indie game developers have trouble with, especially if they are using Eclipse or CodeBlocks with MinGW. Compiling libraries is just one of those things that people just assume you know how to do, although it doesn't seem like there is all that much information, (or information that is clear) on how to properly build libraries. They never even taught me how to do it in college tongue.png.

I am specifically going to teach you how to compile libraries for your indie game using MSYS and MinGW. I am going to use glew32 as an example, since that is a very popular library, especially for those working with OpenGL.

I will explain step by step how to compile the libraries.

Step 1: Download MinGW and MSYS. They should be on the main website, and shouldn't be too hard to find. MSYS will usually be downloaded along with MinGW.

Step 2: Make sure you downloaded MinGW to your C:\ directory, and that msys is inside of the folder.

 

mingw_zps2ff2e915.png

Step 3: Add the folders C:\MinGW\bin and C:\MinGW\mingw32\bin to your PATH: variables. VERY IMPORTANT, I'm guessing a lot of people skip this step by accident. You can find the path variables by going into search, and typing "path variables". You need these in your path variables so that way cmd.exe has global access to the programs inside of these folders, without having to change directories.

Step 4: Download the Glew32... tsk... "libraries", off of the glew website.

Step 5: Open cmd.exe

Step 6: type: cd, and a space after it and then copy/paste the file directory to the Glew folder that has a MakeFile in it. into the cmd.exe window.

Step 7: press enter, and then type bash, and then press enter again. now you should see a dollar sign appear in the cmd window. If you do not see a dollar sign, then chances are that you didn't properly add MinGW\bin or MSYS\bin to your PATH variable.

Step 8: type mingw32-make, and then press enter. Now it should lag a little, but if you wait a while, you should see a lot of weird, err, stuff appear in the window. That's ok, that's normal. That means you did it right!. Now if you wait a while, you should see bash appear at the bottom with the dollar sign again, and it should look something like this.

 

bash_zps0fe5067c.png

Step 9: you have just compiled your libraries! Great! ...where are they? Well if you look inside of the lib folder of your glew32 folder, you should see a bunch of new stuff there that wasn't there before. You should see a libglew32.a and a glew32.dll. Now Those are the important ones! The .a one is the static library, and the .dll is the dynamic one.

 

glew_zpsd62a4d40.png

Step 10: If you wish to use these libraries, i suggest putting them into different folders so that your ide has an easier time finding them. For example, Eclipse will sometimes confuse libglew32.a with libglew32.dll.a.

And that's it!

Now, there are a few gotcha's:

 

Make sure everything you are downloading is of the same bit amount, for example, make sure everything is 32-bit. And I mean, EVERYTHING! Including your program, and your other libraries.

Not all libraries you download off of the internet will have a makefile, and not all makefiles require the same procedures as simply typing mingw32-make. For example, the Freetype library, also a very popular library for game development, requires that you type ./configure first, before typing mingw32-make. It is VERY important to read the read me file of any library you download, as they may provide valuable information.

As for the libraries that do not have makefiles, for example, the boost libraries, which have .jam files instead. You will need a different compiler program sadly. There are many different compiler programs that are beyond the scope of this tutorial i'm afraid, however I am sure there are video tutorials that can teach you how to use them.

And that's it, that's how you compile libraries with MinGW and MSYS for C++. Thank you for reading my tutorial ^^.


problem with variable time, updating objects created on the same frame at different times

15 December 2014 - 02:26 PM

Let's say I'm creating 3 objects in one instance of time.

 

I am using a variable time step, and 10ms go by.

 

within that 10ms, 3 objects are created, but 1 is supposed to be created in 1ms, the other in 2ms, and the third in 5ms.

 

If all these objects are supposed to move 5+ units on the y-axis, and I update using variable time (10ms), then every object will move 50 units up exactly, and end up in the same position.

 

The problem is, since these objects are created at different times, I want them to travel different distances (the first one should only travel 45 units, since 10-1 = 9, and 9*5 == 45).

 

I was thinking of having a time stamp for every object that gets created, and subtracting by another current time stamp, but I don't know how expensive time stamps can be. What if I have 1000 objects created every second, would using multiple time stamps cause any lag? I am using QueryPerformanceCounter.

 

For example, here is a list of particles I am creating:

while(!glfwWindowShouldClose(window))
	{
		QueryPerformanceCounter(&currentTime);

		counterAmmount += deltaTime;

		while(counterAmmount >= 20.0)
		{
			counterAmmount -= 20.0;

			float scaleAmmount = (static_cast<float>(rand() % 1000) / 1000.0f);
			LARGE_INTEGER timeStamp;
			scaleAmmount = scaleAmmount + 0.5f / 2.0f;
			particle particle1;
			particle1.alive = true;
			particle1.lifeTime = 2000.0f;
			particle1.x = 0.0f;
			particle1.y = 0.0f;
			particle1.z = 0.0f;
			particle1.sx = scaleAmmount;
			particle1.sy = scaleAmmount;
			particle1.sz = scaleAmmount;
			particle1.dx = (static_cast<float>((rand() % 1000) - 500) / 1000.0f);
			particle1.dy = (static_cast<float>((rand() % 1000)) / 1000.0f);
			particle1.dz = 1.0f;
			particle1.r = (static_cast<float>((rand() % 1000)) / 1000.0f);
			particle1.g = (static_cast<float>((rand() % 1000)) / 1000.0f);
			particle1.b = (static_cast<float>((rand() % 1000)) / 1000.0f);
			particle1.timeSinceCreated = QueryPerformanceCounter(&timeStamp);

			particleList.push_back(particle1);
		}

		for(std::vector<particle>::iterator iterator = particleList.begin();
			iterator != particleList.end();
			iterator++)
		{
			if(iterator->lifeTime <= 0.0f)
			{
				std::vector<particle>::iterator myAss2 = particleList.begin() + (particleList.size() - 1);
				std::iter_swap(iterator, myAss2);
				particleList.pop_back();
				iterator--;
			}
			else
			{
                                //Using deltaTime causes inconsistencies with multiple particles being created
                                //on the same frame at different times, since there is only ONE delta time :p.
				iterator->sx -= 0.001f * deltaTime;
				iterator->sy -= 0.001f * deltaTime;
				iterator->sz -= 0.001f * deltaTime;
				if(iterator->sx <= 0.0f)
				{
					iterator->sx = 0.0f;
					iterator->sy = 0.0f;
					iterator->sz = 0.0f;
				}
				iterator->x += (iterator->dx * (0.01f)) * deltaTime;
				iterator->y += (iterator->dy * (0.01f)) * deltaTime;
				iterator->lifeTime -= (1.0f) * deltaTime;
			}
		}

Isn't there a better solution? I know that almost every game programmer must have encountered this issue.


VERY weird error. Structs in std::vector being updated more than once

14 December 2014 - 11:58 PM

Hello, I am writing a particle system, and I am trying to load particle objects into a vector.

 

Everytime I create a particle, it starts with a lifetime of 50.0f. The particle also starts at 0,0,0.

 

Every frame the particle increases the y value by 0.01f.

 

Also, all the particle are iterated through, and if the lifetime is <= 0.0f, then I swap and pop it from the list.

 

At first it seems like it should work without any problems at all, but...

 

for some strange reason, the y values seem to be doubled practicly as soon as the 50th particle is created and the particles are updated. It's like every particle that gets created asap, gets pushed above the 0,0,0 point, and new ones get pushed even farther. It's soooo weird D:!

 

Here is the code for the particles:

	while(!glfwWindowShouldClose(window))
	{
		particle particle1;
		particle1.alive = true;
		particle1.lifeTime = 50.0f;
		particle1.x = 0.0f;
		particle1.y = 0.0f;
		particle1.z = 0.0f;

		particleList.push_back(particle1);
		MessageBox(0, "m", "m", MB_OK);

		unsigned int currentSize = particleList.size();

		for(unsigned int iterator = 0;
			iterator < currentSize;
			iterator++)
		{
			particleList[iterator].lifeTime -= 1.0f;
			if(particleList[iterator].lifeTime <= 0.0f)
			{
				std::swap(particleList[iterator], particleList[particleList.size() - 1]);
				particleList.pop_back();
				iterator--;
			}
			else
			{
			}

			particleList[iterator].y += 0.01f;

			currentSize = particleList.size();
		}

I don't know why this is happening tongue.png. It doesn't make any sense at all and I can't think of anything.

Here is the rendering code, although this is more of a general programming question I believe, but just in case:

		glClearColor(0.1f, 0.2f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		glm::mat4 streamedPositions[1000];

		glm::vec4 streamedColors[1000];

		//MessageBox(0, "l", "l", MB_OK);

		for(unsigned int pIndex = 0; pIndex < particleList.size(); pIndex++)
		{
			translationMatrix = glm::translate(glm::mat4(1.0f),
			glm::vec3(particleList[pIndex].x, particleList[pIndex].y, -10.0f));

			worldMatrix = translationMatrix;

			streamedColors[pIndex] = glm::vec4(1.0f, 1.0f, (float)particleList[pIndex].lifeTime / 50.0f, 1.0f);

			streamedPositions[pIndex] = worldMatrix;
		}

		glBindBuffer(GL_ARRAY_BUFFER, streamedColorBuffer);
		glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4 * 1000, streamedColors, GL_STREAM_DRAW);
		glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * 4 * particleList.size() , streamedColors);

		glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, (void*)0);

		glBindBuffer(GL_ARRAY_BUFFER, streamedPositionBuffer);
		glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 16 * 1000, (GLfloat*)&streamedPositions, GL_STREAM_DRAW);
		glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * 16 * particleList.size(), (GLfloat*)&streamedPositions);

		for(unsigned int i = 0; i < 4; i++)
		{
			glVertexAttribPointer(3+i, 4, GL_FLOAT, GL_FALSE, sizeof(float)*16.0f, (void*)0 + ((sizeof(float) * 4 * i)));
		}

		glUseProgram(testProgram);

		location = glGetUniformLocation(testProgram, "worldMatrix");
		glUniformMatrix4fv(location, 1, GL_FALSE, (GLfloat*)&worldMatrix);

		location = glGetUniformLocation(testProgram, "viewMatrix");
		glUniformMatrix4fv(location, 1, GL_FALSE, (GLfloat*)&viewMatrix);

		location = glGetUniformLocation(testProgram, "projectionMatrix");
		glUniformMatrix4fv(location, 1, GL_FALSE, (GLfloat*)&projectionMatrix);

		location = glGetUniformLocation(testProgram, "diffuse");
		glUniform1i(location, 0);

		glVertexAttribDivisor(0, 0);
		glVertexAttribDivisor(1, 0);
		glVertexAttribDivisor(2, 1);
		glVertexAttribDivisor(3, 1);
		glVertexAttribDivisor(4, 1);
		glVertexAttribDivisor(5, 1);
		glVertexAttribDivisor(6, 1);

		glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, particleList.size());

		glfwSwapBuffers(window);
		glfwPollEvents();

The rendering code works fine as far as I can tell, and I am using instanced rendering.


Bullet hell projectiles as separate objects? Or as one whole particle system?

14 December 2014 - 12:11 AM

This is a question that has irked me to it's core.

 

EOSD_screen.jpg

 

Bullets in a bullet hell shmup game lie between the boundaries of simple particle structs, and full blown game objects.

 

It would be VERY flexible to have your bullets as separate game objects, but...

 

Dynamic memory is slow, everyone knows that. If you have a component based architecture, and are storing your game objects in a list, as well as pointers to those game objects in separate lists, and you have multiple enemies on the screen firing 30+ bullets at a time...

 

you'd have to dynamically allocate around 1000 or more objects per frame, including all of the separate rendering components... and physics components... ugh.

 

yeah...

 

that can't be good... or maybe it's not as slow as I think?

 

Or, you could simply treat the bullets like a particle system, and just store them in a fixed size array, inside of one dynamically allocated object.

That way allocations are MUCH faster, and you can simply render and update your particles just like you would update any regular particle emmiter...

 

but with the tradeoff of flexibility, and collision detection speed.

 

if all of your particles are one object, with only one physics component, then your player, or other objects, will have to check for collision with every singe bullet, even if you are culling collisions with a quadtree! Also, what if you want bullets to collide with each other? You can't do this very efficiently, unless you create a separate quadtree for the particle system. But quad trees are expensive, and should only be used sparringly. What if you have over 20 or 30 different bullet emmiters on the screen at once? Then you would need 20-30 separate quadtrees... and then how would you check for collisions between separate bullet emmiters... and... aw screw it.

 

yeah, also has a few problems :/

 

Basically, to sum it up, I can't think of which method to use, or maybe there is a better method?

 

Sometimes I wish I had the source code for the Touhou games so I could see how ZUN did it XP.

 

Idk, what do you think?


Cannot get freetype to render glyph to texture

13 December 2014 - 04:45 PM

I was following this tutorial: http://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Text_Rendering_01,

and trying to get text to render to a quad on the screen. I followed all the rules. I don't know why it isn't working.

 

Here is my code. I try to render only one character, the letter 'H'. I only get a green colored quad :/.

int main()
{
    glfwInit();

    FT_Library ftLibrary;
    if(FT_Init_FreeType(&ftLibrary))
    {
        MessageBox(0, "wouldn't initialize?", "f", MB_OK);
    }

    FT_Face ftFace;
    if(FT_New_Face(ftLibrary, "arial.ttf", 0, &ftFace))
    {
        MessageBox(0, "didn't find the file", "m", MB_OK);
    }

    FT_Set_Pixel_Sizes(ftFace, 0, 64);

    ...

    GLint location;

    glDepthMask(GL_TRUE);
    //glEnable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    GroupOfLetters word1("H", 24, 0.6f, 0.8f, 0.2f, 1.0f);

    GLuint currentLetterTex;

    glActiveTexture(GL_TEXTURE0);
    glGenTextures(1, &currentLetterTex);
    glBindTexture(GL_TEXTURE_2D, currentLetterTex);


    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    while(!glfwWindowShouldClose(window))
    {
        glClearColor(0.2f, 0.4f, 0.6f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glUseProgram(testProgram);

        if(FT_Load_Char(ftFace,
        'H',
        FT_LOAD_RENDER))
        {
            MessageBox(0, "A SERIOUS ERROR!", "m", MB_OK);
        }

        FT_GlyphSlot glyphSlot = ftFace->glyph;

        glTexImage2D(GL_TEXTURE_2D,
                0,
                GL_ALPHA,
                glyphSlot->bitmap.width,
                glyphSlot->bitmap.rows,
                0,
                GL_ALPHA,
                GL_UNSIGNED_BYTE,
                glyphSlot->bitmap.buffer);

        float letterColor[4];
        letterColor[0] = word1.Getred();
        letterColor[1] = word1.Getgreen();
        letterColor[2] = word1.Getblue();
        letterColor[3] = word1.Getalpha();

        scaleMatrix = glm::scale(glm::mat4(1.0f), glm::vec3(0.5f, 0.5f, 1.0f));
        translationMatrix = glm::translate(glm::mat4(1.0f),
                glm::vec3(0.0f, 0.0f, -1.0f));

        worldMatrix = translationMatrix * scaleMatrix;

        location = glGetUniformLocation(testProgram, "worldMatrix");
        glUniformMatrix4fv(location, 1, GL_FALSE, (GLfloat*)&worldMatrix);

        location = glGetUniformLocation(testProgram, "viewMatrix");
        glUniformMatrix4fv(location, 1, GL_FALSE, (GLfloat*)&viewMatrix);

        location = glGetUniformLocation(testProgram, "projectionMatrix");
        glUniformMatrix4fv(location, 1, GL_FALSE, (GLfloat*)&projectionMatrix);

        location = glGetUniformLocation(testProgram, "inTextColor");
        glUniform4fv(location, 1, letterColor);

        location = glGetUniformLocation(testProgram, "diffuse");
        glUniform1i(location, 0);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indiceBuffer);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0);

        glfwSwapBuffers(window);
        glfwPollEvents();

    }

    glfwDestroyWindow(window);

    glfwTerminate();

    return 0;
}

I don't get any errors at all, just a friggin green quad staring right back at me DX<.

 

The shaders are working fine, I tested them with a texture I made with alpha, and it worked. Just what the hell could I possibly be doing wrong here!?


PARTNERS