Right now the LEM is like a ghost to the terrain, it just slips right through on its way down to the bottom of the screen. Obviously I will need to know when the LEM reaches the ground in order to update the score with a good landing or generate an explosion. Collision detection is a big part of video games.
Conceptually the technique here is pretty simple:
- create a "bounding box" around the LEM, basically just the coordinates of 4 points just outside the LEM's image on the screen,
- then for each frame after the LEM has been moved, check to see if any of the terrain pixels lie within with that box.
Again here is where the screen coordinates, with the origin 0,0 being at the center of the screen, caused me some grief. I was having issues with negative values. It didn't help that the PDP-1 uses 1's compliment for negatives whereas everything else I was familiar with used 2's compliment. So I struggled with my implementation.
Finally I took a step back and decided that for purposes of collision detection I could use only positive screen coordinates where the x and y axis ranged from 0 to 1023. Once I made that decision the coding took less than an hour to get working.
The first thing I did was to add some code in the terrain generation Python script to emit a table with the y values expressed as 0-1023 integers.
print("y-coordinates")
count = 0
for y in smoothed_data:
print(count,str(int(y)).zfill(3),'\t\t',oct(int(y))[2:].zfill(6))
count = count+1
It turned out that this approach was faster too because I bypassed having to unpack and convert the Y coordinate from the terrain point. I still converted the values to octal so that they could be inserted into the Lunar Lander code.
/ Y-coordinates of the terrain points in 0-1023 screen coordinates.
ypt, 000620
000601
000534
000455
000404
000360
000360
000360
000360
000360
000360
000353
000322
000253
000203
000151
000143
000130
000105
000061
000042
000035
000036
000036
000036
000036
000036
000041
000052
000066
000100
000105
000106
000106
000106
000106
000106
000105
000100
000067
000057
000051
000050
000047
000050
000050
000050
000050
000050
000050
000050
000050
000050
000050
000050
000050
000050
000050
000051
000061
000074
000110
000117
000120
000127
000142
000156
000166
000170
000175
000207
000223
000234
000237
000240
000240
000240
000240
000240
000245
000266
000315
000343
000357
000362
000401
000430
000457
000475
000500
000506
000521
000535
000545
000550
000547
000550
000550
000550
000550
0 / End of data marker.
Then I added the following code:
/ Check for LEM terrain intersection.
lac gmx / Convert the LEM game coordinates to 0-1023
sar 3s / screen coordinates by dividing by 8.
dac scx
lac gmy
sar 3s
dac scy
lac scx / Create a bounding box.
add (27
dac xmx
lac scx
sub (7
dac xmn
lac scy
add (11
dac ymx
lac scy
sub (22
dac ymn
/ Iterate through the terrain points to see if any intersect with the LEM's bounding box.
dzm xct / Zero x coordinate counter.
init chi,ypt / Point to first word of terrain y 0-1023 data.
chi, lac . / Get the next y coordinate.
sza i / Not zero?
jmp vvl / No - Done checking intersections.
dac yct / Yes - Save Y value for further checking.
sub ymx / Check top of bounding box.
sma / Negative?
jmp nxp / No - y is above the bounding box.
lac yct / Yes - Check bottom of bounding box.
sub ymn
spa / Positive?
jmp nxp / No - y is below the bounding box.
lac xct / Yes - Check left of bounding box.
sub xmn
spa / Positive?
jmp nxp / No - y is left of the bounding box.
lac xct / Yes - check right of bounding box.
sub xmx
sma / Negative?
jmp nxp / No - point does not intersect.
jmp a2 / If we get here the point is inside the LEM's bounding box.
nxp, lac xct / Advance to next x coordinate.
add (12 / Add 10 to the x coordinate.
dac xct
idx chi / Index to the next y coordinate.
jmp chi
These checks should be pretty fast since there will be a lot of "early exits". Having just written that I now realize that the order of these checks could be optimized even further to encourage these early exits, probably starting with the bottom check first since there is no point in continuing if the bottom is above the terrain which will be the case for most of the decent. Added to my TODO list.
In this video I have added four dots around the LEM that show where the bounding box is.
Right now when a collision is detected the game just resets. Time for something more interesting, explosions.
Michael Gardi
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.