chingu 0.7.5 → 0.7.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -29,40 +29,93 @@ module Chingu
29
29
  #
30
30
  # requires the global $window set to the instance of Gosu::Window (automaticly handled if you use Chingu::Window)
31
31
  #
32
+ # Edit will only edit game objects created with the editor itself or that's been loaded with load_game_objects.
33
+ # This makes mixing of loaded game objects and code create game objects possible, in the game, and in the editor.
34
+ #
35
+ # Various shortcuts are available in the editor
36
+ #
37
+ # 1-5: create object 1..5 shown in toolbar
38
+ # DEL: delete selected objects
39
+ # CTRL+A: select all objects (not code-created ones though)
40
+ # S: Save
41
+ # E: Save and Quit
42
+ # Right Mouse Button Click: Copy object that was clicked on for fast duplication
43
+ # Arrows: Scroll within a viewport
44
+ # Page up/down: Modify the zorder of selected game objects
45
+ #
32
46
  class Edit < Chingu::GameState
47
+ attr_accessor :grid, :debug, :file, :hud_color
48
+ attr_reader :classes, :exclude
33
49
 
34
50
  def initialize(options = {})
35
51
  super
36
52
  @grid = options[:grid] || [8,8]
37
- @classes = options[:classes] || []
38
- @only = options[:only] || []
53
+ @classes = Array(options[:classes] || game_object_classes)
54
+ @except = options[:except] || []
55
+ @classes -= Array(@except)
56
+
39
57
  @debug = options[:debug]
40
- @file = options[:file] || "#{previous_game_state.class.to_s.downcase}.yml"
41
58
  @zorder = 10000
42
-
43
- @hud_color = Gosu::Color.new(150,100,100,100)
59
+
60
+ @hud_color = Gosu::Color.new(180,70,70,70)
44
61
  @selected_game_object = nil
45
- self.input = { :left_mouse_button => :left_mouse_button,
46
- :released_left_mouse_button => :released_left_mouse_button,
47
- :right_mouse_button => :right_mouse_button,
48
- :released_right_mouse_button => :released_right_mouse_button,
49
- :delete => :destroy_selected_game_objects,
50
- :backspace => :destroy_selected_game_objects,
51
- :e => :save_and_quit,
52
- :s => :save,
53
- :esc => :save_and_quit,
54
- :holding_up_arrow => :scroll_up,
55
- :holding_down_arrow => :scroll_down,
56
- :holding_left_arrow => :scroll_left,
57
- :holding_right_arrow => :scroll_right,
58
- :page_up => :page_up,
59
- :page_down => :page_down,
60
- :"1" => :create_object_1,
61
- :"2" => :create_object_2,
62
- :"3" => :create_object_3,
63
- :"4" => :create_object_4,
64
- :"5" => :create_object_5,
65
- }
62
+ self.input = {
63
+ :left_mouse_button => :left_mouse_button,
64
+ :released_left_mouse_button => :released_left_mouse_button,
65
+ :right_mouse_button => :right_mouse_button,
66
+ :released_right_mouse_button => :released_right_mouse_button,
67
+
68
+ :delete => :destroy_selected_game_objects,
69
+ :backspace => :reset_selected_game_objects,
70
+
71
+ :holding_numpad_7 => :scale_down,
72
+ :holding_numpad_9 => :scale_up,
73
+ :holding_numpad_4 => :tilt_left,
74
+ :holding_numpad_8 => :tilt_right,
75
+ :holding_numpad_1 => :dec_alpha,
76
+ :holding_numpad_3 => :inc_alpha,
77
+
78
+ :r => :scale_up,
79
+ :f => :scale_down,
80
+ :t => :tilt_left,
81
+ :g => :tilt_right,
82
+ :y => :inc_zorder,
83
+ :h => :dec_zorder,
84
+ :u => :inc_alpha,
85
+ :j => :dec_alpha,
86
+
87
+ :page_up => :inc_zorder,
88
+ :page_down => :dec_zorder,
89
+
90
+ :s => :try_save,
91
+ :a => :try_select_all,
92
+
93
+ :e => :save_and_quit,
94
+
95
+ :esc => :esc,
96
+ :q => :quit,
97
+
98
+ :up_arrow => :move_up,
99
+ :down_arrow => :move_down,
100
+ :left_arrow => :move_left,
101
+ :right_arrow => :move_right,
102
+
103
+ :holding_up_arrow => :try_scroll_up,
104
+ :holding_down_arrow => :try_scroll_down,
105
+ :holding_left_arrow => :try_scroll_left,
106
+ :holding_right_arrow => :try_scroll_right,
107
+
108
+ :plus => :scale_up,
109
+ :minus => :scale_down,
110
+ :mouse_wheel_up => :mouse_wheel_up,
111
+ :mouse_wheel_down => :mouse_wheel_down,
112
+
113
+ :"1" => :create_object_1,
114
+ :"2" => :create_object_2,
115
+ :"3" => :create_object_3,
116
+ :"4" => :create_object_4,
117
+ :"5" => :create_object_5,
118
+ }
66
119
 
