Categories
Geek / Technical Linux Game Development

Wine Talk

This Thursday I am giving a talk on using Wine to run Windows applications on Linux. Wine stands for Wine Is Not an Emulator. It is an implementation of the Win32 API, which means applications run at a normal speed compared to running them in actual emulators like VMWare.

That is, if they run properly. Wine is still not at version 1.0, which means that nothing is expected to work. Still, a great many apps are available as can be seen in the Application Database.

My first test was to install Starcraft. I found a few how-tos, but they aren’t terribly consistent, and it seems that the authoritative document is years old. Fortunately it wasn’t hard to install and run. The only problem I’ve found is that Battle.net isn’t usable. I get a black screen and the mouse cursor disappears so I can’t join in games. Cedega is a fork of the Wine code that was made into a closed source app. It was previously called WineX. It’s database lists Starcraft as highly rated and doesn’t mention the Battle.net problem. Still, I am not ready to shell out $5/month just to have Windows games I’ve already paid for running on my Gnu/Linux system, especially when some months I don’t get to play said games, and especially when there are plenty of native apps already. Also, it seems that newer versions of Wine tend to break the feature whenever it is available. I’ll wait.

My next test was Wizardry 8. I love the Wizardry series, and I feel bad that I haven’t played 8 very much. It works perfectly according to the Wine application database, so I set out to install it. I had forgotten how long it took to install this game! This is one of those 3 CD games which take up a lot of space on my hard drive. At 50% I had already added 1GB to my home directory (well, including Starcraft and the rest of Wine, but still).

Unfortunately when I try to run it, Wizardry 8 thinks I am running a debugger and wants me to stop doing so. I ended up having to find a no-cd crack in order to play this game, which goes to show you how annoying copy protection can be for legitimate owners of games. In the end, I managed to get it to play and aside from a few sound cracks during the opening video, it ran flawlessly. I am very pleased but I wish I didn’t have to go looking for a No-CD crack to play. Still, it shows a legitimate use of what would otherwise be considered illegal under the DMCA.

And Total Annihilation’s setup program wouldn’t even run on the version of Wine that I was using (20050310).

Wine just isn’t ready yet, but then no one pretends it is. Still, I have the ability to play one game as it was meant to be played, and another one works fine in single-player mode. Total Annihilation was possible at one time, so I can look forward to it in the future, I’m sure. Not bad for an incomplete project.

I’ve updated the Wine-Wiki for Wizardry 8, Starcraft, and Total Annihilation. Someone else already added their own comments about Starcraft. Wikis rule.

Categories
General

Day[24]; // off by one errors

When I was really young, I remember the first time I learned that the first hour of the day started at midnight. It was weird realizing that time moved in this sequence: 10PM, 11PM, 12 AM, 1AM, etc. Thinking about it for awhile, I realized it made sense.

To this day, the border between one day and the next throws people off. I like to think of it as an array of hours.

hours Day[24];

So now I have an array of hours called Day. The first hour is hour 0, and the last hour is hour 23. Translated into actual time: if it is after 12AM, you have entered into the next day.

Why am I bringing this up? Because I recently bought tickets for the latest Star Wars movie, and I bought them for opening night. My ticket says very clearly “Wednesday 12:01AM 5/18/2005”. I haven’t been paying attention to when opening night was supposed to be for the world, but I thought that I could trust my ticket. I received a call from my girlfriend today. She informed me that the movie is tomorrow night and not tonight. I think it is absurd, but she worked in a movie theater before and insists it is true.

So I walk to the theater. I ask a few of the desk workers if it is true that the movie isn’t playing tonight but is instead playing tomorrow.

“Yes.”
Why?
“Because it is Wednesday.”
But TONIGHT is Wednesday. TONIGHT is when it is 12:01AM on Wednesday.

At that point, one of them claims to have warned some manager about people getting confused about this issue. The other workers just apologize and say that it is meant to be Thursday morning, Wednesday night. As if them telling me that makes it alright now. One apologizes because that’s how the computer printed them out. As if some person didn’t make the computer do that. One reassures me that I’ll be able to get in tomorrow, as if that was my concern.

