require "spec" require "../../src/engine/physics" describe Physics do it "test basic tick usage" do time = Time.utc one_second = Time::Span.new(seconds: 1) t1 = Physics::Tick.new(n: 0, time: time, last: nil) t2 = Physics::Tick.new(n: 1, time: time + one_second, last: t1) t2.timelaps.should eq(one_second) end it "test basic timer" do timer = Physics::Tick::Timer.new start_time = timer.tick.time timer.tick.n.should eq(0) 12.times { timer.timeskip!(seconds: 1) } timer.tick.n.should eq(12) timer.tick.time.should eq(start_time + Time::Span.new(seconds: 12)) end it "accelerate an object" do a_ball_movement = Vector[0.0, 0.0, 0.0] a_engine_accelerate = Vector[20.0, 0.0, 0.0] timer = Physics::Tick::Timer.new timer.timeskip!(seconds: 1) Physics.accelerate_by_one_tick!(timer.tick, a_ball_movement, a_engine_accelerate) a_ball_movement[0].should eq(20.0) a_ball_movement[1].should eq(0.0) timer.timeskip!(milliseconds: 500) Physics.accelerate_by_one_tick!(timer.tick, a_ball_movement, a_engine_accelerate) a_ball_movement[0].should eq(30.0) a_ball_movement[1].should eq(0.0) timer.timeskip!(milliseconds: 500) Physics.accelerate_by_one_tick!(timer.tick, a_ball_movement, a_engine_accelerate) a_ball_movement[0].should eq(40.0) a_ball_movement[1].should eq(0.0) a_engine_stopped = Vector[0.0, 0.0, 0.0] timer.timeskip!(milliseconds: 500) Physics.accelerate_by_one_tick!(timer.tick, a_ball_movement, a_engine_stopped) a_ball_movement[0].should eq(40.0) a_ball_movement[1].should eq(0.0) a_retro_pulse = Vector[0.0, 0.1, 0.0] timer.timeskip!(milliseconds: 500) Physics.accelerate_by_one_tick!(timer.tick, a_ball_movement, a_retro_pulse) a_ball_movement[0].should eq(40.0) a_ball_movement[1].should eq(0.05) end it "move and accelerate an object" do a_ball_position = Vector[0.0, 0.0, 0.0] a_ball_movement = Vector[0.0, 0.0, 0.0] a_engine_accelerate = Vector[20.0, 0.0, 0.0] timer = Physics::Tick::Timer.new timer.timeskip!(seconds: 1) Physics.move_by_one_tick!(timer.tick, a_ball_position, a_ball_movement, a_engine_accelerate) a_ball_position[0].should eq(10.0) a_ball_position[1].should eq(0.0) a_ball_movement[0].should eq(20.0) a_ball_movement[1].should eq(0.0) timer.timeskip!(seconds: 1) Physics.move_by_one_tick!(timer.tick, a_ball_position, a_ball_movement, a_engine_accelerate) a_ball_position[0].should eq(40.0) a_ball_position[1].should eq(0.0) a_ball_movement[0].should eq(40.0) a_ball_movement[1].should eq(0.0) # cut a second in 2 computations gives the same result as one second timer.timeskip!(milliseconds: 500) Physics.move_by_one_tick!(timer.tick, a_ball_position, a_ball_movement, a_engine_accelerate) a_ball_position[0].should eq(62.5) a_ball_position[1].should eq(0.0) a_ball_movement[0].should eq(50.0) a_ball_movement[1].should eq(0.0) timer.timeskip!(milliseconds: 500) Physics.move_by_one_tick!(timer.tick, a_ball_position, a_ball_movement, a_engine_accelerate) a_ball_position[0].should eq(90.0) a_ball_position[1].should eq(0.0) a_ball_movement[0].should eq(60.0) a_ball_movement[1].should eq(0.0) a_gravity_generator = Vector[0.0, 0.0, 0.0] a_retro_pulse = Vector[0.0, 0.1, 0.0] star_gravity = Vector[-0.01, 0.02, 0.01] total_forces = a_gravity_generator + a_retro_pulse + star_gravity timer.timeskip!(seconds: 1) Physics.move_by_one_tick!(timer.tick, a_ball_position, a_ball_movement, total_forces) a_ball_position[0].round(3).should eq(149.995) a_ball_position[1].round(3).should eq(0.06) a_ball_position[2].round(3).should eq(0.005) a_ball_movement[0].round(3).should eq(59.99) a_ball_movement[1].round(3).should eq(0.12) a_ball_movement[2].round(3).should eq(0.01) end end # v0 = 40 m/s # a = 20 m/s² # t1 = 0.5 s # v1 = v0 + a * t1 = 40 + 20 * 0.6 = 50 m/s (m/s + m/s^2*s = m/s) # [v] = (v0 + v1) / 2 = (40 + 50) / 2 = 45 (m/s + m/s) # d = [v] * (t1 - t0) = 45 * 0.5 = 22.5 (m/s * s)