diff --git a/docs/API/geometry.md b/docs/API/geometry.md index 8f8a901..f89f15c 100644 --- a/docs/API/geometry.md +++ b/docs/API/geometry.md @@ -27,78 +27,310 @@ def tick args end ``` -## intersect_rect? +## anchor_rect + +Returns a new rect that is anchored by an anchor_x and anchor_y value. The width and height of the rectangle is taken into consideration when determining the anchor position: + +```ruby +def tick args + args.state.rect ||= { + x: 640, + y: 360, + w: 100, + h: 100 + } + + # rect's center: 640 + 50, 360 + 50 + args.outputs.borders << args.state.rect.anchor_rect(0, 0) + + # rect's center: 640, 360 + args.outputs.borders << args.state.rect.anchor_rect(0.5, 0.5) + + # rect's center: 640, 360 + args.outputs.borders << args.state.rect.anchor_rect(0.5, 0) +end +``` + +## angle_from **Invocation variants:** -* instance.intersect_rect?(other, tolerance) -* args.geometry.intersect_rect?(rect_1, rect_2, tolerance) -* args.inputs.mouse.intersect_rect?(other, tolerance) +* args.geometry.angle_from start_point, end_point +* start_point.angle_from end_point -Given two rectangle primitives this function will return true or false depending on if the two rectangles intersect or not. An optional final parameter can be passed in representing the tolerence of overlap needed to be considered a true intersection. The default value of tolerance is 0.1 which keeps the function from returning true if only the edges of the rectangles overlap. +Returns an angle in degrees from the end_point to the start_point (if you want the value in radians, you can call .to_radians on the value returned): +```ruby +def tick args + rect_1 ||= { + x: 0, + y: 0, + } -`anchor_x`, and `anchor_y` is taken into consideration if the objects respond to these methods. + rect_2 ||= { + x: 100, + y: 100, + } -Here is an example where one rectangle is stationary, and another rectangle is controlled using directional input. The rectangles change color from blue to read if they intersect. + angle = rect_1.angle_from rect_2 # returns 225 degrees + angle_radians = angle.to_radians + args.outputs.labels << { x: 30, y: 30.from_top, text: "#{angle}, #{angle_radians}" } + + angle = args.geometry.angle_from rect_1, rect_2 # returns 225 degrees + angle_radians = angle.to_radians + args.outputs.labels << { x: 30, y: 60.from_top, text: "#{angle}, #{angle_radians}" } +end +``` + +## angle_to + +**Invocation variants:** + +* args.geometry.angle_to start_point, end_point +* start_point.angle_to end_point +Returns an angle in degrees to the end_point from the start_point (if you want the value in radians, you can call .to_radians on the value returned): ```ruby def tick args - # define a rectangle in state and position it - # at the center of the screen with a color of blue - args.state.box_1 ||= { - x: 640 - 20, - y: 360 - 20, - w: 40, - h: 40, - r: 0, - g: 0, - b: 255 + rect_1 ||= { + x: 0, + y: 0, } - # create another rectangle in state and position it - # at the far left center - args.state.box_2 ||= { + rect_2 ||= { + x: 100, + y: 100, + } + + angle = rect_1.angle_to rect_2 # returns 45 degrees + angle_radians = angle.to_radians + args.outputs.labels << { x: 30, y: 30.from_top, text: "#{angle}, #{angle_radians}" } + + angle = args.geometry.angle_to rect_1, rect_2 # returns 45 degrees + angle_radians = angle.to_radians + args.outputs.labels << { x: 30, y: 60.from_top, text: "#{angle}, #{angle_radians}" } +end +``` + + +## center_inside_rect + +**Invocation variants:** + +* target_rect.center_inside_rect reference_rect +* args.geometry.center_inside_rect target_rect, reference_rect + +Given a target rect and a reference rect, the target rect is centered inside the reference rect (a new rect is returned). + +```ruby +def tick args + rect_1 = { x: 0, - y: 360 - 20, - w: 40, - h: 40, - r: 0, - g: 0, - b: 255 + y: 0, + w: 100, + h: 100 } - # take the directional input and use that to move the second rectangle around - # increase or decrease the x value based on if left or right is held - args.state.box_2.x += args.inputs.left_right * 5 - # increase or decrease the y value based on if up or down is held - args.state.box_2.y += args.inputs.up_down * 5 + rect_2 = { + x: 640 - 100, + y: 360 - 100, + w: 200, + h: 200 + } - # change the colors of the rectangles based on whether they - # intersect or not - if args.state.box_1.intersect_rect? args.state.box_2 - args.state.box_1.r = 255 - args.state.box_1.g = 0 - args.state.box_1.b = 0 + centered_rect = args.geometry.center_inside_rect rect_1, rect_2 + # OR + # centered_rect = rect_1.center_inside_rect rect_2 - args.state.box_2.r = 255 - args.state.box_2.g = 0 - args.state.box_2.b = 0 - else - args.state.box_1.r = 0 - args.state.box_1.g = 0 - args.state.box_1.b = 255 + args.outputs.solids << rect_1.merge(r: 255) + args.outputs.solids << rect_2.merge(b: 255) + args.outputs.solids << centered_rect.merge(g: 255) +end +``` - args.state.box_2.r = 0 - args.state.box_2.g = 0 - args.state.box_2.b = 255 + +## circle_intersect_line? + +The first parameters is a Hash with `x`, `y`, and `radius` keys (or an Object that responds to `x`, `y`, and `radius`). + +The second parameter is a Hash with `x1`, `y1`, `x2`, and `y2` keys (or an Object that responds to `x1`, `y1`, `x2`, and `y2`). + +This function will return `true` if the circle intersects the line, and `false` if it does not. + +> **Note** Take a look at this sample app for a non-trivial example of how to use this function: `./samples/04_physics_and_collisions/11_bouncing_ball_with_gravity/` + + +## create_quad_tree + +Generates a quad tree from an array of rectangles. See `find_intersect_rect_quad_tree` for usage. + + +## distance + +Returns the distance between two points; + +```ruby +def tick args + rect_1 ||= { + x: 0, + y: 0, + } + + rect_2 ||= { + x: 100, + y: 100, + } + + distance = args.geometry.distance rect_1, rect_2 + args.outputs.labels << { + x: 30, + y: 30.from_top, + text: "#{distance}" + } + + args.outputs.lines << { + x: rect_1.x, + y: rect_1.y, + x2: rect_2.x, + y2: rect_2.y + } +end +``` + +## distance_squared + +Given two Hashes with `x` and `y` keys (or Objects that respond to `x` and `y`), this function will return the distance squared between the two points. This is useful when you only want to compare distances, and don't need the actual distance. + +> **Note** Take a look at this sample app for a non-trivial example of how to use this function: `./samples/04_physics_and_collisions/11_bouncing_ball_with_gravity/` + +## find_intersect_rect + +Given a rect and a collection of rects, find_intersect_rect returns the first rect that intersects with the the first parameter. + +`anchor_x`, and `anchor_y` is taken into consideration if the objects respond to these methods. + +If you find yourself doing this: + +`collision = args.state.terrain.find { |t| t.intersect_rect? args.state.player }` + +Consider using find_intersect_rect instead (it's more descriptive and faster): + +`collision = args.geometry.find_intersect_rect args.state.player, args.state.terrain` + +## find_all_intersect_rect + +Given a rect and a collection of rects, find_all_intersect_rect returns all rects that intersects with the the first parameter. + +`anchor_x`, and `anchor_y` is taken into consideration if the objects respond to these methods. + +If you find yourself doing this: + +`collisions = args.state.terrain.find_all { |t| t.intersect_rect? args.state.player }` + +Consider using find_all_intersect_rect instead (it's more descriptive and faster): + +`collisions = args.geometry.find_all_intersect_rect args.state.player, args.state.terrain` + +## find_intersect_rect_quad_tree + +This is a faster collision algorithm for determining if a rectangle intersects any rectangle in an array. In order to use find_intersect_rect_quad_tree, you must first generate a quad tree data structure using create_quad_tree. Use this function if find_intersect_rect isn't fast enough. + +```ruby +def tick args + # create a player + args.state.player ||= { + x: 640 - 10, + y: 360 - 10, + w: 20, + h: 20 + } + + # allow control of player movement using arrow keys + args.state.player.x += args.inputs.left_right * 5 + args.state.player.y += args.inputs.up_down * 5 + + # generate 40 random rectangles + args.state.boxes ||= 40.map do + { + x: 1180 * rand + 50, + y: 620 * rand + 50, + w: 100, + h: 100 + } end - # render the rectangles as border primitives on the screen - args.outputs.borders << args.state.box_1 - args.outputs.borders << args.state.box_2 + # generate a quad tree based off of rectangles. + # the quad tree should only be generated once for + # a given array of rectangles. if the rectangles + # change, then the quad tree must be regenerated + args.state.quad_tree ||= args.geometry.quad_tree_create args.state.boxes + + # use quad tree and find_intersect_rect_quad_tree to determine collision with player + collision = args.geometry.find_intersect_rect_quad_tree args.state.player, + args.state.quad_tree + + # if there is a collision render a red box + if collision + args.outputs.solids << collision.merge(r: 255) + end + + # render player as green + args.outputs.solids << args.state.player.merge(g: 255) + + # render boxes as borders + args.outputs.borders << args.state.boxes +end +``` + +## find_all_intersect_rect_quad_tree + +This is a faster collision algorithm for determining if a rectangle intersects other rectangles in an array. In order to use find_all_intersect_rect_quad_tree, you must first generate a quad tree data structure using create_quad_tree. Use this function if find_all_intersect_rect isn't fast enough. + +```ruby +def tick args + # create a player + args.state.player ||= { + x: 640 - 10, + y: 360 - 10, + w: 20, + h: 20 + } + + # allow control of player movement using arrow keys + args.state.player.x += args.inputs.left_right * 5 + args.state.player.y += args.inputs.up_down * 5 + + # generate 40 random rectangles + args.state.boxes ||= 40.map do + { + x: 1180 * rand + 50, + y: 620 * rand + 50, + w: 100, + h: 100 + } + end + + # generate a quad tree based off of rectangles. + # the quad tree should only be generated once for + # a given array of rectangles. if the rectangles + # change, then the quad tree must be regenerated + args.state.quad_tree ||= args.geometry.quad_tree_create args.state.boxes + + # use quad tree and find_intersect_rect_quad_tree to determine collision with player + collisions = args.geometry.find_all_intersect_rect_quad_tree args.state.player, + args.state.quad_tree + + # if there is a collision render a red box + args.outputs.solids << collisions.map { |c| c.merge(r: 255) } + + # render player as green + args.outputs.solids << args.state.player.merge(g: 255) + + # render boxes as borders + args.outputs.borders << args.state.boxes end ``` + ## inside_rect? **Invocation variants:** @@ -170,167 +402,133 @@ def tick args end ``` -## scale_rect - -Given a Rectangle this function returns a new rectangle with a scaled size. - -* `ratio`: the ratio by which to scale the rect. A ratio of 2 will double the dimensions of the rect while a ratio of 0.5 will halve its dimensions. -* `anchor_x` and `anchor_y` specify the point within the rect from which to resize it. Setting both to 0 will affect the width and height of the rect, leaving `x` and `y` unchanged. Setting both to 0.5 will scale all sides of the rect proportionally from the center. - -```ruby -def tick args - # a rect at the center of the screen - args.state.rect_1 ||= { x: 640 - 20, y: 360 - 20, w: 40, h: 40 } - # render the rect - args.outputs.borders << args.state.rect_1 - - # the rect half the size with the x and y position unchanged - args.outputs.borders << args.state.rect_1.scale_rect(0.5) - - # the rect double the size, repositioned in the center given anchor optional arguments - args.outputs.borders << args.state.rect_1.scale_rect(2, 0.5, 0.5) -end -``` - -## scale_rect_extended +## intersect_rect? -The behavior is similar to scale_rect except that you can independently control the scale of each axis. The parameters are all named: +**Invocation variants:** -* `percentage_x`: percentage to change the width (default value of 1.0) -* `percentage_y`: percentage to change the height (default value of 1.0) -* `anchor_x`: anchor repositioning of x (default value of 0.0) -* `anchor_y`: anchor repositioning of y (default value of 0.0) +* instance.intersect_rect?(other, tolerance) +* args.geometry.intersect_rect?(rect_1, rect_2, tolerance) +* args.inputs.mouse.intersect_rect?(other, tolerance) -```ruby -def tick args - baseline_rect = { x: 640 - 20, y: 360 - 20, w: 40, h: 40 } - args.state.rect_1 ||= baseline_rect - args.state.rect_2 ||= baseline_rect.scale_rect_extended(percentage_x: 2, - percentage_y: 0.5, - anchor_x: 0.5, - anchor_y: 1.0) - args.outputs.borders << args.state.rect_1 - args.outputs.borders << args.state.rect_2 -end -``` +Given two rectangle primitives this function will return true or false depending on if the two rectangles intersect or not. An optional final parameter can be passed in representing the tolerence of overlap needed to be considered a true intersection. The default value of tolerance is 0.1 which keeps the function from returning true if only the edges of the rectangles overlap. -## anchor_rect +`anchor_x`, and `anchor_y` is taken into consideration if the objects respond to these methods. -Returns a new rect that is anchored by an anchor_x and anchor_y value. The width and height of the rectangle is taken into consideration when determining the anchor position: +Here is an example where one rectangle is stationary, and another rectangle is controlled using directional input. The rectangles change color from blue to read if they intersect. ```ruby def tick args - args.state.rect ||= { - x: 640, - y: 360, - w: 100, - h: 100 + # define a rectangle in state and position it + # at the center of the screen with a color of blue + args.state.box_1 ||= { + x: 640 - 20, + y: 360 - 20, + w: 40, + h: 40, + r: 0, + g: 0, + b: 255 } - # rect's center: 640 + 50, 360 + 50 - args.outputs.borders << args.state.rect.anchor_rect(0, 0) - - # rect's center: 640, 360 - args.outputs.borders << args.state.rect.anchor_rect(0.5, 0.5) - - # rect's center: 640, 360 - args.outputs.borders << args.state.rect.anchor_rect(0.5, 0) -end -``` - -## angle_from - -**Invocation variants:** - -* args.geometry.angle_from start_point, end_point -* start_point.angle_from end_point - -Returns an angle in degrees from the end_point to the start_point (if you want the value in radians, you can call .to_radians on the value returned): -```ruby -def tick args - rect_1 ||= { + # create another rectangle in state and position it + # at the far left center + args.state.box_2 ||= { x: 0, - y: 0, + y: 360 - 20, + w: 40, + h: 40, + r: 0, + g: 0, + b: 255 } - rect_2 ||= { - x: 100, - y: 100, - } + # take the directional input and use that to move the second rectangle around + # increase or decrease the x value based on if left or right is held + args.state.box_2.x += args.inputs.left_right * 5 + # increase or decrease the y value based on if up or down is held + args.state.box_2.y += args.inputs.up_down * 5 - angle = rect_1.angle_from rect_2 # returns 225 degrees - angle_radians = angle.to_radians - args.outputs.labels << { x: 30, y: 30.from_top, text: "#{angle}, #{angle_radians}" } + # change the colors of the rectangles based on whether they + # intersect or not + if args.state.box_1.intersect_rect? args.state.box_2 + args.state.box_1.r = 255 + args.state.box_1.g = 0 + args.state.box_1.b = 0 - angle = args.geometry.angle_from rect_1, rect_2 # returns 225 degrees - angle_radians = angle.to_radians - args.outputs.labels << { x: 30, y: 60.from_top, text: "#{angle}, #{angle_radians}" } + args.state.box_2.r = 255 + args.state.box_2.g = 0 + args.state.box_2.b = 0 + else + args.state.box_1.r = 0 + args.state.box_1.g = 0 + args.state.box_1.b = 255 + + args.state.box_2.r = 0 + args.state.box_2.g = 0 + args.state.box_2.b = 255 + end + + # render the rectangles as border primitives on the screen + args.outputs.borders << args.state.box_1 + args.outputs.borders << args.state.box_2 end ``` -## angle_to +## line_angle -**Invocation variants:** +Given a line, this function will return the angle of the line in degrees. -* args.geometry.angle_to start_point, end_point -* start_point.angle_to end_point -Returns an angle in degrees to the end_point from the start_point (if you want the value in radians, you can call .to_radians on the value returned): -```ruby -def tick args - rect_1 ||= { - x: 0, - y: 0, - } +## line_normal - rect_2 ||= { - x: 100, - y: 100, - } +The first parameter is a line (a Hash with `x1`, `y1`, `x2`, and `y2` keys or an Object that responds to `x1`, `y1`, `x2`, and `y2`). - angle = rect_1.angle_to rect_2 # returns 45 degrees - angle_radians = angle.to_radians - args.outputs.labels << { x: 30, y: 30.from_top, text: "#{angle}, #{angle_radians}" } +The second parameter is a Hash with `x` and `y` keys (or an Object that responds to `x` and `y`). - angle = args.geometry.angle_to rect_1, rect_2 # returns 45 degrees - angle_radians = angle.to_radians - args.outputs.labels << { x: 30, y: 60.from_top, text: "#{angle}, #{angle_radians}" } -end -``` +This function will return a Hash with `x` and `y` keys that represents the normal of the line relative to the point provided. -## distance +> **Note** Take a look at this sample app for a non-trivial example of how to use this function: `./samples/04_physics_and_collisions/11_bouncing_ball_with_gravity/` -Returns the distance between two points; + +## line_rise_run + +Given a line, this function returns a Hash with x and y keys representing a normalized representation of the rise and run of the line. ```ruby def tick args - rect_1 ||= { + # draw a line from the bottom left to the top right + line = { x: 0, y: 0, + x2: 1280, + y2: 720 } - rect_2 ||= { - x: 100, - y: 100, - } + # get rise and run of line + rise_run = args.geometry.line_rise_run line - distance = args.geometry.distance rect_1, rect_2 + # output the rise and run of line args.outputs.labels << { - x: 30, - y: 30.from_top, - text: "#{distance}" + x: 640, + y: 360, + text: "#{rise_run}", + alignment_enum: 1, + vertical_alignment_enum: 1, } - args.outputs.lines << { - x: rect_1.x, - y: rect_1.y, - x2: rect_2.x, - y2: rect_2.y - } + # render the line + args.outputs.lines << line end ``` +## line_vec2 + +Given a line, this function will return a Hash with `x` and `y` keys that represents the vector of the line. + +> **Note** Take a look at this sample app for a non-trivial example of how to use this function: ./samples/04_physics_and_collisions/11_bouncing_ball_with_gravity/ + + ## point_inside_circle? **Invocation variants:** @@ -399,40 +597,16 @@ def tick args end ``` -## center_inside_rect - -**Invocation variants:** - -* target_rect.center_inside_rect reference_rect -* args.geometry.center_inside_rect target_rect, reference_rect +## point_on_line? -Given a target rect and a reference rect, the target rect is centered inside the reference rect (a new rect is returned). +The first parameter is a point (a Hash with `x` and `y` keys, or an Object that responds to `x` and `y`). -```ruby -def tick args - rect_1 = { - x: 0, - y: 0, - w: 100, - h: 100 - } +The second parameter is a line (a Hash with `x1`, `y1`, `x2`, and `y2` keys, or an Object that responds to `x1`, `y1`, `x2`, and `y2`). - rect_2 = { - x: 640 - 100, - y: 360 - 100, - w: 200, - h: 200 - } +This function will return `true` if the point is on the line, and `false` if it is not. - centered_rect = args.geometry.center_inside_rect rect_1, rect_2 - # OR - # centered_rect = rect_1.center_inside_rect rect_2 +> **Note** Take a look at this sample app for a non-trivial example of how to use this function: `./samples/04_physics_and_collisions/11_bouncing_ball_with_gravity/` - args.outputs.solids << rect_1.merge(r: 255) - args.outputs.solids << rect_2.merge(b: 255) - args.outputs.solids << centered_rect.merge(g: 255) -end -``` ## ray_test @@ -479,36 +653,6 @@ def tick args end ``` -## line_rise_run - -Given a line, this function returns a Hash with x and y keys representing a normalized representation of the rise and run of the line. - -```ruby -def tick args - # draw a line from the bottom left to the top right - line = { - x: 0, - y: 0, - x2: 1280, - y2: 720 - } - - # get rise and run of line - rise_run = args.geometry.line_rise_run line - - # output the rise and run of line - args.outputs.labels << { - x: 640, - y: 360, - text: "#{rise_run}", - alignment_enum: 1, - vertical_alignment_enum: 1, - } - - # render the line - args.outputs.lines << line -end -``` ## rotate_point @@ -558,135 +702,79 @@ def tick args end ``` -## find_intersect_rect - -Given a rect and a collection of rects, find_intersect_rect returns the first rect that intersects with the the first parameter. - -`anchor_x`, and `anchor_y` is taken into consideration if the objects respond to these methods. - -If you find yourself doing this: - -`collision = args.state.terrain.find { |t| t.intersect_rect? args.state.player }` - -Consider using find_intersect_rect instead (it's more descriptive and faster): -`collision = args.geometry.find_intersect_rect args.state.player, args.state.terrain` +## scale_rect -## find_all_intersect_rect +Given a Rectangle this function returns a new rectangle with a scaled size. -Given a rect and a collection of rects, find_all_intersect_rect returns all rects that intersects with the the first parameter. +* `ratio`: the ratio by which to scale the rect. A ratio of 2 will double the dimensions of the rect while a ratio of 0.5 will halve its dimensions. +* `anchor_x` and `anchor_y` specify the point within the rect from which to resize it. Setting both to 0 will affect the width and height of the rect, leaving `x` and `y` unchanged. Setting both to 0.5 will scale all sides of the rect proportionally from the center. -`anchor_x`, and `anchor_y` is taken into consideration if the objects respond to these methods. +```ruby +def tick args + # a rect at the center of the screen + args.state.rect_1 ||= { x: 640 - 20, y: 360 - 20, w: 40, h: 40 } -If you find yourself doing this: + # render the rect + args.outputs.borders << args.state.rect_1 -`collisions = args.state.terrain.find_all { |t| t.intersect_rect? args.state.player }` + # the rect half the size with the x and y position unchanged + args.outputs.borders << args.state.rect_1.scale_rect(0.5) -Consider using find_all_intersect_rect instead (it's more descriptive and faster): + # the rect double the size, repositioned in the center given anchor optional arguments + args.outputs.borders << args.state.rect_1.scale_rect(2, 0.5, 0.5) +end +``` -`collisions = args.geometry.find_all_intersect_rect args.state.player, args.state.terrain` +## scale_rect_extended -## find_intersect_rect_quad_tree +The behavior is similar to scale_rect except that you can independently control the scale of each axis. The parameters are all named: -This is a faster collision algorithm for determining if a rectangle intersects any rectangle in an array. In order to use find_intersect_rect_quad_tree, you must first generate a quad tree data structure using create_quad_tree. Use this function if find_intersect_rect isn't fast enough. +* `percentage_x`: percentage to change the width (default value of 1.0) +* `percentage_y`: percentage to change the height (default value of 1.0) +* `anchor_x`: anchor repositioning of x (default value of 0.0) +* `anchor_y`: anchor repositioning of y (default value of 0.0) ```ruby def tick args - # create a player - args.state.player ||= { - x: 640 - 10, - y: 360 - 10, - w: 20, - h: 20 - } - - # allow control of player movement using arrow keys - args.state.player.x += args.inputs.left_right * 5 - args.state.player.y += args.inputs.up_down * 5 + baseline_rect = { x: 640 - 20, y: 360 - 20, w: 40, h: 40 } + args.state.rect_1 ||= baseline_rect + args.state.rect_2 ||= baseline_rect.scale_rect_extended(percentage_x: 2, + percentage_y: 0.5, + anchor_x: 0.5, + anchor_y: 1.0) + args.outputs.borders << args.state.rect_1 + args.outputs.borders << args.state.rect_2 +end +``` - # generate 40 random rectangles - args.state.boxes ||= 40.map do - { - x: 1180 * rand + 50, - y: 620 * rand + 50, - w: 100, - h: 100 - } - end - # generate a quad tree based off of rectangles. - # the quad tree should only be generated once for - # a given array of rectangles. if the rectangles - # change, then the quad tree must be regenerated - args.state.quad_tree ||= args.geometry.quad_tree_create args.state.boxes +## vec2_dot_product - # use quad tree and find_intersect_rect_quad_tree to determine collision with player - collision = args.geometry.find_intersect_rect_quad_tree args.state.player, - args.state.quad_tree +Given two Hashes with `x` and `y` keys (or Objects that respond to `x` and `y`), this function will return the dot product of the two vectors. - # if there is a collision render a red box - if collision - args.outputs.solids << collision.merge(r: 255) - end +> **Note** Take a look at this sample app for a non-trivial example of how to use this function: `./samples/04_physics_and_collisions/11_bouncing_ball_with_gravity/` - # render player as green - args.outputs.solids << args.state.player.merge(g: 255) - # render boxes as borders - args.outputs.borders << args.state.boxes -end -``` +## vec2_magnitude -## find_all_intersect_rect_quad_tree +Given a Hash with `x` and `y` keys (or an Object that responds to `x` and `y`), this function will return the magnitude of the vector. -This is a faster collision algorithm for determining if a rectangle intersects other rectangles in an array. In order to use find_all_intersect_rect_quad_tree, you must first generate a quad tree data structure using create_quad_tree. Use this function if find_all_intersect_rect isn't fast enough. +> **Note** Take a look at this sample app for a non-trivial example of how to use this function: `./samples/04_physics_and_collisions/11_bouncing_ball_with_gravity/` -```ruby -def tick args - # create a player - args.state.player ||= { - x: 640 - 10, - y: 360 - 10, - w: 20, - h: 20 - } +## vec2_normal - # allow control of player movement using arrow keys - args.state.player.x += args.inputs.left_right * 5 - args.state.player.y += args.inputs.up_down * 5 +Given a Hash with `x` and `y` keys (or an Object that responds to `x` and `y`), this function will return a Hash with `x` and `y` keys that represents the normal of the vector. - # generate 40 random rectangles - args.state.boxes ||= 40.map do - { - x: 1180 * rand + 50, - y: 620 * rand + 50, - w: 100, - h: 100 - } - end +> **Note** Take a look at this sample app for a non-trivial example of how to use this function: `./samples/04_physics_and_collisions/11_bouncing_ball_with_gravity/` - # generate a quad tree based off of rectangles. - # the quad tree should only be generated once for - # a given array of rectangles. if the rectangles - # change, then the quad tree must be regenerated - args.state.quad_tree ||= args.geometry.quad_tree_create args.state.boxes - # use quad tree and find_intersect_rect_quad_tree to determine collision with player - collisions = args.geometry.find_all_intersect_rect_quad_tree args.state.player, - args.state.quad_tree +## vec2_normalize - # if there is a collision render a red box - args.outputs.solids << collisions.map { |c| c.merge(r: 255) } +Given a Hash with `x` and `y` keys (or an Object that responds to `x` and `y`), this function will return a Hash with `x` and `y` keys that represents the vector normalized. - # render player as green - args.outputs.solids << args.state.player.merge(g: 255) +> **Note** Take a look at this sample app for a non-trivial example of how to use this function: `./samples/04_physics_and_collisions/11_bouncing_ball_with_gravity/` - # render boxes as borders - args.outputs.borders << args.state.boxes -end -``` -## create_quad_tree -Generates a quad tree from an array of rectangles. See `find_intersect_rect_quad_tree` for usage.