From 3eda193d9b6fa7d12d4602fe08efe2ce5b5ef3e8 Mon Sep 17 00:00:00 2001 From: dcrawl Date: Sat, 28 Oct 2023 22:12:53 -0300 Subject: [PATCH] Update numeric.md --- docs/API/ruby/numeric.md | 323 +++++++++++++++++++++++++++------------ 1 file changed, 222 insertions(+), 101 deletions(-) diff --git a/docs/API/ruby/numeric.md b/docs/API/ruby/numeric.md index 55a018c..44dbb47 100644 --- a/docs/API/ruby/numeric.md +++ b/docs/API/ruby/numeric.md @@ -1,108 +1,229 @@ # Numeric + | | | | | --- | --- | --- | | Ancestor | Object | -| Modules | [NumericDeprecated, ValueType, Comparable, Kernel] | +| Modules | NumericDeprecated, ValueType, Comparable, Kernel | +The Numeric class has been extend to provide methods that will help in common game development tasks. -## Instance Methods +## frame_index(sprite_frames, frames_to_hold, looping) -| Method | Parameters | Description | -| --- | --- | --- | -| +@ | | | -| -@ | | | -| __raise_arithmetic_exception__ | | | -| abs | | | -| add | | | -| cap | | | -| cap_min_max | | | -| clamp | | | -| clamp_wrap | | | -| combinations | | | -| each | | | -| each_with_index | | | -| ease | | | -| ease_extended | | | -| ease_spline | | | -| ease_spline_extended | | | -| elapsed? | | | -| elapsed_time | | | -| elapsed_time_percent | | | -| fdiv | | | -| finite? | | | -| five | | | -| fmult | | | -| frame_index | | | -| from_bottom | | | -| from_left | | | -| from_right | | | -| from_top | | | -| global_ease | | | -| global_ease_spline | | | -| greater | | | -| half | | | -| idiv | | | -| imult | | | -| infinite? | | | -| lerp | | | -| lesser | | | -| map | | | -| map_with_index | | | -| map_with_ys | | | -| mid? | | | -| minus | | | -| mod | | | -| mod_zero? | | | -| mult | | | -| multiply | | | -| negative? | | | -| new? | | | -| nonzero? | | | -| numbers | | | -| one | | | -| percentage_of | | | -| plus | | | -| positive? | | | -| quarter | | | -| rand_ratio | | | -| rand_sign | | | -| randomize | | | -| remainder_of_divide | | | -| remap | | | -| seconds | | | -| serialize | | | -| shift_down | | | -| shift_left | | | -| shift_right | | | -| shift_up | | | -| subtract | | | -| ten | | | -| third | | | -| times_with_index | | | -| to_byte | | | -| to_degrees | | | -| to_layout_col | | | -| to_layout_col_from_right | | | -| to_layout_h | | | -| to_layout_row | | | -| to_layout_row_from_bottom | | | -| to_layout_w | | | -| to_radians | | | -| to_square | | | -| to_vector | | | -| to_vector_d | | | -| to_vector_r | | | -| towards | | | -| two | | | -| vector | | | -| vector_x | | | -| vector_x_d | | | -| vector_x_r | | | -| vector_y | | | -| vector_y_d | | | -| vector_y_r | | | -| x_vector | | | -| y_vector | | | -| zero | | | -| zero? | | | -| zmod? | | | +This function is helpful for determining the index of frame-by-frame sprite animation. The numeric value `self` represents the moment the animation started. + +`frame_index` takes three additional parameters: + +* How many sprite frames exist in the animation +* How many ticks to display a single frame of animation +* Whether the animation should repeat + +`frame_index` will return `nil` if the time for the animation is out of bounds of the parameter specification. + +**Example using variables:** + +```ruby +def tick args + start_looping_at = 0 + number_of_sprites = 6 + number_of_frames_to_show_each_sprite = 4 + does_sprite_loop = true + + sprite_index = + start_looping_at.frame_index number_of_sprites, + number_of_frames_to_show_each_sprite, + does_sprite_loop + + sprite_index ||= 0 + + args.outputs.sprites << [ + 640 - 50, + 360 - 50, + 100, + 100, + "sprites/dragon-#{sprite_index}.png" + ] +end +``` + +Example using named parameters. The named parameters version allows you to also specify a `repeat_index` which is useful if your animation has starting frames that shouldn't be considered when looped: + +```ruby +def tick args + start_looping_at = 0 + + sprite_index = + start_looping_at.frame_index count: 6, + hold_for: 4, + repeat: true, + repeat_index: 0, + tick_count_override: args.state.tick_count + + sprite_index ||= 0 + + args.outputs.sprites << [ + 640 - 50, + 360 - 50, + 100, + 100, + "sprites/dragon-#{sprite_index}.png" + ] +end +``` + +The named parameter variant of `frame_index` is also available on Numeric: + +```ruby +def tick args + sprite_index = + Numeric.frame_index start_at: 0, + count: 6, + hold_for: 4, + repeat: true, + repeat_index: 0, + tick_count_override: args.state.tick_count + + sprite_index ||= 0 + + args.outputs.sprites << [ + 640 - 50, + 360 - 50, + 100, + 100, + "sprites/dragon-#{sprite_index}.png" + ] +end +``` + +## elapsed_time(\[tick_number\]) + +For a given number, the elapsed frames since that number is returned. `Kernel.tick_count` is used to determine how many frames have elapsed. An optional numeric argument can be passed in which will be used instead of `Kernel.tick_count`. + +Here is an example of how elapsed_time can be used. + +```ruby +def tick args + args.state.last_click_at ||= 0 + + # record when a mouse click occurs + if args.inputs.mouse.click + args.state.last_click_at = args.state.tick_count + end + + # Use Numeric#elapsed_time to determine how long it's been + if args.state.last_click_at.elapsed_time > 120 + args.outputs.labels << [10, 710, "It has been over 2 seconds since the mouse was clicked."] + end +end +``` + +And here is an example where the override parameter is passed in: + +```ruby +def tick args + args.state.last_click_at ||= 0 + + # create a state variable that tracks time at half the speed of args.state.tick_count + args.state.simulation_tick = args.state.tick_count.idiv 2 + + # record when a mouse click occurs + if args.inputs.mouse.click + args.state.last_click_at = args.state.simulation_tick + end + + # Use Numeric#elapsed_time to determine how long it's been + if (args.state.last_click_at.elapsed_time args.state.simulation_tick) > 120 + args.outputs.labels << [10, 710, "It has been over 4 seconds since the mouse was clicked."] + end +end +``` + +elapsed?(\[offset_tick\]) + +Returns true if `Numeric#elapsed_time` is greater than the number. An optional parameter can be passed into elapsed? which is added to the number before evaluating whether elapsed? is true. + +Example usage (no optional parameter): + +```ruby +def tick args + args.state.box_queue ||= [] + + if args.state.box_queue.empty? + args.state.box_queue << { name: :red, + destroy_at: args.state.tick_count + 60 } + args.state.box_queue << { name: :green, + destroy_at: args.state.tick_count + 60 } + args.state.box_queue << { name: :blue, + destroy_at: args.state.tick_count + 120 } + end + + boxes_to_destroy = args.state + .box_queue + .find_all { |b| b[:destroy_at].elapsed? } + + if !boxes_to_destroy.empty? + puts "boxes to destroy count: #{boxes_to_destroy.length}" + end + + boxes_to_destroy.each { |b| puts "box #{b} was elapsed? on #{args.state.tick_count}." } + + args.state.box_queue -= boxes_to_destroy +end +``` + +Example usage (with optional parameter): + +```ruby +def tick args + args.state.box_queue ||= [] + + if args.state.box_queue.empty? + args.state.box_queue << { name: :red, + create_at: args.state.tick_count + 120, + lifespan: 60 } + args.state.box_queue << { name: :green, + create_at: args.state.tick_count + 120, + lifespan: 60 } + args.state.box_queue << { name: :blue, + create_at: args.state.tick_count + 120, + lifespan: 120 } + end + + # lifespan is passed in as a parameter to ~elapsed?~ + boxes_to_destroy = args.state + .box_queue + .find_all { |b| b[:create_at].elapsed? b[:lifespan] } + + if !boxes_to_destroy.empty? + puts "boxes to destroy count: #{boxes_to_destroy.length}" + end + + boxes_to_destroy.each { |b| puts "box #{b} was elapsed? on #{args.state.tick_count}." } + + args.state.box_queue -= boxes_to_destroy +end +``` + +## new? + +Returns true if `Numeric#elapsed_time == 0`. Essentially communicating that number is equal to the current frame. + +Example usage: + +```ruby +def tick args + args.state.box_queue ||= [] + + if args.state.box_queue.empty? + args.state.box_queue << { name: :red, + create_at: args.state.tick_count + 60 } + end + + boxes_to_spawn_this_frame = args.state + .box_queue + .find_all { |b| b[:create_at].new? } + + boxes_to_spawn_this_frame.each { |b| puts "box #{b} was new? on #{args.state.tick_count}." } + + args.state.box_queue -= boxes_to_spawn_this_frame +end +```