Thanks to everyone who played the game and left feedback! I’m really happy with how it turned out; I was pretty nervous that perhaps people would have trouble with PyOpenGL, but it doesn’t seem to have been a big issue. Apologies up front for the slightly long post :) just felt like I wanted to write down some of my thoughts. Congratulations to the team winners Larry and Dan, and congrats to everyone who participated for the first time and managed to finish a game! There were some really cool and quirky games this comp, I thoroughly enjoyed playing them.

I thought I’d write a few notes about the game development:

Using PyOpenGL and 3D models:

This was my first time using OpenGL 3D in a game, so it was a bit of an experiment, but I found it was relatively OK to understand. Two past pyweek games that I studied a lot to help me understand PyOpenGL were Bouncy the Hungry Rabbit and Eclipsed (I am still amazed that Eclipsed generates all of its 3D models in the code using no external resources). In order to generate the 3D models, I started off trying to teach myself to use Blender, but quickly found that the learning curve was too steep, and time was too short. In the end I fell back on some tools I’d previously used: I used Sculptris to generate the (randomish) asteroids (and followed a Blender tutorial to put a simple texture on it). I used OpenSCAD to do all the other models. I used Wings3D to colour all the 3D models (was using this for the first time this competition, and it was really nice and easy to use) and Meshlab to convert model formats.

One thing I never got to work properly was dealing with semi-transparent objects: I couldn’t understand out to depth filter all of these properly with the blending, so there are a few strange artifacts when the player’s view intercepts with a shield for example. 


I think I got a bit lucky with the gameplay/balancing on this one (although some people mentioned the game was a bit hard), because I was rushed at the end, and spent relatively little time trying to tune this. I left the level development until pretty much the last day. The good thing about a stealth game is that there ends up being lots of ways to get through, and in a lot of cases, most of them probably make the player feel like they are doing to right thing, even if the game designer didn’t intend for the player to be able to get through a certain way. I also feel like I could have added a bit more variation in terms of different types of sentries, different objectives etc. if I had more time.

3D aspects of gameplay:

Probably the most challenging part of this experience for me was figuring out all the vector/rotation coordinate systems and working out how to make the controls feel natural and liberating instead of difficult and unintuitive. I spent pretty much a full day (I think around day 2) figuring out how the control system would work: in the end, the direction the hackerbot moves depends on the view: the ASDW keys map to camera-centric moving that are parallel to the vertical/horizontal directions of the screen. One issue here is that when you are standing on the “horizon” of an asteroid, the up/down keys probably feel more like they should move into/out of the screen, rather than up/down: I experimented with a system that blended between these modes based on how close the hackerbot was to the horizon (based on camera view), but I found the result made the controls feel even more confusing.

In terms of viewing angle, I made the decision early on to stick with camera perspectives that are fixed to the horizon i.e. the camera can pitch and yaw about the OpenGL XY axes, but not “roll” about the axis that sticks into the screen. I think this helps with visual orientation (which some people mentioned got a bit confusing anyway) but it gives the unfortunate side effect that the controls have “singularities” around the poles of the asteroids. I studied games like Super Mario Galaxy to see how they handle the camera perspective: there’s definitely a much more “fluid” feeling with this game, but the gameplay in this case is focussed purely on the “planetoid” you are currently on. In Hackerbot, I wanted the player to be able to have a “synoptic” view of the whole game space at any time, so they can plan where they will jump, navigate around, watch out for sentries etc. so this was my reasoning for keeping the camera this way.

Boss Battle and Future Work:

