Discussion about software development for the old-school Gameboys, ranging from the "Gray brick" to Gameboy Color
(Launched in 2008)
You are not logged in.
Hey! I'm trying to make a platformer, but don't know how to handle collisions etc.
I have a basic understanding of collisions, and don't need raw code. I just need a quick explanation on how I would
do it on the Gameboy.
Offline
Most games simply use primitive shapes (points, circles, squares, rectangles,...) and quickly calculate if one such shape intersects another such shape using common math formulas (for exact intersection) or inequalities (for true/false):
Here's a simple Python 3 example for rectangles:
shapes = [ {'x': 5, 'y': 6, 'w': 8, 'h': 8}, {'x': 6, 'y': 7, 'w': 8, 'h': 8}, {'x': 2, 'y': 5, 'w': 5, 'h': 6}, {'x': 20, 'y': 15, 'w': 10, 'h': 10}, {'x': 18, 'y': 13, 'w': 13, 'h': 13}, {'x': 10, 'y': 12, 'w': 3, 'h': 4}, {'x': 8, 'y': 18, 'w': 1, 'h': 1}, {'x': 8, 'y': 14, 'w': 2, 'h': 2}, ] def findIntersections(): intersections = [] for i in range(0, len(shapes)): shape = shapes[i] for j in range(i + 1, len(shapes)): other_shape = shapes[j] # other shape does not overlap shape in x dimension if ((other_shape['x'] + other_shape['w']) <= shape['x']): continue # shape does not overlap other shape in x dimension if ((shape['x'] + shape['w']) <= other_shape['x']): continue # other shape does not overlap shape in y dimension if ((other_shape['y'] + other_shape['h']) <= shape['y']): continue # shape does not overlap other shape in y dimension if ((shape['y'] + shape['h']) <= other_shape['y']): continue intersections.append((i, j)) return intersections # 35x30 field width = 35 height = 30 field = [[' '] * width for _ in range(height)] for i, shape in enumerate(shapes): x = shape['x'] y = shape['y'] w = shape['w'] h = shape['h'] # draw corners field[y+0][x+0] = '┌' field[y+0][x+w] = '┐' field[y+h][x+0] = '└' field[y+h][x+w] = '┘' # draw horizontal lines for x_ in range(x + 1, x + w): field[y+0][x_] = '─' field[y+h][x_] = '─' # draw vertical lines for y_ in range(y + 1, y + h): field[y_][x+0] = '│' field[y_][x+w] = '│' # draw ID field[y+h//2][x+w//2] = str(i) for line in field: print("".join(line)) for i, j in findIntersections(): print(f'Shape {i} intersects shape {j}.')
Example output:
┌────┐ │ ┌─│─────┐ │ │┌│──────┐ │ 2│││ ││ │ │││ ││ │ │││ 0 ││ └────┘ 1 ││ ││ ┌──┐│ ││ │ ││ ┌────────────┐ └│─┌─┐5─││ │ │ └─│7│──│┘ │ ┌─────────┐│ └─┘──┘ │ │ ││ │ │ ││ 6┐ │ │ ││ └┘ │ │ 4 ││ │ │ 3 ││ │ │ ││ │ │ ││ │ │ ││ │ │ ││ │ └─────────┘│ └────────────┘ Shape 0 intersects shape 1. Shape 0 intersects shape 2. Shape 0 intersects shape 5. Shape 1 intersects shape 2. Shape 1 intersects shape 5. Shape 1 intersects shape 7. Shape 3 intersects shape 4.
Notice that this code does not compute the actual intersection just whether or not the shapes intersect based on inequalities. Depending on your platformer's needs you might need to actually calculate the intersection point(s). (Notice that my codes does not consider the right-most edge as being part of the rectangle, so a shape starting at x=0 with width 2 does not intersect another shape starting at x=2.)
You might need different types of objects, e.g. a player might be a rectangle, a platform, too, but a bullet might just be a single point or a circle/ellipse etc. There are well-known formulas for quickly determining intersections between all these primitive shape types e.g. point inside rectangle, point on line, line intersection etc.
If you order your shapes by y and then x coordinate you can optimize the run-time of the comparisons. You can stop at the first negative comparison when you know all other shapes are organized further down and/or further to the right. Let's sort the list from the example above first by y followed by x coordinate:
shapes = [ shapes = [ {'x': 5, 'y': 6, 'w': 8, 'h': 8}, {'x': 2, 'y': 5, 'w': 5, 'h': 6}, {'x': 6, 'y': 7, 'w': 8, 'h': 8}, {'x': 5, 'y': 6, 'w': 8, 'h': 8}, {'x': 2, 'y': 5, 'w': 5, 'h': 6}, {'x': 6, 'y': 7, 'w': 8, 'h': 8}, {'x': 20, 'y': 15, 'w': 10, 'h': 10}, => {'x': 8, 'y': 14, 'w': 2, 'h': 2}, {'x': 18, 'y': 13, 'w': 13, 'h': 13}, {'x': 8, 'y': 18, 'w': 1, 'h': 1}, {'x': 10, 'y': 12, 'w': 3, 'h': 4}, {'x': 10, 'y': 12, 'w': 3, 'h': 4}, {'x': 8, 'y': 18, 'w': 1, 'h': 1}, {'x': 18, 'y': 13, 'w': 13, 'h': 13}, {'x': 8, 'y': 14, 'w': 2, 'h': 2}, {'x': 20, 'y': 15, 'w': 10, 'h': 10}, ] ]
Taking the re-ordered example above, a collision comparison for shape 0 (x=2,y=5) can stop after having checked for collision with shape 3 (x=8,y=14), because all other shapes are going to be a) further down or b) further to the right as the list is sorted by x and then by y value.
Good luck with your platformer development
Last edited by Tauwasser (2021-06-30 21:02:09)
Offline
for checking collisions with scenery, simply make square collision map array.
Offline
Sorry for late response but thank you!
Tauwasser wrote:
Most games simply use primitive shapes (points, circles, squares, rectangles,...) and quickly calculate if one such shape intersects another such shape using common math formulas (for exact intersection) or inequalities (for true/false):
Here's a simple Python 3 example for rectangles:Code:
shapes = [ {'x': 5, 'y': 6, 'w': 8, 'h': 8}, {'x': 6, 'y': 7, 'w': 8, 'h': 8}, {'x': 2, 'y': 5, 'w': 5, 'h': 6}, {'x': 20, 'y': 15, 'w': 10, 'h': 10}, {'x': 18, 'y': 13, 'w': 13, 'h': 13}, {'x': 10, 'y': 12, 'w': 3, 'h': 4}, {'x': 8, 'y': 18, 'w': 1, 'h': 1}, {'x': 8, 'y': 14, 'w': 2, 'h': 2}, ] def findIntersections(): intersections = [] for i in range(0, len(shapes)): shape = shapes[i] for j in range(i + 1, len(shapes)): other_shape = shapes[j] # other shape does not overlap shape in x dimension if ((other_shape['x'] + other_shape['w']) <= shape['x']): continue # shape does not overlap other shape in x dimension if ((shape['x'] + shape['w']) <= other_shape['x']): continue # other shape does not overlap shape in y dimension if ((other_shape['y'] + other_shape['h']) <= shape['y']): continue # shape does not overlap other shape in y dimension if ((shape['y'] + shape['h']) <= other_shape['y']): continue intersections.append((i, j)) return intersections # 35x30 field width = 35 height = 30 field = [[' '] * width for _ in range(height)] for i, shape in enumerate(shapes): x = shape['x'] y = shape['y'] w = shape['w'] h = shape['h'] # draw corners field[y+0][x+0] = '┌' field[y+0][x+w] = '┐' field[y+h][x+0] = '└' field[y+h][x+w] = '┘' # draw horizontal lines for x_ in range(x + 1, x + w): field[y+0][x_] = '─' field[y+h][x_] = '─' # draw vertical lines for y_ in range(y + 1, y + h): field[y_][x+0] = '│' field[y_][x+w] = '│' # draw ID field[y+h//2][x+w//2] = str(i) for line in field: print("".join(line)) for i, j in findIntersections(): print(f'Shape {i} intersects shape {j}.')Example output:
Code:
┌────┐ │ ┌─│─────┐ │ │┌│──────┐ │ 2│││ ││ │ │││ ││ │ │││ 0 ││ └────┘ 1 ││ ││ ┌──┐│ ││ │ ││ ┌────────────┐ └│─┌─┐5─││ │ │ └─│7│──│┘ │ ┌─────────┐│ └─┘──┘ │ │ ││ │ │ ││ 6┐ │ │ ││ └┘ │ │ 4 ││ │ │ 3 ││ │ │ ││ │ │ ││ │ │ ││ │ │ ││ │ └─────────┘│ └────────────┘ Shape 0 intersects shape 1. Shape 0 intersects shape 2. Shape 0 intersects shape 5. Shape 1 intersects shape 2. Shape 1 intersects shape 5. Shape 1 intersects shape 7. Shape 3 intersects shape 4.Notice that this code does not compute the actual intersection just whether or not the shapes intersect based on inequalities. Depending on your platformer's needs you might need to actually calculate the intersection point(s). (Notice that my codes does not consider the right-most edge as being part of the rectangle, so a shape starting at x=0 with width 2 does not intersect another shape starting at x=2.)
You might need different types of objects, e.g. a player might be a rectangle, a platform, too, but a bullet might just be a single point or a circle/ellipse etc. There are well-known formulas for quickly determining intersections between all these primitive shape types e.g. point inside rectangle, point on line, line intersection etc.
If you order your shapes by y and then x coordinate you can optimize the run-time of the comparisons. You can stop at the first negative comparison when you know all other shapes are organized further down and/or further to the right. Let's sort the list from the example above first by y followed by x coordinate:Code:
shapes = [ shapes = [ {'x': 5, 'y': 6, 'w': 8, 'h': 8}, {'x': 2, 'y': 5, 'w': 5, 'h': 6}, {'x': 6, 'y': 7, 'w': 8, 'h': 8}, {'x': 5, 'y': 6, 'w': 8, 'h': 8}, {'x': 2, 'y': 5, 'w': 5, 'h': 6}, {'x': 6, 'y': 7, 'w': 8, 'h': 8}, {'x': 20, 'y': 15, 'w': 10, 'h': 10}, => {'x': 8, 'y': 14, 'w': 2, 'h': 2}, {'x': 18, 'y': 13, 'w': 13, 'h': 13}, {'x': 8, 'y': 18, 'w': 1, 'h': 1}, {'x': 10, 'y': 12, 'w': 3, 'h': 4}, {'x': 10, 'y': 12, 'w': 3, 'h': 4}, {'x': 8, 'y': 18, 'w': 1, 'h': 1}, {'x': 18, 'y': 13, 'w': 13, 'h': 13}, {'x': 8, 'y': 14, 'w': 2, 'h': 2}, {'x': 20, 'y': 15, 'w': 10, 'h': 10}, ] ]Taking the re-ordered example above, a collision comparison for shape 0 (x=2,y=5) can stop after having checked for collision with shape 3 (x=8,y=14), because all other shapes are going to be a) further down or b) further to the right as the list is sorted by x and then by y value.
Good luck with your platformer development
Offline