67
120
  x = 20
68
121
  y = 60
@@ -71,71 +124,37 @@ module Chingu
71
124
 
72
125
  # We initialize x,y,zorder,rotation_center after creation
73
126
  # so they're not overwritten by the class initialize/setup or simular
74
- game_object = klass.create
127
+ game_object = klass.create(:paused => true)
75
128
  game_object.x = x
76
129
  game_object.y = y
77
130
  game_object.zorder = @zorder
131
+ game_object.options[:toolbar] = true
78
132
 
79
133
  # Scale down big objects, don't scale objects under [32, 32]
80
134
  if game_object.image
81
- game_object.factor_x = 32 / game_object.image.width if game_object.image.width > 32
82
- game_object.factor_y = 32 / game_object.image.height if game_object.image.height > 32
83
- end
135
+ game_object.factor_x = 32.0 / game_object.image.width if game_object.image.width > 32
136
+ game_object.factor_y = 32.0 / game_object.image.height if game_object.image.height > 3
137
+ game_object.cache_bounding_box if game_object.respond_to?(:bounding_box)
138
+ end
84
139
  x += 40
85
140
  end
86
141
  end
87
-
88
- def setup
142
+
143
+ #
144
+ # SETUP
145
+ #
146
+ def setup
147
+ @scroll_border_thickness = 50
148
+ @file = options[:file] || previous_game_state.filename + ".yml"
89
149
  @title = Text.create("File: #{@file}", :x => 5, :y => 2, :factor => 1, :size => 16, :zorder => @zorder)
90
150
  @title.text += " - Grid: #{@grid}" if @grid
91
- @text = Text.create("", :x => 200, :y => 20, :factor => 1, :size => 16, :zorder => @zorder)
151
+ @text = Text.create("", :x => 300, :y => 20, :factor => 1, :size => 16, :zorder => @zorder)
92
152
  @status_text = Text.create("-", :x => 5, :y => 20, :factor => 1, :size => 16, :zorder => @zorder)
93
- #@title2 = Text.create("(1-10) Create object at mouse pos (DEL) Delete selected object (S) Save (E) Save and Quit (ESC) Quit without saving", :x => 5, :y => 30, :factor => 1)
94
- end
95
-
96
- def create_object_nr(number)
97
- c = @classes[number].create(:x => x, :y => y, :parent => previous_game_state) if @classes[number]
98
- c.update
99
- #@text.text = "Created a #{c.class} @ #{c.x} / #{c.y}"
100
- end
101
-
102
- def create_object_1; create_object_nr(0); end
103
- def create_object_2; create_object_nr(1); end
104
- def create_object_3; create_object_nr(2); end
105
- def create_object_4; create_object_nr(3); end
106
- def create_object_5; create_object_nr(4); end
107
-
108
- def draw
109
- # Draw prev game state onto screen (the level we're editing)
110
- previous_game_state.draw
111
-
112
- super
113
-
114
- #
115
- # Draw an edit HUD
116
- #
117
- $window.draw_quad( 0,0,@hud_color,
118
- $window.width,0,@hud_color,
119
- $window.width,100,@hud_color,
120
- 0,100,@hud_color, @zorder-1)
121
-
122
- #
123
- # Draw red rectangles/circles around all selected game objects
124
- #
125
- selected_game_objects.each { |game_object| game_object.draw_debug }
126
-
127
- if @cursor_game_object
128
- @cursor_game_object.draw_at($window.mouse_x, $window.mouse_y)
129
- else
130
- #
131
- # draw a simple triagle-shaped cursor
132
- #
133
- $window.draw_triangle( $window.mouse_x, $window.mouse_y, Color::WHITE,
134
- $window.mouse_x, $window.mouse_y + 10, Color::WHITE,
135
- $window.mouse_x + 10, $window.mouse_y + 10, Color::WHITE, @zorder + 10)
136
- end
137
153
  end
