logo

ShrimpWorks

// why am I so n00b?

I’ve had to do quite a bit of stuff with images in Delphi recently (lots of manual drawing too), and discovered TCanvas’ TextOut method will only draw text onto one line, line breaks and newlines are ignored. Google search results suggested Windows’ DrawText function, however despite all the formatting and alignment flags it takes, it refused to draw text centred vertically.

Anyway, here’s a small-ish procedure which will take your multi-line text, and draw it centred on the canvas you pass it. You also need to pass the width and height of the canvas you’re drawing to. It assumes the font can everything else has been set by you, prior to calling it. Also, be sure “Graphics” is in your “uses” section.

procedure multilineCanvasText(canvas: TCanvas; text: String; width, height: Integer);
var
  textSize: TSize;
  lines: TStringList;
  i, blockHeight: Integer;
begin
  // lazy man's way of splitting text by line into a list (split by #13#10)
  lines := TStringList.Create;
  lines.Text := text;

  // see how high our block of text is going to be, based on the font the canvas
  // currently has set
  textSize := canvas.TextExtent('LOZL!');
  blockHeight := textSize.cy * lines.Count;
  blockHeight := blockHeight;

  // go through each line and output it
  for i := 0 to lines.Count - 1 do
  begin
    // we need the width of each line, so we can center it on the canvas
    textSize := canvas.TextExtent(lines[i]);
    // render the text
    canvas.TextOut((width div 2) - (textSize.cx div 2),
                   (height div 2) - (blockHeight div 2) + (textSize.cy * i),
                   lines[i]);
  end;
  freeAndNull(lines);
end;

Well, only one for now.

Sadly, I no longer need my laptop for work, as I have been provided with a proper desktop machine (this may be a good thing, since I can now boot Debian permanently, as I’ll no longer need to use Delphi on it). Anyway, I kind of liked having my work stuff and private stuff portable with me. So, I got something a little more portable, which I can both work (well, do basic documents, do all my emailing, track to-do’s, contacts, etc), and personal (fill it with random fun stuff) stuff on.

Enter, the iPAQ hx2750 :D. Complete with wireless LAN, so I can connect to networks at home, work, and the occasional Mug and Bean, Bluetooth for sending files between the handheld and laptop, and sending photos to to from the phone (I can even dial contacts on the iPAQ via bluetooth on the phone :P, and of course use it as a dial-up modem when a network is not available), SD slot for extra storage, and another way to transfer files between laptop and handheld, and a bunch of other leet stuff it can do.

I’ve also got PocketPuTTY up and running, so when I feel the urge I can pop onto whatever boxen I need, Python CE has already been helpful, as it enabled me to write a small .tar file extraction script for some other files I wanted. Even though I’m still first and foremost an Unreal fanboy, I couldn’t resist installing Pocket Quake. Pocket RAR and Adobe Reader have also come in rather handy.

Pocket Word is quite reasonable, and maintains document’s original formatting quite nicely. Pocket Outlook works very well for receiving, reading, and sending emails, and if ever offered the option of Outlook or Pocket Outlook, I’d have to choose the pocket version :P. It handels POP and IMAP mail equally well, and even does IMAPS without complication.

All-in-all, I’m rather impressed, and I find myself using it rather regularly throughout the day, especially for keeping track of projects and things at work, which was partly the main idea anyway.

Guess it shouldn’t have taken so long for me to get around to doing this, but at least it’s done now.

Attached to this post you’ll find a zip file, containing a small example application which allows you to spawn PyODE physics-enabled cubes with the middle mouse button into a PyOgre world. You can then bounce and roll the cubes around by holding the left or right mouse buttons.

The code is fairly straight-forward, and I’ve included quite a number of comments. Should be easy enough to follow what’s going on if you’ve been through the PyOgre tutorials.

A note of performance and stability - you can safely spawn loads of cubes as long as there are not too many collisions going on at once (after around 50 cubes, things start to get really sluggish if there are too many inter-cube collisions going on). In practice though, I doubt you’d need that many collisions happening at any one time. Also, If you make a large pile of cubes, lift them all up, and let them fall down together, it seems to bomb out as there are too many collisions happening when they all land on top of eachother at once. I haven’t debugged this very much, so I’m not sure yet if it’s a ODE limitation, or something bad I’m doing in the code. If anyone works it out, I’d be interested to know.