The ticket says one thing, but they “meant” another. I’ve been fairly upset about it all afternoon. I drove in today instead of taking the train since I knew I wouldn’t be back at a reasonable hour. I planned on using tomorrow to work on my presentation. Now because I was supposed to just know what they meant, I can’t work on the presentation tomorrow, and I didn’t get started on the presentation today until I got home hours later than I normally would have.

So tomorrow I will be going to a movie a day after what the ticket says. Imagine if the bank or your job worked this way. Direct deposit goes through on Friday? Nope. It’s actually Saturday. Father says to daughter, “Be home by midnight” only to find out that she is gone for a day longer than he thought she should be.

If the movie is 12:01AM on a Wednesday, it means I need to leave my house on Tuesday to make it in time. Unless you’re the movie theater, in which case it means you need to leave on Wednesday night, almost a full day after 12:01AM. GAH!

Categories
Geek / Technical General

DePaul Linux Community Install Fest

May 14th, this Saturday, will be the DePaul Linux Community Install Fest. It’s open to everyone, so if you’re in the Chicagoland area, check out the information on DLC’s website. Here’s a handy map to the event.

Categories
General

Learning Kyra: Hit Detection

The Learning Kyra series to date:

  1. Learning Kyra
  2. Learning More Kyra
  3. Learning Kyra: Attack of the Clones
  4. Learning Kyra: Tiles and Z-Ordering

I covered collision detection already, but it was in a limited capacity in Attack of the Clones. Basically, I checked if a sprite was colliding with a specific object. But what happens when I want to check for collisions with objects that have been added dynamically and prevent me from anticipating them at compile time?

The code below creates a number of sprites from the same resource. Kyra comes with the Grinning Lizard Utilities, so those are prefaced with Gl. I think that it makes it confusing if you want to mix your code with OpenGL, but whatever. One of the utilities is GlDynArray, which acts very much like the C++ Standard Library’s vector class. While it is in the provided demo code, I couldn’t find any mention of it in the documentation. I simply followed along with the demo in shooter.cpp. I created an array and added 10 ghost sprites to it. In the code below, MAX_GHOSTS is equal to 10. I also add those sprites to the tree.

KrSpriteResource* ghostRes = engine->Vault()->GetSpriteResource(GHOST_ghost);
GLASSERT( ghostRes );

KrSprite* ghost = new KrSprite( ghostRes );
ghost->SetPos( GHOST_START_X, GHOST_START_Y - 64);
engine->Tree()->AddNode( midgroundTree, ghost );

GlDynArray< KrImage* > otherGhost;
for (int i = 0; i < MAX_GHOSTS; ++i)
otherGhost.PushBack( new KrSprite( ghostRes ));
for (int i = 0; i < (int)otherGhost.Count(); ++i) {
otherGhost[i]->SetPos( GHOST_START_X, GHOST_START_Y );
engine->Tree()->AddNode( midgroundTree, otherGhost[i] );
}

So now I have a bunch of ghosts bunched up in the center, which is where GHOST_START_X, GHOST_START_Y sets them. I placed the player’s ghost about two tiles higher. Since I was going for simplicity, and I mostly hacked out this code without designing it first, I just made the sprites in otherGhost move around randomly. Another utility is GlRandom, which provides random number generators that are superior to rand() provided by C++. The following code demonstrates how I used it:

GlRandom random;

...
//the following is in the main loop
for (int i = 0; i < otherGhost.Count(); ++i) {

...
otherGhost[i]->SetPos( otherGhost[i]->X() + (random.Rand(3) - 1) * moveSpeed , otherGhost[i]->Y() + ( random.Rand(3) - 1) * moveSpeed);

...
}

So now each of the sprites in otherGhost move in random directions. I move the original ghost much the same way as I moved my clone sprite in previous Learning Kyra entry. Well, there is movement for the player and other objects, but what about collision?

if (engine->Tree()->CheckSiblingCollision(ghost, &hit, 0) ) {
for (int i = 0; i < (int)hit.Count(); ++i) {
engine->Tree()->DeleteNode(hit[i]);
int j = otherGhost.Find(hit[i]);
otherGhost.Remove(j);
}
if (otherGhost.Count() < 1 )
done = true;
}

