Skip to content

Commit 4acda3e

Browse files
authored
Merge pull request #9 from AustinEast/dirty-and-sleep
Dirty flag + Quadtree improvements
2 parents 9202be4 + 876cf32 commit 4acda3e

File tree

13 files changed

+430
-233
lines changed

13 files changed

+430
-233
lines changed

echo/Body.hx

Lines changed: 162 additions & 87 deletions
Large diffs are not rendered by default.

echo/Collisions.hx

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,9 @@ using Lambda;
1111
*/
1212
class Collisions {
1313
/**
14-
* Queries a World's Listeners for Collisions
14+
* Updates the World's dynamic QuadTree with any Bodies that have moved.
1515
*/
16-
public static function query(world:World, ?listeners:Listeners) {
17-
// Populate the Quadtree
18-
var quadtree = listeners == null ? world.quadtree : QuadTree.get();
19-
quadtree.clear();
20-
quadtree.set(world.x + (world.width * 0.5), world.y + (world.height * 0.5), world.width, world.height);
16+
public static function update_quadtree(world:World) {
2117
world.for_each(b -> {
2218
b.collided = false;
2319
for (shape in b.shapes) {
@@ -27,13 +23,21 @@ class Collisions {
2723
if (r.transformed_rect != null) r.transformed_rect.collided = false;
2824
}
2925
}
30-
if (b.active && b.is_dynamic()) {
31-
if (b.cache.quadtree_data.bounds == null) b.cache.quadtree_data.bounds = b.bounds();
32-
else b.bounds(b.cache.quadtree_data.bounds);
33-
quadtree.insert(b.cache.quadtree_data);
26+
if (b.active && b.is_dynamic() && b.dirty) {
27+
if (b.quadtree_data.bounds == null) b.quadtree_data.bounds = b.bounds();
28+
else b.bounds(b.quadtree_data.bounds);
29+
world.quadtree.update(b.quadtree_data);
3430
}
31+
b.dirty = false;
3532
});
36-
33+
}
34+
/**
35+
* Queries a World's Listeners for Collisions.
36+
* @param world The World to query.
37+
* @param listeners Optional collection of listeners to query. If this is set, the World's listeners will not be queried.
38+
*/
39+
public static function query(world:World, ?listeners:Listeners) {
40+
update_quadtree(world);
3741
// Process the Listeners
3842
var members = listeners == null ? world.listeners.members : listeners.members;
3943
for (listener in members) {
@@ -46,14 +50,14 @@ class Collisions {
4650
var col = body_and_body(ba, bb);
4751
if (col != null) listener.quadtree_results.push(col);
4852
case Right(ab):
49-
body_and_bodies(ba, ab, world, listener.quadtree_results, quadtree);
53+
body_and_bodies(ba, ab, world, listener.quadtree_results, world.quadtree);
5054
}
5155
case Right(aa):
5256
switch (listener.b) {
5357
case Left(bb):
54-
body_and_bodies(bb, aa, world, listener.quadtree_results, quadtree);
58+
body_and_bodies(bb, aa, world, listener.quadtree_results, world.quadtree);
5559
case Right(ab):
56-
bodies_and_bodies(aa, ab, world, listener.quadtree_results, quadtree);
60+
bodies_and_bodies(aa, ab, world, listener.quadtree_results, world.quadtree);
5761
}
5862
}
5963
// Narrow Phase
@@ -78,12 +82,10 @@ class Collisions {
7882
continue;
7983
}
8084
// Preform the full collision check
81-
var use_a_cache = result.a.is_static();
82-
var ssa = use_a_cache ? result.a.cache.shapes : result.a.shapes;
85+
var ssa = result.a.shapes;
8386

8487
for (sa in ssa) {
85-
var use_b_cache = result.b.is_static();
86-
var ssb = use_b_cache ? result.b.cache.shapes : result.b.shapes;
88+
var ssb = result.b.shapes;
8789
for (sb in ssb) {
8890
var col = sa.collides(sb);
8991
if (col != null) result.data.push(col);
@@ -104,7 +106,6 @@ class Collisions {
104106
listener.collisions.push(result);
105107
}
106108
}
107-
if (listeners != null) quadtree.put();
108109
}
109110
/**
110111
* Enacts the Callbacks defined in a World's Listeners

echo/Echo.hx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ import echo.util.BodyOrBodies;
1616
* Echo holds helpful utility methods to help streamline the creation and management of Physics Simulations.
1717
*/
1818
class Echo {
19+
/**
20+
* Cache'd `Listeners` collection to help with memory management.
21+
*/
1922
static var listeners:Listeners = new Listeners();
2023
/**
2124
* Shortcut for creating a new `World`
@@ -50,20 +53,17 @@ class Echo {
5053
* @param b The second `Body` or Array of Bodies to collide against
5154
* @param options Options to define the Collision Check's behavior
5255
*/
53-
public static function check(world:World, ?a:BodyOrBodies, ?b:BodyOrBodies, ?options:ListenerOptions):Listener {
54-
var listener:Listener;
55-
56+
public static function check(world:World, ?a:BodyOrBodies, ?b:BodyOrBodies, ?options:ListenerOptions) {
5657
listeners.clear();
5758

58-
if (a == null) listener = b == null ? listeners.add(world.members, world.members, options) : listeners.add(b, b, options);
59-
else if (b == null) listener = listeners.add(a, a, options);
60-
else listener = listeners.add(a, b, options);
59+
if (a == null && b == null) listeners.add(world.members, world.members, options);
60+
else if (a == null) listeners.add(b, b, options);
61+
else if (b == null) listeners.add(a, a, options);
62+
else listeners.add(a, b, options);
6163

6264
Collisions.query(world, listeners);
6365
Physics.separate(world, listeners);
6466
Collisions.notify(world, listeners);
65-
66-
return listener;
6767
}
6868
/**
6969
* Steps a `World` forward.
@@ -252,7 +252,7 @@ class Echo {
252252
}
253253
}
254254
}
255-
world.refresh();
255+
world.reset_quadtrees();
256256
}
257257
}
258258
return world;
@@ -279,7 +279,7 @@ class Echo {
279279
}
280280
}
281281
}
282-
world.refresh();
282+
world.reset_quadtrees();
283283
}
284284
return world;
285285
}

echo/Listener.hx

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import echo.util.BodyOrBodies;
1212
*/
1313
@:structInit()
1414
class Listener {
15+
public static var defaults(get, null):ListenerOptions;
1516
/**
1617
* The first Body or Array of Bodies the listener checks each step.
1718
*/
@@ -62,29 +63,31 @@ class Listener {
6263
* Threshold determining how close two separating bodies must be before position correction occurs. Helps reduce jitter.
6364
*/
6465
public var correction_threshold:Float;
66+
67+
static function get_defaults():ListenerOptions return {
68+
separate: true,
69+
percent_correction: 0.9,
70+
correction_threshold: 0.013
71+
}
6572
}
6673
/**
6774
* Container used to store Listeners
68-
*
69-
* TODO: Turn into an iterable
7075
*/
7176
class Listeners implements IDisposable {
72-
public static var listener_defaults(get, null):ListenerOptions;
73-
7477
public var members:Array<Listener>;
7578

7679
public function new(?members:Array<Listener>) {
7780
this.members = members == null ? [] : members;
7881
}
7982
/**
80-
* Add a new Listener to listen for collisions
81-
* @param a The first `Body` or Array of Bodies to collide against
82-
* @param b The second `Body` or Array of Bodies to collide against
83-
* @param options Options to define the Listener's behavior
84-
* @return Listener
83+
* Add a new Listener to the collection.
84+
* @param a The first `Body` or Array of Bodies to collide against.
85+
* @param b The second `Body` or Array of Bodies to collide against.
86+
* @param options Options to define the Listener's behavior.
87+
* @return The new Listener.
8588
*/
8689
public function add(a:BodyOrBodies, b:BodyOrBodies, ?options:ListenerOptions):Listener {
87-
options = echo.util.JSON.copy_fields(options, listener_defaults);
90+
options = echo.util.JSON.copy_fields(options, Listener.defaults);
8891
var listener:Listener = {
8992
a: a,
9093
b: b,
@@ -103,26 +106,26 @@ class Listeners implements IDisposable {
103106
return listener;
104107
}
105108
/**
106-
* Removes a Listener from the Container
107-
* @param listener Listener to remove
108-
* @return Listener
109+
* Removes a Listener from the Container.
110+
* @param listener Listener to remove.
111+
* @return The removed Listener.
109112
*/
110113
public function remove(listener:Listener):Listener {
111114
members.remove(listener);
112115
return listener;
113116
}
114-
117+
/**
118+
* Clears the collection of all Listeners.
119+
*/
115120
public function clear() {
116-
members = [];
121+
members.resize(0);
117122
}
118-
123+
/**
124+
* Disposes of the collection. Do not use once disposed.
125+
*/
119126
public function dispose() {
120127
members = null;
121128
}
122129

123-
static function get_listener_defaults():ListenerOptions return {
124-
separate: true,
125-
percent_correction: 0.9,
126-
correction_threshold: 0.013
127-
}
130+
public inline function iterator():Iterator<Listener> return members.iterator();
128131
}

echo/Macros.hx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
package echo;
22

3+
#if macro
34
import haxe.macro.Expr;
45
import haxe.macro.Context;
56

67
class Macros {
7-
#if macro
8-
static var dataFields:Array<Field> = []; // add fields here
8+
static var dataFields:Array<Field> = [];
99

1010
static function build_body() {
11-
if (dataFields.length == 0) return null; // No change, more optimal than returning array of fields.
11+
if (dataFields.length == 0) return null;
1212
var fields = Context.getBuildFields();
1313
for (f in dataFields) fields.push(f);
1414
return fields;
1515
}
1616
/**
17-
* Build Macro to add extra fields to the body class. Inspired by [@Yanrishatum](https://github.com/Yanrishatum).
17+
* Build Macro to add extra fields to the Body class. Inspired by [@Yanrishatum](https://github.com/Yanrishatum).
1818
*
1919
* Example: in build.hxml - `--macro echo.Macros.add_data("entity", "some.package.Entity")
2020
* @param name
@@ -28,5 +28,5 @@ class Macros {
2828
pos: Context.currentPos()
2929
});
3030
}
31-
#end
3231
}
32+
#end

echo/Material.hx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package echo;
2+
3+
import hxmath.math.Vector2;
4+
/**
5+
* TODO - A Structure that describes the physical properties of a `Body`.
6+
*/
7+
class Material {
8+
/**
9+
* Value to determine how much of a Body's `velocity` should be retained during collisions (or how much should the `Body` "bounce" in other words).
10+
*/
11+
public var elasticity:Float;
12+
/**
13+
* A measure of how fast a Body will move its velocity towards 0 when there is no acceleration.
14+
*/
15+
public var drag:Vector2;
16+
17+
public var friction:Float;
18+
}

echo/Shape.hx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,15 +212,15 @@ class Shape implements IProxy {
212212
inline function set_x(value:Float):Float {
213213
if (parent_frame == null) return local_x = value;
214214

215-
var pos = sync_pos.set(value, y);
215+
var pos = new Vector2(value, y);
216216
set_local_position(parent_frame.transformTo(pos));
217217
return _x;
218218
}
219219

220220
inline function set_y(value:Float):Float {
221221
if (parent_frame == null) return local_y = value;
222222

223-
var pos = sync_pos.set(x, value);
223+
var pos = new Vector2(x, value);
224224
set_local_position(parent_frame.transformTo(pos));
225225
return _y;
226226
}

0 commit comments

Comments
 (0)