chingu 0.7.5 → 0.7.6

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.
@@ -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.