physicist 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +6 -0
  3. data/bin/physicist +4 -1
  4. data/lib/physicist/body.rb +222 -0
  5. data/lib/physicist/laboratory/app.rb +104 -0
  6. data/lib/physicist/laboratory/commands/create_scientist.rb +7 -0
  7. data/lib/physicist/laboratory/commands/jump_scientist.rb +7 -0
  8. data/lib/physicist/laboratory/commands/move_scientist.rb +7 -0
  9. data/lib/physicist/laboratory/events/scientist_created_event.rb +7 -0
  10. data/lib/physicist/laboratory/events/scientist_updated_event.rb +7 -0
  11. data/lib/physicist/laboratory/events/space_created_event.rb +7 -0
  12. data/lib/physicist/laboratory/handlers/create_scientist_handler.rb +34 -0
  13. data/lib/physicist/laboratory/handlers/jump_scientist_handler.rb +10 -0
  14. data/lib/physicist/laboratory/handlers/move_scientist_handler.rb +10 -0
  15. data/lib/physicist/laboratory/listeners/scientist_created_event_listener.rb +15 -0
  16. data/lib/physicist/laboratory/listeners/scientist_updated_event_listener.rb +15 -0
  17. data/lib/physicist/laboratory/listeners/space_created_event_listener.rb +9 -0
  18. data/lib/physicist/laboratory/models/scientist.rb +84 -0
  19. data/lib/physicist/laboratory/models/space.rb +14 -0
  20. data/lib/physicist/laboratory/screen.rb +52 -0
  21. data/lib/physicist/laboratory/view.rb +27 -0
  22. data/lib/physicist/laboratory/views/scientist_view.rb +57 -0
  23. data/lib/physicist/laboratory/views/workspace_view.rb +18 -0
  24. data/lib/physicist/simple_body.rb +26 -0
  25. data/lib/physicist/version.rb +1 -1
  26. data/lib/physicist.rb +5 -119
  27. data/media/images/cosmos.jpg +0 -0
  28. data/media/images/tiles.png +0 -0
  29. data/media/images/walk.png +0 -0
  30. data/spec/physicist_spec.rb +5 -5
  31. metadata +26 -3
  32. data/lib/physicist/laboratory.rb +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dd83597bea0363b5b29832d055ca424a40739170
4
- data.tar.gz: 9d82f12a68cc2bc631a2fc336918643d7041c2e9
3
+ metadata.gz: a8e6b5748e0166acbf9e69a28946931999a82817
4
+ data.tar.gz: f1abc35f92cf0157ffcd366602d0b5d722438930
5
5
  SHA512:
6
- metadata.gz: f8e64f7f5f427b8d12e21675659389bf6cae97806d705ad7cd2d7c251360e0bdae8dd922b210b40344b771c9c1b5df3597f7d19af282afe5705c9ecf5978ad37
7
- data.tar.gz: 79b9502573ac874cece9b0ac486ea4e2a617ebe6fc58b01ecd0915d21903feb30d225759199a2fd1b9729603476de9086e9a26e64ae8c1117471df289263fba1
6
+ metadata.gz: 6aab3cf912156901fa5051c0b2259feedc77bb960bedc59c049fadc4744e799d6d2c2e6ce7bc6222d0be2e80b6368eead4d9c8bf34d471d3c4c2710d90576f7e
7
+ data.tar.gz: 74b51b92552615d50c7d7ab5f9f44ee43f3139a9fe897ca92913562285efb2976d68a2be5b07c65551d6cbf5dab9d7bb10d080be7054a229bc870efebdcb0c73
data/Gemfile CHANGED
@@ -2,7 +2,13 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
+
5
6
  group :development do
6
7
  gem 'kramdown'
7
8
  gem 'pry'
9
+
10
+ # really for laboratory app only...
11
+ gem 'dedalus' #, path: '../dedalus'
12
+ gem 'gosu'
13
+ gem 'joyce' #, path: '../joyce'
8
14
  end
data/bin/physicist CHANGED
@@ -5,10 +5,13 @@ if File.directory?(File.join(root,'.git'))
5
5
  Dir.chdir(root) do
6
6
  begin
7
7
  require 'bundler/setup'
8
+ require 'physicist'
9
+ require 'physicist/laboratory/app'
10
+ Physicist::Laboratory::App.kickstart!
8
11
  rescue LoadError => e