Please don’t ask for advice on stuff like per-polygon collisions, terrain collision and the like, I have not really messed with this beyond the state of this example. Once you get the basics going after checking out the example, I’m sure a few questions shot off at the PyOgre Forums would turn up more useful results than asking me :).

Have fun ;).

As we all know, PNG images are so much cooler than BMP images. Especially with alpha channels.

A while ago, I found this rather spiffy PNG library for Delphi, which allows you to load PNG files into a TPicture or similar, complete with alpha channels. Generally, it works simplest with TImage, however being a TGraphic subclass, you can do all sorts of drawing and everything else on it.

ANYWAY, I wanted to be able to use these things on buttons (standard TSpeedButton and TBitBtn), however their Glyph property is a TBitmap, preventing us from doing a simple Button.Glyph.LoadFromfile and loading a PNG file. The other option is to load up the PNG on it’s own with a TPNGObject, and assign it to the glyph property, however the alpha gets buggered.

So I came up with a crackful work-around (as I’m finding 90% of all Delphi coding is):

procedure pngGlyph(Btn: TControl; Img: String);
var
    PNG: TPNGObject;
    BMP: TBitmap;
begin
    PNG := TPNGObject.Create;
    BMP := TBitmap.Create;

    try
        PNG.LoadFromFile('path\to\glyphs\'+Img+'.PNG');   // Update the path to your .png files, or update this to get them somewhere else.

        BMP.Width := PNG.Width;
        BMP.Height := PNG.Height;
        BMP.Canvas.Brush.Style := bsSolid;
        BMP.Canvas.Brush.Color := clBtnFace;
        BMP.Canvas.FillRect(Rect(0, 0, PNG.Width, PNG.Height));
        BMP.Canvas.Draw(0, 0, PNG);
        BMP.Canvas.Pixels[0, BMP.Height-1] := clBtnFace;

        if (Btn is TSpeedButton) then
            (Btn as TSpeedButton).Glyph.Assign(BMP);
        if (Btn is TBitBtn) then
            (Btn as TBitBtn).Glyph.Assign(BMP);
    finally
        PNG.Free;
        BMP.Free;
    end;
end;

To use it, you call it like pngGlyph(SpeedOrBitButton, 'glyphname');, and the procedure will hack your button’s glyph into something that looks nice. You can use fully alpha-enabled PNG files, and they should look right.

Of coarse it would be better to create a new button type with this procedure inside that, so you don’t have to call this for every button you want to add a PNG to, but I don’t really feel like re-adding a million buttons, it’s quicker for me to do a million procedure calls :).

Heh :D

So I’ve started work on my own small RSS aggregator for some or other web project I may or may not actually complete. And no, it’s nothing like Gregarius, it’s more of an ‘internal function’ of a larger project.

So anyway, after checking out the various RSS version specs and things, I hunted down as many feeds as I could to get an idea of the kinds of data I’m going to end up sifting through.

Wow. Despite the fact that there are standards out there doesn’t seem to mean much. Nearly every feed is a world apart from the next one, either throwing in millions of useless custom tags, renaming standard tags to some other random thing that made sense to the author and nobody else, leaving out loads of actual useful information, mixing and matching the specs as they feel the urge, and a million other randomnesses.

Anyway, on the way to making sense of it all, I fed some of them through MagpieRSS, which actually does a fairly reasonable job of making them a bit more sane. Still, I have to guess a lot of fields and things, and pretty much hope for the best.

At the moment, people’s RSS feeds generally seems more psychotic than some of their use of HTML.

Well, in the interests of Monster Hunt surviving a bit longer, I’m releasing the full UnrealScript source code.

Included is a basic license document, outlining in simple terms what you may and may not do. Basically, you may make any kind of MH mod or ‘sub-mod’, however you must give due credit for the original creation. Even if it’s very basic, please read it if you intend using it for creating a mod.

You’ll find the file at the end of this post… Have fun :)

MonsterHuntSource.zip

I was browsing around the BeyondUnreal Forums the other day, and came across an 11 page thread, with around 720 replies, about Monster Hunt. Interested to see what’s up, I checked the CSports rankings for Unreal Tournament, and was shocked to find MH is the #4 most played UT gametype in the world. Coming in after CTF, DM, and TDM.

