Posts Tagged ‘c++’

Song lyrics in C++

August 13th, 2013

The other day while hacking away on some C++ code and listening to music, something occurred to me: if I’m programming in C++, shouldn’t the music I’m listening to be in the same language?

So I took a few verses from various random songs and coded up C++ translations of the lyrics. Here’s what I was able to hack together.

 
2Pac – Dear Mama

English:

When I was young me and my mama had beef
Seventeen years old kicked out on the streets
Though back at the time, I never thought I’d see her face
Ain’t a woman alive that could take my mama’s place

C++:

// When I was young me and my mama had beef
if (this->young()) {
    this->append(new Beef());
    mama.append(new Beef());
}

// Seventeen years old kicked out on the streets
// Though back at the time, I never thought I'd see her face
if (this->getAge() == 17) {
    this->remove(getShelter());
    this->seeFace(false);
}

// Ain't a woman alive that could take my mama's place
mama.replacement = NULL;

 
 
The Beatles – Hey Jude

English:

Hey Jude, don’t make it bad
Take a sad song and make it better
Remember to let her into your heart
Then you can start to make it better

C++:

// Hey Jude, don't make it bad
jude.it->make(!JudeState::BAD);

// Take a sad song and make it better
sadSong.improve();

// Remember to let her into your heart
jude.setReminder(new Event(JudeState::ENTER, jude.getHeart()));

// Then you can start to make it better
jude.it->make(JudeState::BETTER);

 
 
David Bowie – Man Who Sold The World

English:

Oh no, not me
I never lost control
You’re face to face
With The Man Who Sold The World

C++:

// Oh no, not me
// I never lost control
assert(this->control != NULL);

// You're face to face
// With The Man Who Sold The World
Man m;
m.sell(world);
you->setFacing(&m);
m.setFacing(you);

 
 
Lady Gaga – Born This Way

English:

Don’t hide yourself in regret
Just love yourself and you’re set
I’m on the right track, baby
I was born this way

C++:

// Don't hide yourself in regret
if (!you->visible && you->regret)
    you->visible = true;

// Just love yourself and you're set
you->love(you);

// I'm on the right track, baby
getTrack(Track::RIGHT)->set(this);

// I was born this way
assert(this->state == this->creationState);

 
 
The Police – Every Breath You Take

English:

Every breath you take
Every move you make
Every bond you break
I’ll be watching you

C++:

while(true) {
    switch(you->getEvent()) {

    // Every breath you take
    case BREATH:

    // Every move you make
    case MOVE:

    // Every bond you break
    case BOND_BREAK:

    // Every step you take
    case STEP:

        // I'll be watching you
        this->watch(you);
        break;

    default:
        assert(false);
    }
}

 
 
Kanye West – Power

English:

No one man should have all that power
The clocks tickin’ I just count the hours
Stop trippin’ I’m tripping off the power
Till then, fuck that the world’s ours

C++:

// No one man should have all that power
for(int i = 0; i < men.size(); i++) {
    Man* man = men.get(i);
    if (man->has(allThatPower))
        man->remove(allThatPower);
}

// The clocks tickin' I just count the hours
setTimer(1, &countHours);

// Stop trippin' I'm tripping off the power
you->tripping = false;
bool power = true;
this->tripping = power;

// Till then, fuck that the world's ours
if (getCurrentTime() != then) {
    that->fuck();
    world.setOwner(this);
}

Accelerated 2D graphics with OpenGL and SDL: part 1

October 13th, 2010

As some of you know, I’m working on an old-school puzzle game with Hryx. This game makes use of OpenGL’s graphics capabilities, but not for 3D graphics. Nope, the game is entirely two dimensional.

So why OpenGL? Because it’s really, really fast on most systems. Much faster than the slowpoke graphics in SDL.

This is going to be part one of a two part series on doing 2D graphics using OpenGL. And step one? Getting some 2D sprites loaded.

Loading the sprite with SDL_image
Now since we’re using SDL for our game, we decided on the excellent SDL_image to do the image loading.

