physicist 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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?