138
-
154
+
155
+ #
156
+ # UPDATE
157
+ #
139
158
  def update
140
159
  # Sync all changes to previous game states game objects list
141
160
  # This is needed since we don't call update on it.
@@ -143,11 +162,11 @@ module Chingu
143
162
 
144
163
  super
145
164
 
146
- #
147
- # We got a selected game object
148
- #
149
- if @selected_game_object
150
- @text.text = "#{@selected_game_object.class.to_s} @ #{@selected_game_object.x} / #{@selected_game_object.y} - zorder: #{@selected_game_object.zorder}"
165
+ @status_text.text = "#{self.mouse_x} / #{self.mouse_y}"
166
+
167
+ if s = @selected_game_object
168
+ @text.text = "#{s.class.to_s} @ #{s.x.to_i} / #{s.y.to_i}"
169
+ @text.text += " [Scale: #{sprintf("%.2f", s.factor_x)}/#{sprintf("%.2f", s.factor_y)} Angle: #{s.angle.to_i} Z: #{s.zorder}]"
151
170
  end
152
171
 
153
172
  #
@@ -155,8 +174,8 @@ module Chingu
155
174
  #
156
175
  if @left_mouse_button && @selected_game_object
157
176
  selected_game_objects.each do |selected_game_object|
158
- selected_game_object.x = self.x + selected_game_object.options[:mouse_x_offset]
159
- selected_game_object.y = self.y + selected_game_object.options[:mouse_y_offset]
177
+ selected_game_object.x = self.mouse_x + selected_game_object.options[:mouse_x_offset]
178
+ selected_game_object.y = self.mouse_y + selected_game_object.options[:mouse_y_offset]
160
179
  selected_game_object.x -= selected_game_object.x % @grid[0]
161
180
  selected_game_object.y -= selected_game_object.y % @grid[1]
162
181
  end
@@ -166,68 +185,110 @@ module Chingu
166
185
  @selected_game_object.bounding_box.x = @selected_game_object.x
167
186
  @selected_game_object.bounding_box.y = @selected_game_object.y
168
187
  end
188
+ elsif @left_mouse_button
189
+ if defined?(self.previous_game_state.viewport)
190
+ self.previous_game_state.viewport.x = @left_mouse_click_at[0] - $window.mouse_x
191
+ self.previous_game_state.viewport.y = @left_mouse_click_at[1] - $window.mouse_y
192
+ end
193
+ end
194
+
195
+ if inside_window?($window.mouse_x, $window.mouse_y)
196
+ scroll_right if $window.mouse_x > $window.width - @scroll_border_thickness
197
+ scroll_left if $window.mouse_x < @scroll_border_thickness
198
+ scroll_up if $window.mouse_y < @scroll_border_thickness
199
+ scroll_down if $window.mouse_y > $window.height - @scroll_border_thickness
169
200
  end
170
201
 
171
- @status_text.text = "Mouseposition: #{x} / #{y}"
172
- end
173
-
174
- def selected_game_objects
175
- previous_game_state.game_objects.select { |o| o.options[:selected] }
176
202
  end
177
203
 
178
- def destroy_selected_game_objects
179
- selected_game_objects.each(&:destroy)
204
+ #
205
+ # DRAW
206
+ #
207
+ def draw
208
+ # Draw prev game state onto screen (the level we're editing)
209
+ previous_game_state.draw
210
+
211
+ super
212
+
213
+ #
214
+ # Draw an edit HUD
215
+ #
216
+ $window.draw_quad( 0,0,@hud_color,
217
+ $window.width,0,@hud_color,
218
+ $window.width,100,@hud_color,
219
+ 0,100,@hud_color, @zorder-1)
220
+
221
+ #
222
+ # Draw red rectangles/circles around all selected game objects
223
+ #
224
+ selected_game_objects.each { |game_object| game_object.draw_debug }
225
+
226
+ if @cursor_game_object
227
+ @cursor_game_object.draw_at($window.mouse_x, $window.mouse_y)
228
+ else
229
+ draw_cursor_at($window.mouse_x, $window.mouse_y)
230
+ end
180
231
  end