Using SDL_image to load a sprite into memory is absurdly easy.

string filename = "myImage.png";
SDL_Surface* surface = IMG_Load( filename.c_str() );

That’s it!

But wait… that loads the graphic into an SDL surface. We need it to be an OpenGL texture! Damn.

OpenGL textures
In OpenGL, there’s no such thing as a “sprite.” You just have “textures.” So we’ll need to take our sprite and map it to a texture. The texture will be referenced with an integer (a GLuint) rather than a pointer.

But there’s an interesting restriction we have to work around that SDL simply doesn’t have. On most systems, OpenGL textures must have dimensions are are powers of two: 2, 4, 8, 16, and so on.

So once we load our SDL_Surface, we’ll make a new surface where we’ve rounded up the dimensions to the next highest power of two. The new surface will be filled with the alpha “color” and then we can blit (copy) over the existing image to the top left corner of our new image.

SDL_PixelFormat *format = surface->format;
Uint32 width = surface->w;
Uint32 height = surface->h;
Uint32 widthPow = (unsigned) pow( 2, ceil( log( width ) / log( 2 ) ) );
Uint32 heightPow = (unsigned) pow( 2, ceil( log( height ) / log( 2 ) ) );

// Create new empty surface.
SDL_Surface* newSurface = SDL_CreateRGBSurface( SDL_SRCALPHA,
	   widthPow, heightPow, 32,
	   rmask, bmask, gmask, amask );

// Fill sprite with alpha.
Uint32 alpha = 0;
alpha = SDL_MapRGBA( format, 0, 0, 0, amask );
SDL_Rect rect;
rect.x = 0;
rect.y = 0;
rect.h = heightPow;
rect.w = widthPow;
int ret = SDL_FillRect( newSurface, &rect, alpha);
surface->flags &= !SDL_SRCALPHA;

SDL_SetAlpha( newSurface, SDL_SRCALPHA, SDL_ALPHA_TRANSPARENT );

// Copy image data to our new surface.
ret = SDL_BlitSurface( surface, 0, newSurface, 0 );

Great, we got our surface loaded. Now it’s time to create an OpenGL texture, then take our SDL surface and copy it to the texture.

// This will be our OpenGL texture.
GLuint texture = 0;

// Bind the texture.
glPixelStorei(GL_UNPACK_ALIGNMENT,4);
glGenTextures(1, &texture );
glBindTexture(GL_TEXTURE_2D, texture);

// Convert surface to Open GL format.
gluBuild2DMipmaps(GL_TEXTURE_2D, 4,
	widthPow, heightPow, GL_RGBA,GL_UNSIGNED_BYTE, newSurface->pixels);

// Free our temporary SDL buffers.
SDL_FreeSurface( surface );
SDL_FreeSurface( newSurface );

Easy, huh?

Dealing with 24-bit surfaces
Up until now we’ve only dealt with is 32-bit images. One thing I hadn’t dealt with until now is 24-bit color-keyed images. A color-keyed image means you have RGB but no alpha or “A” channel to tell you what should be invisible. Instead, you just take one color (often black) and just say that it’s 100% transparent.

What we’re going to have to do is make the SDL_surface color keyed before we copy it to the OpenGL texture.

First, we’re going to need some functions for plotting individual pixels on an SDL texture. Unfortunately there’s no built in functions for this, so I stole some from this site.

Uint32 GetPixel( SDL_Surface *surface, int x, int y )
{
	Uint32 color = 0;
	char* pPosition = ( char* ) surface->pixels;
	pPosition += ( surface->pitch * y );
	pPosition += ( surface->format->BytesPerPixel * x );
	memcpy ( &color , pPosition , surface->format->BytesPerPixel );
	return color;
}

void SetPixel( SDL_Surface *surface, int x, int y, Uint32 color )
{
	char* pPosition = ( char* ) surface->pixels;
	pPosition += ( surface->pitch * y );
	pPosition += ( surface->format->BytesPerPixel * x );
	memcpy ( pPosition , &color , surface->format->BytesPerPixel );
}