Very simply, if the main ghost collides with any of the other ghosts, those ghosts disappear. When the last one disappears, the main loop ends, and since I hacked this out instead of designing it, so does the program. Still, it is game-like. I experimented with other options to see what else I could do.

Instead of removing the ghosts from the tree, you could make them stationary, sort of like in Freeze Tag. As they get hit, I remove them from the otherGhost vector to keep them from moving about, but I also added the following to fade them a bit:

KrColorTransform color = hit[i]->CTransform( 0 );
color.SetAlpha( 50 );
hit[i]->SetColor(color, 0);

While it isn’t fun or polished in any way, I don’t think I can expect too much more from this specific project, at least not without struggling through painful changes. I didn’t set specific goals so the project simply evolved. I’ll consider this project complete and move on to a new project that will benefit from my new experience and some better design. You can download the project as it stands from one of the links below:


KyraGame-r1.tar.gz
KyraGame-r1.zip
Kyra Source in .tar.gz format
Kyra Source in .zip format

NOTE: You will need Kyra v2.0.7 to use this code. Also, the comments in the code weren’t all updated to reflect the fact that I’ve changed it. It is licensed under the GPL or LGPL as specified.

Categories
Geek / Technical

Snapback2 How-To

Not too long ago I created my own automated backup script. Shortly afterwards, helpful people sent me links to other, more robust scripts that have been written. One of those was called Snapback2.

Snapback2 is a backup script based on rsync and hard-links. I could explain what that means, but why reinvent an already well invented wheel? Again?

My original script was alright, but it worked by making an exact copy of everything each time it ran. For my 4 GB home directory, backing it up weekly over the course of a month would result in a backup directory that is 16-20 GB in size! That’s a lot of wasted space, especially when some files don’t change at all.

Snapback2 uses hard links and only stores changes between one backup to the next, which means that if I only changed files that were 30MB in size, then the next backup will be 30MB as well. If no changes were made, then no space is wasted at all. Clearly this method is superior to what I have written.

Setting up Snapback2 is supposed to be very simple, but I found that the documentation assumes you know what you’re doing. The following is my Snapback2 How-To:

You can download Snapback2 at http://search.cpan.org/~mikeh/Snapback2-0.5/ for the latest version as of this writing. Technically you should be able to use Perl to download it from CPAN, but I didn’t. Most of the prerequisites should be on your Linux-based system already. According to the documentation, you’ll need:

Gnu toolset, including cp, rm, and mv
rsync 2.5.7 or higher
ssh
Perl 5.8 or higher
Perl module Config::ApacheFormat

On my Debian Sarge system, I have rsync 2.6.4, so your distribution will likely have at least 2.5.7. Similarly, I have Perl 5.8.4. The one thing that you need to do is get and install Config::ApacheFormat. To do so, make sure you have root privileges and run:

# perl -MCPAN -e 'install Config::ApacheFormat'

If it is the first time you’ve used CPAN through Perl, you will be prompted to configure it. If you aren’t sure, you can simply cancel the configuration step and it apparently grabs some defaults just fine. Any and all dependencies will also be installed.

Once you have all of the prerequisites, you can install Snapback2. Again, you could probably do the same thing above to grab it from CPAN, and it will probably grab Config::ApacheFormat for you, but as I didn’t do that, I won’t cover it here.

If you grabbed the tar.gz file from the link I provided above, you should run the following:

# tar xzf Snapback2-0.5.tar.gz

It will create a directory called Snapback2-0.5. The README tells you what to do, but for completeness, here are the next steps:

# cd Snapback2-0.5
# perl Makefile.PL
# make
# make test
# make install

Snapback2 should now be installed on your system. If it isn’t, you should double-check that you have all the prerequisites. The fourth line in the previous list runs tests before installing. If something failed, you should know why from the test results. Even if you did install it successfully, it isn’t going to do anything yet. You now need to make a configuration file.

You can read the documentation setting up the configuration file in the man page for snapback2, but you can also view it online.

Here is my file, snapback.conf:

Hourlies 4
Dailies 7
Weeklies 4
Monthlies 12
AutoTime Yes

AdminEmail gberardi

LogFile /var/log/snapback.log
ChargeFile /var/log/snapback.charges