181
-
232
+
182
233
  #
183
234
  # CLICKED LEFT MOUSE BUTTON
184
235
  #
185
236
  def left_mouse_button
186
- @left_mouse_button = true
237
+ @left_mouse_button = true
238
+ @selected_game_object = false
187
239
 
188
- if @cursor_game_object && game_object_at(x, y)==nil && game_object_icon_at($window.mouse_x, $window.mouse_y) == nil
189
- game_object = @cursor_game_object.class.create(:parent => previous_game_state)
190
- game_object.update
191
- game_object.options[:selected] = true
192
- game_object.x = x
193
- game_object.y = y
240
+ if defined?(self.previous_game_state.viewport)
241
+ @left_mouse_click_at = [self.previous_game_state.viewport.x + $window.mouse_x, self.previous_game_state.viewport.y + $window.mouse_y]
242
+ else
243
+ @left_mouse_click_at = [$window.mouse_x, $window.mouse_y]
194
244
  end
195
245
 
196
- # Get editable game object that was clicked at (if any)
197
- @selected_game_object = game_object_at(x, y)
246
+ # Put out a new game object in the editor window and select it right away
247
+ @selected_game_object = create_new_game_object_from(@cursor_game_object) if @cursor_game_object
198
248
 
199
249
  # Check if user clicked on anything in the icon-toolbar of available game objects
200
250
  @cursor_game_object = game_object_icon_at($window.mouse_x, $window.mouse_y)
201
-
251
+
252
+ # Get editable game object that was clicked at (if any)
253
+ @selected_game_object ||= game_object_at(self.mouse_x, self.mouse_y)
254
+
255
+ if @selected_game_object && defined?(self.previous_game_state.viewport)
256
+ self.previous_game_state.viewport.center_around(@selected_game_object) if @left_double_click
257
+ end
258
+
202
259
  if @selected_game_object
203
260
  #
204
261
  # If clicking on a new object that's wasn't previosly selected
205
262
  # --> deselect all objects unless holding left_ctrl
206
263
  #
207
264
  if @selected_game_object.options[:selected] == nil
208
- selected_game_objects.each { |x| x.options[:selected] = nil } unless holding?(:left_ctrl)
265
+ selected_game_objects.each { |object| object.options[:selected] = nil } unless holding?(:left_ctrl)
209
266
  end
210
267
 
211
- @selected_game_object.options[:selected] = true
268
+ @selected_game_object.options[:selected] = !@selected_game_object.options[:selected]
269
+
212
270
  #
213
271
  # Re-align all objects x/y offset in relevance to the cursor
214
272
  #
215
273
  selected_game_objects.each do |selected_game_object|
216
- selected_game_object.options[:mouse_x_offset] = selected_game_object.x - self.x
217
- selected_game_object.options[:mouse_y_offset] = selected_game_object.y - self.y
274
+ selected_game_object.options[:mouse_x_offset] = selected_game_object.x - self.mouse_x + 20
275
+ selected_game_object.options[:mouse_y_offset] = selected_game_object.y - self.mouse_y + 20
218
276
  end
219
277
  else
220
- selected_game_objects.each { |x| x.options[:selected] = nil } unless holding?(:left_ctrl)
278
+ deselect_selected_game_objects unless holding?(:left_ctrl)
221
279
  end
222
280
  end
223
281
 
224
282
  def right_mouse_button
225
- @cursor_game_object = game_object_at(x, y)
226
- selected_game_objects.each { |x| x.options[:selected] = nil }
283
+ if @cursor_game_object
284
+ @cursor_game_object = nil
285
+ else
286
+ @cursor_game_object = game_object_at(self.mouse_x, self.mouse_y)
287
+ end
227
288
  end
228
289
  def released_right_mouse_button
229
290
  end
