Decoded: Sopwith (1984) by David L. Clark Source file: SWCOLLSN.C Beginner friendly, line-by-line code walkthrough by MaiZure SWCOLLSN.C manages collisions between game objects, player score and ground destruction Original code: http://davidlclark.com/page/sopwith-source-code Original code with line numbers http://www.maizure.org/projects/decoded-sopwith/SWCOLLSN_linenum.txt 1 COMMENT 2 COMMENT 3 BLANK 4 COMMENT 5 COMMENT 6 COMMENT 7 COMMENT 8 COMMENT 9 COMMENT 10 COMMENT 11 COMMENT 12 COMMENT 13 COMMENT 14 BLANK 15 COMMENT 16 BLANK 17 COMMENT 18 COMMENT 19 COMMENT 20 COMMENT 21 COMMENT 22 COMMENT 23 COMMENT 24 COMMENT 25 COMMENT 26 COMMENT 27 COMMENT 28 COMMENT 29 COMMENT 30 Includes the main game header (sw.h) 31 BLANK 32 BLANK 33 Import the ends of the object list declared in SWMAIN.C 34 Import the plane objects arrays from SWMAIN.C 35 Import the list of objects from SWMAIN.C 36 Import the current (runtime) ground array from SWGROUND.C 37 Import the initial ground height array from SWGROUND.C 38 Import the playmode defined in SWINIT.C 39 Import the player object 40 Import the number of screen bullet holes 41 Import the number of splattered birds 42 Import the splatter ox flag 43 Import the number of active targets (ground targets) 44 Import the communications buffer 45 Import the game number 46 Import the object end status 47 Import ground redraw flag 48 Import the current game speed settings 49 Import the performance counters 50 BLANK 51 Create a local list of killed objects indexed like the object list 52 Create a local list of killer objects with the same index 53 Create a specific index for the killed list 54 BLANK 55 Create a local variable for collision point delta x check 56 Create a local variable for collision point delta y check 57 Create a local variable for collision object check 58 Create a local variable to index collision arrays 59 Create a local variables for collision offset checks 60 BLANK 61 BLANK 62 BLANK MAIN COLLISION TEST ROUTINE 63 Declare and define swcollsn with no arguments 64 BLOCK START - swcollsn, collision check procedure called from game loop 65 Declare local object pointers 66 Declare local position holding variables 67 Declare local more x position holders for testing values 68 BLANK 69 Clear collision pointers for upcoming checks 70 Set default x collision adjustment to 2 pixels 71 Set default y collision adjustment to 1 pixel 72 BLOCK START - Swap collision adjustment, for every other frame... 73 Change the x adjustment to its additive inverse 74 Change the y adjustment to its additive inverse 75 BLOCK END - Swap collision adjustment 76 Set the active display to auxillery 77 Save the top object's x position 78 START BLOCK - Loop through all objects and test positions (outer loop) 79 Set both x test variables to the object in the loop 80 BLANK 81 Set maximum x variable to the end of the object's graphic in world space. (For instance, a 16x16 plane located at 850, 30 would mean xmax is 865) 82 Find the world space of the y object graphic offset. Previous example would be at ymin = 15. Recall that Sopwith world space has a y of 0 for the bottom of the screen 83 BLANK 84 Loop from the testing object's next object... 85 While we still have objects, and the next isn't beyond the base object.. 86 START BLOCK - Loop though all other objects (inner loop) 87 Save the new object's x to compare with the old object 88 BLANK 89 If the new object isn't below the old object... 90 And is within sprite distance... 91 Test for pixel-perfect collision between the two objects. Any deaths are tagged in the killer/killed array and handled below 92 BLOCK END - Loop through all other objects (inner loop) 93 BLANK 94 If the original object is a plane.. 95 And the plane is still active... 96 And not parked.. 97 And if the plane is at a low altitude 98 Or if it's a missle or bomb.. 99 below a certain altitude... 100 Test for crash in to ground or target. Any deaths are tagged in the killer/killed array 101 BLOCK END - Loop through all objects 102 BLANK 103 Set killed pointer to the killed array 104 Set killer pointer to the killer array 105 Loop through all objects until we've reached the kill pointer (could be empty and nothing happens) 106 Perform a kill for the two objects indexed in both arrays. Possible tag for collision later 107 BLANK 108 Set the killed pointer to the collision check array 109 BLOCK START - Loop through all objects tagged for collision death 110 If the object's delta x matches the collision check 111 Match the collision delta y 112 BLOCK END - Loop through all objects tagged for collision death 113 BLOCK END - swcollsn 114 BLANK 115 BLANK 116 BLANK 117 BLANK TESTS FOR OBJECTS COLLISION 118 Declare and define colltest with 2 arguments 119 Both arguments are pointers to objects 120 BLOCK START - colltest, tests two objects for collision 121 Declares pointers for both input objects and a temporary swap pointer 122 Declares variables for object types 123 BLANK 124 Sets one local pointer to the first input object 125 Sets the other local pointer to the second input object 126 Sets local type variable to that of the first input object 127 Sets other local type variable to that of the second input object 128 If the first object is plane thats already dead or a ghost... 129 or the second object is plane thats dead or a ghost... 130 or both objects are explosion shrapel 131 then return from collision check -- no explosion occurred 132 BLANK 133 BLOCK START - Pointer swap, if object 1 is lower than object 2 134 Set temp pointer to object 1's pointer 135 Set object 1's pointer to object 2's pointer 136 Set object 2's pointer to object 1 137 BLOCK END - Pointer swap 138 BLANK 139 Draw object 1 in the lower right of the screen 140 If drawing the other object relative to the first.., 141 results in a non-zero comparison (See SWGRAPH.ASM)... 142 ..then there was a pixel collision.. 143 BLOCK START - Set collision flags for future processing 144 Flag object 1 for death 145 Flag object 2 as the killer 146 Flag object 2 for death 147 Flag object 1 as the killer 148 BLOCK END - Set collision flags 149 Clear the collision test 150 BLOCK END - colltest 151 BLANK 152 BLANK 153 BLANK TESTS POINT FOR GROUND COLLISION 154 Declare tstcrash with 1 argument 155 Argument 1 is the object to test 156 BLOCK START - tstcrash, tests an object for collision with the ground 157 Declares a local object pointer 158 Declares local position variables 159 Declares a crash boolean 160 BLANK 161 Sets the local pointer to the input object 162 Draws the input object in the lower right of the screen 163 BLANK 164 Sets the max width to the width of the object graphic 165 BLOCK START - Loop through the width of the object 166 If the ground is higher than the sprite 167 Set hit to true -- the ground is above the entire graphic 168 End the test 169 End ground check 170 Otherwise, if the plane is below the ground... 171 Then skip check 172 Otherwise, test for collision by drawing the ground pixel and hit if color result was unexpected. 173 End test 174 BLOCK END - Loop through the width of the object 175 Clear the collision drawing test 176 BLANK 177 If the plane is hit and we have room in the kill array.. 178 Flag the object for death 179 There is no killer 180 End collision check 181 BLOCK END - tstcrash 182 BLANK 183 BLANK 184 BLANK DESTROY OBJECTS 185 Declares and defines kill with 2 arguments 186 Both arguments are object pointers 187 BLOCK START - Performs kill actions between two objects based on type 188 Declares pointers to objects 189 Declares local state, type, and iterators 190 BLANK 191 Point to object 1 192 Point to object 2 193 If object 2 has no pointer, then it must be NULL (ground) 194 If the 2nd object is a bird or flock... 195 but the 2nd type isn't a plane 196 Then exit the function -- no kill occurred 197 BLANK 198 SWITCH on object 1's type 199 BLANK 200 CASE Bomb or... 201 CASE Missile 202 Create an explosion on object 203 Mark the bomb or missile as dead 204 If there is no 2nd object, there must have been a collision with ground 205 Make crater damage 206 Stop playing the sound for the bomb or missile 207 Return to swcollsn 208 BLANK 209 CASE shots/bullets 210 Mark bullets for destruction 211 Return to swcollsn 212 BLANK 213 CASE flares 214 If the flares hit a bomb, missle or the ground.. 215 Destroy the flares 216 Return to swcollsn 217 BLANK 218 CASE explosive shrapnel 219 If the shrapnel hit the ground.. 220 Mark the shrapnel to disppear 221 Stop playing shrapnel sound 222 End check for ground hit 223 Return to swcollsn 224 BLANK 225 CASE target building 226 If the building has already been destroyed.. 227 Return to swcollsn 228 If a flare or shrapnel hit the building....then no damage 229 Return to swcollsn 230 BLANK 231 If a bullet hit the building... 232 And the cumulative damage of the building... 233 Is less than the game number (target health == game number) 234 Then it's still alive, return to swcollsn 235 BLANK 236 Flag the building for destruction 237 Create explosion 238 BLANK 239 Set the display to primary video memory 240 Update the world minimap with the new state of object 1 241 Set the display to aux 242 BLANK 243 Apply score to destroyer based on orientation (type), and color 244 Decrement the target counter and if there are no more... 245 Trigger end game 246 Return to swcollsn 247 BLANK 248 CASE airplane 249 If the plane has already crashed... 250 ...or is a ghost that crashed.. 251 Return to swcollsn 252 BLANK 253 If the plane is the player and has already won the game 254 Then return, player can't die during end sequence 255 BLANK 256 If the plane collided with a flare or... 257 ..a bird, but the plane is parked... 258 Then return - no damage 259 BLANK 260 BLOCK START - Plane crash in to ground, if plane hit the ground 261 If the plane is falling, the plane crashes so.. 262 Stop playing the plane sound 263 Start an explosion 264 Damage the ground 265 End case for falling plane but.. 266 If the plane is still alive, it still crashes 267 Add scores to the plane 268 Start can explosion 269 Damage the ground 270 End case for plane crashing 271 BLANK 272 In all cases, the plane crashed 273 Return to swcollsn 274 BLOCK END - Plane crash in to ground 275 BLANK 276 If the plane was already destroyed then 277 Return to swcolln -- no crash 278 BLANK 279 If the plane is falling... 280 and the plane is the player... 281 and the player hit bullets 282 Then add a shot hole to the screen 283 Otherwise, if the plaer hit a bird... 284 Or flock.. 285 Add some splattered birds 286 Return to swcollsn 287 End case for falling player 288 BLANK (this block needs some serious refactor) 289 If the plane hits shots or birds... 290 or oxen, or flocks 291 and this is the player... 292 Then if it really really really was bullets.. 293 Add a shot hole on the screen 294 But if it was an oxen 295 Splat that ox 296 Otherwise it must be a birdie 297 Smash! 298 But if we're flying....and we've hit something 299 Change to wounded 300 End case for flying damage 301 Return to swcollsn 302 But if we're stalled 303 Then we stalled AND wounded 304 Return to swcollsn 305 End case for stalled 306 BUT IF WE HIT SOMETHING THAT ISN'T COVERED YET..... 307 Make a small explosion anyway 308 BLOCK START - Plane hit plane 309 Set a collision x point.. 310 To the average of both object's x movement vectors 311 Plus the turn x adjustment 312 Set a collision y point... 313 To the avearge of both ocject's y movement vectors 314 Plus the turn y adjustment 315 Record the object that collides 316 BLOCK END - Plane hit plane 317 End case for hitting something else 318 BLANK 319 Object hits a plane 320 Add score for the plane 321 Return to swcollsn 322 BLANK 323 CASE Bird 324 If the bird hits something that can hurt it, kill the birds 325 Return swcollsn 326 BLANK 327 CASE Flock 328 If the flock doesn't hit other birds... 329 But it is a flying object... 330 Then loop through 8 times... 331 And separate the block in to birds.. 332 Destroy the flock 333 Twice! 334 End case for flock 335 Return to swcollsn 336 BLANK 337 CASE Oxen 338 If the oxen is already dead... 339 Return to swcollsn 340 If the oxen hit an explosion or a flare.. 341 Return to swcollsn 342 Otherwise, deduct some score for whoever hit it 343 Kill the oxen 344 Return to swcollsn 345 SWITCH END - On object type 346 BLOCK END - kill 347 BLANK 348 BLANK 349 BLANK PENALIZE PLAYER SCORE 350 Declare scorepenalty with 3 arguments 351 Argument 1 is the object type hit 352 Argument 2 is a pointer to the plane that hit the object 353 Argument 3 is the score penalty to assess 354 BLOCK START - scorepenalty, assesses a score penalty to a player 355 Declare a local pointer to an object 356 BLANK 357 Points to the input plane 358 If the plane hits a shot, bomb, missile.. 359 Or another plane that.. 360 Is still flying.. 361 Or is wounded.. 362 Or is falling... 363 ..and hasn't exploded yet 364 And the plane isn't on the ground 365 Then assess the penalty 366 Return true for the penalty 367 End case for true penalty 368 Return false for no penalty 369 BLOCK END - scorepenalty 370 BLANK 371 BLANK 372 BLANK 373 BLANK ADD SCORE FOR TARGETS 374 Declare and define scoretarg with 2 argument 375 Argument 1 is the target destroyed 376 Argument 2 is the score amount 377 BLOCK START - scoretarg, add score for target destruction 378 Declare local object pointer 379 BLANK 380 Point to the target to destroy 381 If we're not in multiplayer mode.. 382 Or there's only one player.. 383 Then if the target's color matches the players color... 384 Deduct the score amount from the playe 385 Otherwise it's an enemy target so.. 386 Add the score to the player 387 Update the score display 388 Otherwise it's multiplayer so figure out which player it is.. 389 Add the target score to the player of the opposite color 390 Update the player's score 391 End case for multiplayer update 392 BLOCK END - scoretarg 393 BLANK 394 BLANK 395 BLANK 396 BLANK 397 BLANK ADD SCORE FOR PLANES 398 Declare scorepln with 1 argument 399 Argument 1 is the object that scored 400 BLOCK START - scorepln, adds/subtracts score to the target object 401 BLANK 402 Adds or subtracts 50 points depending on color of target and plane 403 BLOCK END - scorepln 404 BLANK 405 BLANK 406 BLANK 407 BLANK DISPLAY SCORE 408 Declare dispscore with 1 argument 409 Argument 1 is the pointer to the player's plane 410 BLOCK START - dispscore, update the score display 411 Declare a local pointer to the player object 412 BLANK 413 Position the cursor at (2,24) or (9,24) depending on the player 414 Match the score color to the player color 415 Display the score with 6 characters 416 BLOCK END - dispscore 417 BLANK 418 BLANK 419 BLANK 420 BLANK DEBUG DISPLAY 421 Declare dispd with 2 arguments 422 Both arguments are integers, one for the value and the other for size 423 BLOCK START - dispd, display value (usually for debug purposes) 424 Declare an iterator intialized to zero 425 Declare more iterators 426 Declare a boolean flag initialized to true 427 BLANK 428 If the input number is negative.. 429 Flip the sign 430 Print a negative sign 431 Increment our iterator 432 End case for negative numvers 433 Loop through decimal magnitudes starting with 10000 down to 10 434 If there the value place is non-zero or it's not first, then... 435 Clear the first flag 436 Print the (coerced) number 437 Increment the count iterator 438 End loop through magnitudes 439 Otherwise, print the score, (always zero here?) 440 Increment the counter 441 If we still have places remaining 442 Print spaces 443 BLOCK END - dispd 444 BLANK 445 BLANK 446 BLANK 447 BLANK 448 BLANK 449 BLANK BOMB DAMAGE ON GROUND 450 Defines the impact strength of bombs on the ground. Bomb graphic is 8x8 and these values are the delta y subtracted from the ground height across the 8 pixels 451 BLANK 452 Declare and define crater with 1 argument 453 Argument 1 is an input object 454 BLOCK START - crater, makes a crater in the ground 455 Declare local variables for position 456 Declares more local variables for position 457 BLANK 458 Set variable to the middle of the sprite in world space 459 Set another variable 7 pixels in front of the middle 460 BLANK 461 BLOCK START - Damage ground 462 Start at the current ground height 463 If the ground has been damaged below a height of 20.. 464 Set the base height to 20 465 Subtract the damage from the vector on line 450 and check base 466 Clamp base if necessary...no bombing through the world 467 Remove the clamped amount of damage from the ground 468 BLOCK END - Damage ground 469 Set flag to redraw ground 470 BLOCK END - crater 471 BLANK 472 BLANK 473 BLANK 474 BLANK TEST EQUALITY BETWEEN TWO INPUT FUNCTIONS 475 Defines equal with 2 arguments 476 Argument 1 and 2 are function pointers 477 BLOCK START - equal, tests if two function pointers are the same 478 Returns true or false if function pointers are the same 479 BLOCK END - equal 480 EOF˙