Exclude core.*

SnapbackRoot /etc/snapback

DestinationList /home/gberardi/LauraGB

<Backup 192.168.2.41>
Directory /home
</Backup>

I didn’t change it much from what was in Snapback2-0.5/examples. I installed Snapback2 on the machine called MariaGB. MariaGB will connect to 192.168.2.41, which is the IP address of my main machine called LauraGB. This is why the DestinationList refers to LauraGB. If I wanted to backup another system, say BobGB, I would keep those backups separate in their own directory called BobGB. Normally, the ssh/rsync request would ask for a password. When I setup the backups to run automatically, it won’t be useful to me if I need to be present to login. You can do the following to create a secure public/private key pair:

$ ssh-keygen -t rsa

The above line will create keys based on RSA encryption, although you could alternatively use DSA. You will be prompted for a passphrase, which is optional. Still, a good passphrase is much better than no phrase at all. Using the defaults, you should now have two files in your .ssh directory: id_rsa and id_rsa.pub. The first one is your private key. DO NOT give it to anyone. The second one is your public key, which you could give to anyone. When setting up key-based authentication, you will append the contents of this file to the server’s .ssh/authorized_keys file. Next time you login, instead of being prompted for a password, you will find yourself at a prompt, ready to work. For more detailed information, read this document about using key-based authentication with SSH.

So now, if I run the following command on MariaGB:

# snapback2

It will backup any changes from LauraGB’s /home directory to MariaGB. If, however, it hasn’t been an hour since the last backup, it won’t do anything.

Still, manually running this command isn’t very useful, and while I could install a cron job to run snapback2, I will instead make sure that snapback_loop is running. It acts as a daemon, checking to see if a file gets created in /tmp/backups. Now I can create the following entry in my crontab:

# Create file for snapback_loop to run
0,30 * * * * touch /tmp/backups/snapback

So now, every 30 minutes, I create the file /tmp/backups/snapback, which snapback_loop will take as its cue to delete that file and run snapback2. Then snapback2 will make a backup if there has been enough time since the last backup was made.

Now, I have automated backups that run regularly. Some caveats:

  • Verify that snapback2 is in /usr/local/bin. On my system, snapback2 would run manually, but snapback_loop would output errors to /tmp/backups/errors that weren’t too clear. I had to create a symlink to /usr/bin/snapback2 in /usr/local/bin in order to get it to run.
  • Make sure snapback_loop is running with root privileges. It has to call snapback2, which will need access to files in /var/log and other directories which will have restricted access. If you run it as a regular user, you may get errors. You could also change the location of the log file, but /var/log is a standard spot to keep such output.
  • Because you are running it with root privileges, you’ll need to make sure root is the one with the public key in authorized keys rather than your user account. Otherwise, you’ll get errors like “permission denied” when rsync tries to connect to the other machine.

If you don’t use a second computer, you can always use a second hard drive instead. Either way, you now have an effortless system for automating your backups!

Categories
General

Learning Kyra: Tiles and Z-Ordering

Another entry in the Learning Kyra series. The series to date:

  1. Learning Kyra
  2. Learning More Kyra
  3. Learning Kyra: Attack of the Clones

The first three entries in the series documented my attempts at learning about the engine. I had a goal to become more familiar with the engine by the end of the month, so those articles were more focused. While that month has since passed, I am still learning plenty about the engine.

Recently I learned how to create tiles. Originally I was creating sprites, and they are sufficient for making games. However, I can also use tiles, but the documentation warns:

A Tile — in contrast to a sprite — is always square (width == height.) It can be rotated and flipped, however. You should always use Sprites unless you need to rotate and flip the image.

Making sprite images and making tile images are similar activities. When I use the Kyra Sprite Editor, I need to specify tile instead of sprite. Tiles are simpler since I do not need to mark hotspots and verify that they are aligned correctly. I was able to get three tiles very quickly, and saving created the .xml file to use. Then I used the Kyra Encoder and created the appropriate .dat and .h files. I copied those over to my source code directory.

