Monday, November 6, 2017

PyWeek 24: HackerBot


"HackerBot" was my solo entry for PyWeek 24 (October 2017), a twice yearly video game development competition that gets competitors to build a complete game from scratch in seven days using the python programming language. This competition's theme was "They're Behind Everything" and I made a 3D stealth game in which you control a little hacking robot trying to break into a space-based installation and steal data. You can "hack" into (and take control of) more powerful NPCs in order to help complete objectives (hence you're behind everything).

 


The game character is a little bot that can crawl around and jump from asteroid to asteroid. You need to avoid being detected by much more powerful "SentryBots" and turrets that essentially one-shot you. Your only "weapon" is your ability to "hack" into things when they get close enough: you can hack into shield generators to shut them down and access new areas, you can sneak behind guarding turrets and put them out of operation and you can even hack into passing SentryBots, take control, and wreak some havoc with their on-board weapons. The game features six levels and a giant boss battle to boot!

 


I was super excited to win both the individual entry and overall competition winner with a score of 4.29 out of 5.0. This score puts the game into the top ten PyWeek entries of all time (tied in at number 7, out of more than 1000 games over more than 10 years!) so I was pretty pleased with the result :).


Playthroughs:
Here you can find a full playthrough of the game, broken up into two parts:


You can currently download the game as either a source release (works with Windows/OSX/Linux, but requires additional installations) or as a standalone Windows application (I'm still in the process of getting the standalone OSX version working):

Windows (tested on Windows 7/10):
hackerbot_pyweek24_windows.zip (41Mb)

Mac OSX: stay tuned!

Source Distribution (compatible with Windows/Mac OSX/Linux, requires python 2.7, pygame, numpy and PyOpenGL, see installation notes in README):
hackerbot_pyweek24_source_v11.zip (8.3Mb)

If you are having trouble getting the game to run, or have a bug/crash to report, please email: randomprojectlab@gmail.com


Saturday, March 18, 2017

PyWeek 23: My Enemy's Enemy is my Friend


"My Enemy's Enemy is my Friend" was my solo entry for PyWeek 23 (February 2017), a twice yearly video game development competition that gets competitors to build a complete game from scratch in seven days using the python programming language. This competition's theme was "The Lesser of Two Evils" and I made a 3D tactical space shooter in which you work for an insurgency against an oppressive colonial government after your family is killed in a government attack; your character reflects on your retaliation against government civilians and is forced to question what action should be taken when faced with two evils. This comp I went solo for the first time since my first entry back in 2014 (my usual wingman for Team Chimera, Lucid, was taking a break).


The game was inspired by 1990's space shooters such as Colony Wars and X-Wing vs. Tie Fighter. Instead of using 3D hardware acceleration via graphics libraries such as opengl (or the pyopengl python bindings), I decided to experiment with the idea of doing 3D all on the CPU, in python. I was keen on this idea because installing 3D library dependancies in python can be a bit of a pain, with slightly unpredictable results ... also, I just got stuck on the idea early in the process, and I'm stubborn :). I managed to implement a basic engine for rendering 3D flat shaded graphics by performing camera projection and lighting calculations for triangular faced models using numpy and rendering faces using "pygame.draw.polygon". I added to this a basic horizon texture mapping (using numpy and "pygame.draw.surfarray" and rendering of circular particles using "pygame.draw.circle" and circle radius computed based on camera depth using numpy. The array of resulting 3D effects was pretty simple, but I think it worked pretty well: I had something that looked at about the same level (maybe a touch better?) as Starfox did on the SNES.


I ended up ranking second in the individual entries and third overall, a result I was very happy with. I received a fairly high "production" score (4.8 out of 5.0), so I was pretty miffed that players thought the graphics were decent enough.

Playthroughs:

Here you can find a full playthrough of the game, broken up into three parts (with a fourth showing an alternative ending to the game):

I'm currently working on getting a binary release/installer for OSX/Windows, but for now you can play them game by installing the source distribution (requires python, pygame and numpy) by downloading the game from the pyweek page: My Enemy's Enemy is my Friend.



Thursday, February 2, 2017

Global Game Jam January 2017


Global Game Jam is an annual event held at approximately 700 sites simultaneously across the world in which participants join teams to create a video game in 48 hours. I participated in the event for the first time this year in January at the North Sydney Institute of TAFE's site and had a blast! This year's theme was "Waves" and joining in an enthusiastic team with three other people I met at the event, we created our game "Jet Ski Jousting".

I was a little apprehensive when I turned up to the event on a Friday afternoon, not knowing anyone, and not being sure if I'd even be able to join a team. Luckily I ran into a pair who had done the event for at least the last three years and needed some audio. Overall there were about 60-70 people there (I guess) and everyone was super friendly and inclusive. There were a range of different games types and platforms, people doing standard PC games, tablet games, VR etc.

I did the sound and music for the game (and a little bit of UI art) which was a great experience, as I've mostly been involved in programming or game design in previous projects. I used Musescore to compose the background theme and a little victory jingle, and used Audacity to chop and post-process a range of open-licenced sounds I found online, mostly through Freesound.org for sound effects. I combined these all together and integrated them into our game (which was built in Unity) using FMod, which I had never used before; it was relatively easy to pick-up with a few pointers from one of our other team members who knew what he was doing.


Jet Ski Jousting runs on Android and PC/OSX (source distribution requires Unity) and can be downloaded here: Jet Ski Jousting (Global Game Jam 2017)

I had a bit of spare time on one of the mornings so I also worked on a little side-project game. I had brought along my Wii Balance Board that I picked up from an Op Shop a few weeks ago, and a Raspberry Pi 3. I previously got the Wii Balance Board to talk to the RPi over Bluetooth using python, so I worked off this to build a game in python/pygame called "waverider". It's a sort of motion-racing game where you have to accelerate a particle along a wave function by leaning left and right to steer the particle up or down the hills in the wave function, racing another particle to get to the end of the course.


Good thing about using the RPi was that I could plug it into a ceiling mounted TV hanging above a busy thoroughfare and leave the balance board on the ground nearby, so passerbys could casually play. People seemed to enjoy the game; a bit of physical movement was probably a nice respite from intense work in front of a computer screen.


The code for the game is available here: Waverider (Global Game Jam 2017)

Tuesday, January 31, 2017

Wii Balance Board


A few weeks ago I walked into Vinnies to drop off some old clothes and knick-knacks we no longer needed. On display I found an old Wii console, complete with wiimote, nunchuk, a couple of games and a Wii Balance Board, all for $20 ... Bargain! I couldn't help myself so I went ahead and bought it, hence bringing home more junk to fill the space left by the clothes we gave away :).

The balance board is pretty cool: it has four weight sensors on the four corners of the board that allow for a measurement of the total weight of the person standing on the board and also data on their center of gravity in two dimensions. I found this cool app on osx for connecting to the balance board and providing a simple bathroom scales. Worked well on my Macbook so I decided to dig around for libraries that could connect to the board and provide the same data. I found two different solutions here and here, both of which were in python (which works for me), but unfortunately seemed to be Linux only. I decided that perhaps I would make this a Raspberry Pi project. I had trouble getting the first solution to work, as it was a patch to an existing svn repository that didn't seem to be there anymore (at least it seems like the project has switched to a different versioning system, and I wasn't so sure how to go ahead with the patch). I found I could get the second method (Gr8W8Upd8M8) working well.

