chingu 0.6.2 → 0.6.3
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.
- data.tar.gz.sig +3 -2
- data/README.rdoc +53 -12
- data/chingu.gemspec +2 -2
- data/examples/example14.rb +11 -5
- data/examples/example4.rb +3 -3
- data/examples/example6.rb +11 -2
- data/examples/example9.rb +6 -2
- data/examples/game1.rb +6 -8
- data/examples/high_score_list.yml +2 -2
- data/lib/chingu.rb +1 -1
- data/lib/chingu/basic_game_object.rb +8 -6
- data/lib/chingu/core_ext/array.rb +23 -0
- data/lib/chingu/game_object.rb +2 -3
- data/lib/chingu/game_state.rb +19 -9
- data/lib/chingu/game_state_manager.rb +10 -1
- data/lib/chingu/helpers/class_inheritable_accessor.rb +22 -20
- data/lib/chingu/helpers/game_object.rb +1 -0
- data/lib/chingu/helpers/gfx.rb +1 -1
- data/lib/chingu/parallax.rb +8 -8
- data/lib/chingu/text.rb +1 -1
- data/lib/chingu/traits/bounding_box.rb +29 -2
- data/lib/chingu/traits/bounding_circle.rb +20 -3
- data/lib/chingu/traits/collision_detection.rb +11 -10
- data/lib/chingu/window.rb +9 -2
- metadata +2 -2
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
@@ -1,2 +1,3 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
���M���ʜ��G��5mǂ��tz��5��~ :kLJ����_�Qˡ��e�z��(
|
2
|
+
2�7����qh�y�rA�d
|
3
|
+
q�G_"Z\��{�N:g�k�� ��Y�m�Aĺ��a��RZ_bW���Fп��".�s��AQ7�~�㏉A�R� �]$k�a��D-�1����N#�S�_�u�@og�k��J �</J��ҋ�!�*a�4�!HL�8vG�J7�.��t}��7��x!p��L�ϙ��e�)�Z�Ž�
|
data/README.rdoc
CHANGED
@@ -90,6 +90,8 @@ Both $window and game states gets some new graphical helpers, currently only 3,
|
|
90
90
|
fill() # Fills whole window with color 'color'.
|
91
91
|
fill_rect() # Fills a given Rect 'rect' with Color 'color'
|
92
92
|
fill_gradient() # Fills window or a given rect with a gradient between two colors.
|
93
|
+
draw_circle() # Draws a circle
|
94
|
+
draw_rect() # Draws a rect
|
93
95
|
|
94
96
|
If you base your models on GameObject (or BasicGameObject) you get:
|
95
97
|
Enemy.all # Returns an Array of all Enemy-instances
|
@@ -445,13 +447,41 @@ Chingus inputhandler will detect that Menu is a GameState-class, create a new in
|
|
445
447
|
|
446
448
|
=== Traits
|
447
449
|
Traits (often called behaivors) is a way of adding logic to any class inheriting from BasicGameObject / GameObject.
|
448
|
-
Chingus trait-implementation is just ordinary ruby modules with 3 special methods:
|
450
|
+
Chingus trait-implementation is just ordinary ruby modules with 3 special methods:
|
449
451
|
- setup_trait
|
450
452
|
- update_trait
|
451
453
|
- draw_trait
|
452
454
|
Each of those 3 methods must call "super" to continue the trait-chain.
|
453
455
|
|
454
|
-
|
456
|
+
Inside a certian trait-module you can also have a module called ClassMethods, methods inside that module will be added,
|
457
|
+
yes you guessed it, as class methods. If initialize_trait is defined inside ClassMethods it will be called class-evaluation time
|
458
|
+
(basicly on the has_trait :some_trait line).
|
459
|
+
|
460
|
+
A simple trait could be:
|
461
|
+
|
462
|
+
module Chingu
|
463
|
+
module Trait
|
464
|
+
module Inspect
|
465
|
+
module ClassMethods
|
466
|
+
def initialize_trait(options)
|
467
|
+
# possible initialize stuff here
|
468
|
+
end
|
469
|
+
|
470
|
+
def inspect
|
471
|
+
"There's {self.size} active instances of class {self.to_s}"
|
472
|
+
end
|
473
|
+
end
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
class Enemy < GameObject
|
478
|
+
has_trait :inspect # includes Chingu::Trait::Inspect and extends Chingu::Trait::Inspect::ClassMethods
|
479
|
+
end
|
480
|
+
10.times { Enemy.create }
|
481
|
+
Enemy.inspect # => There's 10 active instances of class Enemy
|
482
|
+
|
483
|
+
|
484
|
+
Example of using traits :velocity and :timer:
|
455
485
|
|
456
486
|
class Ogre < Chingu::GameObject
|
457
487
|
has_traits :velocity, :timer
|
@@ -466,8 +496,8 @@ Example:
|
|
466
496
|
# These 2 parameters will affect @x and @y every game-iteration
|
467
497
|
# So if your ogre is standing on the ground, make sure you cancel out the effect of @acceleration_y
|
468
498
|
#
|
469
|
-
|
470
|
-
|
499
|
+
self.velocity_x = 1 # move constantly to the right
|
500
|
+
self.acceleration_y = 0.4 # gravity is basicly a downwards acceleration
|
471
501
|
end
|
472
502
|
|
473
503
|
def hit_by(object)
|
@@ -475,7 +505,7 @@ Example:
|
|
475
505
|
# during() and then() is provided by the timer-trait
|
476
506
|
# flash red for 300 millisec when hit, then go back to normal
|
477
507
|
#
|
478
|
-
during(100) {
|
508
|
+
during(100) { self.color = @red; self.mode = :additive }.then { self.color = @white; self.mode = :default }
|
479
509
|
end
|
480
510
|
end
|
481
511
|
|
@@ -483,7 +513,7 @@ The flow for a game object then becomes:
|
|
483
513
|
|
484
514
|
-- creating a GameObject class X ( with a "has_trait :bounding_box, :scale => 0.80" )
|
485
515
|
1) trait gets merged into X, instance and class methods are added
|
486
|
-
2) GameObject.initialize_trait(:scale => 0.80)
|
516
|
+
2) GameObject.initialize_trait(:scale => 0.80) (initialize_trait is a class-method!)
|
487
517
|
-- creating an instance of X
|
488
518
|
1) GameObject#initialize(options)
|
489
519
|
2) GameObject#setup_trait(options)
|
@@ -497,7 +527,7 @@ There's a couple of traits included as default in Chingu:
|
|
497
527
|
|
498
528
|
==== Trait "timer"
|
499
529
|
Adds timer functionality to your game object
|
500
|
-
during(300) {
|
530
|
+
during(300) { self.color = Color.new(0xFFFFFFFF) } # forces @color to white every update for 300 ms
|
501
531
|
after(400) { self.destroy } # destroy object after 400 ms
|
502
532
|
between(1000,2000) { self.rotate(10) } # starting after 1 second, call rotate(10) every update during 1 second
|
503
533
|
every(2000) { Sound["bleep.wav"].play } # play bleep.wav every 2 seconds
|
@@ -514,7 +544,7 @@ You can also scale the calculated rect with has_trait-options:
|
|
514
544
|
# Make player think he's better @ dodging bullets then he really is ;)
|
515
545
|
has_trait :bounding_box, :scale => 0.80
|
516
546
|
|
517
|
-
==== Trait "
|
547
|
+
==== Trait "bounding_circle"
|
518
548
|
Adds accessor 'radius', which returns a Fixnum based on current image size,factor_x and factor_y
|
519
549
|
You can also scale the calculated radius with has_trait-options:
|
520
550
|
|
@@ -530,14 +560,23 @@ Adds class and instance methods for basic collision detection.
|
|
530
560
|
|
531
561
|
# Class method example
|
532
562
|
# This will collide all Enemy-instances with all Bullet-instances using the attribute #radius from each object.
|
533
|
-
Enemy.
|
563
|
+
Enemy.each_bounding_circle_collision(Bullet) do |enemy, bullet|
|
534
564
|
end
|
535
565
|
|
536
566
|
# You can also use the instance methods. This will use the Rect bounding_box from @player and each EnemyRocket-object.
|
537
567
|
@player.each_bounding_box_collision(EnemyRocket) do |player, enemyrocket|
|
538
568
|
player.die!
|
539
569
|
end
|
570
|
+
|
571
|
+
#
|
572
|
+
# each_collision automatically tries to access #radius and #bounding_box to see what a certain game object provides
|
573
|
+
# It knows how to collide radius/radius, bounding_box/bounding_box and radius/bounding_box !
|
574
|
+
# Since You're not explicity telling what collision type to use it might be slighty slower.
|
575
|
+
#
|
576
|
+
[Player, PlayerBullet].each_collision(Enemy, EnemyBullet) do |friend, foe|
|
540
577
|
|
578
|
+
end
|
579
|
+
|
541
580
|
* API isn't stabilized yet! *
|
542
581
|
|
543
582
|
==== (IN DEVELOPMENT) Trait "retrofy"
|
@@ -562,7 +601,7 @@ Chingu solves this problem behind the scenes for the most common assets. The 2 l
|
|
562
601
|
Image["player.png"]
|
563
602
|
|
564
603
|
You also have:
|
565
|
-
Sound["shot.
|
604
|
+
Sound["shot.wav"]
|
566
605
|
Song["intromusic.ogg"]
|
567
606
|
|
568
607
|
The default settings are like this:
|
@@ -589,7 +628,7 @@ Text is a class to give the use of Gosu::Font more rubyish feel and fit it bette
|
|
589
628
|
@font.draw("A Text", 200, 50, 55, 2.0)
|
590
629
|
|
591
630
|
# Chingu
|
592
|
-
@text = Chingu::Text.create(
|
631
|
+
@text = Chingu::Text.create("A Text", :x => 200, :y => 50, :zorder => 55, :factor_x => 2.0)
|
593
632
|
@text.draw
|
594
633
|
|
595
634
|
@text.draw is usually not needed as Text is a GameObject and therefore automaticly updated/drawn (it #create is used instead of #new)
|
@@ -610,7 +649,7 @@ GameObject.all is naming straight from rails for example. Most stuff in GameObje
|
|
610
649
|
|
611
650
|
As far as possible, use correct rubyfied english game_objects, not gameobjects. class HighScore, not Highscore.
|
612
651
|
|
613
|
-
== TODO
|
652
|
+
== TODO - this list is discontinued and no longer updated
|
614
653
|
* add :padding and :align => :topleft etc to class Text
|
615
654
|
* (skip) rename Chingu::Window so 'include Chingu' and 'include Gosu' wont make Window collide
|
616
655
|
* (done) BasicObject vs GameObject vs ScreenObject => Became BasicGameObject and GameObject
|
@@ -656,9 +695,11 @@ As far as possible, use correct rubyfied english game_objects, not gameobjects.
|
|
656
695
|
|
657
696
|
== CREDITS:
|
658
697
|
* Jacius of Rubygame (For doing cool stuff that's well documented as re-usable). So far rect.rb and named_resource.rb is straight outta Rubygame.
|
698
|
+
* Banister (of texplay fame) for general feedeback and help with ruby-internals and building the trait-system
|
659
699
|
* Jduff for input / commits
|
660
700
|
* Jlnr,Philymore,Shawn24,JamesKilton for constructive feedback/discussions
|
661
701
|
* Ariel Pillet for codesuggestions and cleanups
|
702
|
+
* Deps for making the first real full game with Chingu (and making it better in the process)
|
662
703
|
* Thanks to http://github.com/tarcieri for require_all code, good stuff
|
663
704
|
|
664
705
|
== REQUIREMENTS:
|
data/chingu.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{chingu}
|
5
|
-
s.version = "0.6.
|
5
|
+
s.version = "0.6.3"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["ippa"]
|
9
|
-
s.date = %q{2009-11-
|
9
|
+
s.date = %q{2009-11-26}
|
10
10
|
s.description = %q{OpenGL accelerated 2D game framework for Ruby.
|
11
11
|
Builds on the awesome Gosu (Ruby/C++) which provides all the core functionality.
|
12
12
|
It adds simple yet powerful game states, prettier input handling, deployment safe asset-handling, a basic re-usable game object and automation of common task.}
|
data/examples/example14.rb
CHANGED
@@ -11,8 +11,8 @@ class Game < Chingu::Window
|
|
11
11
|
super(640,400)
|
12
12
|
self.input = {:esc => :exit, :q => :decrease_size, :w => :increase_size, :a => :decrease_speed, :s => :increase_speed}
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
20.times { Circle.create(:x => width/2, :y => height/2) }
|
15
|
+
20.times { Box.create(:x => width/2, :y => height/2) }
|
16
16
|
@blue = Color.new(0xFF0000FF)
|
17
17
|
@white = Color.new(0xFFFFFFFF)
|
18
18
|
end
|
@@ -38,7 +38,10 @@ class Game < Chingu::Window
|
|
38
38
|
#
|
39
39
|
# Collide Boxes/Circles, Boxes/Boxes and Circles/Circles (basicly all objects on screen)
|
40
40
|
#
|
41
|
-
|
41
|
+
# Before optmization: 25 FPS (20 boxes and 20 circles)
|
42
|
+
# Cached radius and rects:
|
43
|
+
#
|
44
|
+
#[Box, Circle].each_collision(Box, Circle) { |o, o2| o.color, o2.color = @blue, @blue }
|
42
45
|
|
43
46
|
#
|
44
47
|
# Only collide boxes with other boxes
|
@@ -69,8 +72,8 @@ class Circle < GameObject
|
|
69
72
|
self.velocity_x = 3 - rand * 6
|
70
73
|
self.velocity_y = 3 - rand * 6
|
71
74
|
self.factor = 2
|
72
|
-
|
73
|
-
|
75
|
+
self.input = [:holding_left, :holding_right, :holding_down, :holding_up] # NOTE: giving input an Array, not a Hash
|
76
|
+
cache_bounding_circle
|
74
77
|
end
|
75
78
|
|
76
79
|
def holding_left; @x -= 1; end
|
@@ -94,11 +97,14 @@ class Box < GameObject
|
|
94
97
|
self.velocity_x = 3 - rand * 6
|
95
98
|
self.velocity_y = 3 - rand * 6
|
96
99
|
self.factor = 2
|
100
|
+
cache_bounding_box
|
97
101
|
end
|
98
102
|
|
99
103
|
def update
|
100
104
|
self.velocity_x = -self.velocity_x if @x < 0 || @x > $window.width
|
101
105
|
self.velocity_y = -self.velocity_y if @y < 0 || @y > $window.height
|
106
|
+
#@x = @x.to_i
|
107
|
+
#@y = @y.to_i
|
102
108
|
end
|
103
109
|
end
|
104
110
|
|
data/examples/example4.rb
CHANGED
@@ -34,7 +34,7 @@ class Game < Chingu::Window
|
|
34
34
|
push_game_state(Intro)
|
35
35
|
|
36
36
|
# Yes you can do crazy things like this :)
|
37
|
-
self.input = { :left_mouse_button => lambda{Chingu::Text.create(:text => "Woff!")}, :esc => :exit}
|
37
|
+
self.input = { :left_mouse_button => lambda{Chingu::Text.create(:text => "Woff!")}, :esc => :exit}
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
@@ -51,8 +51,8 @@ class Player < Chingu::GameObject
|
|
51
51
|
def move_down; @y += 1; end
|
52
52
|
|
53
53
|
def fire
|
54
|
-
#puts $window.
|
55
|
-
#puts $window.game_state_manager.inside_state
|
54
|
+
#puts "current_scope: #{$window.current_scope.to_s}"
|
55
|
+
#puts "inside_state: #{$window.game_state_manager.inside_state}"
|
56
56
|
Bullet.create(:x => @x - 20, :y => @y)
|
57
57
|
Bullet.create(:x => @x, :y => @y)
|
58
58
|
Bullet.create(:x => @x + 20, :y => @y)
|
data/examples/example6.rb
CHANGED
@@ -43,9 +43,18 @@ class Game < Chingu::Window
|
|
43
43
|
end
|
44
44
|
|
45
45
|
class State1 < Chingu::GameState
|
46
|
-
|
47
|
-
|
46
|
+
|
47
|
+
#
|
48
|
+
# This is another way of achieving the same thing as the out-commeted draw-code
|
49
|
+
# Since .create is used, it's automatically updated and drawn
|
50
|
+
#
|
51
|
+
def setup
|
52
|
+
Chingu::GameObject.create(:image => "ruby.png", :rotation_center => :top_left)
|
48
53
|
end
|
54
|
+
|
55
|
+
#def draw
|
56
|
+
# Image["ruby.png"].draw(0,0,0)
|
57
|
+
#end
|
49
58
|
end
|
50
59
|
|
51
60
|
class State2 < Chingu::GameState
|
data/examples/example9.rb
CHANGED
@@ -76,9 +76,13 @@ class ParticleState < Chingu::GameState
|
|
76
76
|
end
|
77
77
|
|
78
78
|
#
|
79
|
-
# GameObject.each_collsion /
|
79
|
+
# GameObject.each_collsion / each_bounding_box_collision wont collide an object with itself
|
80
80
|
#
|
81
|
-
FireCube.
|
81
|
+
# FireCube.each_bounding_circle_collision(FireCube) do |cube1, cube2| # 30 FPS on my computer
|
82
|
+
#
|
83
|
+
# Let's see if we can optimize each_collision, starts with 19 FPS
|
84
|
+
#
|
85
|
+
FireCube.each_collision(FireCube) do |cube1, cube2|
|
82
86
|
cube1.die!
|
83
87
|
cube2.die!
|
84
88
|
end
|
data/examples/game1.rb
CHANGED
@@ -35,12 +35,10 @@ class Level < Chingu::GameState
|
|
35
35
|
def initialize(options = {})
|
36
36
|
super
|
37
37
|
|
38
|
-
@parallax = Parallax.create
|
39
|
-
|
40
|
-
|
41
|
-
@
|
42
|
-
@parallax << ParallaxLayer.new(:image => Image["city1.png"].retrofy, :center => 0, :damping => 1, :factor => $window.factor)
|
43
|
-
@player = Player.create(:x => 10, :y => 10)
|
38
|
+
@parallax = Parallax.create(:rotation_center => :top_left)
|
39
|
+
@parallax << { :image => Image["city2.png"].retrofy, :damping => 2, :factor => $window.factor }
|
40
|
+
@parallax << { :image => Image["city1.png"].retrofy, :damping => 1, :factor => $window.factor }
|
41
|
+
@player = Player.create(:x => 30, :y => 10)
|
44
42
|
|
45
43
|
@bg1 = Color.new(0xFFCE28FF)
|
46
44
|
@bg2 = Color.new(0xFF013E87)
|
@@ -95,12 +93,12 @@ class Level < Chingu::GameState
|
|
95
93
|
push_game_state(GameOver) if solid_pixel_at?(@player.x, @player.y)
|
96
94
|
|
97
95
|
# Collide player with enemies and enemy bullets
|
98
|
-
@player.
|
96
|
+
@player.each_bounding_circle_collision(Enemy) do |player, enemy|
|
99
97
|
enemy.die
|
100
98
|
push_game_state(GameOver)
|
101
99
|
end
|
102
100
|
|
103
|
-
Bullet.
|
101
|
+
Bullet.each_bounding_circle_collision(Enemy) do |bullet, enemy|
|
104
102
|
bullet.die
|
105
103
|
if enemy.hit_by(bullet)
|
106
104
|
@player.score += 20
|
data/lib/chingu.rb
CHANGED
@@ -7,7 +7,7 @@ module Chingu
|
|
7
7
|
# It will also acts as a container for the trait-system of chingu.
|
8
8
|
#
|
9
9
|
class BasicGameObject
|
10
|
-
include Chingu::ClassInheritableAccessor
|
10
|
+
include Chingu::Helpers::ClassInheritableAccessor # adds classmethod class_inheritable_accessor
|
11
11
|
|
12
12
|
attr_reader :options, :paused, :visible
|
13
13
|
attr_accessor :parent
|
@@ -65,9 +65,10 @@ module Chingu
|
|
65
65
|
#
|
66
66
|
# A GameObject either belong to a GameState or our mainwindow ($window)
|
67
67
|
#
|
68
|
-
if !@parent && $window && $window.respond_to?(:game_state_manager)
|
69
|
-
|
70
|
-
end
|
68
|
+
#if !@parent && $window && $window.respond_to?(:game_state_manager)
|
69
|
+
# @parent = $window.game_state_manager.inside_state || $window
|
70
|
+
#end
|
71
|
+
@parent = $window.current_scope if !@parent && $window
|
71
72
|
|
72
73
|
# if true, BasicGameObject#update will be called
|
73
74
|
@paused = options[:paused] || false
|
@@ -97,6 +98,7 @@ module Chingu
|
|
97
98
|
#
|
98
99
|
instance.parent.add_game_object(instance) if instance.parent
|
99
100
|
|
101
|
+
|
100
102
|
return instance
|
101
103
|
end
|
102
104
|
|
@@ -168,14 +170,14 @@ module Chingu
|
|
168
170
|
# Bullet.all.each do {} # Iterate through all bullets in current game state
|
169
171
|
#
|
170
172
|
def self.all
|
171
|
-
$window.
|
173
|
+
$window.current_scope.game_objects.of_class(self).dup
|
172
174
|
end
|
173
175
|
|
174
176
|
#
|
175
177
|
# Returns
|
176
178
|
#
|
177
179
|
def self.size
|
178
|
-
$window.
|
180
|
+
$window.current_scope.game_objects.of_class(self).size
|
179
181
|
end
|
180
182
|
|
181
183
|
#
|
@@ -9,4 +9,27 @@ class Array
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
12
|
+
|
13
|
+
def each_bounding_circle_collision(*args)
|
14
|
+
list = (self + args).uniq
|
15
|
+
collide_pair = []
|
16
|
+
list.each_with_index { |nr, i| self[i..size].collect { |nr2| collide_pair << [nr,nr2] } }
|
17
|
+
collide_pair.each do |class1,class2|
|
18
|
+
class1.each_bounding_circle_collision(class2) do |object1, object2|
|
19
|
+
yield object1, object2
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def each_bounding_box_collision(*args)
|
25
|
+
list = (self + args).uniq
|
26
|
+
collide_pair = []
|
27
|
+
list.each_with_index { |nr, i| self[i..size].collect { |nr2| collide_pair << [nr,nr2] } }
|
28
|
+
collide_pair.each do |class1,class2|
|
29
|
+
class1.each_bounding_box_collision(class2) do |object1, object2|
|
30
|
+
yield object1, object2
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
12
35
|
end
|
data/lib/chingu/game_object.rb
CHANGED
@@ -37,7 +37,6 @@ module Chingu
|
|
37
37
|
include Chingu::Helpers::InputClient # Adds input and input=
|
38
38
|
include Chingu::Helpers::RotationCenter # Adds easy and verbose modification of @center_x and @center_y
|
39
39
|
|
40
|
-
|
41
40
|
def initialize(options = {})
|
42
41
|
super
|
43
42
|
|
@@ -45,7 +44,7 @@ module Chingu
|
|
45
44
|
if options[:image].is_a?(Gosu::Image)
|
46
45
|
@image = options[:image]
|
47
46
|
elsif options[:image].is_a? String
|
48
|
-
@image = Image[options[:image]]
|
47
|
+
@image = Gosu::Image[options[:image]]
|
49
48
|
end
|
50
49
|
|
51
50
|
@x = options[:x] || 0
|
@@ -76,7 +75,7 @@ module Chingu
|
|
76
75
|
@mode = options[:mode] || :default # :additive is also available.
|
77
76
|
@zorder = options[:zorder] || 100
|
78
77
|
|
79
|
-
|
78
|
+
#setup_trait(options) if self.respond_to?(:setup_trait)
|
80
79
|
end
|
81
80
|
|
82
81
|
# Quick way of setting both factor_x and factor_y
|
data/lib/chingu/game_state.rb
CHANGED
@@ -54,20 +54,23 @@ module Chingu
|
|
54
54
|
include Chingu::Helpers::GameObject # Adds game_objects_of_class etc ...
|
55
55
|
include Chingu::Helpers::InputDispatcher # Input dispatch-helpers
|
56
56
|
include Chingu::Helpers::InputClient # GameState can have it's own inputmap
|
57
|
+
include Chingu::Helpers::ClassInheritableAccessor # adds classmethod class_inheritable_accessor
|
57
58
|
|
58
59
|
attr_reader :options
|
59
60
|
attr_accessor :game_state_manager, :game_objects
|
60
61
|
|
61
|
-
|
62
|
+
class_inheritable_accessor :trait_options
|
63
|
+
@trait_options = Hash.new
|
62
64
|
def trait_options; self.class.trait_options; end
|
63
|
-
|
65
|
+
|
64
66
|
#
|
65
67
|
# Adds a trait or traits to a certain game class
|
66
68
|
# Executes a standard ruby "include" the specified module
|
67
69
|
#
|
68
70
|
def self.has_trait(trait, options = {})
|
69
|
-
|
71
|
+
|
70
72
|
if trait.is_a?(::Symbol) || trait.is_a?(::String)
|
73
|
+
## puts "has_trait #{trait}, #{options}"
|
71
74
|
begin
|
72
75
|
# Convert user-given symbol (eg. :timer) to a Module (eg. Chingu::Traits::Timer)
|
73
76
|
mod = Chingu::Traits.const_get(Chingu::Inflector.camelize(trait))
|
@@ -75,14 +78,21 @@ module Chingu
|
|
75
78
|
# Include the module, which will add the containing methods as instance methods
|
76
79
|
include mod
|
77
80
|
|
78
|
-
#
|
79
|
-
|
80
|
-
|
81
|
+
# Does sub-module "ClessMethods" exists?
|
82
|
+
# (eg: Chingu::Traits::Timer::ClassMethods)
|
83
|
+
if mod.const_defined?("ClassMethods")
|
84
|
+
# Add methods in scope ClassMethods as.. class methods!
|
85
|
+
mod2 = mod.const_get("ClassMethods")
|
86
|
+
extend mod2
|
81
87
|
|
82
|
-
|
83
|
-
|
84
|
-
|
88
|
+
# If the newly included trait has a initialize_trait method in the ClassMethods-scope:
|
89
|
+
# ... call it with the options provided with the has_trait-line.
|
90
|
+
if mod2.method_defined?(:initialize_trait)
|
91
|
+
initialize_trait(options)
|
92
|
+
end
|
93
|
+
end
|
85
94
|
rescue
|
95
|
+
puts $!
|
86
96
|
end
|
87
97
|
end
|
88
98
|
end
|
@@ -114,6 +114,7 @@ module Chingu
|
|
114
114
|
current_game_state.finalize if current_game_state.respond_to?(:finalize) && options[:finalize]
|
115
115
|
|
116
116
|
# So BasicGameObject#create connects object to new state in its setup()
|
117
|
+
# Is this doubled in GameState.initialize() ?
|
117
118
|
self.inside_state = new_state
|
118
119
|
|
119
120
|
# Call setup
|
@@ -131,8 +132,10 @@ module Chingu
|
|
131
132
|
@game_states[-1] = new_state
|
132
133
|
end
|
133
134
|
end
|
134
|
-
##
|
135
|
+
## MOVED: self.inside_state = current_game_state
|
135
136
|
end
|
137
|
+
|
138
|
+
self.inside_state = nil # no longer 'inside' (as in within initialize() etc) a game state
|
136
139
|
end
|
137
140
|
alias :switch :switch_game_state
|
138
141
|
|
@@ -157,6 +160,7 @@ module Chingu
|
|
157
160
|
new_state.setup if new_state.respond_to?(:setup) && options[:setup]
|
158
161
|
|
159
162
|
# Make sure the game state knows about the manager
|
163
|
+
# Is this doubled in GameState.initialize() ?
|
160
164
|
new_state.game_state_manager = self
|
161
165
|
|
162
166
|
# Give the soon-to-be-disabled state a chance to clean up by calling finalize() on it.
|
@@ -172,6 +176,8 @@ module Chingu
|
|
172
176
|
end
|
173
177
|
## MOVED: self.inside_state = current_game_state
|
174
178
|
end
|
179
|
+
|
180
|
+
self.inside_state = nil # no longer 'inside' (as in within initialize() etc) a game state
|
175
181
|
end
|
176
182
|
alias :push :push_game_state
|
177
183
|
|
@@ -195,6 +201,7 @@ module Chingu
|
|
195
201
|
@game_states.pop
|
196
202
|
|
197
203
|
# So BasicGameObject#create connects object to new state in its setup()
|
204
|
+
# Is this doubled in GameState.initialize() ?
|
198
205
|
self.inside_state = current_game_state
|
199
206
|
|
200
207
|
# Call setup on the new current state
|
@@ -205,7 +212,9 @@ module Chingu
|
|
205
212
|
transitional_game_state = @transitional_game_state.new(current_game_state, @transitional_game_state_options)
|
206
213
|
self.switch_game_state(transitional_game_state, :transitional => false)
|
207
214
|
end
|
215
|
+
|
208
216
|
## MOVED: self.inside_state = current_game_state
|
217
|
+
self.inside_state = nil # no longer 'inside' (as in within initialize() etc) a game state
|
209
218
|
end
|
210
219
|
alias :pop :pop_game_state
|
211
220
|
|
@@ -3,27 +3,29 @@
|
|
3
3
|
# But we use the rails-name for it, class_inheritable_accessor, which should make ppl more @ home.
|
4
4
|
#
|
5
5
|
module Chingu
|
6
|
-
module
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
module ClassMethods
|
12
|
-
def class_inheritable_accessor(*args)
|
13
|
-
@cattr_inheritable_attrs ||= [:cattr_inheritable_attrs]
|
14
|
-
@cattr_inheritable_attrs += args
|
15
|
-
args.each do |arg|
|
16
|
-
class_eval %(
|
17
|
-
class << self; attr_accessor :#{arg} end
|
18
|
-
)
|
19
|
-
end
|
20
|
-
@cattr_inheritable_attrs
|
6
|
+
module Helpers
|
7
|
+
module ClassInheritableAccessor
|
8
|
+
def self.included(base)
|
9
|
+
base.extend(ClassMethods)
|
21
10
|
end
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def class_inheritable_accessor(*args)
|
14
|
+
@cattr_inheritable_attrs ||= [:cattr_inheritable_attrs]
|
15
|
+
@cattr_inheritable_attrs += args
|
16
|
+
args.each do |arg|
|
17
|
+
class_eval %(
|
18
|
+
class << self; attr_accessor :#{arg} end
|
19
|
+
)
|
20
|
+
end
|
21
|
+
@cattr_inheritable_attrs
|
22
|
+
end
|
23
|
+
|
24
|
+
def inherited(subclass)
|
25
|
+
@cattr_inheritable_attrs.each do |inheritable_attribute|
|
26
|
+
instance_var = "@#{inheritable_attribute}"
|
27
|
+
subclass.instance_variable_set(instance_var, instance_variable_get(instance_var))
|
28
|
+
end
|
27
29
|
end
|
28
30
|
end
|
29
31
|
end
|
data/lib/chingu/helpers/gfx.rb
CHANGED
@@ -115,7 +115,7 @@ module Chingu
|
|
115
115
|
def draw_circle(cx,cy,r,color)
|
116
116
|
0.step(360, CIRCLE_STEP) do |a1|
|
117
117
|
a2 = a1 + CIRCLE_STEP
|
118
|
-
$window.draw_line cx + offset_x(a1, r), cy + offset_y(a1, r), color, cx + offset_x(a2, r), cy + offset_y(a2, r), color, 9999
|
118
|
+
$window.draw_line cx + Gosu.offset_x(a1, r), cy + Gosu.offset_y(a1, r), color, cx + Gosu.offset_x(a2, r), cy + Gosu.offset_y(a2, r), color, 9999
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
data/lib/chingu/parallax.rb
CHANGED
@@ -36,7 +36,8 @@ module Chingu
|
|
36
36
|
#
|
37
37
|
# Options (in hash-format):
|
38
38
|
#
|
39
|
-
#
|
39
|
+
# repeat_x: [true|false] repeat layer on X-axis
|
40
|
+
# repeat_y: [true|false] repeat layer on Y-axis
|
40
41
|
#
|
41
42
|
def initialize(options = {})
|
42
43
|
super(options)
|
@@ -61,7 +62,7 @@ module Chingu
|
|
61
62
|
# returns true if any part of the parallax-scroller is inside the window
|
62
63
|
#
|
63
64
|
def inside_window?
|
64
|
-
return true if @
|
65
|
+
return true if @repeat_x || @repeat_y
|
65
66
|
@layers.each { |layer| return true if layer.inside_window? }
|
66
67
|
return false
|
67
68
|
end
|
@@ -122,31 +123,30 @@ module Chingu
|
|
122
123
|
#
|
123
124
|
def draw
|
124
125
|
@layers.each do |layer|
|
125
|
-
layer.draw
|
126
|
+
#layer.draw
|
126
127
|
|
127
128
|
save_x, save_y = layer.x, layer.y
|
128
129
|
|
129
130
|
# If layer lands inside our window and repeat_x is true (defaults to true), draw it until window ends
|
130
131
|
while layer.repeat_x && layer.x < $window.width
|
131
132
|
while layer.repeat_y && layer.y < $window.height
|
132
|
-
layer.y += layer.image.height
|
133
133
|
layer.draw
|
134
|
+
layer.y += layer.image.height
|
134
135
|
end
|
135
136
|
layer.y = save_y
|
136
137
|
|
137
|
-
layer.x += layer.image.width
|
138
138
|
layer.draw
|
139
|
+
layer.x += layer.image.width
|
139
140
|
end
|
140
141
|
|
141
|
-
# Special loop for when repeat_y is
|
142
|
+
# Special loop for when repeat_y is true but not repeat_x
|
142
143
|
if layer.repeat_y && !layer.repeat_x
|
143
144
|
while layer.repeat_y && layer.y < $window.height
|
144
|
-
layer.y += layer.image.height
|
145
145
|
layer.draw
|
146
|
+
layer.y += layer.image.height
|
146
147
|
end
|
147
148
|
end
|
148
149
|
|
149
|
-
|
150
150
|
layer.x = save_x
|
151
151
|
end
|
152
152
|
self
|
data/lib/chingu/text.rb
CHANGED
@@ -32,8 +32,23 @@ module Chingu
|
|
32
32
|
trait_options[:bounding_box] = options
|
33
33
|
end
|
34
34
|
end
|
35
|
-
|
36
|
-
def
|
35
|
+
|
36
|
+
def setup_trait(options)
|
37
|
+
@cached_bounding_box = nil
|
38
|
+
super
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# Returns an instance of class Rect
|
43
|
+
#
|
44
|
+
def bounding_box
|
45
|
+
if @cached_bounding_box
|
46
|
+
@cached_bounding_box.x = self.x + @_x_diff
|
47
|
+
@cached_bounding_box.y = self.y + @_y_diff
|
48
|
+
|
49
|
+
return @cached_bounding_box
|
50
|
+
end
|
51
|
+
|
37
52
|
width = self.image.width * self.factor_x.abs
|
38
53
|
height = self.image.height * self.factor_y.abs
|
39
54
|
|
@@ -49,6 +64,18 @@ module Chingu
|
|
49
64
|
end
|
50
65
|
alias :bb :bounding_box
|
51
66
|
|
67
|
+
def cache_bounding_box
|
68
|
+
@cached_bounding_box = nil
|
69
|
+
@cached_bounding_box = self.bounding_box
|
70
|
+
@_x_diff = @cached_bounding_box.x - self.x
|
71
|
+
@_y_diff = @cached_bounding_box.y - self.y
|
72
|
+
end
|
73
|
+
|
74
|
+
#def update_trait
|
75
|
+
# cache_bounding_box if trait_options[:bounding_box][:cache] && !@cached_bounding_box
|
76
|
+
# super
|
77
|
+
#end
|
78
|
+
|
52
79
|
def draw_trait
|
53
80
|
if trait_options[:bounding_box][:debug]
|
54
81
|
$window.draw_rect(self.bounding_box, Chingu::DEBUG_COLOR, Chingu::DEBUG_ZORDER)
|
@@ -31,15 +31,22 @@ module Chingu
|
|
31
31
|
|
32
32
|
module ClassMethods
|
33
33
|
def initialize_trait(options = {})
|
34
|
-
trait_options[:
|
34
|
+
trait_options[:bounding_circle] = options
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
+
def setup_trait(options)
|
39
|
+
@cached_radius = nil
|
40
|
+
super
|
41
|
+
end
|
42
|
+
|
38
43
|
def radius
|
44
|
+
return @cached_radius if @cached_radius
|
45
|
+
|
39
46
|
width = self.image.width * self.factor_x.abs
|
40
47
|
height = self.image.height * self.factor_y.abs
|
41
48
|
radius = (width + height) / 4
|
42
|
-
radius = radius * trait_options[:
|
49
|
+
radius = radius * trait_options[:bounding_circle][:scale] if trait_options[:bounding_circle][:scale]
|
43
50
|
return radius
|
44
51
|
end
|
45
52
|
|
@@ -47,13 +54,23 @@ module Chingu
|
|
47
54
|
radius * 2
|
48
55
|
end
|
49
56
|
|
57
|
+
def cache_bounding_circle
|
58
|
+
@cached_radius = nil
|
59
|
+
@cached_radius = self.radius
|
60
|
+
end
|
61
|
+
|
62
|
+
#def update_trait
|
63
|
+
# cache_bounding_circle if trait_options[:bounding_circle][:cache] && !@cached_radius
|
64
|
+
# super
|
65
|
+
#end
|
66
|
+
|
50
67
|
def circle_left; self.x - self.radius; end
|
51
68
|
def circle_right; self.x + self.radius; end
|
52
69
|
def circle_top; self.y - self.radius; end
|
53
70
|
def circle_bottom; self.y + self.radius; end
|
54
71
|
|
55
72
|
def draw_trait
|
56
|
-
if trait_options[:
|
73
|
+
if trait_options[:bounding_circle][:debug]
|
57
74
|
$window.draw_circle(self.x, self.y, self.radius, Chingu::DEBUG_COLOR)
|
58
75
|
end
|
59
76
|
super
|
@@ -49,11 +49,12 @@ module Chingu
|
|
49
49
|
if self.respond_to?(:bounding_box) && object2.respond_to?(:bounding_box)
|
50
50
|
bounding_box_collision?(object2)
|
51
51
|
elsif self.respond_to?(:radius) && object2.respond_to?(:radius)
|
52
|
-
|
52
|
+
bounding_circle_collision?(object2)
|
53
53
|
else
|
54
|
-
|
54
|
+
bounding_box_bounding_circle_collision?(object2)
|
55
55
|
end
|
56
56
|
end
|
57
|
+
alias :collision? :collides?
|
57
58
|
|
58
59
|
#
|
59
60
|
# Collide self with a given game object by checking both objects bounding_box'es
|
@@ -67,8 +68,8 @@ module Chingu
|
|
67
68
|
# Collide self using distance between 2 objects and their radius.
|
68
69
|
# Returns true if colliding.
|
69
70
|
#
|
70
|
-
def
|
71
|
-
distance(self.x, self.y, object2.x, object2.y) < self.radius + object2.radius
|
71
|
+
def bounding_circle_collision?(object2)
|
72
|
+
Gosu.distance(self.x, self.y, object2.x, object2.y) < self.radius + object2.radius
|
72
73
|
end
|
73
74
|
|
74
75
|
#
|
@@ -76,7 +77,7 @@ module Chingu
|
|
76
77
|
#
|
77
78
|
# http://stackoverflow.com/questions/401847/circle-rectangle-collision-detection-intersection
|
78
79
|
#
|
79
|
-
def
|
80
|
+
def bounding_box_bounding_circle_collision?(object2)
|
80
81
|
rect = self.respond_to?(:bounding_box) ? self.bounding_box : object2.bounding_box
|
81
82
|
circle = self.respond_to?(:radius) ? self : object2
|
82
83
|
radius = circle.radius.to_i
|
@@ -110,10 +111,10 @@ module Chingu
|
|
110
111
|
# Explicit radius-collision
|
111
112
|
# Works like each_collsion but with inline-code for speedups
|
112
113
|
#
|
113
|
-
def
|
114
|
+
def each_bounding_circle_collision(klasses = [])
|
114
115
|
Array(klasses).each do |klass|
|
115
116
|
klass.all.each do |object|
|
116
|
-
yield(self, object) if distance(self.x, self.y, object.x, object.y) < self.radius + object.radius
|
117
|
+
yield(self, object) if Gosu.distance(self.x, self.y, object.x, object.y) < self.radius + object.radius
|
117
118
|
end
|
118
119
|
end
|
119
120
|
end
|
@@ -135,7 +136,7 @@ module Chingu
|
|
135
136
|
#
|
136
137
|
# Works like each_collision but with inline-code for speedups
|
137
138
|
#
|
138
|
-
def
|
139
|
+
def each_bounding_circle_collision(klasses = [])
|
139
140
|
Array(klasses).each do |klass|
|
140
141
|
object2_list = klass.all
|
141
142
|
#total_radius = object1.radius + object2.radius # possible optimization?
|
@@ -143,7 +144,7 @@ module Chingu
|
|
143
144
|
self.all.each do |object1|
|
144
145
|
object2_list.each do |object2|
|
145
146
|
next if object1 == object2 # Don't collide objects with themselves
|
146
|
-
yield object1, object2 if distance(object1.x, object1.y, object2.x, object2.y) < object1.radius + object2.radius
|
147
|
+
yield object1, object2 if Gosu.distance(object1.x, object1.y, object2.x, object2.y) < object1.radius + object2.radius
|
147
148
|
end
|
148
149
|
end
|
149
150
|
end
|
@@ -190,7 +191,7 @@ module Chingu
|
|
190
191
|
# self.all.each do |object1|
|
191
192
|
# object2_list.each do |object2|
|
192
193
|
# next if object1 == object2 # Don't collide objects with themselves
|
193
|
-
# yield object1, object2 if object1.
|
194
|
+
# yield object1, object2 if object1.bounding_box_bounding_circle_collision?(object2)
|
194
195
|
# end
|
195
196
|
# end
|
196
197
|
#end
|
data/lib/chingu/window.rb
CHANGED
@@ -59,8 +59,15 @@ module Chingu
|
|
59
59
|
@milliseconds_since_last_tick = 0
|
60
60
|
end
|
61
61
|
|
62
|
-
|
63
|
-
|
62
|
+
#
|
63
|
+
# Returns self inside GameState.initialize (a game state is not 'active' inside initialize())
|
64
|
+
# Or returns current active game state (as in a switched to or pushed game state)
|
65
|
+
# ... Falls back to returning $window
|
66
|
+
#
|
67
|
+
# current_scope is used to make GameObject.all and friends work everywhere.
|
68
|
+
#
|
69
|
+
def current_scope
|
70
|
+
game_state_manager.inside_state || game_state_manager.current_game_state || self
|
64
71
|
end
|
65
72
|
|
66
73
|
#
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chingu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ippa
|
@@ -30,7 +30,7 @@ cert_chain:
|
|
30
30
|
hxtMlw==
|
31
31
|
-----END CERTIFICATE-----
|
32
32
|
|
33
|
-
date: 2009-11-
|
33
|
+
date: 2009-11-26 00:00:00 +01:00
|
34
34
|
default_executable:
|
35
35
|
dependencies:
|
36
36
|
- !ruby/object:Gem::Dependency
|
metadata.gz.sig
CHANGED
Binary file
|