The code to load a tile is different from the code to load a sprite, and the tutorial doesn’t cover it. I had to look at the Bug-Eyed Monster (BEM) demo code to find an example that I could use. To load a sprite, you have to do a few steps:

  1. Load the .dat file
  2. Get the KrSpriteResource as specified in the header file you created
  3. Create the KrSprite from the KrSpriteResource

Loading a tile is a little more complex:

  1. Load the .dat file
  2. Get the KrResource
  3. Get the KrTileResource by using KrResource::ToTileResource()
  4. Create the KrSprite from the KrTileResource

Ok, so there is only one more step, but it took me some time to find how to retrieve a KrTileResource. For instance, to get the KrSpriteResource, there is a function: GetSpriteResource(name_of_resource). To get a KrTileResource, however, you first need a generic resource by using GetResource(ALLCAPS_TAG, name_of_resource), and I couldn’t find the documentation on what that tag should be. It turned out that they were defined in kyraresource.h, and the one I needed was KYRATAG_TILE. Again, it was not in the tutorial so it took some work for me to learn what was needed. Here is the relevant code, keeping in mind that when I used the encoder, I prefaced everything with Tiles2_ (I already had a previous attempt with Tiles_) :

KrResource* res = engine->Vault()->GetResource( KYRATAG_TILE, Tiles2_tile2 );
GLASSERT( res );
KrTileResource* tileRes = res->ToTileResource();
GLASSERT( tileRes );
KrTile* tile = new KrTile( tileRes );
GLASSERT( tile );

tile->SetPos( 130, 98 );
tile->SetRotation(1);
engine->Tree()->AddNode(0, tile);

Anyway, I imagined that the tiles I created would be pretty cool to work with since they have alpha transparency. I could make clouds or chain-link fences, for instance. As I moved a sprite to the tile, I expected that the sprite would show through the tile’s transparent spots; however, when adding an image to the engine’s tree, the order matters. Since I added the sprite after the tile, the sprite image overlapped the tile image. I switched the order in the code, and it worked perfectly fine.

But then I was concerned. In a game, elements will get added dynamically. I wouldn’t want to find that a new enemy can walk over tunnels, or that the hero walks under floor tiles! Then I learned how the BEM demo handled Z-Ordering.

Everything that can be in the engine’s tree inherents from the base class KrImNode. KrSprite and KrTile are both KrImage classes, and KrImage is a KrImNode. KrImNode isn’t an abstract class, and it is the key to handling Z-Ordering.

Usually when I add a sprite or tile to the engine, I use the following code:

engine->Tree()->AddNode(0, tile);

AddNode()’s first parameter in this case is 0, which means that in the tree, it is a child of the root. If I add a second child, it will be drawn over the first child when the following code gets run:

engine->Draw()

BEM handles Z-Ordering by creating subtrees. Background images should be added to the backgroundTree while foreground images should be added to the foregroundTree. You create those trees in the following way:

KrImNode* backgroundTree = new KrImNode;
KrImNode* foregroundTree = new KrImNode;

engine->Tree()->AddNode(0, backgroundTree);
engine->Tree()->AddNode(0, foregroundTree);

Now, when I create a tile that goes in the background, I use AddNode(backgroundTree, tile1). Naturally I would have a separate subtree or two for entities I want to always be between the background and the foreground. If I need to create tiles for the foreground, I can add them to the foregroundTree:

engine->Tree()->AddNode(foregroundTree, tile2);

And tile2 will always be drawn on top of any images that are siblings to tile1, even if I add an image to backgroundTree after adding tile2.

Now that tiles and the Z-Ordering methods are added to my toolbox, I’m becoming much more dangerous with the Kyra Sprite Engine. Using just what I know now, I can probably make a fairly simple game without struggling with an unfamiliar library. There are still a few features to learn, however, including:

  • Fonts
  • Alpha blending and color transformations
  • Scaling
  • Canvases
  • Sub-window views

I may tackle one or two of these in the next Learning Kyra post.

Categories
General

Reading in 2005

Earlier this year, I noticed some developers are making book lists on their blogs. Sillytech and Joost Ronkes Agerbeek’s lists are two of them. I have been keeping a private list of books I am reading and have read, but I think it will be useful to post the list online as well.

I plan on having a sidebar similar to what is on Games From Within. In the meantime, you can see a listing in this blog post.