Seems people have been making maps like nuts, there seem to be over 300 of them, there are a few mutators and mods available for it as well. I found there’s even a pretty large fansite, Planet Monster Hunt.

Not too bad for a mod I thought I had retired nearly four years ago ;).

My idea for implementing non-physics physics into my little game framework didn’t work out too well, so I gave in and took a look around for options.

It seems only ODE is available to Python, via PyODE. Not many [open source] physics engines seem to have Python bindings, which I find rather odd.

As it turns out, it isn’t actually all that of a mission to get ODE and Ogre working together, and the results I’ve got so far are quite acceptable. I can spawn loads of cubes (of varying sizes) and throw them around the scene and they bounce and jump around in a suitable fasion.

PyODE and PyOgre playing nicely

I haven’t tried with balls or polygon-accurate stuff yet, that’s next on the to-do list. I also intend writing a short how-to for PyODE and PyOgre integration at some point, as I was a little confused to start with, not knowing quite where or how to begin, and there is no PyODE/PyOgre example code floating around to reference.

EDIT: Example using PyODE and PyOgre now available -

It seems as though the guys at work are seriously looking into the option of doing some game development next year some time, and they’ve been busy checking out various engines and frameworks to help with this. Despite being the only person at work who plays games seriously, and my history of developments on the Unreal engine, I haven’t really been included much with what’s going on.

However, since game development (of any kind) is the number one thing I’d like to be doing with my life (NOT point of sale systems!!), I’ve decided to involve myself anyway :D.

I have been playing around with a couple of game and physics engines (games being discussed are potentially vehicle-based), and Irrlicht particularly seems rather nice. Korpse however, suggested I take a look at Ogre. I was very pleasently surprised to find the PyOgre project, which exposes about everything Ogre can do, to Python (you don’t even need the Ogre SDK, it works completely on it’s own), and seems very well supported. I’m a lot more comfortable with Python than I am with C++ :).

The only down side, is that Ogre is not a complete game engine, but rather simply a graphics engine. Meaning, I’ll have to work out how to add sound, physics, advanced input options (Ogre does support keyboards at least), etc on my own. There are a lot of options available for all of those, so I’m not really worried about it at the moment.

I’ve begin putting together a bit of a basic framework for myself, trying to base how things work around how UnrealScript works and interacts with classes and objects. It’s working out pretty cool, thanks again to Python.

As a test project, I’ve decided to put together a sort of basic World War II flight sim. All you need really is a model, some terrain, and basic flight physics (which I plan on simulating without the use of a physics engine, in a similar fasion to how I did some stuff in Unreal Tournament [pre-Karma]).

Since the scripting is going well, I decided to take a shot at a quick model. I came across Wings 3D – a simple “subdivision modeler”. Basically you start off with whatever primitive shape (cube, spheres, cylinder, etc) you think will suit what you’re going to build, and stretch and warp it into the final product. I’ve never modeled like this before, but it works surprisingly well.

After 2 hours work, I got the following result from a 16-sided cylinder:

There are quite a number of rather ugly polygons, but it was a learning experience :).

Update: DynaBar 2 is available, the download link below is out of date.

Finally got around to making a proper release of something :).

Presenting DynaBar, a PHP script which can create dynamic images through the use of plugins, inspired by the Userbars.com website.

I thought it would be cool to be able to have userbars with dynamic data in them, stuff like game server status, stats, etc., etc. to make them a little more exciting. I also wanted to learn a bit more about PHP’s image manipulation, so this proved a good oppertunity for that.

Basically, the whole thing works off a plugin system, which lets you drop in a PHP script (the plugin), set up a config file (the userbar), and link to an image. DynaBar then goes about loading the plugin, requesting it’s data (so it goes off and collects stats, or whatever), and building the final image (putting on the [optional] scanline effect, glossy shine, and layering the text data from the plugin on all of that).

I’ve also created a small designer script, which allows you or any users to create new userbars using plugins or whatever, with their own images and content, in a simple wizard-like interface. The end result is ready-to-use forum or HTML code. :).

Here are some examples, using plugins included in the package:

Image lost in time Simple, plain text (nothing dynamic about it).

Image lost in time This one queries LastFM for which song I’ve played most recently in my media player.

Image lost in time Finally, here we have Battlefield 2 stats, coming from BF2Tracker’s clan XML feed.

Grab the download from the bottom of this post. Please read the README in the doc/ directory.