-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathCore Functionality.txt
117 lines (99 loc) · 6.18 KB
/
Core Functionality.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
Jump Core Functionality requirements as of commit b2a1aa63e3244c33f94eb2d00f3de72cda62e7ab
1) Step at even intervals (default to 128 updates/second)
- Run as many steps as is needed to consume the given delta unless one of the two following occur:
- If less than 1/128 of a second has passed, do a non-update (just add/remove any pending bodies)
- If more than 1 second has passed, trim the total calculations in one call to 1 second
2) Track the occupied spaces of all non-level-tile bodies
Definitions:
* Dynamic Body - A body that freely moves about the world - possibly controlled by a player, or some other entity. Collides with Static and Kinetic Bodies
* Kinetic Body - A body that can move around in the world, but does not collide with anything else.
* Static Body - A body that is stationary and therefore does not collide with anything.
* Potential Collision - The loose bounding boxes of two bodies overlap. This might be a collision, but we haven't done the full calculation yet. This is held in an object called SATStrategy. This object is a body (the focus) and a list of other bodies it might be colliding with
* Manifold - A vector that describes the calculated translation needed to separate two bodies
* Manifold Bundle - A list of all calculated vectors that can separate two bodies. This contains both the shortest solution as well as any others found
* Crushed - A body is has been resolved in opposing directions in a single collision resolution step
Core Step Loop:
1) Move all bodies
1) Update effects of gravity
2) Update any controls that might be attached
3) Reset any collision variables in preparation for this collision step
- This includes things like:
- Grounded
- Parent objects (in case of contact with moving platforms)
- Resolution Locked to false
- Last Resolution
4) Update occupied spaces
2) Collision loop (continues for 10 steps, or until no collisions exist)
1) Find all potential collisions between Dynamic -> Level (based on grid)
2) Check for any ongoing contacts to have ended (Does this make sense to be here?)
3) Find all potential collisions between Dynamic -> Static/Kinetic bodies
4) Perform *Collision Resolution*
5) Loop back to step 1 if collisions are found and resolved
*Collision Resolution*
1) Sort all potential solutions (collisions against static objects are prioritized)
2) For each potential collision
1) *Satisfy* the collision
2) Buffer any new contact events
3) *Apply* the resolution
3) Return true if at least one potential collision resulted in a body being moved
*Satisfy*
1) For each suspect body in the potential collision
1) *Find the Manifold*, taking into account any needed resolution that's already been found
2) Flag contact if the manifold is non-zero (indicating some amount of movement was needed / contact had occurred)
3) Bail early if both bodies are Dynamic
4) Mark the potential collision as a locking resolution if it was against
1) A static body
2) A kinetic body
3) the other body is already resolution locked
5) Add the found Manifold to the cumulative resolution
6) Normalize the manifold
7) Check against the previously resolved directions
- If opposing resolutions are found, the body was 'crushed'
8) Add the normalized manifold to the list of axes resolved against
9) Call *Post Resolve*
2) Set the end resolution to the cumulative resolution calculated from all the suspect bodies
3) Return true if we moved the body, false otherwise
*Find The Manifold*
1) *Calculate the Manifold* candidate based on the two bodies, taking into account the cumulative resolution
2) This is where we originally tried to handle angled platforms, currently this step doesn't exist
3) Return the candidate
*Calculate The Manifold*
1) Copy the body's bounding box and translate it by the cumulative resolution calculated up to this point
2) Calculate the Manifold Bundle (Separating Axis Theorem is used here)
3) If we get null back, return the zero manifold (a zero length vector indicating no overlap was found)
4) Otherwise, *Solve The Bundle* and return the selected Manifold
*Solve The Bundle*
1) Sort the bundle by Manifold length from shortest to longest
2) Take note of the relative movement between the two bodies
3) For each Manifold:
1) Calculate the dot product between the relative movement and the manifolds axis
2) If the dot product is non-zero (indicating that we are being resolved along the line of relative movement):
1) *Handle Tile Collisions* specially
2) Otherwise, just return the manifold
*Handle Tile Collisions*
1) Store the dot product of the calculated resolved position with the current Manifold
2) Store the dot product of the body's last position against the Manifold axis (these two points let us know relative positioning of the body/tile)
3) Check that the tile collision is a *Valid Tile Collision*
*Valid Tile Collision*
1) Fail early if it's not a valid collision for the neighbour value of the tile
2) Return true if the resolution position and last position of the body are opposing each other. (Is this actually valid? the next two steps seem more reliable/correct)
3) If the Manifold's distance is negative, return true if the last position is greater than the resolution position.
4) If the Manifold's distance is positive, return true if the last postition is less than the resolution position.
5) Handle one-way validation (walk through this and see how it works... I'm confused by my own work)
*Post Resolve*
1) If body was resolved against a kinetic body against gravity:
1) add the kinetic body as a parent of this body
2) add this body as a child of the kinetic body
3) For each dynamic body:
1) Update any render state watchers
2) Fire all contact ended events for each dynamic body
3) Fire all continued contacts for each dynamic body
Boiled down requirements:
1) Move everything
2) Find any potential collisions
3) Find any true contacts
4) Fire events for any contacts
5) Validate contacts (such as using neighbour values for tile contacts)
6) Resolve collisions iteratively
- Resolve Dynamic -> Static collisions before Dynamic -> Kinetic
This makes sure that collisions feel consistent, especially where kinetic platforms move through static platforms