Books I Am Currently Reading

  • On Writing by Stephen King

Books I Have Read in 2005

  • 100 Ways to Motivate Yourself by Steve Chandler (Audio Book)
  • Alice’s Adventures in Wonderland by Lewis Carroll (ebook)
  • C++ Coding Standards by Herb Sutter
  • The Curious Incident of the Dog in the Night-Time by Mark Haddon
  • First Things First by Stephen Covey
  • Getting Things Done by David Allen
  • Live Without a Net by Lou Anders (Editor)
  • The Object-Oriented Thought Process by Matt Weisfeld
  • Ready for Anything by David Allen
  • The Seven Habits of Effective People by Stephen Covey
  • Through the Looking Glass by Lewis Carroll (ebook)

Some people try to read at least one book a week. It’s the 18th week or so for the year, so I am about six books behind. I never actually set such a goal, of course, but I should. I’ve found that I can have much more intelligent conversations and tell much funnier jokes (at least to me) since I’ve started reading regularly. I have learned so much more than I would have if I had neglected the literature, and some of it, such as Getting Things Done, has changed my life in amazing ways.

I’ve found that I’ve been focusing on personal productivity a bit too much, so I’ve tried to add works of fiction to the mix. Besides science fiction, I’m interested in mystery novels as well, but I am not familiar with what is good outside of Sherlock Holmes and Hercules Poirot. Anyone have any suggestions?

Categories
Game Development Personal Development

Goals and Habits: Program for 5 hrs/week

Since I think coding practice should be a higher priority in my life, I’ve scheduled two days out of the week to program. Monday and Tuesday evenings after work, I will spend at least two hours programming. Four hours of the week can easily be accounted for there, and I could always do more on those days and others.

Previously I assumed I could squeeze time out of my week to program, but since I didn’t have any hard rules about it, I never did it. The thinking was that I could always program “tomorrow”, and of course tomorrow always had its own excuses.

Eventually procrastination became a habit. If I did have time in front of my computer, I ended up checking email or configuring something that I didn’t need to configure at that moment. Even now I catch myself getting distracted too easily during my programming time. I find myself trying to check my email or reading blog entries and have to force myself to continue programming.

Breaking old habits is hard, as everyone knows. I recently bought Steve Chandler’s 100 Ways to Motivate Yourself audio book. I listen to it in the car and am amazed at how much education you can get in a 30 minute drive. One of the things he talks about is breaking bad habits. He says we can’t simply drop bad habits. We must replace them with better habits. In my situation, I simply need to get my mind to think that it is time to program whenever I am in front of my computer instead of having it think that it is time for recreational web browsing. He also talks about will power and the need to exercise it. The more we practice control, the stronger our will becomes. The two tips go hand in hand.

Each time I refuse to check my email during my designated programming times, I get that much closer to replacing habitual time wasters like useless email and web browsing with habitual productive activities. Building will power in this way applies elsewhere. For instance, each time I make myself check my calendar before making a committment, the more useful and powerful my calendar becomes. Each time I check my lists when I am deciding on my next action, the more important my lists become to me, which means I’ll use them more.

Creating good habits and getting rid of old ones is great for accomplishing goals. If I make a regular habit of programming each day, I simply have to hit my goal for the week, and therefore I can’t NOT hit my goals for the month. As Chandler says, “It’s mathematical.”

Categories
Game Development

Chicago Indie Gamer Meeting for April

Today was the Chicago Indie Gamer Club meeting for April. I was not able to accomplish my goals for this month before the meeting.

As bad as I may feel for failing, I’m really glad this meeting exists. In the past, I’ve had spurts of game development between periods when I didn’t do anything. Without the deadline this meeting imposes on me each month, I may not even notice that I’ve spent a week or two not working on my projects. I probably would coast into May without realizing how much time has gone by since I last coded.

I know I had setbacks at the beginning of this month. The hardware failures and reinstallation of my main computer required that I take some time to recover to get to the point where the system was usable again. I had a couple of games to review. I was updating my resume. I wrote some scripts to help with automating backups.

