Compare commits
10 Commits
test-sfml-
...
master
Author | SHA1 | Date | |
---|---|---|---|
caf4be7e97 | |||
84aed9ff1e | |||
b0f0940949 | |||
78f7a803e0 | |||
3ae8401c5c | |||
ccbd7e5d53 | |||
93b86a3a47 | |||
10b903a7fc | |||
849b9af9f1 | |||
01e8efd5c6 |
3
Makefile
3
Makefile
|
@ -25,7 +25,8 @@ deps_update:
|
||||||
deps_opt:
|
deps_opt:
|
||||||
@[ -d lib/ ] || make deps
|
@[ -d lib/ ] || make deps
|
||||||
doc:
|
doc:
|
||||||
crystal docs ./src/zero_epsilon.cr ./src/tests/physics_sandbox.cr ./lib/crsfml/src/crsfml.cr ./lib/imgui/src/imgui.cr
|
crystal docs ./src/zero_epsilon.cr ./src/tests/physics_sandbox.cr ./lib/crsfml/src/crsfml.cr ./lib/imgui/src/imgui.cr ./lib/imgui-sfml/src/imgui-sfml.cr
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm $(NAME)
|
rm $(NAME)
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,15 @@ module Gravity
|
||||||
EARTH2 = Gravity::Body(2).new(mass: 5972200000000000000000000.0, position: Vector(Float64, 2).zero)
|
EARTH2 = Gravity::Body(2).new(mass: 5972200000000000000000000.0, position: Vector(Float64, 2).zero)
|
||||||
EARTH3 = Gravity::Body(3).new(mass: 5972200000000000000000000.0, position: Vector(Float64, 3).zero)
|
EARTH3 = Gravity::Body(3).new(mass: 5972200000000000000000000.0, position: Vector(Float64, 3).zero)
|
||||||
|
|
||||||
getter :mass, :position, :g
|
getter :mass, :position, :g, :name
|
||||||
|
|
||||||
def initialize(@mass : Float64, @position : Vector(Float64, N) = Vector(Float64, N).zero, @g : Float64 = G)
|
@@name_idx = 0
|
||||||
|
def self.next_name
|
||||||
|
@@name_idx += 1
|
||||||
|
"default~#{@@name_idx}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(@mass : Float64, @position : Vector(Float64, N) = Vector(Float64, N).zero, @g : Float64 = G, @name : String = Body(0).next_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def acceleration(position : Vector(Float64, N)) : Vector(Float64, N)
|
def acceleration(position : Vector(Float64, N)) : Vector(Float64, N)
|
||||||
|
|
|
@ -2,10 +2,18 @@ require "crsfml"
|
||||||
|
|
||||||
require "./gravity"
|
require "./gravity"
|
||||||
|
|
||||||
# TODO move this to engine
|
|
||||||
class Projectable(N)
|
class Projectable(N)
|
||||||
property :gravity_body, :color, :size, :outline_color, :outline_size
|
property :gravity_body, :color, :size, :outline_color, :outline_size
|
||||||
|
|
||||||
|
@@hook_new : Proc(Projectable(2), Nil) = ->(obj : Projectable(2)) { nil }
|
||||||
|
def self.set_hook_new(hook_proc : Proc(Projectable(2), Nil))
|
||||||
|
@@hook_new = hook_proc
|
||||||
|
end
|
||||||
|
|
||||||
|
def trigger_hook_new
|
||||||
|
@@hook_new.call(self)
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(
|
def initialize(
|
||||||
@gravity_body : Gravity::Body(N),
|
@gravity_body : Gravity::Body(N),
|
||||||
@color : Tuple(Int32, Int32, Int32),
|
@color : Tuple(Int32, Int32, Int32),
|
||||||
|
@ -13,6 +21,11 @@ class Projectable(N)
|
||||||
@outline_color : Tuple(Int32, Int32, Int32) = {0, 0, 0},
|
@outline_color : Tuple(Int32, Int32, Int32) = {0, 0, 0},
|
||||||
@outline_size : Int32 = 0
|
@outline_size : Int32 = 0
|
||||||
)
|
)
|
||||||
|
trigger_hook_new
|
||||||
|
end
|
||||||
|
|
||||||
|
def name
|
||||||
|
@gravity_body.name
|
||||||
end
|
end
|
||||||
|
|
||||||
def position
|
def position
|
||||||
|
|
|
@ -24,9 +24,11 @@ class Game
|
||||||
@screen_center_position : Vector(Float64, 2)
|
@screen_center_position : Vector(Float64, 2)
|
||||||
@center_position : Vector(Float64, 2)
|
@center_position : Vector(Float64, 2)
|
||||||
@joystick_moved : Vector(Float64, 2)
|
@joystick_moved : Vector(Float64, 2)
|
||||||
|
@selected_projectable : Projectable(2)
|
||||||
|
@click_coordinates : Vector(Float64, 2)?
|
||||||
|
|
||||||
SECOND_IN_NANO = 1_000_000_000
|
SECOND_IN_NANO = 1_000_000_000
|
||||||
DEFAULT_ZOOM = 5/16
|
DEFAULT_ZOOM = 3/16
|
||||||
|
|
||||||
def accuracy_frequency_nano_rate
|
def accuracy_frequency_nano_rate
|
||||||
((SECOND_IN_NANO * @timescale) // @framerate).to_u64
|
((SECOND_IN_NANO * @timescale) // @framerate).to_u64
|
||||||
|
@ -85,10 +87,17 @@ class Game
|
||||||
# # What's the current position of the Y axis on joystick #0?
|
# # What's the current position of the Y axis on joystick #0?
|
||||||
# position = SF::Joystick.get_axis_position(0, SF::Joystick::Y)
|
# position = SF::Joystick.get_axis_position(0, SF::Joystick::Y)
|
||||||
|
|
||||||
|
@click_coordinates = nil
|
||||||
|
|
||||||
|
@projectables = Array(Projectable(2)).new
|
||||||
|
Projectable(2).set_hook_new ->(projectable : Projectable(2)) {
|
||||||
|
@projectables << projectable
|
||||||
|
}
|
||||||
|
|
||||||
sun_offset = Vector[3*10.0**11, 3*10.0**11]
|
sun_offset = Vector[3*10.0**11, 3*10.0**11]
|
||||||
@bodies = {
|
@bodies = {
|
||||||
vessel: Gravity::MovingBody(2).new(mass: 1.0, g: 0.1, position: Vector[10.0, 10.0]),
|
vessel: Gravity::MovingBody(2).new(name: "vessel", mass: 1.0, g: 0.1, position: Vector[10.0, 10.0]),
|
||||||
star: Gravity::MovingBody(2).new(mass: 300000.0, g: 0.1, position: Vector[1000.0, 1000.0], speed: Vector[0.0, 0.0]),
|
star: Gravity::MovingBody(2).new(name: "star", mass: 300000.0, g: 0.1, position: Vector[1000.0, 1000.0], speed: Vector[0.0, 0.0]),
|
||||||
pla1: Gravity::MovingBody(2).new(mass: 15000.0, g: 0.1, position: Vector[500.0, 500.0], speed: Vector[12.0, 0.0]),
|
pla1: Gravity::MovingBody(2).new(mass: 15000.0, g: 0.1, position: Vector[500.0, 500.0], speed: Vector[12.0, 0.0]),
|
||||||
pla2: Gravity::MovingBody(2).new(mass: 18000.0, g: 0.1, position: Vector[1000.0, 1500.0], speed: Vector[-6.0, -6.0]),
|
pla2: Gravity::MovingBody(2).new(mass: 18000.0, g: 0.1, position: Vector[1000.0, 1500.0], speed: Vector[-6.0, -6.0]),
|
||||||
pla3: Gravity::MovingBody(2).new(mass: 12000.0, g: 0.1, position: Vector[1500.0, 1500.0], speed: Vector[-6.0, 0.0]),
|
pla3: Gravity::MovingBody(2).new(mass: 12000.0, g: 0.1, position: Vector[1500.0, 1500.0], speed: Vector[-6.0, 0.0]),
|
||||||
|
@ -124,9 +133,10 @@ class Game
|
||||||
color: {50, 150, 50},
|
color: {50, 150, 50},
|
||||||
size: 10,
|
size: 10,
|
||||||
)
|
)
|
||||||
@projectables = {
|
# @projectables = {
|
||||||
@star, @pla1, @pla2, @pla3, @star, @vessel_p,
|
# @star, @pla1, @pla2, @pla3, @star, @vessel_p,
|
||||||
}
|
# }
|
||||||
|
@selected_projectable = @vessel_p
|
||||||
@g = Gravity::Field(2).new(@gravited)
|
@g = Gravity::Field(2).new(@gravited)
|
||||||
@vessel = Vessel(2).new(name: "Starbird", gravity_body: @bodies[:vessel], gravity_field: @g)
|
@vessel = Vessel(2).new(name: "Starbird", gravity_body: @bodies[:vessel], gravity_field: @g)
|
||||||
@vessel.navigation.zoom_ratio = DEFAULT_ZOOM
|
@vessel.navigation.zoom_ratio = DEFAULT_ZOOM
|
||||||
|
@ -134,6 +144,8 @@ class Game
|
||||||
@ui_events_handler = UI::EventHandler.new
|
@ui_events_handler = UI::EventHandler.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
MAX_DISTANCE_TO_SELECT_PROJECTABLE = 15
|
||||||
|
|
||||||
def handle_events
|
def handle_events
|
||||||
joystick_moved_modified = false
|
joystick_moved_modified = false
|
||||||
|
|
||||||
|
@ -144,11 +156,47 @@ class Game
|
||||||
when SF::Event::Closed
|
when SF::Event::Closed
|
||||||
@window.close
|
@window.close
|
||||||
exit
|
exit
|
||||||
|
when SF::Event::Resized
|
||||||
|
@width = event.width.to_i32
|
||||||
|
@height = event.height.to_i32
|
||||||
|
@view.viewport = default_viewport
|
||||||
|
@center_position = Vector[0.0, 0.0]
|
||||||
|
@view.center = {@center_position[0], @center_position[1]}
|
||||||
|
@window.view = @view
|
||||||
when SF::Event::KeyPressed
|
when SF::Event::KeyPressed
|
||||||
Log.debug "KeyPressed #{event}"
|
Log.debug "KeyPressed #{event}"
|
||||||
when SF::Event::MouseMoved
|
when SF::Event::MouseMoved
|
||||||
|
when SF::Event::MouseButtonReleased
|
||||||
|
clicked_on_imgui_item = ImGui.is_any_item_hovered || ImGui.is_any_item_active
|
||||||
|
if !clicked_on_imgui_item
|
||||||
|
# don't match if click on the buttons of ImGui
|
||||||
|
# click_coord = @window.map_pixel_to_coords({event.x, event.y}, @view)
|
||||||
|
# m = (proj.position - Vector[click_coord.x, click_coord.y]).magnitude
|
||||||
|
# mmhhhh it does not work as expected, bugged
|
||||||
|
event_position = Vector[event.x, event.y]
|
||||||
|
nearest_proj = @projectables.map do |projectable|
|
||||||
|
pixel = @window.map_coords_to_pixel({projectable.position[0], projectable.position[1]}, @view)
|
||||||
|
{
|
||||||
|
projectable: projectable,
|
||||||
|
distance: (Vector[pixel.x, pixel.y] - event_position).magnitude,
|
||||||
|
}
|
||||||
|
end.sort_by!{ |tuple| tuple[:distance] }.first
|
||||||
|
if nearest_proj[:distance] <= MAX_DISTANCE_TO_SELECT_PROJECTABLE
|
||||||
|
@selected_projectable.outline_color = {0, 0, 0}
|
||||||
|
@selected_projectable.outline_size = 0
|
||||||
|
@selected_projectable = nearest_proj[:projectable]
|
||||||
|
@selected_projectable.outline_color = {255, 0, 0}
|
||||||
|
@selected_projectable.outline_size = 5
|
||||||
|
pp "Select a new body #{@selected_projectable.name}"
|
||||||
|
@click_coordinates = nil
|
||||||
|
else
|
||||||
|
@selected_projectable.outline_color = {0, 0, 0}
|
||||||
|
@selected_projectable.outline_size = 0
|
||||||
|
@click_coordinates = Vector[event.x.to_f64, event.y.to_f64]
|
||||||
|
end
|
||||||
|
end
|
||||||
when SF::Event::MouseButtonEvent
|
when SF::Event::MouseButtonEvent
|
||||||
Log.debug "MouseButtonEvent #{event}"
|
pp "MouseButtonEvent #{event}"
|
||||||
when SF::Event::JoystickButtonPressed
|
when SF::Event::JoystickButtonPressed
|
||||||
@joystick_moved.zero! # reset 0
|
@joystick_moved.zero! # reset 0
|
||||||
joystick_moved_modified = :vector # force exact set
|
joystick_moved_modified = :vector # force exact set
|
||||||
|
@ -220,6 +268,7 @@ class Game
|
||||||
@graviting.each { |graviting| accelerate_by_tick(graviting) }
|
@graviting.each { |graviting| accelerate_by_tick(graviting) }
|
||||||
|
|
||||||
draw_bridge(gravity_field)
|
draw_bridge(gravity_field)
|
||||||
|
draw_bodies
|
||||||
|
|
||||||
object_position =
|
object_position =
|
||||||
if @vessel.navigation.zoom_select == 0
|
if @vessel.navigation.zoom_select == 0
|
||||||
|
@ -285,4 +334,4 @@ class Game
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Game.new(framerate: 120, width: 1200, height: 1000).execute_loop
|
Game.new(framerate: 120, width: 800, height: 600).execute_loop
|
||||||
|
|
|
@ -36,7 +36,8 @@ module PhysicsSandboxDraw
|
||||||
label: "Set timescale###set_timescale",
|
label: "Set timescale###set_timescale",
|
||||||
data: @timescale,
|
data: @timescale,
|
||||||
min: 0.1,
|
min: 0.1,
|
||||||
max: 3600 * 24 * 7,
|
max: 60,
|
||||||
|
# max: 3600 * 24 * 7,
|
||||||
flags: (
|
flags: (
|
||||||
ImGui::ImGuiSliderFlags::Logarithmic
|
ImGui::ImGuiSliderFlags::Logarithmic
|
||||||
),
|
),
|
||||||
|
@ -295,15 +296,23 @@ module PhysicsSandboxDraw
|
||||||
|
|
||||||
def draw_navigation(gravity_field)
|
def draw_navigation(gravity_field)
|
||||||
# ImGui.text "Total Accele is : [#{acceleration[0].round(4)}, #{acceleration[1].round(4)}] m/s²"
|
# ImGui.text "Total Accele is : [#{acceleration[0].round(4)}, #{acceleration[1].round(4)}] m/s²"
|
||||||
ImGui.text "Pulse Accele is : [#{@vessel.gravity_body.acceleration[0].round(4)}, #{@vessel.gravity_body.acceleration[1].round(4)}] m/s²"
|
draw_table(title: "Applied forces", headers: {"Name", "X", "Y", "unit"}) do
|
||||||
ImGui.text "GraviticBody is : [#{gravity_field[0].round(4)}, #{gravity_field[1].round(4)}] m/s²"
|
draw_table_line "Pulse Accele", "#{@vessel.gravity_body.acceleration[0].round(4)}", "#{@vessel.gravity_body.acceleration[1].round(4)}", "m/s²"
|
||||||
ImGui.text "Current speed is : #{@vessel.gravity_body.speed.magnitude.round(4)} m/s"
|
draw_table_line "Gravitic Field", "#{gravity_field[0].round(4)}", "#{gravity_field[1].round(4)}", "m/s²"
|
||||||
|
end
|
||||||
|
ImGui.text "Current speed #{@vessel.gravity_body.speed.magnitude.round(4)} m/s"
|
||||||
|
ImGui.text ""
|
||||||
|
|
||||||
|
relative_speed = @vessel.gravity_body.speed - @selected_projectable.speed
|
||||||
draw_table(title: "Actual vectors", headers: {"Name", "X", "Y", "unit"}) do
|
draw_table(title: "Actual vectors", headers: {"Name", "X", "Y", "unit"}) do
|
||||||
draw_table_line "Position", @vessel.gravity_body.position[0].round(3).to_s, @vessel.gravity_body.position[1].round(3).to_s, "m"
|
draw_table_line "Position", @vessel.gravity_body.position[0].round(3).to_s, @vessel.gravity_body.position[1].round(3).to_s, "m"
|
||||||
draw_table_line "Speed", @vessel.gravity_body.speed[0].round(3).to_s, @vessel.gravity_body.speed[1].round(3).to_s, "m/s"
|
draw_table_line "Speed", @vessel.gravity_body.speed[0].round(3).to_s, @vessel.gravity_body.speed[1].round(3).to_s, "m/s"
|
||||||
draw_table_line "Acceleration", @vessel.gravity_body.acceleration[0].round(3).to_s, @vessel.gravity_body.acceleration[1].round(3).to_s, "m/s²"
|
draw_table_line "Acceleration", @vessel.gravity_body.acceleration[0].round(3).to_s, @vessel.gravity_body.acceleration[1].round(3).to_s, "m/s²"
|
||||||
|
draw_table_line "Selected body", "#{@selected_projectable.position[0].round(4)}", "#{@selected_projectable.position[1].round(4)}", "m"
|
||||||
|
draw_table_line "", @selected_projectable.name, "", ""
|
||||||
|
draw_table_line "Relative speed", "#{relative_speed[0].round(4)}", "#{relative_speed[1].round(4)}", "m/s"
|
||||||
end
|
end
|
||||||
|
ImGui.text ""
|
||||||
|
|
||||||
ImGui.text "Zoom on"
|
ImGui.text "Zoom on"
|
||||||
ImGui.radio_button("vessel##navigation_zoom", pointerof(@vessel.navigation.zoom_select), 0)
|
ImGui.radio_button("vessel##navigation_zoom", pointerof(@vessel.navigation.zoom_select), 0)
|
||||||
|
@ -336,7 +345,6 @@ module PhysicsSandboxDraw
|
||||||
end
|
end
|
||||||
|
|
||||||
def draw_bridge(gravity_field)
|
def draw_bridge(gravity_field)
|
||||||
|
|
||||||
if ImGui.begin("Bridge")
|
if ImGui.begin("Bridge")
|
||||||
if ImGui.tree_node_ex("Captain", ImGui::ImGuiTreeNodeFlags.new(ImGui::ImGuiTreeNodeFlags::DefaultOpen))
|
if ImGui.tree_node_ex("Captain", ImGui::ImGuiTreeNodeFlags.new(ImGui::ImGuiTreeNodeFlags::DefaultOpen))
|
||||||
draw_captain
|
draw_captain
|
||||||
|
@ -357,4 +365,23 @@ module PhysicsSandboxDraw
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def draw_bodies
|
||||||
|
if ImGui.begin("Bodies")
|
||||||
|
if ImGui.tree_node_ex("Bodies", ImGui::ImGuiTreeNodeFlags.new(ImGui::ImGuiTreeNodeFlags::DefaultOpen))
|
||||||
|
|
||||||
|
draw_table(title: "Bodies", headers: {"Name", "X", "Y"}) do
|
||||||
|
@projectables.each do |projectable|
|
||||||
|
draw_table_line projectable.name, projectable.position[0].to_s, projectable.position[1].to_s
|
||||||
|
end
|
||||||
|
if !(click_coordinates = @click_coordinates).nil?
|
||||||
|
draw_table_line "[click]", click_coordinates[0].to_s, click_coordinates[1].to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ImGui.tree_pop
|
||||||
|
end
|
||||||
|
ImGui.end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user