I modified the code to create a daemon thread that would continuously read data from the balance board and provide it to a queue such that the sensor could be monitored continuously by a background process and interface with an application in the foreground.

The python code that provides the interface to the balance board can be found here: wii_balance_board.py

I ended up using the code in a Global Game Jam game I made using python and pygame (waverider). I'll talk more about that in my next post.

Wednesday, December 21, 2016

3D Printed Nintendo Christmas Tree Decorations


Following on from my last 3D print, and to celebrate the recent release of the NES Classic Edition Console, I made some 3D printed Nintendo character Christmas tree ornaments. The sprite art is taken from Nintendo Entertainment Systems games The Legend of Zelda (Link), Metroid (Samus), Super Mario Bros. 3 (Mario) and Kirby's Adventure (Kirby).


I made the models using OpenSCAD and by importing in arrays that contained the pixel values. I then created a separate 3D object for each colour set, matching up the colours to the available colours of filament I had. Like in my previous multi-colour print, I made the pixels 2 mm squares, but subtracted a small buffer in size of 0.25 mm for edges that adjoin onto different colours. Because some of the sprites were kind of complicated, and I didn't feel like having to glue any pieces, I designed a black border around the sprites, so everything would be nice and self contained and just snap into place. It took a fair bit of time to put them all together, but it was kinda fun, like doing a jigsaw puzzle.


You can download all the stl files here: Nintendo Christmas Tree Decorations (Thingiverse)

Merry Christmas!

Sunday, December 18, 2016

Procedurally Generated Island Overworld Map