Cool, now we can plot pixels! Feel free to go crazy and write a routine to draw circles or something!

But all we really need to do here is to take pixels that correspond with our color key and set the alpha channel to the alpha mask channel color.

if ( 24 == format->BitsPerPixel )
{
   Uint32 colorKey = format->colorkey;

   for ( int y = 0; y < surface->h; ++y )
   {
	   for (int x = 0; x < surface->w; x++)
	   {
		   Uint32 color = GetPixel( surface, x, y );
		   if ( color == colorKey )
		   {
			   SetPixel( newSurface, x, y, 0 );
		   }
	   }
   }
}

Putting it all together
Here is the final code to load an image file to a texture using SDL.

#include 
#include 
#include 
#include 
#include 

#if SDL_BYTEORDER == SDL_LIL_ENDIAN
   static const Uint32 rmask = 0x000000FF;
   static const Uint32 bmask = 0x0000FF00;
   static const Uint32 gmask = 0x00FF0000;
   static const Uint32 amask = 0xFF000000;
#else
   static const Uint32 rmask = 0xFF000000;
   static const Uint32 bmask = 0x00FF0000;
   static const Uint32 gmask = 0x0000FF00;
   static const Uint32 amask = 0x000000FF;
#endif



Uint32 GetPixel( SDL_Surface *surface, int x, int y )
{
	Uint32 color = 0;
	char* pPosition = ( char* ) surface->pixels;
	pPosition += ( surface->pitch * y );
	pPosition += ( surface->format->BytesPerPixel * x );
	memcpy ( &color , pPosition , surface->format->BytesPerPixel );
	return color;
}


void SetPixel( SDL_Surface *surface, int x, int y, Uint32 color )
{
	char* pPosition = ( char* ) surface->pixels;
	pPosition += ( surface->pitch * y );
	pPosition += ( surface->format->BytesPerPixel * x );
	memcpy ( pPosition , &color , surface->format->BytesPerPixel );
}


GLuint loadTexture( std::string filename )
{
	SDL_Surface* surface = IMG_Load( filename.c_str() );

	if ( NULL == surface )
	{
	   // Error!
	   return 0;
	}


	SDL_PixelFormat *format = surface->format;
	Uint32 width = surface->w;
	Uint32 height = surface->h;
	Uint32 widthPow = (unsigned) pow( 2, ceil( log( width ) / log( 2 ) ) );
	Uint32 heightPow = (unsigned) pow( 2, ceil( log( height ) / log( 2 ) ) );

	// Create new empty surface.
	SDL_Surface* newSurface = SDL_CreateRGBSurface( SDL_SRCALPHA,
		   widthPow, heightPow, 32,
		   rmask, bmask, gmask, amask );

	// Fill sprite with alpha.
	Uint32 alpha = 0;
	alpha = SDL_MapRGBA( format, 0, 0, 0, amask );
	SDL_Rect rect;
	rect.x = 0;
	rect.y = 0;
	rect.h = heightPow;
	rect.w = widthPow;
	int ret = SDL_FillRect( newSurface, &rect, alpha);
	surface->flags &= !SDL_SRCALPHA;

	SDL_SetAlpha( newSurface, SDL_SRCALPHA, SDL_ALPHA_TRANSPARENT );

	// Copy image data to our new surface.
	ret = SDL_BlitSurface( surface, 0, newSurface, 0 );

	// Change color key to alpha transparency.
	// Used for 24-bit images.
	if ( 24 == format->BitsPerPixel )
	{
	   Uint32 colorKey = format->colorkey;

	   for ( int y = 0; y < surface->h; ++y )
	   {
		   for (int x = 0; x < surface->w; x++)
		   {
			   Uint32 color = GetPixel( surface, x, y );
			   if ( color == colorKey )
			   {
				   SetPixel( newSurface, x, y, 0 );
			   }
		   }
	   }
	}

	// This will be our OpenGL texture.
	GLuint texture = 0;

	// Bind the texture.
	glPixelStorei(GL_UNPACK_ALIGNMENT,4);
	glGenTextures(1, &texture );
	glBindTexture(GL_TEXTURE_2D, texture);

	// Convert surface to Open GL format.
	gluBuild2DMipmaps(GL_TEXTURE_2D, 4,
		widthPow, heightPow, GL_RGBA,GL_UNSIGNED_BYTE, 
                newSurface->pixels);

	// Free our temporary SDL buffers.
	SDL_FreeSurface( surface );
	SDL_FreeSurface( newSurface );

	return texture;
}