230
-
291
+
231
292
  #
232
293
  # RELASED LEFT MOUSE BUTTON
233
294
  #
@@ -235,66 +296,273 @@ module Chingu
235
296
  @left_mouse_button = false
236
297
  end
237
298
 
299
+ #
300
+ # Returns a list of game objects the editor can create. 2 types of object gets this flag:
301
+ # - An object loaded with load_game_objects
302
+ # - An object created from within the editor
303
+ #
304
+ # This helps us mix code-created with editor-created objects inside the editor and not muck around with
305
+ # the code-created ones.
306
+ #
307
+ def editable_game_objects
308
+ previous_game_state.game_objects.select { |o| o.options[:created_with_editor] }
309
+ end
310
+
311
+ #
312
+ # Returns a list of selected game objects
313
+ #
314
+ def selected_game_objects
315
+ editable_game_objects.select { |o| o.options[:selected] }
316
+ end
317
+
318
+ #
319
+ # Call destroy on all selected game objects
320
+ #
321
+ def destroy_selected_game_objects
322
+ selected_game_objects.each(&:destroy)
323
+ end
324
+
325
+ def deselect_selected_game_objects
326
+ selected_game_objects.each { |object| object.options[:selected] = nil }
327
+ end
328
+
329
+ def empty_area_at_cursor
330
+ game_object_at(self.mouse_x, self.mouse_y)==nil &&
331
+ game_object_icon_at($window.mouse_x, $window.mouse_y) == nil
332
+ end
333
+
334
+ #
335
+ # Get all classes based on GameObject except Chingus internal classes.
336
+ #
337
+ def game_object_classes
338
+ ObjectSpace.enum_for(:each_object, class << GameObject; self; end).to_a.select do |game_class|
339
+ game_class.instance_methods && !game_class.to_s.include?("Chingu::")
340
+ end
341
+ end
342
+
343
+ def create_object_nr(number)
344
+ c = @classes[number].create(:x => self.mouse_x, :y => self.mouse_y, :parent => previous_game_state) if @classes[number]
345
+ c.options[:created_with_editor] = true
346
+ c.update
347
+ #@text.text = "Created a #{c.class} @ #{c.x} / #{c.y}"
348
+ end
349
+
350
+ def create_object_1; create_object_nr(0); end
351
+ def create_object_2; create_object_nr(1); end
352
+ def create_object_3; create_object_nr(2); end
353
+ def create_object_4; create_object_nr(3); end
354
+ def create_object_5; create_object_nr(4); end
355
+
356
+ #
357
+ # Resets selected game objects defaults, angle=0, scale=1.
358
+ #
359
+ def reset_selected_game_objects
360
+ selected_game_objects.each do |game_object|
361
+ game_object.angle = 0
362
+ game_object.scale = 1
363
+ end
364
+ end
365
+
238
366
  def game_object_icon_at(x, y)
239
367
  game_objects.select do |game_object|
240
368
  game_object.respond_to?(:collision_at?) && game_object.collision_at?(x,y)
241
369
  end.first
242
370
  end
243
371
 
372
+ #
373
+ # Get editable object at X/Y .. if there's many objects at the same coordinate..
374
+ # .. get the one with highest zorder.
375
+ #
244
376
  def game_object_at(x, y)
245
- previous_game_state.game_objects.select do |game_object|
377
+ editable_game_objects.select do |game_object|
246
378
  game_object.respond_to?(:collision_at?) && game_object.collision_at?(x,y)
247
- end.first
379
+ end.sort {|x,y| y.zorder <=> x.zorder }.first
248
380
  end
249
-
250
- def save
251
- save_game_objects(:game_objects => previous_game_state.game_objects, :file => @file, :classes => @classes)
381
+
382
+ #
383
+ # draw a simple triangle-shaped cursor
384
+ #
385
+ def draw_cursor_at(x, y, c = Color::WHITE)
386
+ $window.draw_triangle(x, y, c, x, y+10, c, x+10, y+10, c, @zorder + 10)
387
+ end
388
+
389
+ def try_select_all
390
+ editable_game_objects.each { |x| x.options[:selected] = true } if holding?(:left_ctrl)
391
+ end
392
+ def try_save
393
+ save if holding?(:left_ctrl)
252
394
  end
