NoshBar's Dumping Ground




Introduction:


I touched my first computer at age 16. I almost made a game immediately.
I almost made a game every month of every year for the next 16 years.
There's only so much self-respect you can lose until you just have to prove that you're capable of finishing something.

The time had come where I asked my life for 8 hours of uninterrupted codery goodness, and this is how it went...

(DOWNLOADS are at the bottom)

The game idea:


Something simple that can be finished in 8 hours.
Something that has few actions performable by the player.
Something that can easily have randomly generated levels.
Those infinite jumping games are popular, they only have tilt left and right, they also use the only physics/maths I understand, velocity.
I hate infinite running/jumping games, no sense of accomplishment.
Make a jumping game with a defined set of levels and each level must have a finishing point/goal.
For some reason, people like competing, so make the levels timed.

The engine:


I've looked at many frameworks in the past few years, I've also ALMOST finished quite a few myself.
The LÖVE framework seemed to have a simple enough API to get a grips with, and even though I'm not that familiar with Lua, it didn't seem like it would take long to learn.
10 minutes of messing around with the engine and its examples and I was sold. For prototyping, it was gold.
And if worse came to worst, I could always write my own lightweight framework for all the platforms, and oh hey, I just recently put the Lua engine into Tweenimator to see if I could, I wonder if... NO, FOCUS!

The editor:


Sublime Text setup with a LÖVE "build" command.
Tools->Build System->New Build System
{
"selector": "main.lua",
"cmd": ["F:/apps/LOVE/love", "$file_path"]
}

I also used the Lick addition for LÖVE so that every time I saved changes to my code, the game would restart automatically.

The prototype:




107 lines.
The orange rectangle at the bottom is the permanent floor.
The orange square is the player.
The blue tiles are all platforms you can pass through upwards but rebound off when falling.

Bah, this is dull, if you had a level with platforms stacked in a neat center row, everyone would always have the same time, it's impossible to be quicker.
Make it so that the player can SLAM DOWN to hit a platform quicker and thus improve their time.
Hmm, better, but not great.
AHA, make it so that platforms are in two states that the player can switch between, making them only collidable with their current colour!
Muuuch better.
For some reason the dual colours make me think of Tron (and Transformers, and Jumper (hey!) and...)
That's it, I'm going full Tron on this one... while being respectful of IP and copyright and what-not...

The graphics:


No matter what I make, it'll suck.
But I'm also against just leaving things as plain squares.
Well, seeing as I'm Tronning this lot up, may as well make everything glow like a sonofafemaledog. JJ Abrams would be proud.

Open Paint.NET.
Draw something on one layer (text, block, whatever)
Duplicate layer, shift it down and right one.
Change the colour to blue or orange.
Apply Photo->Glow effect to both layers, SHAZAM!


I need something for the background, to parallax scroll, because no game is complete without it.
Think "jumping" as the theme.
That's it, I'm going Tron, may as well print some source code with some "jmp" instructions in.
Open the Tweenimator binary in OllyDbg to see some assembly, holy balls, look at all those jumps at the entry-point, jackpot!
Also, this game shall be called "jmp:err", or "jmperr"

The audio:


Music.
No matter what I make, it'll suck.
Go through some chiptunes for ambient music, they all sound too "busy".
Search for randomly generated music.
The Trance Music Generator sounds promising.
Download 3 different MID files from it, find one that might work.
Convert the MID to OGG using VLC with the jRhodes3 soundfont (audio codec) I'm so fond of.
The resulting file is 5MB and a bit busy in the middle... sod it, open it in Audacity and strip it all down to one tiny 10 second looping sample... no one sane is going to keep the music on any way.

Sound effects.
I don't need anything complicated, just a few blips and bloops for jumping, boosting and... menu sounds.
Make some samples using an online sound effects generator.

The menus:


Every game needs menus to be "complete". Damn.
I need text for this. It must look Tronny.
Hello Tr2n.ttf!
Find some menu code examples on the LÖVE forums (can't remember where exactly, sorry source!).
Modify it so that every menu item has a data item associated with it that is displays next to the menu text. This is useful for displaying times next to levels and...
Make options menu for adjusting volumes, modify menu so that it can take left/right as input and call appropriate callbacks.

The persistence:


Time to save/load scores and configuration options.
Hmm, Lua must have some simple function to do this, right?
It does, it's called the Lua Community, huzzah!

The result:






911 lines of slightly mutated ill-tempered spaghetti code.

The game works. There are some features/patterns left to the player to find out, kind of like the first few times you play Mario Brothers.

It's nice to have finally finished a game.
Well. Almost.
See.
It's like this...

The splash screen is vile...
The graphics and audio are terrible...
Showing the code to any living organism would result in it bleeding out of the spaces between its cells.
The gameplay is good enough, but there are so many things I could do to improve it...
There still isn't any real sense of "winning"... you make it to level 10, it shows a different "win" message, then lets you go on forever...

... or at least that's the theory.
Every level is assigned a random seed.
Every level is randomly generated according to this seed, each platform is placed within vertical reach of the previous one.
There is no check to see if the horizontal + vertical distance is reachable... but all of the first 10 levels are completable... either by magic, or by the magic numbers I came up with for platform heights and widths.

I don't know how the game works really.
But I felt myself playing it quite a lot while developing it... something I never expected to do.

Most importantly, I finally came closer to finishing something...

The summary:


Editor:
Sublime Text with LÖVE build system

Engine:
LÖVE with helper libraries
- Lick
- Menu.lua
- table saving stuff

Visual:
- Tr2n.ttf
- OllyDbg for generating some ASM code for my background
- MWSnap (my keyboard doesn't have a print-screen button on it, required for capturing assembly output in OllyDbg)
- Paint.NET

Audio:
- Sound Effect Generator
- Random Music Generator
- VLC using the jRhodes3 soundfont
- Audacity

The download:


Windows Executable
OSX Executable
Generic .LOVE file for existing LÖVE 0.8+ installations

[ view entry ] permalink print article


Seeing as Google Reader is going out of action in June and that it's the only way I would ever know what was important in my life, I decided it was time to make the Google Reader Replacement I kept threatening to make.

project-GRR will hopefully not only replicate the behaviour of Google Reader that I enjoy, but add useful features such as:
  • Storing all the posts in a database for later retrieval
  • Optionally download the destination page of every news item into a PDF
  • Be able to filter new items, either removing or highlighting them depending on keywords present

The idea is also that you can either use this with a web-server somewhere, or just run it locally purely using the PHP binary and its built-in web-server.

At the moment it's still a work in progress with a few product-breaking bugs, but it definitely has potential.

So for now you can get it off GitHub here:
https://github.com/noshbar/project-GRR



[ view entry ] permalink print article

Goal


Ever since I started to code I wanted to have a game character move from one place to another intelligently, no pre-canned paths.

The A* search algorithm allows you to do this, but due to my age/indifference/attention span I never got round to understanding how it worked ("Heuristics? Weightings? I don't... I... I could just make more particle blood...")

Now that we live in a world filled with free and easily accessible information such as Wikipedia, I could finally find an example that would make sense to me.

With the information on Wikipedia and this article, I gave myself one day to implement the algorithm myself (that last link was the "I can actually do this!" turning point for me, the images with values on were the part that finally made sense to me).


Impatience and Tools



As I didn't have much time to do this, I thought I'd stick with the basics I knew:
Visual Studio Express to develop in C++
SDL and SDL_image for graphics
Tiled for map creation
Paint.NET for tile creation

Seeing as I had absolutely no desire whatsoever to mess around with an XML or JSON library in C++, I made a quick Python script to convert Tiled's native .TMX format into a C++ .H header file containing a class that I could use to get the tile and collision properties of an X,Y co-ordinate.

Using Tiled, tiles in the tileset were given values relating to how costly they were to travel over. I guess this is what they call "weighting". For me it worked out as a multiplier where roads where a multiplier of 1, grass is a multiplier of 20, and sea is a multiplier of 100 (a pure obstacle then really).

So in the end I made diagonal tiles cost just a bit more than travelling across two tiles so it would prefer to keep to the road, and "G" and "H" values would end up being multiplied by the preference value of the current tile.
enum
{
Tile_Weight = 10,
Tile_Weight_Diagonal = Tile_Weight * 2 + 1,
};

openTile->G = CostSoFar;
openTile->H = (abs(DestinationX - openTile->X) + abs(DestinationY - openTile->Y)) * Tile_Weight;

openTile->G *= world->map.Cost(openTile->X, openTile->Y);
openTile->H *= world->map.Cost(openTile->X, openTile->Y);


Result




Not too crappy actually.

I had several criteria I wanted a path to follow:
  • A car should prefer to drive on a road
  • A car may drive on grass if it's the only option
  • A car should not take a shortcut by travelling diagonally across a corner tile, i.e., skipping a curved round turn by crossing grass
  • A car can take a shortcut diagonally across grass if it means getting back to the road quicker


As this was all done in a day, I have no doubt that there are issues I haven't found, but I finally understand how it all works and for a small amount of time I felt good about myself.


[ view entry ] permalink print article


Because I suffer from rare diseases (like getting to know people in shops really well then not being able to go there anymore because I feel like I'm making them feel awkward), I ended up porting the smallpt global illumination renderer from 99 lines of C++ code to 666 lines of Turbo Pascal 3 code.

Doing this meant I got to play with loads of things:
  • Turbo Pascal 1, 3, 4, 5 and 7, Delphi...
  • Lazarus
  • FreePascal (for Android and iPhone and GBA)
  • Pascal Script and DWScript (hint: unless you've run out of paint to watch dry, you really want to use the DWScript version)
  • FreeDOS
  • Virtual Machines like Bochs, VirtualBox, DOSBox




See most of the gory blah-blah details here

[ view entry ] ( 472 views ) permalink print article

Purpose


I tried to find a simple example that showed me:

  • How to call some Lua script from within C
  • How to call a C function from within the Lua script
  • How to pass an instance of a structure/class to the script and have it call functions on it

Being naive I thought finding something like this would be easy. We all know how stories starting with "Being naive..." end (in road-side ditches surrounded by police tape).
I used the latest Lua release (5.2) and stumbled across errors where functions were deprecated (lua_open no longer exists), examples where there was so much going on I simply couldn't understand the basics, examples where a script.lua file was simply executed, examples where in order to pass a C object over I had to create something called a MetaTable and and...

So here it is, a simple example that pretends it's a game. The idea would be that you have an enemy object and it's intelligence would be stored in a Lua script that is loaded at the start of the game, and the "onUpdate" function in that script is called every frame wherein it can change the position, state, colour, happiness, whatever of the object.

Note


This contains no error checking to keep things simple. The Lua documentation on how to do error checking is great, and you should check the result of every call you make, as well as checking to see if variables are actually the type you expect them to be before using them.
Also, I started using Lua for the first time today, so this is simply an example that works for me, your mileage and joy in ignorance may vary.

Code


#include <stdio.h>
#include <stdlib.h>
#include "lua.hpp"

/* This is our game object structure, specifying all the properties that may pertain to an
   object instance in our game. For this example, only the position is important. */
typedef struct GameObject
{
	int x;
	int y;
}
GameObject;

/* This function is called from Lua via GameObject.move to move our object instance.
   In Lua-land it passes 3 parameters: the instance; and x and y. */
static int GameObject_move(lua_State *Lua)
{
	GameObject *instance   = (GameObject*)lua_topointer(Lua, 1);
	const int   x          = lua_tointeger(Lua, 2);
	const int   y          = lua_tointeger(Lua, 3);

	/* adjust the position of the instance and print out that we've done something. */
	instance->x += x;
	instance->y += y;
	printf("GameObject_move(%d, %d)\n\tinstance->x = %d\n\tinstance->y = %d\n", x, y, instance->x, instance->y);

	return 0;
}

/* This is called from C-land and simply serves as a helper function to set up the update
   function and call it. */
static void scriptOnUpdate(lua_State *Lua, GameObject *Instance)
{
	/* Fetch the Lua function and make it the thing currently on the stack */
	lua_getglobal(Lua, "onUpdate");
	/* Push the first argument onto the stack, which is the instance we are currently updating */
	lua_pushlightuserdata(Lua, Instance);
	/* Call the function on the stack telling it that it has 1 parameter and no return values */
	lua_call(Lua, 1, 0);
}

/* This sets up the Lua context and registers our functions with it. */
static lua_State* createLuaContext()
{
	/* Build up an array of functions we want to expost for the "GameObject" namespace. */
	/* Add whatever functions you want to expose to this array. */
	const luaL_Reg gameObjectFunctions[] =
	{
		{ "move", GameObject_move }, /* Lua GameObject.move() maps to GameObject_move() in C-land */
		{ 0, 0 }                     /* NULL terminator to signal the end of the array */
	};

	/* This is the Lua script we plan on running, it would probably be in a resource file somewhere. */
	/* scriptOnUpdate() above calls this function, which in turn calls the GameObject_move() function above */
	const char *script = 
		"function onUpdate(instance)\n" \
		"    GameObject.move(instance, 4, 2)\n" \
		"end\n";

	lua_State *lua = luaL_newstate();      /* Creates a new context, lua_open replacement in versions > 5 */
	luaL_openlibs(lua);                    /* Adds the default Lua libraries to the context */
	luaL_newlib(lua, gameObjectFunctions); /* Adds our functions to the context */
	lua_setglobal(lua, "GameObject");      /* Assigns a namespace to our most recently added functions */
	luaL_loadstring(lua, script);          /* Loads our script into the context */
	lua_call(lua, 0, 0);                   /* This "primes" our context, without this, things will fail! */

	return lua;
}

int main(int argc, char *argv[])
{
	/* This is our game instance that we intend on passing to the Lua script for it to have its way with. */
	GameObject instance;
	instance.x = 6;
	instance.y = 8;

	lua_State *lua = createLuaContext(); /* Set up the lua context */
	scriptOnUpdate(lua, &instance);      /* Call the Lua script "onUpdate" function passing our current object instance */
	lua_close(lua);                      /* ... and we're done. clean up shop and go home! */

	printf("\nPress return to quit.\n");
	getchar();
	return 0;
}


[ view entry ] ( 437 views ) permalink print article

<<First <Newer | Older> Last>>