While I recorded a demo movie with FRAPS, when I converted it to something Youtube would take, the quality was just unacceptable. I’ve had luck with FRAPS in the past – I imagine I’ll have to play with some stuff to make it work.
However, while I was waiting for stuff to convert/render, I played a bit with py2exe – and it just works. Amazing. Now I just need to build an installer..
Pretty productive evening – got the animations converted from bmp to png with the alpha information – only took ten minutes to write the utility and it worked like a champ. It takes less time to load now then before – and it is loading 8 times as many images (somewhere north of 1000 images)
I got all the models loading with the new system, too, and built proper mechanisms for creating sprites and updating their animations, rather than the kludgy ones I was using before. I still need to load character information (NPC and PC) from disk rather than hardcoding them, but that can wait until I work on the game proper.
And I got animations working! That’s pretty awesome. I even used Fraps to record a short video of the animations in action – I’ll post when that’s available as I need to upload it to Youtube first.
So.. next task is to work on the py2exe stuff and installer stuff to produce a package that can be installed anywhere. And then I’ll be looking for victims to try it out on, just to see how it behaves. Not really a game, but it does a lot of the stuff the final engine will do, so if it runs ok, what follows should too.
Pretty pleased with the progress overall.
No, this project isn’t dead yet. Between vacation, returning to work from vacation and having to catch up, a cranky toddler cutting in on sleep and work time and the release of two games (Avadon and Deus Ex: Human Revolution), I just haven’t had the time to actually work on code. I haven’t been neglecting the project completely, though – I’ve done some design work and a bit of dialog/description writing and figured out a solution to a game problem that’s been bugging me (how to allow the player to advance the character in ability (ie, those RPG element things) while still keeping Vincent’s fundamental vulnerability – he’s not an action hero). Still, none of that stuff actually gets me to the ‘tech demo’ point that I’m supposed to be heading towards.
Tonight, though, I clicked on ‘Eclipse’ instead of ‘Steam’ and made some real progress. Most of it is, again, invisible – this time, it is animation loading – loading the images and creating the animation sequences for the assorted sprites. It works nicely now, though I’ve made a discovery – bmps just won’t cut it. Even though I wrote that chromakey function a few updates ago that allows me to use transparency with them, that function does far too much string manipulation (building up RGB and RGBA strings) to be performant – in other words, its speed sucks. This being a 2D tile based game, nothing in it should make my computer pause, but loading a few hundred images and doing the chromakey on them is taking upwards of 10 seconds on my modern machine. Eeek. Sucks. The obvious solution is to convert all those bmps to something that stores the alpha channel in it, so next time I’ll be writing a small utility that will detect the right chromakey (probably just taking the top left pixel), set the alpha channel appropriately and convert them all to pngs. There’s probably something out there that will do that, but it won’t take very long – pyglet has a image.save function and I’ve already got the chromakey loader that will just take a few mods.
Still need to call the appropriate animation as needed, though that’s pretty easy – all I’ve done is set Vincent to the ‘stopped’ animation (which just continually spins him in a circle). I suspect I won’t actually use that as a stopped animation – I think I’ll just leave him still when stopped – but for now, he spins his way from place to place. Quick screenshot showing him actually in a different position than facing due south All the infrastructure for that is in place, though, I’ve got a ‘getAnimation’ method that gets finds the right animation given an action and a direction for a given sprite model.
Hopefully, the next update will be soon!
I’ve gotten some stuff done, but most of it doesn’t show up in the screenshots – planning, refactoring, some writing for the actual game, a few enhancements – Vincent now goes to where you left-click on the map and he also knows which direction he’s going in – north-east, south-west, whatever. That last one is important for the animations. I’ve designed the system for the animations, now just need to write it.
Brief update this time.. I managed to drop in my old A* pathfinding (using the algorithm from a great A* pathfinding tutorial) with almost no troubles at all. It was nicely modular and well commented – good job, me of 5 years ago or whatever. I also solved the ‘problem for another day’ – Pyglet doesn’t have any chromokey (making a particular RGB value be transparent) support, but it isn’t hard to roll your own. I wrote a function to do that – takes an image file location and a chromokey RGB value, then reads the file as RGB, loops through each pixel and if the RGB matches the chromokey sets the alpha to 0, sets alpha to 255 otherwise. Easy peasy. So that meant once I had Vincent wandering from waypoint to waypoint whenever you hit J (instead of teleporting), I could add in 5 NPCs who do their own wandering. They don’t wait for you to ask, though. They just cruise randomly from one waypoint to another. If their path is blocked by something temporary (like an NPC) they will wait a random time, then look for a new destination. So they don’t end up jamming in doorways forever.
Works pretty well thus far. The big next step is animations, which means I need to figure out which animation to play at any given time – what direction they are going in, whether they are moving, etc. More XML files, I think, to define the frames and the delays between frames. Pyglet has an animation Class, which will help a lot, I just need to populate a set of them properly for each sprite and set the right animation to go at the right time.
I’ve also got a few pathfinding improvements to do – I’m not weighting diagonals differently than left,right,up,down right now, which means that movement can be odd (southeast, northeast instead of east, east for instance). I’m also not paying attention to tile weight (beyond impassable walls) – I want doors, for instance, to be more expensive. I want to have tiles that they will tend to avoid if possible, but will cross if necessary.
After that, though, it’ll be time to play with p2exe and get something out there to see how she works on various machines.
After the animations go in, I should put up a video. But for now, just a screenshot. Till next time :
So, I shelved the minimap – I’m not 100% sure what I WANT from it yet – I may just go with a map screen, instead of a minimap. Pixels are precious, after all. It’ll take some thinking, so on to something else.
Some improvements to the tmx (tiled’s file format) loader – now loading some tileset information, too. This lets me set tile properties on the tileset in tiled, which means I can put weights on tiles (for pathfinding), mark things as impassable (for pathfinding), mark waypoints (for destinations for pathfinding), etc. Worked well, except for a real head scratching moment where I realized that tile ids are 1 based in the map data section (so I have to subtract 1 to get to my system), but in the tileset description, they are 0 based. But, whatever, solved now.
Then it was time to get a character sprite into the system. I’m currently using Reiner`s Tilesets for character sprites – he has some very decent 2D human sprites that he created that he offers for free use. Amazingly awesome. Most of them are very inappropriate for a sci-fi game, but there’s some generic enough to work for now. The downloads are bmp with an odd brown for transparent regions. I’m sure there’s a way to tweak transparency in Pyglet, but a quick look didn’t find it. So I just opened the one image I’m currently using in GIMP and recreated it as a properly transparent background PNG. Given that each sprite has about 200 bmps (for animations), I’m hoping I can figure out a way to do that on image load, or at least automate it… a problem for another day, though
So, anyways, ‘Vincent’ (the name of the main character) actually shows up now. He picks a random waypoint to start at (the waypoint tile is the tile marked with the ’12′ – I just picked it because it was distinctive). If you hit J he teleports to another one. He even blogs about it on the main text window.
Next time is A* pathfinding – setting Vincent travelling (rather than teleporting) between waypoints. Then multiple characters, all moving from random waypoint to random waypoint. And then animations, so they look right doing so (and right about then is the ‘another day’ referred to above, where I’ll have to solve that transparency problem). And then finally floating name labels for each character, so they can be told apart.
At that point, I’ll be packaging up the thing as a nicely installing exe, just to make sure I *can*. And trying it on crappy computers, to see if it works.
Nice to have a plan! How long I stick to that plan, who knows…
So.. meet Vincent :
Don’t get used to it
Made some good progress today as far as map reading / creation / tilesets go. I just tore out my first implementation of a minimap – not happy at all with how it worked. Rule of thumb – my computer should never even think about working hard in this game (modern quad processor box with 8gb RAM). It is gonna be important to test on low end boxes. Pyglet seems to have either very high level stuff (which works great for most things) or very low level stuff (which is a pain), but not so much in between. I know how to do what I want to do now, so it’ll be a matter of just doing it.
Still, I did throw out my test level loader and replace it with an XML parser to read tmx files from Tiled (a free 2D tile map editor). This means I get a level creator for free – one less thing to write. Downside is xml is potentially slow – though a 100×100 map is instant on my computer, even though that’s 10,000 lines of tile data. Tiled supports compression buried in the xml files for the tile data, so if reading the levels turns out to be a bottle neck, I can always implement that. I’ll solve that problem if/when I get to it – that’s a philosophy borrowed from Agile. Don’t solve problems until you have to and solve them only in the case that you’re using. That’s a hard lesson to learn – we tend to love general solutions that work in all cases, but they are harder to write and often harder to use. Write what you need and stop If it later turns out you NEED the general solution, write that THEN. Most of the time, you won’t need it. You think you do, but you probably don’t.
I also put together a temporary tileset, based on a few of the textures I have. Needs a lot more work, but it is better than solid colours. You’ll see part of it in the screenshot below. I also wiped out my previous tile displaying code in favour of something more clever – batch groups for Sprites. Seems weird to me to use Sprites for background tiles, but it seems expected in Pyglet. Their Sprite object is pretty lightweight – I set up an array of the sprites to cover the tile viewing area and whenever I change the viewpoint, I reassign the images for the view sprites to match the map tile. – the Sprites don’t actually move. Fixed a few other issues with changing window dimensions while I was at it.
I think that was it. In the screenshot, you can see a frames per second counter – I have updates set to a max of 60 FPS (no point in anything higher for this sort of game) and as you can see, to a nearest rounding error, it is there. I’ll be interested to see what it does on my piece of crap laptop when I get to the point where I’m packaging it. Ultimately planning on offering Mac, Linux and PC. Should work ok, from what I can tell – Python and Pyglet are both cross-platform and so far I have no other dependencies. And both Mac and PC have py2exe /py2app creators that create native apps (no need to install Python or libaries). Linux will, as always, be a bit more ‘do it yourself’.
Till later, here’s a screenshot. Trying to stay away from the temptation to do all greens and browns and blues – need some colour from time to time :