But even with those excuses, I clearly failed. I never made programming the priority that it should be. I should not be trying to squeeze in some coding time around the rest of my schedule. Instead, I should dedicate blocks of time to coding and have everything else fall around them. For example, I just reinstalled Kyra on my system this past week. My computer has been operational since the beginning of the month. So why the delay? I wasn’t programming, so I wasn’t using the library. I didn’t need Kyra installed if I wasn’t using it, so I never noticed that it was not installed until recently. So when I was ready to code the other day, I had to spend some time installing a library that should have already been ready to use. I spent the little time I had spared just getting the system ready, and it resulted in lost practice time.

I plan to rectify these issues with the goals I set for next month. Even though I never mentioned them at the meeting, I’ll list them here:

  • Block out time for regularly scheduled programming
  • Continue to practice programming for 5 hours per week
  • Make a simple game by the end of the month
  • Setup an automated build system by the end of the month
  • Setup a cross-complier on my system by the end of the month

The first goal is kind of a metagoal. It is primarily to help me accomplish the next goal. If I have regularly scheduled programming practice, I can’t possibly miss my goal of programming so many hours per week. The third goal is likely going to be worked upon during my practice times. While I could work on anything to satisfy the second goal, I can also be efficient and kill two birds with one stone.

The last two goals are important. The automated build system will make the process of building the project from scratch incredibly easy. I don’t manually compile my code at the moment since I use GNU Make, but I have to manually invoke make each time I want to use it. That option is nice to have, but I can easily miss something in the full build. I don’t want to create a demo download that won’t actually install on a potential customer’s computer because it was missing a file. Automating the builds will help by removing the concern to do testing and builds from my mind. I can discover the results and work from there rather than worry about the correct steps to carry out.

The cross-compiler will make it possible for me to use a single code base on a single system and build for multiple platforms. I can currently compile for Linux-based systems, but I would like to compile my projects as Windows applications as well. Rather than copy the code to a Windows machine and run a Windows-based compiler, I can use a cross-compiler on my Debian machine and make it compile a Win32 binary. I will need to test it to verify that it works obviously, but I would be testing the native binaries as well.

I don’t believe my goals are overly difficult or ambitious, but even if I don’t accomplish everything, I know I can accomplish at least some of them. By the end of May, I hope to have great, tangible results.

Categories
Game Development Personal Development

What Happened to my Productivity?!?

It’s April 19th. The Chicago Indie Game Developer meeting is in less than six days. My goals for this month were to continue programming for 5 hours per week and to complete a simple game. While the month isn’t over yet, I haven’t accomplished these goals at all.

Last month was great. I programmed. I learned how to use Kyra. I learned a lot.

This month, I hit a stumbling block right away when my video card needed to be replaced. I also spent some time updating my resume to look for a full-time job. I have a couple of game reviews to do for Game Tunnel. Still, if I claim that all of these things prevented me from accomplishing my goals, I’d be lying to myself. My computer was back up and running within a few days of the problem. I didn’t spend more than a few hours total over a week on my resume. And I haven’t been playing the games too much either.

So where did my time go? Actually, the more accurate question is, “How did I squander my time?” How did I let an hour or two go by without at least doing something for a few minutes that is related to my goals? Even if it was an overwhelming amount to do, which is certainly not the case, at least ONE thing could get completed, right?

This past week I’ve been in a funk because I feel like I haven’t accomplished anything at all. My game review is overdue, my job search hasn’t really started yet, and I haven’t coded anything since I reinstalled. It doesn’t help at all that I may be getting sick as well. I’m feeling stressed and worried, which wastes my energy, which only serves to make me feel more stressed and worried.

So April is a bust.

Or is it?

While I can’t do anything about the delays at the beginning of the month, I’m allowed to reset my goals. Clearly I failed in programming for the past three weeks, but nothing prevents me from doing so for this week. I haven’t created the game, but nothing prevents me from trying to make a simple game in less than a week. It’s been done before, and I’ve already mentioned my intent to participate in my own Game in a Day. Perhaps I won’t finish the game. But attempting to do so puts me in a better position than where I am currently, so that’s reason enough for me.

Nothing prevents me from accomplishing my goals. Except me.

Look at that. My stress is gone. It’s been replaced with resolve. Fancy that.