I've had a mild interest in procedurally generated worlds for video games for a while now. I recently found this article by Amit Patel from Red Blob Games on building procedurally-generated game worlds using randomized voronoi diagrams and a graph-based approach to defining spatial attributes. I had played a bit previously using Perlin noise to define world elevations, and then basing spatial attributes on elevation contours, which is cool but always ends up with pretty random, unrealistic looking landscapes. This graph-based approach seemed to provide a bit more flexibility in how the landscape looked and how to add additional objects into the world (like rivers, roads etc) in a way that seemed to provide a bit more control. I also found this 8x8 pixel micro tileset, which sparked my interest to try and build up a random island overworld generator, based on the tiles here.

I wanted to generate landscapes that could form the overworld of an adventure style game. Basically something where the player has a constrained world to explore that contains a variety of different biomes (provided by the tileset), villages, roads and locations representing the entrance to caves or dungeons that would form the basis of the objective of the game (enter caves, defeat monsters, recover treasure etc).


Working in python, I started by defining random points in a 2D space using stratified random sampling, to make sure points were not too 'clumpy'. Instead of using voronoi diagrams to generate polygons, I went straight to using a Delaunay triangulation to define the local connectivity of points (using this nice pure-python implementation). The triangulations would later be used to rasterise landscape tiles and define paths and distances between locations. Following from Amit's approach, I created a series of points regularly spaced around the border of the map and defined them as water. I then selected a fixed number of the other random points and defined them as land. I then performed flood fills along the triangulated network to define all remaining points as land or water based on whichever predefined node is closest. I then incremented through triangles, and those that contained a majority of land nodes were rasterised into land tiles, where the remaining tiles were labelled as water/ocean.

This gave me a bulk of land surrounded by water, usually as one island but some times split into two. Each node on land is then labelled by it's distance to the closest water/ocean node, which helps define what type of tile is used (light/dark grass, light/dark dirt) and the probability it will be occupied by a trees or mountains. I then added a few lakes by defining random starting locations on land and seeded some water patches using region growing. I added some villages: one that appears on a random mountain tile, one in a forest (distance layer with probability of tree being 1.0) and two on the coast (distance to water less than one edge on the triangulated network). I then finally drew roads between the mountain village and the forest village and biggest coastal village using A* paths along the triangulated network.


The micro tileset has tiles for a temperate landscape and for mid-winter, as well as one devoid of trees (like a desert or devastated terrain). Originally I had wanted to integrate all of them into one map with different biomes, but they didn't really look that good together. So in the end I decided to make the rendering of the map seasonal, so for every map there is one rendering for summer and one for winter. For the winter rendering I also add in a few icebergs in the surrounding waters.

I'm not sure exactly what I'm going to do with this yet, but I'll probably end up expanding upon it to make an adventure game. I was thinking about also making a random dungeon generator that utilises the dungeon portion of the micro tileset.

For now, source code available here: mit-mit-randomprojectlab/RandomOverworldGenerator

Saturday, December 17, 2016

Random 3D Printing Projects


Thinkspace had a 24 hour 3D design and printing competition a few months ago for which the design brief/theme was jewellery. I only had a hour or two to spare so I did up a quick puzzle ring: its designed to be printed in four separate parts, in four separate colours, each a little ring with tabs that click into each other. The tabs are positioned so there is a unique way of arranging the pieces (like a puzzle). It's not that hard to solve or anything. I made it in OpenSCAD. It's pretty much just a series of cylinders with holes, and the tabs are just rectangular pegs and cutouts.

OpenSCAD script and stl model files available here.

Working on this design got me excited about making 3D prints that could be put together from multiple parts printed in different colours, so I played with this idea a bit more. I made a little pixel art model of Link holding up the triforce from the original NES Legend of Zelda. It's a cool sprite because it's a small number of pixels and only requires three colours. I used an OpenSCAD to build the models from an array that contained the sprite data.


Since the sprite is mostly green, I printed the green layer to have a backing that would support the rest of the design. The pieces from the orange and "skin" coloured layers sort of just snap into the remaining gaps. First time I did the print, I designed all parts to have a pixel size of 2mm. When I went to snap them in I found they wouldn't fit, as the printer seemed to have a tiny bit of 'bleed' such that a 2mm pixel that stuck out didn't exactly fit into a 2mm gap. I redesigned the parts such that any pixels that were designed to adjoin another layer were about 0.25mm smaller such that they would smoothly fit together. The resulting prints worked well, but some bits required glueing, as they otherwise would float off the side.


Continuing on the Legend of Zelda theme I made some little heart containers and Link's sword. I ended up turing them into pairs of earrings by supergluing some sterling silver earring posts and backs on the 3D prints.

The 3D parts for the earrings can be found here.