253
395
 
396
+ def quit
397
+ pop_game_state(:setup => false)
398
+ end
399
+ def save
400
+ save_game_objects(:game_objects => editable_game_objects, :file => @file, :classes => @classes)
401
+ end
254
402
  def save_and_quit
255
- save
403
+ save unless holding?(:left_ctrl)
256
404
  quit
257
405
  end
406
+
407
+ def move_left
408
+ scroll_left && return if selected_game_objects.empty?
409
+ selected_game_objects.each { |game_object| game_object.x -= 1 }
410
+ end
411
+ def move_right
412
+ scroll_right && return if selected_game_objects.empty?
413
+ selected_game_objects.each { |game_object| game_object.x += 1 }
414
+ end
415
+ def move_up
416
+ scroll_up && return if selected_game_objects.empty?
417
+ selected_game_objects.each { |game_object| game_object.y -= 1 }
418
+ end
419
+ def move_down
420
+ scroll_down && return if selected_game_objects.empty?
421
+ selected_game_objects.each { |game_object| game_object.y += 1 }
422
+ end
258
423
 
259
- def quit
260
- pop_game_state(:setup => false)
424
+ def try_scroll_left
425
+ scroll_left if selected_game_objects.empty?
426
+ end
427
+ def try_scroll_right
428
+ scroll_right if selected_game_objects.empty?
429
+ end
430
+ def try_scroll_up
431
+ scroll_up if selected_game_objects.empty?
432
+ end
433
+ def try_scroll_down
434
+ scroll_down if selected_game_objects.empty?
435
+ end
436
+
437
+ def mouse_wheel_up
438
+ if selected_game_objects.empty?
439
+ scroll_up(40)
440
+ else
441
+ tilt_left && return if holding?(:left_shift)
442
+ inc_zorder && return if holding?(:left_ctrl)
443
+ inc_alpha && return if holding?(:left_alt)
444
+ scale_up
445
+ end
261
446
  end
262
447
 
263
- def game_object_classes
264
- ObjectSpace.enum_for(:each_object, class << GameObject; self; end).to_a.select do |game_class|
265
- game_class.instance_methods
448
+ def mouse_wheel_down
449
+ if selected_game_objects.empty?
450
+ scroll_down(40)
451
+ else
452
+ tilt_right && return if holding?(:left_shift)
453
+ dec_zorder && return if holding?(:left_ctrl)
454
+ dec_alpha && return if holding?(:left_alt)
455
+ scale_down
266
456
  end
267
457
  end
458
+
459
+ def tilt_left
460
+ selected_game_objects.each { |game_object| game_object.angle -= 5 }
461
+ end
462
+ def tilt_right
463
+ selected_game_objects.each { |game_object| game_object.angle += 5 }
464
+ end
465
+ def scale_up
466
+ scale_up_x && scale_up_y
467
+ end
468
+ def scale_down
469
+ scale_down_x && scale_down_y
470
+ end
471
+ def inc_zorder
472
+ selected_game_objects.each { |game_object| game_object.zorder += 1 }
473
+ end
474
+ def dec_zorder
475
+ selected_game_objects.each { |game_object| game_object.zorder -= 1 }
476
+ end
477
+ def inc_alpha
478
+ selected_game_objects.each { |game_object| game_object.alpha += 1 }
479
+ end
480
+ def dec_alpha
481
+ selected_game_objects.each { |game_object| game_object.alpha -= 1 }
482
+ end
483
+ def scale_up_x
484
+ selected_game_objects.each { |game_object| game_object.factor_x += grid_factor_x_for(game_object) }
485
+ end
486
+ def scale_up_y
487
+ selected_game_objects.each { |game_object| game_object.factor_y += grid_factor_x_for(game_object) }
488
+ end
489
+ def scale_down_x
490
+ selected_game_objects.each { |game_object| game_object.factor_x -= grid_factor_y_for(game_object) }
491
+ end
492
+ def scale_down_y
493
+ selected_game_objects.each { |game_object| game_object.factor_y -= grid_factor_y_for(game_object) }
494
+ end
268
495
 
