NoshBar's Dumping Ground





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 ] ( 440 views ) permalink print article


Sometimes someone I know feels down,
sometimes that person is me,
sometimes I want to see what monstrosity
I can make with default assets in programs.

This was going to be a life-affirming cheerleader,
but the giggles got hold of the controls.
(click the image for a larger version)

Text made in Blender
Cheerleader set up in Daz3D
Background from here


[ view entry ] ( 949 views ) permalink print article

Recently I started looking at ways to get Drumpster to output MIDI on non-Windows platforms and came across FluidSynth. It allows for MIDI playback and conversion to WAV files if you so choose. In order to do so, you need to provide a SoundFont (which provides instrument samples that are used to convert the MIDI data to wave data).

In my search for some free SoundFonts, I came across the Rhodes Piano one listed here (decompressor here), and I find it absolutely beautiful to listen to. It has a melancholic joy to it (making me think of Everclear), sometimes sounding menacing like the music in Tron.

So armed with the Rhodes SoundFont and a Windows binary from here, I converted a few MIDI files and put them up on SoundCloud.



To convert some yourself, an example commandline for this would be:
fluidsynth.exe -F output.wav input.mid jRhodes3.sf2


P.S. It also turns out that FluidSynth has a delightfully easy to use Python wrapper here.

[ view entry ] ( 2386 views ) permalink print article

This new version of Drumpster has been "ready" for ages now, I didn't want to release it because it simply isn't good enough.
(the "MIDI Playback" button doesn't do anything unless you enable it in the configuration file first, there aren't proper icons for most binaries, I haven't tested it properly on all the platforms (32-bit or 64-bit OSX build... how should I know!?), the lyrics don't always load correctly...)
However, when compared to v0.1, this has several major fixes and enhancements that make it worthwhile.

I also have a sneaking suspicion that I am going to have to rewrite the whole MIDI loading to notes on a timeline process. I currently load notes and convert them to their absolute time in milliseconds, mostly because I'm a dunce and I have no idea what I'm doing.
What I've noticed is that this conversion process isn't ideal as a song with a slow tempo will throw the notes towards you at the same pace as a fast tempo song... meaning that the notes will either be scrunched up together or very far apart, making it difficult to read sometimes.
So now I will have to store the notes and their tempo and change the rate of note flow accordingly.

Major fixes


  • MIDI loader is more stable and maps things more correctly now.
  • The splash-screen now works, a side-affect of the OpenGL code being slightly less beaten by the crazy-dog stick.
  • The OBJ loader is a bazillion times faster now, and is less against actually loading OBJ files.


Enhancements


  • Android build - I've tested it on a single device, all I own, if you have any tales of woe/joy, I'd love to hear about them at my Hotmail address, noshbar@, or
  • BlackBerry PlayBook build
  • The WebOS build has a funky feature where you can drag the timeline/fretboard back and forwards through time with your finger.
  • Lyrics are now loaded from the MIDI file and displayed during gameplay.
  • You can enable buggy MIDI audio playback by adding the following line to the drumpster.cfg file:
    [sound]
    midi_backtrack=true



[ view entry ] ( 784 views ) permalink print article

<<First <Newer | Older> Last>>