That’s it! Next time: displaying our new OpenGL texture on the screen as a 2d sprite.

C++ 2D generic array class

October 16th, 2009

Recently I found myself writing a templated 2d array class in C++ for a personal project, and I thought I’d share. If you want to learn about 2d arrays or templates in C++, this article should provide a little insight for you. On the other hand, if you’re an experienced C++ developer, you should be able to slam out a class just like mine in minutes, but the code is at the end so you don’t have to.

Yes, you’re welcome to use this code or expand on it for your own project. It’s available under a BSD license which should be appropriate for most projects.

Usage
The Array2D class can be used like so:

// Create a 3x5 array of longs and fill it with zeroes.
Array2D<long> myArray( 3, 5 );
myArray.setAll( 0 );

// Now we're going to set the 0, 0 element to 23 and then retrieve it.
myArray.set( 23, 0, 0 );
long twentyThree = myArray.get( 0, 0 );

Make sense? Let’s walk through a few key parts.

Template
Back in the old days, you’d have to write your own list class for each data type you wanted to put in a list. For example you might have ListInt and ListString to store ints and strings, respectively. But nowdays you can just have one generic List class that stores any data type.

In C++ the Standard Template Library classes take care of a lot of data types for you. For lists we typically use the vector class and instantiate it with vector<int> for a list integers and vector<string> for a list of strings. It’s a real time saver. Yay for lazy programmers!

We make our Array2D class generic by using a C++ template. Here’s how it works.

template <class T>
class Array2D
{

This is what tells the compiler than you have to instantiate the class with a specific type, for example MyClass; instead of just MyClass;. We’re calling our data type T. Now how do we use it? Here’s how:

Data storage
The data is stored as a double pointer of type T. This double pointer mechanism seemskind of clumsy, but it’s the only way to create a 2D array in C++.

T** data;

Our data is actually stored as [y][x] because that felt more comfortable to me. It’s just a convention I happen to like, I swear I’m not dyslexic.

Memory management
I found myself copying and pasting allocation, deallocation, etc. code just to use a damn 2D array, which it what inevitably led to the code we have here today.

data = new T*[height];
for ( int i = 0; i < height; i++ )
{
	data[i] = new T[width];
}

This is actually fairly straightforward — we’re creating one array for the height, which contains pointers to array for the width. Pretend you just created y vectors of size x.

Deallocation is pretty much the same, so I won’t go into it here. Basically we just delete everything we created here, but in the opposite order.

Accessing data
How do we change and retrieve data in our class? Easily.

T get( const int& x, const int& y )
{
	return data[y][x];
}

void set( const T& t, const int& x, const int& y )
{
	data[y][x] = t;
}

Internally, the data access looks like you would expect for a 2D array. There’s also methods for retrieving the dimensions so the user can iterate over it.

We only expose a getter and setter, never a pointer to the actual data. Otherwise the user could delete a row and the whole program would come crashing down.

One other note — this class was designed for speed. If you’re wondering what’s up with the paramters like “const int& z” it’s pretty simple. It tells the compiler that instead of making a copy, you can pass a reference to the same data into the function. The const means that we won’t change that value inside the function (we would get a compiler error if we did) so there’s no need to worry. This gives us a little extra speed because pass by reference is a little faster than pass by value, since no copy is made.

Okay! I hope I didn’t lose any C++ beginners there. If you’re lost, play with the code because that’s the best way to learn. Hell, add some more features just for fun:

Features you might want to add:

