Tag Archives: SFML

Bitmap (Pixel) Fonts

One function most games need is the ability to display information to the user using text and numbers. It’s not uncommon for graphics libraries to have support for TTF fonts (see SFML and SDL). However, given the style of game I’m working on, what I would prefer is a bitmap font.

Just type “video game bitmap fonts” into Google image search and you can see how different they are compared to TTF. If you’re making a low resolution or pixel style game then bitmap fonts really fit the theme.

I’ve found libraries that deal with TTF fonts. I’ve also found programs that will supposedly turn TTF fonts into bitmap fonts. But the fonts I want are built from the ground up as a bitmap image, and I haven’t really found any way of using bitmap fonts (with SFML .NET specifically) within a project that satisfies that.

It seemed like a decent sized task to work on myself, so I took a stab at it.

Continue reading Bitmap (Pixel) Fonts

Langton’s Ant

langton_good

A little while ago I came across the topic of Cellular Automata. I was fascinated about the idea that complex (and even Turing-complete) behavior can come from a system that follows a few simple rules.

One of the more simple types of cellular automaton is Langton’s ant. This type seemed like a good choice to start with. I’ve been wanting to get into Python for a while now so I figured this would be a good project to get my feet wet.

Continue reading Langton’s Ant

Generating a Dungeon (part 3)

When I last left off I had the rooms (or data equivalent of rooms) created, the last thing that needed to be done was add in cycles so that the dungeon layout is not a tree. That’s what I’ll be tackling in this post.

I’ve updated the generateMap() function and added a call to the new function fixTree() at the end:

fixTree()

void GeneratedMap::fixTree()
{
//get all dead ends
std::vector<Room*> deadEnds;
for (unsigned int i = 0; i < rooms.size(); i++)
{
if (rooms[i]->isDeadEnd())
deadEnds.push_back(rooms[i]);
}
std::random_shuffle(deadEnds.begin(), deadEnds.end());

unsigned int i = 0;
int addedCount = 0;
int cyclesToAdd = (deadEnds.size() * CYCLE_PERCENT) / 100;
//keep adding cycles until the quantity is met or we run out of
//dead ends to try
while (i < deadEnds.size() && addedCount < cyclesToAdd)
{
Room* de = deadEnds[i++];
std::vector<Room*> adjacentRooms = getAdjacentRooms(de);
if (adjacentRooms.size() <= 0)
{
adjacentRooms.clear();
continue;
}
std::random_shuffle(adjacentRooms.begin(), adjacentRooms.end());

unsigned int j = 0;
Room* aj = nullptr;
//find first non-connected room
do
{
if (!de->areConnected(adjacentRooms[j]))
aj = adjacentRooms[j];
j++;
} while (j < adjacentRooms.size() && aj == nullptr);

//if no non-connected room is found try the next dead-end
if (aj == nullptr)
{
adjacentRooms.clear();
continue;
}

aj->hasSecondEntrance = true;

//rooms are adjacent, but not connected, now we connect them... with
//wizardry...
int directionOfOther = de->directionOfOtherRoom(aj);
int miny = 0, minx = 0, shift = 0;
if (directionOfOther == Room::LEFT || directionOfOther == Room::RIGHT)
{
miny = std::max(de->topLeft.y, aj->topLeft.y);
int maxy = std::min(de->bottomRight.y, aj->bottomRight.y);
int dy = std::abs(maxy - miny);
shift = dy <= 0 ? 0 : rand() % (dy + 1);
}
else if (directionOfOther == Room::UP || directionOfOther == Room::DOWN)
{
minx = std::max(de->topLeft.x, aj->topLeft.x);
int maxx = std::min(de->bottomRight.x, aj->bottomRight.x);
int dx = std::abs(maxx - minx);
shift = dx <= 0 ? 0 : rand() % (dx + 1);
}

switch (directionOfOther)
{
case Room::LEFT:
aj->startingCell2 = Vector2i(aj->bottomRight.x, miny + shift);
aj->previousCell2 = Vector2i(de->topLeft.x, miny + shift);
break;
case Room::RIGHT:
aj->startingCell2 = Vector2i(aj->topLeft.x, miny + shift);
aj->previousCell2 = Vector2i(de->bottomRight.x, miny + shift);
break;
case Room::UP:
aj->startingCell2 = Vector2i(minx + shift, aj->bottomRight.y);
aj->previousCell2 = Vector2i(minx + shift, de->topLeft.y);
break;
case Room::DOWN:
aj->startingCell2 = Vector2i(minx + shift, aj->topLeft.y);
aj->previousCell2 = Vector2i(minx + shift, de->bottomRight.y);
break;
}

addedCount++;
}
}

Continue reading Generating a Dungeon (part 3)