To me, when a game has a conclusive boss battle it adds so much: this gives a sort of “story arc” by creating a distinctive climax to the experience. I worked hard on trying to get a good boss battle for this game, but I only got about halfway through what I wanted to achieve. To be perfectly honest, it’s pretty much a stretch to implement this sort of thing in a pyweek with such a short time timeframe. My original concept for the “Juggernaut” was to have it slowly move around the play space and to create a situation where you had to “lure” it to certain asteroids and then jump away to create a situation where you could lead it’s laser fire into destroying shield generators. Then would come the “missile hacking”, after which hitting it with a few missiles, the Juggernaut would become “disabled” for 30 seconds, giving you an opportunity to “jump” onto it, crawl around and hack into a data port mounted on it’s back which when hacked would allow you to trigger a 10 second self destruct sequence. With another day to spend on it, I could have possibly got this all working and tune the difficulty so it wasn’t too hard. I basically ran out of time on the last day, so just ended up implementing the missile hack with a static Juggernaut (which was probably the most disappointing part of the final game for me). This is something that I might try to work on and include in an update for the game.

If you have actually read this far, thanks again, and hope to see you in six months for the next pyweek! I’m super happy that this comp exists and at the amount of time and effort people put into it!

(log in to comment)


Congratulations to our champion!you deserve it! thank you to bring such excellent game this time. Yeah, I read all your post, I no doubt you can manage 3D game, because you already did quite well last pyweek, you are good at math, I can tell :) Two things give me deep impression, one thing is you master so many modules to do the 3D model, which make me a little worried wether I can do a 3D game without accumulation. the other is your 4 years old son can wake you up, I never expect my son to wake me up, every time I neally tired out to make him fall sleep :)
Thanks! I spent quite a bit of time in the week before the comp playing with 3D modelling tools, only to fall back on OpenSCAD (which is not ideal for "nice" looking models :) ). I'd be keen in the future to learn how to use Blender, because it looks quite powerful, but it just looks so hard to get started in.

Congrats on "No Entry" ... I am now considering whether I will try a tablet/phone game for next competition, or perhaps try to re-implement an old game to work on Android :) 

wow, glad to hear you have such idea, it is easy to get start with kivy, but there are pitfalls as well :) For packaging, kivy use buildozer or python for android, I really know nothing about the mechanism, I just follow the steps and twist my finger to try my luck, exactly like using pyinstaller :) I also remembered pygame can be implement on android,, there is also video tutorial on Youtube, but I do not know it still exist, I can not access Youtube nowadays due to my awesome country blocked it... I want to try kivy just because I found people around me are all playing mobile games, and we can play game on subway,or even lay on bed :)
One thing I never got to work properly was dealing with semi-transparent objects: I couldn’t understand out to depth filter all of these properly with the blending, so there are a few strange artifacts when the player’s view intercepts with a shield for example. 

Aside from complicated techniques like depth peeling, the only real way for semi-transparent objects is to depth-sort them and use painter's algorithm.

Alternatively you can use additive blending and disable depth buffer writes, because addition is commutative. It looks different but for an energy effect like shields it will look fine.

The issue you describe with the view intersecting a shield, if I guess correctly what you're referring to, is due to view frustum culling. You'll always have it (unless you fudge around it) but if you set the near Z plane closer to the camera in glFrustum()/gluPerspective() (say to 0.01) it might be less obvious.

I'm always amazed when anyone even attempts 3D in a Pyweek and in not only pulling it off flawlessly but getting a full game working you set the bar incredibly high for anyone in the future!

Excellent idea to constrain the motion on the planets to make it easy to pick up and understandable for players. The complexity of everything explodes in 3D and you could easily spend a week on the camera alone. You did a great job of choosing approaches that worked both from a development and gameplay perspective.

hey mauve: yes, I think that's what I needed to do: depth sort all game objects and use painter's algorithm to paint in depth order. Thats actually probably not too hard to do on a game object by game object basis, so I might try that out.

With the view intersection, I think my view frustrum was OK. I just meant that sometimes the hackerbot would be painted blue when it occluded a shield from the perspective of the camera (because I was calling it's draw methods before blending with the shield), yet it still ends up being drawn on top, so presumably it is getting depth ordered correctly by OpenGL ... to get the blending to work I had to turn off depth filtering when calling the opengl functions for the shield (and then turn it straight on again), so I guess this is why the blending doesn't work properly in depth order.

To be honest, I didn't have a great understanding of how it was all working ... I just experimented and hacked around with it until it looked about right :)

Thanks Paul!