Introduction
In response to queries about some of the internal workings of Paradroid I shall attempt to address those plus any others I can think of. I don't have source materials that I can check to confirm exact numbers or timings.
Note that the Zzap!64 Diary of a Game article may also answer a few questions, plus a previous article herein about the transfer game.
The Plan
My intention for this game was to make all of the game levels interconnect to make a cohesive space ship environment. Gribbly's Day Out had 16 completely independent levels made out of custom macro blocks, a mechanism which I reused in Uridium, but for Paradroid I decided to try making the decks out of 4x4 character blocks.
One 256 character set made up the graphics for the game backgrounds. I split that into 2 parts, firstly the characters you can move over, and secondly, those you can't. That gives a simple cut-off point to test for when doing the object to background collisions. Simples!
I then defined a number of 4x4 blocks for the walls, decks, consoles and, energisers and lifts. There didn't turn out to be too many of those, I'm guessing well under 128. I recall I used a simple run-length algorithm to be able to pack down the map data. What I did then is give a list of blocks starting top left of the map, across and then down to the next line. Your list then would be individual block numbers, or I'd set the top bit and give a number of repeats for the preceding block. This would allow me to fill the space outside the ship, do horizontal walls and deck strips really cheaply. Thinking back, there are only really 3 types of block you'd want to repeat, so I might have been able to utilise one byte even more cheaply: i.e.
0 empty space
1 horizontal wall
2 empty deck block
3 another repeatable block
4-127 other blocks
128-159 repeat block 0 by 1 to 32 times
160-191 repeat block 1 by 1 to 32 times
192-223 repeat block 2 by 1 to 32 times
224-255 repeat block 3 by 1 to 32 times
Or perhaps I wasn't that clever back then, I can't totally remember! Anyway, that's how I might do it now.
The maps were 40x4 characters wide, and something like 18x4 deep, which allowed the small scale map to fit on the screen exactly. I then had to draw a single character to represent each block for the small scale map. For Paradroid 90 it did an on-demand scale-down of the full-size characters.
We did not develop map-editors in those days. With an overall development time of around 5 to 6 months for a game, we didn't want to spend a month writing an editor when it would only take 2 weeks to create the data. Many times though when we met other programmers they would proudly show off their editors and whilst we were very impressed, we thought it would be a lot of work to do. For Paradroid 90 we did use the Rainbow Islands editor that was created in STOS by John Cumming, and we used a custom packer, worthy of it's own entry later.
So then, the maps are stored as 4x4 macro blocks to make the data smaller, and are unpacked into a character map of 160x72, of which 39x19 are displayed on the screen at a time. The game mechanisms all use the character map from then on, the macro blocks are never used for anything other than setting up the decks.
3D Ships
The layouts of the decks all mesh together and are connected by the lifts. I built the ship out of Lego and we had that in the office for a while. I reckon we borrowed the bricks from Steve's son, Mark, so we had to give them back eventually. It was important to me that everything fitted together, not least of all to aid navigation around the place. I still got up to some tricks by splitting a deck into 2 parts that had to be reached separately.
The side of the ship can be seen from the consoles and when you are operating the lifts. The data to connect the lifts to the decks was a tricky one to get sorted out, I remember picking the bones out of that for ages. You have to tie the deck locations of the lifts to the shafts, and the on-screen position of the deck/shaft on the side-view. The whole design also then required that no two lift shafts overlap on the side-view map. That resulted in some re-arrangements of the maps.
Survive
Now if could project back in time another 3 years to my COBOL days, I wrote a game on the mainframe called Survive. It was a multi-player real-time game and the setting was 10 levels of a dungeon, connected by transporters, and each level was divided into rooms, and the objective was to be the last player left alive. You could only see other players by line of sight on the map, and there were 2 non-player assassins somewhere roaming in the dungeon.
The assassins were particularly deadly and the players tended to gang up on them first before turning on each other. We used to play the game on up to 6 terminals (all of them!) in the main office after work. We didn't need headphone communications, we just used to yell to each other, or AT each other.
The algorithm for the assassins was straightforward: they had paths drawn on the map for them. I set up letters on the map that only they could see, using a J for a junction where they could make a random choice of exit, dis-favouring the direction they had come from, and I just put a string of Ps for pathway to the next junction, or a number for a jump point to another level. So the assassins could wander from level to level. If an assassin spotted a player, it went into chase mode, and could come off the pathways and was free-roaming. I made sure there was a pathway into every room. The assassins didn't fire at the players, they had to touch them, so you had a chance to run away.
If the assassin lost sight of the player it would then wait for a few seconds in case the player came back into view, and if not it would resume patrolling. Now I could have stored the route back to the last patrol position they were on, but that might have been lengthy, and convoluted, so I figured that since by definition they could not see a player then no player could see them, so I could just transport them instantly back to the last patrol point they were on before they started chasing. Not totally realistic, but quick and simple.
Back into Space
When it came to Paradroid then, I wanted to do the same kind of thing as the assassins, except that I didn't want the robots to use the lifts. It was important that once a deck was cleared and the lights go out that the level stays cleared. That way you can start eliminating areas that you've been to, otherwise it would be like herding cats. I sort of bypassed this for Paradroid 90 by allowing pirates to beam in undetected to levels, not triggering the lights if the level was empty of robots. The pirates start beaming in only after a certain time to give the player an extra threat if they're taking too long.
I got to thinking then, how do I get my robots to navigate around the decks in an intelligent-looking fashion? I couldn't mark their routes on the map because the map is only made of bigger blocks that don't allow for more detail. I didn't want to let them roam totally free because they'd wander aimlessly into the furniture, I also wasn't going to be writing a complete AI algorithm whereby robots might sidestep out of each other's way, and in any case they were running rogue and might indeed destroy each other. Actually, since I was keen to use sprite to sprite collision to resolve issues and sprites were not allocated to a robot unless you could see it by line of sight, then no collisions are considered that you can't see, robots could pass though each other undetected. But can you prove it?
Patrol Networks
Steve Turner and I might well have had discussions on how to implement the robots. It's a big part of the game, and we used it in Paradroid 90, Fire and Ice, and our final unfinished tank game. Survive contained the answer to 2 issues. Firstly, robots need to navigate along preset lines, and need places for their initial positions. So we need points, and lines to connect them.
All robots on a deck are initialised when you arrive onto that deck, and are patrolling from the off. Most games only initialise meanies as they are about to appear on screen. The Paradroid approach helps to randomise the deck so it's different every time. The actual robots that will appear are decided at ship initialisation time rather than deck initialisation, since you don't want a robot to change into another one if you leave it on a deck and go back later. Incidentally, if you enter a lift, change decks and back again to the original, it knows and everything carries on exactly as it was.
For every deck then, there is a patrol network than covers all of the real estate. This consists of a number of map points, each of which has a set of indexes to other points nearby. There might be only one, there could be up to five. Robots have a designated patrol point on which to start, and there can be two types of robot. Firstly, all robots can be one of four different types, so I specify the lowest, and then randomly add a number from 0 to 3. Some of the robots can also have another modifier added, which is the ship number, so if you clear a couple of ships then by the third, the value of about half of the robots goes up by another two. Notwithstanding that it does limit the robots to the one before the 999, you wouldn't want to meet a ship full of those. For Paradroid '90 I could designate a specific robot at any particular location, which allowed me to place sentry robots wherever needed.
Robots traverse the patrol network by choosing a random index from those available and homing towards that point. When they get there they chose a new exit, turn to face the exit and then move off. This data was particularly sensitive too, because without an editor I was relying on my typing. I drew the routes on paper and numbered the points. It wasn't very modifiable if I wanted to add another point later, so I tried to be comprehensive. If I accidentally used an over-large index it could pick up any random data and a robot might march off the map. Since the robots couldn't collide with the background as long as the data is correct, then I didn't need to do much background collision detection. There were special characters in front of the doors that, if detected, caused the door to open nice and quickly, like on Star Trek, so the robots didn't have to wait. The characters that make up the door are substituted for ones that show the door opening, and finally fully open, where the character codes are also changed such that you can see and pass through.
The Robots
There are 24 different robot types that may be around the ship, including the 001 player's Influence Device, to the single 999 Cyborg. Each one has a designated weapon, armour, and energy. I've watch a youtube video where a chap was comparing Paradroid with Paradroid 90, and had not grasped that un-armoured robots can be damaged by the explosion of another robot. Getting the knack of firing and not following the bullet into the target is important. While stopped, you can press the button and then flick the joystick in the direction you want to fire. While you do then accelerate in that direction, it takes a while to speed up.
If you ram an armoured robot with an unarmoured one you will take damage. A heavily armoured robot can easily destroy the lower ranks just by running into them. If memory serves, equally armoured droids will not take damage on a collision.
Re-energising
Robot energy is based on rank, the higher the first number, the more energy the robot starts with. Energy status is shown by the rotating top and bottom of the robot sprites. The faster the rotation, the more energy it has. However, when the player is influencing a higher robot, the more it will fight back, and the capacity lowers with time. Temporary damage from bullets and collisions is shown by the slowing rotation speed of the sprite top and bottom. You can re-energise by standing on an energiser plate up to the current maximum capacity, but the capacity will continue to degrade. This forces repeated transfer to new robots.
The Alert Status
Variously placed around the decks are alert status displays. Whilst these have no direct importance to the game, they show how quickly the player is destroying robots, and are the key to those very high scores.
When a robot is destroyed, the alert status is increased according to the first number of the robot, its series. The alert status then reduces over time. If you can raise the alert status by multiple quick kills then the alert goes from green to yellow, and you receive 5 points for every second or so that the alert status is yellow. More quick kills and you can get the status up to amber to get 10 points per second, or red to get 15 points per second. It therefore is a good idea to plan a full assault on the cargo decks to get a big robot and take out as much as possible as quickly as you can.
The alert status was a single byte variable. Killing a robot adds its series number to the variable, ensuring no overflow occurs, of course, since 255 has to be the maximum value. It is commonplace to increment a frame counter variable every game frame, and then use that value logically ANDed with a mask to get things to occur at slower intervals. Picking out one second intervals is not necessary, but it is simple to pick out every 16 or 32 frames. Having chosen the interval, you can decrement a non-zero alert status value (to avoid underflow) and then use the top two bits to determine what reward, if any, to award.
0 Yorumlar