  • What about a 3D array, a 4D array, etc?
  • Matrix functions: matrix addition, cross product, dot product…
  • Overload the square brackets for easy access
  • Resize funtion

Okay, now on to the source listing!

Array2D.h

// Copyright (c) 2009, Eric Gregory
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//    * Redistributions of source code must retain the above copyright
//      notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//    * Neither the name of Eric Gregory nor the
//      names of its contributors may be used to endorse or promote products
//      derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY ERIC GREGORY ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL ERIC GREGORY  BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef ARRAY2D_H_
#define ARRAY2D_H_

template <class T>
class Array2D
{
public:

	Array2D()
	{
		data = NULL;
		width = 0;
		height = 0;
	}

	Array2D( const int& width, const int& height )
	{
		data = NULL;
		allocate( width, height );
	}

	~Array2D()
	{
		deallocate();
	}

	T get( const int& x, const int& y )
	{
		return data[y][x];
	}

	void set( const T& t, const int& x, const int& y )
	{
		data[y][x] = t;
	}

	void setAll( const T& t )
	{
		for ( int y = 0; y < height; y++ )
		{
			for ( int x = 0; x < width; x++ )
			{
				data[y][x] = t;
			}
		}
	}

	int getWidth()
	{
		return width;
	}

	int getHeight()
	{
		return height;
	}

private:

	void allocate( const int& width, const int& height )
	{
		// Remember dimensions.
		this->width = width;
		this->height = height;

		// Allocate.
		data = new T*[height];
		for ( int i = 0; i < height; i++ )
		{
			data[i] = new T[width];
		}
	}

	void deallocate()
	{
		if ( NULL == data )
		{
			// Nothing to do.
			return;
		}

		// Free the memory.
		for ( int i = 0; i < height; i++ )
		{
			delete[] data[i];
		}
		delete[] data;

		// Reset.
		width = 0;
		height = 0;
		data = NULL;
	}

	int width;
	int height;
	T** data;
};

#endif /* ARRAY2D_H_ */

C/C++ with Eclipse Galileo on Mac OS 10.6

September 13th, 2009

Getting Eclipse to compile your C/C++ applications on Linux has always been a breeze.  On Windows, it’s always been hell.  And on Mac, it’s somewhere in between.

Here’s what you need to get started:

Your Mac OS install DVD has a few optional components that aren’t part of the standard installation.  One of these is XCode, which is Apple’s wonky IDE.  It comes with the GNU toolchain, which is exactly what you’ll need.  If you’ve installed the right thing, you should be able to open a new terminal window (note: a NEW terminal window) and run “gcc”.  If it’s installed, it will return with something like “gcc: no input files.”  Which is true — you didn’t give it any input files.

Now onto the next problem.  Eclipse’s C/C++ Development Tools (CDT) plugin doesn’t work with 64-bit binaries without some significant tweaks because it won’t recognize the binary as a valid application. And on Snow Leopard, GCC compiles 64-bit by default.  Damn!

There’s two workarounds for this, use whichever one suits you best (but not both!):

  1. Switch back to 32 bit binaries. In each project, right click and select Properties, and open the C/C++ Build section, and click settings.  Under MacOS X C++ Linker, click Miscellaneious.  There’s three text fields; in the one that just says Linker flags, add “-arch i386” (without the quotes).  Then go to the GCC C++ Compiler section, hit Miscellaneous, and add the same text to the Other flags box.  Now you just need to do a clean build, and you should be good to go.
  2. Don’t use the Run dialog.  You can use the Run External command to run the 64-bit executable.  This can be somewhat annoying if you have several build options, or you like changing the name of your project.  But it works.

Remember, you only need to make ONE of the above changes. Don’t make both!

Hopefully this helped someone out there.  And even more hopefully, this will be fixed in the next verison of Eclipse.

Update: forgot the “i” in “i386” and added emphasis about only making one of the two changes.