496
+ def grid_factor_x_for(object)
497
+ @grid[0].to_f / object.image.width.to_f
498
+ end
499
+ def grid_factor_y_for(object)
500
+ @grid[0].to_f / object.image.height.to_f
501
+ end
502
+
503
+ def esc
504
+ deselect_selected_game_objects
505
+ @cursor_game_object = nil
506
+ end
269
507
  def page_up
270
- selected_game_objects.each { |game_object| game_object.zorder += 1 }
271
- #self.previous_game_state.viewport.y -= $window.height if defined?(self.previous_game_state.viewport)
508
+ self.previous_game_state.viewport.y -= $window.height if defined?(self.previous_game_state.viewport)
272
509
  end
273
510
  def page_down
274
- selected_game_objects.each { |game_object| game_object.zorder -= 1 }
275
- #self.previous_game_state.viewport.y += $window.height if defined?(self.previous_game_state.viewport)
511
+ self.previous_game_state.viewport.y += $window.height if defined?(self.previous_game_state.viewport)
276
512
  end
277
- def scroll_up
278
- self.previous_game_state.viewport.y -= 10 if defined?(self.previous_game_state.viewport)
513
+ def scroll_up(amount = 10)
514
+ self.previous_game_state.viewport.y -= amount if defined?(self.previous_game_state.viewport)
279
515
  end
280
- def scroll_down
281
- self.previous_game_state.viewport.y += 10 if defined?(self.previous_game_state.viewport)
516
+ def scroll_down(amount = 10)
517
+ self.previous_game_state.viewport.y += amount if defined?(self.previous_game_state.viewport)
282
518
  end
283
- def scroll_left
284
- self.previous_game_state.viewport.x -= 10 if defined?(self.previous_game_state.viewport)
519
+ def scroll_left(amount = 10)
520
+ self.previous_game_state.viewport.x -= amount if defined?(self.previous_game_state.viewport)
285
521
  end
286
- def scroll_right
287
- self.previous_game_state.viewport.x += 10 if defined?(self.previous_game_state.viewport)
522
+ def scroll_right(amount = 10)
523
+ self.previous_game_state.viewport.x += amount if defined?(self.previous_game_state.viewport)
288
524
  end
289
- def x
290
- x = $window.mouse_x
525
+ def mouse_x
526
+ x = $window.mouse_x
291
527
  x += self.previous_game_state.viewport.x if defined?(self.previous_game_state.viewport)
292
528
  end
293
- def y
529
+ def mouse_y
294
530
  y = $window.mouse_y
295
531
  y += self.previous_game_state.viewport.y if defined?(self.previous_game_state.viewport)
296
532
  end
297
533
 
534
+ def inside_window?(x = $window.mouse_x, y = $window.mouse_y)
535
+ x >= 0 && x <= $window.width && y >= 0 && y <= $window.height
536
+ end
537
+
538
+ def create_new_game_object_from(template)
539
+ game_object = template.class.create(:parent => previous_game_state)
540
+ game_object.update
541
+ #game_object.options[:selected] = true
542
+ game_object.options[:created_with_editor] = true
543
+ game_object.x = self.mouse_x
544
+ game_object.y = self.mouse_y
545
+
546
+ unless template.options[:toolbar]
547
+ game_object.angle = template.angle
548
+ game_object.factor_x = template.factor_x
549
+ game_object.factor_y = template.factor_y
550
+ game_object.color = template.color.dup
551
+ game_object.zorder = template.zorder
552
+ game_object.update
553
+ else
554
+ # Resize the new game object to fit the grid perfectly!
555
+ wanted_width = game_object.image.width + @grid[0] - (game_object.image.width % @grid[0])
556
+ wanted_height = game_object.image.height + @grid[1] - (game_object.image.height % @grid[1])
557
+ game_object.factor_x = wanted_width.to_f / game_object.image.width.to_f
558
+ game_object.factor_y = wanted_height.to_f / game_object.image.height.to_f
559
+ end
560
+
561
+ game_object.options[:mouse_x_offset] = game_object.x - self.mouse_x
562
+ game_object.options[:mouse_y_offset] = game_object.y - self.mouse_y
563
+ return game_object
564
+ end
565
+
298
566
  #
299
567
  # If we're editing a game state with automaticly called special methods,
300
568
  # the following takes care of those.