9
12
  warn e.message
10
13
  warn "Run `gem install bundler` to install Bundler"
11
- exit -1
14
+ exit(-1)
12
15
  end
13
16
  end
14
17
  end
@@ -0,0 +1,222 @@
1
+ module Physicist
2
+ class Body
3
+ attr_reader :position, :velocity, :t0, :dimensions
4
+
5
+ def initialize(position:, velocity:, t0:, dimensions:)
6
+ @position = position
7
+ @velocity = velocity
8
+ @dimensions = dimensions
9
+ @t0 = t0
10
+ end
11
+
12
+ def width
13
+ dimensions[0]
14
+ end
15
+
16
+ def height
17
+ dimensions[1]
18
+ end
19
+
20
+ def gravity
21
+ 50.0
22
+ end
23
+
24
+ def friction
25
+ 10.0
26
+ end
27
+
28
+ def at(t, obstacles:[])
29
+ # p [ :body, at: t, pos: position, vel: velocity ]
30
+ x0, _ = *position
31
+ vx0,vy0 = *velocity
32
+
33
+ x_speed = vx0.abs
34
+ sign_x = vx0 > 0.0 ? 1.0 : (vx0 < -0.0 ? -1.0 : 0.0)
35
+
36
+ dt = t - t0
37
+
38
+ vy = vy0 + (gravity * dt)
39
+
40
+ fric = friction * dt
41
+ x_halted = false
42
+
43
+ vx = if (3*fric) < x_speed
44
+ vx0 + (fric * -sign_x)
45
+ else
46
+ x_halted = true
47
+ x_stopping_distance = (vx0 ** 2) / (3 * friction)
48
+ 0
49
+ end
50
+
51
+ xt,yt,vxt,vyt = deduce_y_coordinate(vy,t,obstacles:obstacles) do |y,_vyt|
52
+ if x_halted
53
+ [x0 + (x_stopping_distance * sign_x), y, vx, _vyt]
54
+ else
55
+ deduce_x_coordinate(y,vx,t,obstacles:obstacles) do |x,_vxt|
56
+ [x, y, _vxt, _vyt]
57
+ end
58
+ end
59
+ end
60
+
61
+ vxt = 0 if -0.05 < vx && vx < 0.05
62
+ vyt = 0 if -0.05 < vy && vy < 0.05
63
+
64
+ Body.new(
65
+ position: [xt,yt],
66
+ velocity: [vxt,vyt],
67
+ dimensions: dimensions,
68
+ t0: t
69
+ )
70
+ end
71
+
72
+ private
73
+ def deduce_x_coordinate(y,vx,t,obstacles:,&blk)
74
+ x0,_ = *position
75
+ dt = t - t0
76
+
77
+ next_x_obstacle = next_obstacle_on_x_axis(y,vx,t,obstacles:obstacles)
78
+ if next_x_obstacle
79
+ ox,_ = *next_x_obstacle.position
80
+ ow,_ = *next_x_obstacle.dimensions
81
+
82
+ distance_to_next_x_obstacle =
83
+ if vx > 0
84
+ ((x0+width) - ox).abs
85
+ elsif vx < 0
86
+ ((x0) - (ox+ow)).abs
87
+ end
88
+
89
+ distance_travelled_in_x_axis_if_no_obstacles = vx * dt
90
+ p [ :next_x_obs, at: ox, distance: distance_to_next_x_obstacle, distance_without_obs: distance_travelled_in_x_axis_if_no_obstacles ]
91
+ # require 'pry'
92
+ # binding.pry
93
+
94
+ if distance_travelled_in_x_axis_if_no_obstacles.abs < distance_to_next_x_obstacle
95
+ p [ :travel_x_less_than_obs_x ]
96
+ yield [x0 + (vx*dt), vx]
97
+ else
98
+ p [ :travel_x_more_than_obs_x ]
99
+ if vx > 0
100
+ yield [next_x_obstacle.position[0]-width, 0]
101
+ else
102
+ yield [next_x_obstacle.position[0]+next_x_obstacle.dimensions[0], 0]
103
+ end
104
+ end
105
+ else
106
+ yield [x0 + (vx*dt), vx]
107
+ end
108
+ end
109
+
110
+ def deduce_y_coordinate(vy,t,obstacles:,&blk)
111
+ _,y0 = *position
112
+ dt = t - t0
113
+
114
+ next_y_obstacle = next_obstacle_on_y_axis(vy,t,obstacles:obstacles)
115
+
116
+ if next_y_obstacle
117
+ distance_to_next_y_obstacle =
118
+ if vy > 0
119
+ ((y0+height) - next_y_obstacle.position[1]).abs
120
+ else
121
+ (y0 - (next_y_obstacle.position[1] + next_y_obstacle.dimensions[1])).abs
122
+ end
123
+ distance_travelled_in_y_axis_if_no_obstacles = (vy * dt)
124
+
125
+ if distance_travelled_in_y_axis_if_no_obstacles.abs < distance_to_next_y_obstacle
126
+ yield [y0 + (vy * dt), vy ]
127
+ else
128
+ if vy > 0
129
+ yield [next_y_obstacle.position[1] - 1.01, 0] # (height + 0.1), 0]
130
+ else
131
+ yield [next_y_obstacle.position[1] + next_y_obstacle.dimensions[1] + 0.1, 0]
132
+ end
133
+ end
134
+ else
135
+ yield [y0 + (vy * dt), vy]
136
+ end
137
+ end
138
+
139
+ def next_obstacle_on_x_axis(y,vx,t,obstacles:)
140
+ x0,_ = *position
141
+
142
+ obstacles_along_axis = obstacles.select do |obstacle|
143
+ _,oy = *obstacle.position
144
+ _,oh = *obstacle.dimensions
145
+
146
+ oy <= y + height && y <= oy + oh
147
+ end
148
+
149
+ obstacles_in_direction_of_movement =
150
+ if vx > 0
151
+ obstacles_along_axis.select do |obstacle|
152
+ ox,_ = *obstacle.position
153
+ # ow,oh = *obstacle.dimensions
154
+
155
+ ox >= x0 + width
156
+ end
157
+ elsif vx < 0
158
+ # require 'pry'
159
+ # binding.pry
160
+ obstacles_along_axis.select do |obstacle|
161
+ ox,_ = *obstacle.position
162
+ ow,_ = *obstacle.dimensions
163
+ x0 >= ox + ow
164
+ # ox + ow >= x0
165
+ end
166
+ else
167
+ []
168
+ end
169
+
170
+ if obstacles_in_direction_of_movement.any?
171
+ obstacles_in_direction_of_movement.min_by do |obstacle|
172
+ ox,_ = *obstacle.position
173
+ (x0 - ox).abs
174
+ end
175
+ else
176
+ nil
177
+ end
178
+ end
179
+
180
+ def next_obstacle_on_y_axis(vy,t,obstacles:)
181
+ x0,y0 = *position
182
+
183
+ # x0 += width/4
184
+ w = width #/2
185
+
186
+ obstacles_along_axis = obstacles.select do |obstacle|
187
+ ox,_ = *obstacle.position
188
+ ow,_ = *obstacle.dimensions
189
+ ox <= x0 + w && x0 <= ox + ow
190
+ end
191
+
192
+ obstacles_in_direction_of_movement =
193
+ if vy > 0
194
+ obstacles_along_axis.select do |obstacle|
195
+ _,oy = *obstacle.position
196
+
197
+ oy >= y0 + height
198
+ end
199
+ elsif vy < 0
200
+ obstacles_along_axis.select do |obstacle|
201
+ _,oy = *obstacle.position
202
+ _,oh = *obstacle.dimensions
203
+
204
+ oy + oh <= y0
205
+ end
206
+ else
207
+ []
208
+ end
209
+
210
+ if obstacles_in_direction_of_movement
211
+ obstacles_in_direction_of_movement.min_by do |obstacle|
212
+ _,oy = *obstacle.position
213
+
214
+ # distance to me
215
+ (y0 - oy).abs
216
+ end
217
+ else
218
+ nil
219
+ end
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,104 @@
1
+ require_relative 'screen'
2
+ require_relative 'view'
3
+
4
+ require_relative 'commands/create_scientist'
5
+ require_relative 'commands/move_scientist'
6
+ require_relative 'commands/jump_scientist'
7
+
8
+ require_relative 'handlers/create_scientist_handler'
9
+ require_relative 'handlers/move_scientist_handler'
10
+ require_relative 'handlers/jump_scientist_handler'
11
+
12
+ require_relative 'events/scientist_created_event'
13
+ require_relative 'events/scientist_updated_event'
14
+ require_relative 'events/space_created_event'
15
+
16
+ require_relative 'listeners/scientist_created_event_listener'
17
+ require_relative 'listeners/scientist_updated_event_listener'
18
+ require_relative 'listeners/space_created_event_listener'
19
+
20
+ require_relative 'models/scientist'
21
+ require_relative 'models/space'
22
+
23
+ require_relative 'views/scientist_view'
24
+ require_relative 'views/workspace_view'
25
+
26
+ module Physicist
27
+ module Laboratory
28
+ class App < Joyce::Application
29
+ viewed_with Physicist::Laboratory::View
30
+
31
+ attr_accessor :scientist
32
+
33
+ def setup(*)
34
+ p [ :lab_setup! ]
35
+ fire(
36
+ create_scientist(
37
+ scientist_id: scientist_id,
38
+ name: "Bill Bye",
39
+ title: "Science Guy",
40
+ position: [0,2],
41
+ velocity: [0,0]
42
+ )
43
+ )
44
+ end
45
+
46
+ def tick
47
+ Scientist.all.each(&:tick)
48
+
49
+
50
+ # poll for movement keys...
51
+ if window.button_down?(Gosu::KbLeft)
52
+ fire(move_scientist(:left))
53
+ elsif window.button_down?(Gosu::KbRight)
54
+ fire(move_scientist(:right))
55
+ end
56
+
57
+ # TODO
58
+ p [ :check_jump ]
59
+ if window.button_down?(Gosu::KbUp)
60
+ p [ :jump! ]
61
+ fire(jump)
62
+ else
63
+ p [ :no_jump! ]
64
+ end
65
+ end
66
+
67
+ def press(key)
68
+ if key == Gosu::KbLeft
69
+ fire(move_scientist(:left))
70
+ elsif key == Gosu::KbRight
71
+ fire(move_scientist(:right))
72
+ end
73
+
74
+ if key == Gosu::KbUp
75
+ fire(jump)
76
+ end
77
+ end
78
+
79
+ def scientist_view
80
+ ScientistView.where(scientist_id: scientist_id).first || NullScientistView.new
81
+ end
82
+
83
+ def workspace_view
84
+ WorkspaceView.where(space_id: scientist_view.space_id).first || NullWorkspaceView.new
85
+ end
86
+
87
+ def create_scientist(*args)
88
+ CreateScientist.create(*args)
89
+ end
90
+
91
+ def move_scientist(direction)
92
+ MoveScientist.create(scientist_id: scientist_id, direction: direction)
93
+ end
94
+
95
+ def jump
96
+ JumpScientist.create(scientist_id: scientist_id)
97
+ end
98
+
99
+ def scientist_id
100
+ @scientist_id ||= SecureRandom.uuid
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,7 @@
1
+ module Physicist
2
+ module Laboratory
3
+ class CreateScientist < Metacosm::Command
4
+ attr_accessor :scientist_id, :name, :title, :position, :velocity
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Physicist
2
+ module Laboratory
3
+ class JumpScientist < Metacosm::Command
4
+ attr_accessor :scientist_id
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Physicist
2
+ module Laboratory
3
+ class MoveScientist < Metacosm::Command
4
+ attr_accessor :scientist_id, :direction
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Physicist
2
+ module Laboratory
3
+ class ScientistCreatedEvent < Metacosm::Event
4
+ attr_accessor :scientist_id, :space_id, :name, :title, :position, :velocity
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Physicist
2
+ module Laboratory
3
+ class ScientistUpdatedEvent < Metacosm::Event
4
+ attr_accessor :scientist_id, :position, :velocity, :updated_at
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Physicist
2
+ module Laboratory
3
+ class SpaceCreatedEvent < Metacosm::Event
4
+ attr_accessor :space_id, :grid_map
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,34 @@
1
+ module Physicist
2
+ module Laboratory
3
+ class CreateScientistHandler
4
+ def handle(scientist_id:, name:, title:, position:, velocity:)
5
+ p [ :creating_space ]
6
+
7
+ map_data = (
8
+ [
9
+ [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
10
+ [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ],
11
+ [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ],
12
+ [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ],
13
+ [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ],
14
+ [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ],
15
+ [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ],
16
+ [ 1, nil, nil, nil, nil, 2, nil, nil, nil, nil, 1 ],
17
+ [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
18
+ ]
19
+ )
20
+
21
+ space = Space.create(grid_map: map_data)
22
+
23
+ p [ :creating_scientist, name: name ]
24
+ space.create_scientist(
25
+ id: scientist_id,
26
+ name: name,
27
+ title: title,
28
+ position: position,
29
+ velocity: velocity
30
+ )
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,10 @@
1
+ module Physicist
2
+ module Laboratory
3
+ class JumpScientistHandler
4
+ def handle(scientist_id:)
5
+ scientist = Scientist.find(scientist_id)
6
+ scientist.jump
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Physicist
2
+ module Laboratory
3
+ class MoveScientistHandler
4
+ def handle(scientist_id:, direction:)
5
+ scientist = Scientist.find(scientist_id)
6
+ scientist.move(direction: direction)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ module Physicist
2
+ module Laboratory
3
+ class ScientistCreatedEventListener < Metacosm::EventListener
4
+ def receive(scientist_id:, space_id:, name:, title:, position:, velocity:)
5
+ ScientistView.create(
6
+ scientist_id: scientist_id,
7
+ space_id: space_id,
8
+ display_name: "#{name} the #{title}",
9
+ position: position,
10
+ velocity: velocity
11
+ )
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Physicist
2
+ module Laboratory
3
+ class ScientistUpdatedEventListener < Metacosm::EventListener
4
+ def receive(scientist_id:, position:, velocity:, updated_at:)
5
+ p [ :scientist_updated, pos: position, vel: velocity ]
6
+ scientist_view = ScientistView.find_by(scientist_id: scientist_id)
7
+ scientist_view.update(
8
+ position: position,
9
+ velocity: velocity,
10
+ t0: updated_at
11
+ )
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ module Physicist
2
+ module Laboratory
3
+ class SpaceCreatedEventListener < Metacosm::EventListener
4
+ def receive(space_id:, grid_map:)
5
+ WorkspaceView.create(space_id: space_id, grid_map: grid_map)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,84 @@
1
+ module Physicist
2
+ module Laboratory
3
+ # user avatars are 'scientists'
4
+ class Scientist < Metacosm::Model
5
+ belongs_to :space
6
+
7
+ # attr_accessor :space_id #??
8
+ attr_accessor :name, :title
9
+ attr_accessor :position, :velocity
10
+ attr_accessor :updated_at
11
+
12
+ def tick
13
+ update(
14
+ position: current.position,
15
+ velocity: current.velocity,
16
+ updated_at: Time.now
17
+ )
18
+ end
19
+
20
+ def ground_speed
21
+ 5
22
+ end
23
+
24
+ def max_ground_speed
25
+ 10
26
+ end
27
+
28
+ def leg_strength # ??
29
+ -12
30
+ end
31
+
32
+ def max_jump_velocity
33
+ -30
34
+ end
35
+
36
+ def move(direction:)
37
+ vx,vy = *current.velocity
38
+ speed = ground_speed
39
+ dvx = direction == :left ? -speed : speed
40
+ vxt = vx + dvx
41
+ return unless vxt.abs < max_ground_speed
42
+ p [ :move, dir: direction, current: current, dvx: dvx, vxt: vxt ]
43
+
44
+ # TODO more specific event?
45
+ update(
46
+ position: current.position,
47
+ velocity: [vxt, vy],
48
+ updated_at: Time.now
49
+ )
50
+ end
51
+
52
+ def jump
53
+ p [ :jump, current: current ]
54
+ vx, vy = *current.velocity
55
+ return if vy.abs > 0.0
56
+
57
+ dvy = leg_strength
58
+ update(
59
+ position: current.position,
60
+ velocity: [vx, vy + dvy],
61
+ updated_at: Time.now
62
+ )
63
+ end
64
+
65
+ def current
66
+ @body = body.at(Time.now, obstacles: space.obstacles)
67
+ end
68
+
69
+ def body
70
+ construct_body
71
+ end
72
+
73
+ def construct_body
74
+ # ...integrate physicist bodies...
75
+ Physicist::Body.new(
76
+ position: position,
77
+ velocity: velocity,
78
+ t0: updated_at || Time.now,
79
+ dimensions: [1,1]
80
+ )
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,14 @@
1
+ module Physicist
2
+ module Laboratory
3
+ class Space < Metacosm::Model
4
+ has_many :scientists
5
+
6
+ # attr_accessor :scientists
7
+ attr_accessor :grid_map
8
+
9
+ def obstacles
10
+ SimpleBody.collection_from_tiles(grid_map)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,52 @@
1
+ module Physicist
2
+ module Laboratory
3
+ class Screen < Dedalus::Screen
4
+ include Dedalus::Elements
5
+ attr_accessor :scientist, :map_grid, :camera
6
+
7
+ def show
8
+ [
9
+ Paragraph.new(text: "Welcome to the lab, #{scientist.display_name}!"),
10
+ Paragraph.new(text: "Pos: #{scientist.current.position}"),
11
+ Paragraph.new(text: "Vel: #{scientist.current.velocity}"),
12
+ field
13
+ ]
14
+ end
15
+
16
+ def field
17
+ SpriteField.new(
18
+ grid: map_grid,
19
+ scale: 1.0,
20
+ camera_location: camera,
21
+ tiles_path: "media/images/tiles.png",
22
+ tile_width: 64,
23
+ tile_height: 64,
24
+ tile_class: "Dedalus::Elements::MapTile",
25
+ sprite_map: sprite_map
26
+ )
27
+ end
28
+
29
+ def sprite_map
30
+ { scientist.current.position => [avatar_for(scientist)] }
31
+ end
32
+
33
+ def avatar_for(scientist)
34
+ Dedalus::Elements::Sprite.new(
35
+ path: 'media/images/walk.png',
36
+ frame: 0,
37
+ invert_x: false,
38
+ asset_width: 64,
39
+ asset_height: 64,
40
+ scale: 1.0
41
+ )
42
+ end
43
+
44
+ def heading
45
+ [
46
+ Heading.new(text: "[Physics Laboratory]"),
47
+ Paragraph.new(text: "Hello, #{scientist.name_with_title}")
48
+ ]
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,27 @@
1
+ module Physicist
2
+ module Laboratory
3
+ class View < Dedalus::ApplicationView
4
+ def app_screen
5
+ Screen.new(
6
+ scientist: scientist_view,
7
+ map_grid: application.workspace_view.grid_map,
8
+ camera: camera_location
9
+ )
10
+ end
11
+
12
+ def scientist_view
13
+ application.scientist_view
14
+ end
15
+
16
+ def tile_size
17
+ 64
18
+ end
19
+
20
+ def camera_location
21
+ cx, cy = *scientist_view.current.position
22
+ mx, my = (window.width / 2) / tile_size, (window.height / 2) / tile_size
23
+ [ cx - mx, cy - my ]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,57 @@
1
+ require 'ostruct'
2
+ module Physicist
3
+ module Laboratory
4
+ class ScientistView < Metacosm::View
5
+ attr_accessor :scientist_id, :space_id
6
+ attr_accessor :display_name, :position, :velocity, :t0
7
+
8
+ after_update {
9
+ @body = construct_body
10
+ }
11
+
12
+ def current # at(t)
13
+ @body = body.at(Time.now, obstacles: workspace_view.obstacles)
14
+ end
15
+
16
+ def workspace_view
17
+ WorkspaceView.find_by(space_id: space_id)
18
+ end
19
+
20
+ def body
21
+ # ... integrate physicist bodies ...
22
+ @body ||= construct_body
23
+ end
24
+
25
+ def construct_body
26
+ Physicist::Body.new(
27
+ position: position,
28
+ velocity: velocity,
29
+ t0: t0 || Time.now,
30
+ dimensions: [1,1]
31
+ )
32
+ end
33
+ end
34
+
35
+ class NullScientistView
36
+ def display_name
37
+ 'Nohbdy'
38
+ end
39
+
40
+ def position
41
+ [0,0]
42
+ end
43
+
44
+ def velocity
45
+ [0,0]
46
+ end
47
+
48
+ def space_id
49
+ nil
50
+ end
51
+
52
+ def current
53
+ OpenStruct.new(position: position, velocity: velocity)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,18 @@
1
+ module Physicist
2
+ module Laboratory
3
+ class WorkspaceView < Metacosm::View
4
+ # has_many :scientist_views
5
+ attr_accessor :space_id, :grid_map
6
+
7
+ def obstacles
8
+ SimpleBody.collection_from_tiles(grid_map)
9
+ end
10
+ end
11
+
12
+ class NullWorkspaceView
13
+ def grid_map
14
+ [[1,2],[3,4]]
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ module Physicist
2
+ class SimpleBody
3
+ attr_reader :position, :dimensions
4
+
5
+ def initialize(position:,dimensions:)
6
+ @position = position
7
+ @dimensions = dimensions
8
+ end
9
+
10
+ def self.collection_from_tiles(tile_grid)
11
+ # p [ :assembling_bodies_from_tiles, grid: tile_grid ]
12
+ simple_bodies = []
13
+
14
+ tile_grid.each_with_index do |row, y|
15
+ row.each_with_index do |cell, x|
16
+ if cell
17
+ simple_bodies << new(position: [x,y], dimensions: [1,1])
18
+ end
19
+ end
20
+ end
21
+
22
+ # p [ bodies: simple_bodies ]
23
+ simple_bodies
24
+ end
25
+ end
26
+ end
@@ -1,4 +1,4 @@
1
1
  module Physicist
2
2
  # physicist version
3
- VERSION = "0.1.0"
3
+ VERSION = "0.1.1"
4
4
  end
data/lib/physicist.rb CHANGED
@@ -1,120 +1,6 @@
1
- require 'physicist/version'
2
-
3
- module Physicist
4
- class SimpleBody
5
- attr_reader :position, :dimensions
6
-
7
- def initialize(position:,dimensions:)
8
- @position = position
9
- @dimensions = dimensions
10
- end
11
- end
12
-
13
- class Body
14
- attr_reader :position, :velocity, :t0, :dimensions
15
-
16
- def initialize(position:, velocity:, t0:, dimensions:)
17
- @position = position
18
- @velocity = velocity
19
- @dimensions = dimensions
20
- @t0 = t0
21
- end
22
-
23
- def width
24
- dimensions[0]
25
- end
26
-
27
- def height
28
- dimensions[1]
29
- end
30
-
31
- def at(t, obstacles:[])
32
- x0,y0 = *position
33
- vx0,vy0 = *velocity
34
-
35
- dt = t - t0
36
-
37
- vx = vx0 # - dry friction ?
38
- vy = vy0 + (gravity * dt)
39
-
40
- next_y_obstacle = next_obstacle_on_y_axis(vy,t,obstacles:obstacles)
41
-
42
- if next_y_obstacle
43
- distance_to_next_y_obstacle =
44
- if vy > 0
45
- ((y0+height) - next_y_obstacle.position[1]).abs
46
- else
47
- (y0 - next_y_obstacle.position[1]).abs
48
- end
49
- # if vy > 0
50
- # distance_to_next_y_obstacle -= height
51
- # end
52
-
53
- distance_travelled_in_y_axis_if_no_obstacles = (vy * dt)
1
+ require 'gosu' # note: must require gosu *first*
2
+ require 'dedalus'
54
3
 
55
- # require 'pry'
56
- # binding.pry
57
-
58
- if distance_travelled_in_y_axis_if_no_obstacles < distance_to_next_y_obstacle
59
- # the no-obstacles within relevant distance case
60
- # # TODO handle other coordinate (x)
61
- x = x0 + (vx * dt)
62
- y = y0 + (vy * dt)
63
-
64
- else
65
- # TODO handle other coordinate here too...
66
- x = x0 + (vx * dt)
67
- y = y0 + distance_to_next_y_obstacle # - height
68
- vy = 0
69
- end
70
- else
71
- x = x0 + (vx * dt)
72
- y = y0 + (vy * dt)
73
- end
74
-
75
- Body.new(
76
- position: [x,y],
77
- velocity: [vx,vy],
78
- dimensions: dimensions,
79
- t0: t
80
- )
81
- end
82
-
83
- def next_obstacle_on_y_axis(vy,t,obstacles:)
84
- x0,y0 = *position
85
-
86
- obstacles_along_axis = obstacles.select do |obstacle|
87
- ox,_ = *obstacle.position
88
- ow,_ = *obstacle.dimensions
89
- ox <= x0 + width && x0 <= ox + ow
90
- end
91
-
92
- obstacles_in_direction_of_movement = if vy > 0
93
- obstacles_along_axis.select do |obstacle|
94
- _,oy = *obstacle.position
95
- # _,oh = *obstacle.dimensions
96
-
97
- oy >= y0 + height # && y0 < oy + oh
98
- end
99
- elsif vy < 0
100
- obstacles_along_axis.select do |obstacle|
101
- _,oy = *obstacle.position
102
- _,oh = *obstacle.dimensions
103
-
104
- oy + oh <= y0 # + height # && y0 > oy + oh
105
- end
106
- end
107
-
108
-
109
- obstacles_in_direction_of_movement.min_by do |obstacle|
110
- _,oy = *obstacle.position
111
- # distance to me
112
- (y0 - oy).abs
113
- end
114
- end
115
-
116
- def gravity
117
- 9.8
118
- end
119
- end
120
- end
4
+ require 'physicist/version'
5
+ require 'physicist/simple_body'
6
+ require 'physicist/body'
Binary file
Binary file
Binary file
@@ -88,7 +88,7 @@ describe Body do
88
88
  context "with an obstacle directly beneath the body" do
89
89
  let(:obstacles) do
90
90
  [
91
- SimpleBody.new(position: [ x0, y0 + height ], dimensions: [ width, height ])
91
+ SimpleBody.new(position: [ x0, y0 + height ], dimensions: [ width, height ])
92
92
  ]
93
93
  end
94
94
 
@@ -96,7 +96,7 @@ describe Body do
96
96
  _,vy = *body_at_t.velocity
97
97
  _,y = *body_at_t.position
98
98
  expect(vy).to eq(0)
99
- expect(y0).to eq(y)
99
+ expect(y0 + 0.99).to eq(y)
100
100
  end
101
101
  end
102
102
 
@@ -113,7 +113,7 @@ describe Body do
113
113
  it 'should stop vertical movement after 1s' do
114
114
  _,vy = *body_at_t.velocity
115
115
  _,y = *body_at_t.position
116
- expect(y0 + 9.8).to eq(y)
116
+ expect(y0 + 10.79).to eq(y)
117
117
  expect(vy).to eq(0)
118
118
  end
119
119
  end
@@ -124,8 +124,8 @@ describe Body do
124
124
  it 'should be in freefall' do
125
125
  _,vy = *body_at_t.velocity
126
126
  _,y = *body_at_t.position
127
- expect(y0 + 9.8).to eq(y)
128
- expect(vy).to eq(9.8)
127
+ expect(y0 + 50.0).to eq(y)
128
+ expect(vy).to eq(50.0)
129
129
  end
130
130
  end
131
131
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: physicist
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joseph Weissman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-12 00:00:00.000000000 Z
11
+ date: 2016-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -134,8 +134,31 @@ files:
134
134
  - features/step_definitions/physicist_steps.rb
135
135
  - gemspec.yml
136
136
  - lib/physicist.rb
137
- - lib/physicist/laboratory.rb
137
+ - lib/physicist/body.rb
138
+ - lib/physicist/laboratory/app.rb
139
+ - lib/physicist/laboratory/commands/create_scientist.rb
140
+ - lib/physicist/laboratory/commands/jump_scientist.rb
141
+ - lib/physicist/laboratory/commands/move_scientist.rb
142
+ - lib/physicist/laboratory/events/scientist_created_event.rb
143
+ - lib/physicist/laboratory/events/scientist_updated_event.rb
144
+ - lib/physicist/laboratory/events/space_created_event.rb
145
+ - lib/physicist/laboratory/handlers/create_scientist_handler.rb
146
+ - lib/physicist/laboratory/handlers/jump_scientist_handler.rb
147
+ - lib/physicist/laboratory/handlers/move_scientist_handler.rb
148
+ - lib/physicist/laboratory/listeners/scientist_created_event_listener.rb
149
+ - lib/physicist/laboratory/listeners/scientist_updated_event_listener.rb
150
+ - lib/physicist/laboratory/listeners/space_created_event_listener.rb
151
+ - lib/physicist/laboratory/models/scientist.rb
152
+ - lib/physicist/laboratory/models/space.rb
153
+ - lib/physicist/laboratory/screen.rb
154
+ - lib/physicist/laboratory/view.rb
155
+ - lib/physicist/laboratory/views/scientist_view.rb
156
+ - lib/physicist/laboratory/views/workspace_view.rb
157
+ - lib/physicist/simple_body.rb
138
158
  - lib/physicist/version.rb
159
+ - media/images/cosmos.jpg
160
+ - media/images/tiles.png
161
+ - media/images/walk.png
139
162
  - physicist.gemspec
140
163
  - spec/physicist_spec.rb
141
164
  - spec/spec_helper.rb
@@ -1 +0,0 @@
1
- # a tiny dedalus app for visually checking physicist flow?