As mentioned in my last post – “der Luchs” is (re-) programming his game “Menschenjagd”.
We met at an event last month and came to talk to each other. One thing led to another and he asked my opinion about it – and me not being shy – told it :-).
Sascha does not think of himself of being a “programmer” – inspite of him releasing game after game on various platforms (including more than 10 games for the vectrex). He keeps saying “I am an musician – not a programmer” – that might be one of the reasons he is a bit shy about showing (or sharing) his source code with other people. (Let me tell you: On many different levels – “I have seen much worse! -Nothing to be ashamed of!”)
On the other hand – I myself always liked “opening my sources” for two reasons:
a) so others can profit from the time I invested
b) so I can profit when others discover flaws in my programming
Actually so far mainly bullet point a) seems to work out the way as intended. And that does NOT mean that I don’t produce flaws – but I think people (in general) don’t care about giving much feedback.
Anyway. I would like to ask your opinion about our thoughts about the way the player/enemies/shots “navigate” the labyrinth in Menschenjagd.
First – although I programmed a lot vectrex stuff – for many assembler years I have not used many (if at all) BIOS routines – so using BIOS was not natural to me anymore (getting Obj_Hit to work needed some surfing 🙂 ).
Challenge Labyrinth – how to navigate?
In the upper playfield the player (and the enemies) are located in a labyrinth. Naturally the walls of the labyrinth should prevent the player (and the enemy) from just passing thru. Trying out the most obvious thing first – collision detection using Obj_hit of the Vectrex BIOS.
For that particular collision detection, each wall segment was treated as an object and each player as another object. If a collision was immanent – than the move was not allowed.
In order for this to work, all labyrinth segements had to be tested against all players (I summarize under the term “player” also the enemies from now on). This actually did work – but needless to say – this was quite time consuming – and for various reasons (which I am not going into) – to slow.
In the following I am trying to explain with my own words the labyrinth test we came up with. Comments – especially more performant suggestions are as always welcome.
We divided the labyrinth into “tiles”, like the following (badly drawn) picture shows:
This is roughly the algorythm currently implemented (for one direction).
If a player moves in the labyrinth it now calls a function “is_allowed_direction” – the function returns yes or no – and the game continues.
There is no collision detection involved at all – and the tests that must be done in general are done really fast (compared to collision detection).
The actual implemented routine is a bit more complex than above. To give you a picture just a few more pointers.
– the players “screen” coordinates are completely disjunct from the labyrinth coordinates, but they must naturally be “synced”
– the labyrinth coordinates consist of
* coarse coordinates (which exactly represent the tile positions 6×10 in the case of the above shown labyrinth)
* fine coordinates, which range from -7 to +7. 0 (zero) is the center of a tile, and +-7 is a position close to the edge of a tile.
When a fine positions absolute value reaches eight it resets to the negative and the coarse position is updated accordingly
– the coordinates in the labyrinth start with 0,0 in the top left corner and can only grow “positive” from there, this is because the data representation in memory is just an array – and with these coordinates it can be addressed easily
– some additional testing must be done so the player can not “enter” horizontal lines while going left and right (same for vertical and up/down)
– the routines support player “sizes” so the player can move between the labyrinth walls (in the above picture – the read lines are “wider” than just one pixel)
– using the “fine positioning” – you actually only have to test when the coarse position changes (so -> only every 16 “pixel”) (or – here comes the player width – (16 – playerWidth) )