gosu_android 0.0.4 → 0.0.5

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/README.md CHANGED
@@ -1,27 +1,36 @@
1
1
  Gosu-Android
2
2
  ============
3
- A Gosu implementation for Adroid devices.
3
+ A [Gosu](http://www.libgosu.org/) implementation for Adroid devices.
4
4
 
5
5
  Installation
6
6
  -----------
7
7
 
8
- ### Easy way
8
+ Install [ruboto](https://github.com/ruboto/ruboto/) and create a project.
9
9
 
10
- * Create a file named Gemfile.apk in your ruboto project and add the lines
10
+ ### Recomended
11
+
12
+ With this installation method you will have a clean enviroment (bundler) to make your gosu games.
13
+
14
+ * Create a file named `Gemfile.apk` in your ruboto project and add the lines:
11
15
 
12
16
  ```ruby
13
- source "http://rubygems.org"
14
- gem 'gosu_android'
17
+ source "http://rubygems.org"
18
+ gem 'gosu_android'
15
19
  ```
16
20
 
17
- * Create a folder inside `res` folder call `drawable-nodpi` and copy this file https://github.com/neochuky/gosu-android/tree/master/res/drawable-nodpi/character_atlas8.png
18
- in it.
21
+ * Create a folder inside `res` called `drawable-nodpi` and copy this [file] (https://github.com/neochuky/gosu-android/tree/master/res/drawable-nodpi/character_atlas8.png)
22
+ in it. On linux you can do it easily with:
23
+ `mkdir res/drawable-nodpi`
24
+ `wget https://raw.github.com/neochuky/gosu-android/master/res/drawable-nodpi/character_atlas8.png`
25
+ `mv character_atlas8.png res/drawable-nodpi`
26
+
27
+ ### Alternative
28
+ With this installation method you will have a dirty enviroment (simple file copy) to try the samples.
19
29
 
20
- ### Not so easy way
21
- `gem install gosu_android`
30
+ * `gem install gosu_android`
22
31
 
23
- As with ruboto, place yourself in the root directory of your app, then execute
24
- `gosu_android -a` or `gosu_android --add` to automatically copy every gosu_android file to your ruboto project.
32
+ * As with ruboto, place yourself in the root directory of your app.
33
+ * Then execute `gosu_android -a` or `gosu_android --add` to automatically copy every gosu_android file to your ruboto project.
25
34
  It will also copy all the media files that are use in gosu_android examples.
26
35
 
27
36
  General Information
@@ -29,7 +38,7 @@ General Information
29
38
  * This is still an early effort, so there are a number of features that had not yet been added.
30
39
  * There are some known bugs that I hope to fix soon.
31
40
  * In its current status there are some small changes to Gosu Window initialization, check examples.
32
- * A new object with some basic physics has been added.
41
+ * A new object with some basic physics has been added, check out the [wiki](https://github.com/neochuky/gosu-android/wiki/The-new-gosu-android-physics) to learn more.
33
42
 
34
43
  Troubleshooting
35
44
  -------------------
@@ -1,105 +1,232 @@
1
1
  require 'gosu'
2
+ require 'chipmunk'
3
+
4
+ SUBSTEPS = 6
5
+
6
+ module Resources
7
+ if defined? Ruboto
8
+ Resources::BALL = Ruboto::R::drawable::yellow_square
9
+ Resources::BEEP = Ruboto::R::raw::beep
10
+ Resources::SONG = Ruboto::R::raw::chriss_onac_tempo_red
11
+ Resources::BLOCK = Ruboto::R::drawable::bar_hor
12
+ else
13
+ Resources::BALL = "media/yellow_square.png"
14
+ Resources::BEEP = "media/beep.wav"
15
+ Resources::SONG = "media/chriss_onac_tempo_red.mp3"
16
+ Resources::BLOCK = "media/bar_hor.png"
17
+ end
18
+ end
19
+
20
+ class Ball
21
+ attr_reader :shape
22
+ def initialize window, shape, file_name, x, y, z, size, velocity_x, velocity_y
23
+ @shape = shape
24
+ @shape.body.p = CP::Vec2.new(x, y) # position
25
+ @shape.body.v = CP::Vec2.new(velocity_x, velocity_y) # velocity
26
+ @z = z
27
+ @image = Gosu::Image.new(window, file_name, false)
28
+ end
29
+
30
+ def bounce other_object
31
+ #Calculate new velocity, after the hit
32
+ if other_object.type == :vertical
33
+ @shape.body.v.x = -@shape.body.v.x
34
+ else
35
+ @shape.body.v.y = -@shape.body.v.y
36
+ end
37
+ end
38
+
39
+ def validate_position
40
+ #Check that the ball did not go under the screen
41
+ if @shape.body.p.y > 480
42
+ @shape.body.p.y = 200
43
+ @shape.body.v.y = -@shape.body.v.x
44
+ end
45
+ end
46
+
47
+ def draw
48
+ @image.draw(@shape.body.p.x, @shape.body.p.y, @z)
49
+ end
50
+ end
51
+
52
+ class StillObject
53
+ attr_reader :type, :shape, :deletable
54
+ def initialize(window, shape, file_name, x, y, z, type, deletable)
55
+ @image = Gosu::Image.new(window, file_name)
56
+ @z = z
57
+ @deletable = deletable
58
+ @type = type
59
+ @shape = shape
60
+ @shape.body.p = CP::Vec2.new(x , y ) # position
61
+ @shape.body.v = CP::Vec2.new(0, 0) # velocity
62
+ end
63
+
64
+ def draw
65
+ @image.draw(@shape.body.p.x, @shape.body.p.y, @z)
66
+ end
67
+ end
2
68
 
3
69
  class GameWindow < Gosu::Window
4
70
  def initialize
5
71
  super 600, 480, false, 30
6
72
  self.caption = "Gosu Arkanoid"
7
- self.physics_manager.gravity_y = 0
8
73
  @score = 0
9
- @song = Gosu::Song.new(self, Ruboto::R::raw::chriss_onac_tempo_red)
10
- @beep = Gosu::Sample.new(self, Ruboto::R::raw::beep)
74
+ @song = Gosu::Song.new(self, Resources::SONG)
75
+ @beep = Gosu::Sample.new(self, Resources::BEEP)
11
76
  @p1x = 0
12
-
13
- @ball = Gosu::Square.new(self, Ruboto::R::drawable::ball, 100, 200, 0, 50, 20, 100, 100)
14
-
15
- @player_x = 300
16
- @player_y = 473
17
- @size = 110
18
- # 25 is to compesate square size of the ball
19
- @size2 = @size/2 - 25
20
- @player = Gosu::Plane.new(self,Ruboto::R::drawable::bar_hor, [@player_x, @player_y], [@player_x + @size, @player_y], 0)
77
+ @stillObjects = Array.new
78
+ # Time increment over which to apply a physics "step" ("delta t")
79
+ @dt = self.update_interval/(1000.0*SUBSTEPS)
80
+ @space = CP::Space.new
81
+
82
+ #Ball body, rguments for body new are mass and inertia
83
+ ball_body = CP::Body.new(1.0, 150.0)
84
+
85
+ #Shape, we define a square shape
86
+ ball_shape_array = [CP::Vec2.new(-5.0, -5.0), CP::Vec2.new(-5.0, 5.0), CP::Vec2.new(5.0, 5.0), CP::Vec2.new(5.0, -5.0)]
87
+ #Arguments are the body, the shape and an offset to be added to each vertex
88
+ ball_shape = CP::Shape::Poly.new(ball_body, ball_shape_array, CP::Vec2.new(0,0))
89
+ #Set a name for collisions
90
+ ball_shape.collision_type = :ball
91
+ #Add the body and the shape to the space
92
+ @space.add_body(ball_body)
93
+ @space.add_shape(ball_shape)
94
+
95
+ @ball = Ball.new(self, ball_shape, Resources::BALL, 100, 200, 0, 10, 100, 100)
96
+
97
+ #Size of the image we are using for the blocks
98
+ @size = 110
99
+ new_block_body_shape CP::Vec2.new(1.0, 1.0), CP::Vec2.new(@size, 1.0)
100
+ @player = StillObject.new(self, @shape_block, Resources::BLOCK, 300, 473, 0, :horizontal, false)
21
101
 
22
102
  #Left plane
23
- @p1 = Gosu::Plane.new(self, Ruboto::R::drawable::bar, [0, 0], [0, 480], 0)
103
+ new_block_body_shape CP::Vec2.new(1.0, 1.0), CP::Vec2.new(1.0, 480.0)
104
+ @p1 = StillObject.new(self, @shape_block,Resources::BLOCK, 0, 0, 0, :vertical, false)
24
105
  #Top plane
25
- @p2 = Gosu::Plane.new(self, Ruboto::R::drawable::bar, [600, 0], [0, 0], 0)
106
+ new_block_body_shape CP::Vec2.new(1.0, 1.0), CP::Vec2.new(600.0, 1.0)
107
+ @p2 = StillObject.new(self, @shape_block,Resources::BLOCK, 0, 0, 0, :horizontal, false)
26
108
  #Right plane
27
- @p3 = Gosu::Plane.new(self,Ruboto::R::drawable::bar, [600, 480], [600, 0], 0)
109
+ new_block_body_shape CP::Vec2.new(1.0, 1.0), CP::Vec2.new(1.0, 480.0)
110
+ @p3 = StillObject.new(self, @shape_block,Resources::BLOCK, 600, 0 , 0, :vertical, false)
28
111
 
29
112
  @blocks = []
30
113
  @blocks_position = []
31
114
  block_x = 150
32
115
  block_y = 120
33
- img = Ruboto::R::drawable::bar_hor
116
+ img = Resources::BLOCK
34
117
  2.times do |i|
35
118
  3.times do |j|
36
- @blocks.push Gosu::Plane.new(self, img, [block_x + (@size + 30)*i , block_y + 30*j ], [block_x + (@size + 30)*(i + 1), block_y + 30*j ], 0)
37
- @blocks_position.push [block_x + (@size + 30)*i, block_y + 30*j]
119
+ new_block_body_shape CP::Vec2.new(1.0, 1.0), CP::Vec2.new(@size, 1.0)
120
+ @blocks.push StillObject.new(self, @shape_block, img, block_x + (@size + 30)*i, block_y + 30*j , 0, :horizontal, true)
121
+ @stillObjects.push @blocks.last
38
122
  end
39
123
  end
40
124
 
41
- 6.times do |i|
42
- self.apply_physics @blocks[i]
43
- end
44
-
45
- self.apply_physics @ball
46
- self.apply_physics @player
47
- self.apply_physics @p1
48
- self.apply_physics @p2
49
- self.apply_physics @p3
125
+ @stillObjects.push @p1, @p2, @p3, @player
50
126
  @font = Gosu::Font.new(self, Gosu::default_font_name, 20)
51
127
  @song.play true
128
+
129
+ @remove_shapes = []
130
+ @space.add_collision_func(:ball, :block) do |ball_shape, block_shape|
131
+ #Search block_shape in stills obects, if is not found it means that the
132
+ #ball already hit it and should be gone, but chipmunk was faster and it
133
+ #generated another collision before it could be erased.
134
+ index = @stillObjects.index{|obj| obj.shape==block_shape}
135
+ if(index != nil )
136
+ @beep.play
137
+ @ball.bounce @stillObjects[index]
138
+ if(@stillObjects[index].deletable )
139
+ @score += 10
140
+ #Bodies and shapes cannot be deleted here so we mark them for later
141
+ @remove_shapes << block_shape
142
+ @blocks.delete @stillObjects[index]
143
+ @stillObjects.delete_at index
144
+ end
145
+ end
146
+ end
52
147
  end
53
-
148
+
149
+ #Creates a new body and shape for a block
150
+ def new_block_body_shape pos0, pos1
151
+ #Arguments for body new are mass and inertia
152
+ @body_block = CP::Body.new(10.0, 150.0)
153
+ @shape_block = CP::Shape::Segment.new(@body_block, pos0, pos1, 0)
154
+
155
+ @shape_block.collision_type = :block
156
+ @space.add_body(@body_block)
157
+ @space.add_shape(@shape_block)
158
+ end
159
+
54
160
  def update
55
- if @ball.center[1] > 480
56
- @ball.position[1] = 200
57
- @ball.velocity[1] = -@ball.velocity[0]
58
- @beep.play
59
- end
161
+
162
+ SUBSTEPS.times do
163
+ #Delete the block body and shape from the space
164
+ @remove_shapes.each do |shape|
165
+ @space.remove_body(shape.body)
166
+ @space.remove_shape(shape)
167
+ end
168
+
169
+ @remove_shapes.clear
170
+ #Check the ball current position
171
+ @ball.validate_position
172
+ #Move the objects in the world one dt
173
+ @space.step(@dt)
174
+ end
175
+
176
+ if button_down? Gosu::KbA then
177
+ if @player.shape.body.p.x > 0
178
+ @player.shape.body.p.x -= 10
179
+ end
180
+ end
181
+
182
+ if button_down? Gosu::KbD then
183
+ if @player.shape.body.p.x + @size < 600
184
+ @player.shape.body.p.x += 10
185
+ end
186
+ end
187
+
60
188
  end
61
189
 
62
- def object_collided( x, y, other_object )
63
- if(@blocks.include? other_object )
64
- @score += 1
65
- self.stop_physics other_object
66
- @blocks_position.delete_at(@blocks.index other_object)
67
- @blocks.delete other_object
68
- end
69
- @beep.play
70
- end
71
-
72
190
  def touch_moved(touch)
73
- touch.y = touch.y - @size2
74
- @player_x = touch.x
75
- @player.bottom_limit[0] = @player_x
76
- @player.top_limit[0] = @player_x + @size
191
+ #On a touch interface translate directly the player's position
192
+ @player.shape.body.p.x = touch.x
77
193
  end
78
194
 
195
+ def button_down(id)
196
+ if id == Gosu::KbEscape then
197
+ close
198
+ end
199
+ end
200
+
79
201
  def draw
80
202
  @blocks.each_index do |i|
81
- @blocks[i].draw(@blocks_position[i][0], @blocks_position[i][1], 0)
203
+ @blocks[i].draw
82
204
  end
83
205
 
84
206
  @ball.draw
85
- @player.draw(@player_x, @player_y, 0)
207
+ @player.draw
86
208
  @font.draw("Score: #{@score}", 10, 10, 3, 1.0, 1.0, 0xffffff00)
87
209
  end
88
210
 
89
211
  end
90
212
 
91
- class ArkanoidActivity
92
- def on_create(bundle)
93
- super(bundle)
94
- Gosu::AndroidInitializer.instance.start(self)
95
- rescue Exception => e
96
- puts "#{ e } (#{ e.class } #{e.message} #{e.backtrace.inspect} )!"
213
+ if not defined? Ruboto
214
+ window = GameWindow.new
215
+ window.show
216
+ else
217
+ class ArkanoidActivity
218
+ def on_create(bundle)
219
+ super(bundle)
220
+ Gosu::AndroidInitializer.instance.start(self)
221
+ rescue Exception => e
222
+ puts "#{ e } (#{ e.class } #{e.message} #{e.backtrace.inspect} )!"
223
+ end
224
+
225
+ def on_ready
226
+ window = GameWindow.new
227
+ window.show
228
+ rescue Exception => e
229
+ puts "#{ e } (#{ e.class } #{e.message} #{e.backtrace.inspect} )!"
230
+ end
97
231
  end
98
-
99
- def on_ready
100
- window = GameWindow.new
101
- window.show
102
- rescue Exception => e
103
- puts "#{ e } (#{ e.class } #{e.message} #{e.backtrace.inspect} )!"
104
- end
105
232
  end
@@ -0,0 +1,29 @@
1
+ require 'gosu'
2
+
3
+ class GameWindow < Gosu::Window
4
+ def initialize
5
+ super 600, 480, false, 30
6
+ self.caption = "Gosu Load Image"
7
+ @image = Gosu::Image.new(self, Ruboto::R::drawable::ship)
8
+ end
9
+
10
+ def draw
11
+ @image.draw(0, 0, 0)
12
+ end
13
+ end
14
+
15
+ class LoadImageActivity
16
+ def on_create(bundle)
17
+ super(bundle)
18
+ Gosu::AndroidInitializer.instance.start(self)
19
+ rescue Exception => e
20
+ puts "#{ e } (#{ e.class } #{e.message} #{e.backtrace.inspect} )!"
21
+ end
22
+
23
+ def on_ready
24
+ window = GameWindow.new
25
+ window.show
26
+ rescue Exception => e
27
+ puts "#{ e } (#{ e.class } #{e.message} #{e.backtrace.inspect} )!"
28
+ end
29
+ end
@@ -1,83 +1,151 @@
1
1
  require 'gosu'
2
2
 
3
+ class Ball
4
+ attr_accessor :velocity
5
+ attr_reader :position, :center
6
+ def initialize window, file_name, x, y, z, size, velocity_x, velocity_y
7
+ @position = [x,y]
8
+ @size = size / 2
9
+ @center = [@position[0] + @size, @position[1] + @size]
10
+ @z = z
11
+ @velocity = [velocity_x, velocity_y]
12
+ @image = Gosu::Image.new(window, file_name, false)
13
+ @dt = window.update_interval/1000.0
14
+ end
15
+
16
+ def update
17
+ @position[0] += @velocity[0]*@dt
18
+ @position[1] += @velocity[1]*@dt
19
+ @center[0] = @position[0] + @size
20
+ @center[1] = @position[1] + @size
21
+ end
22
+
23
+ def generate_contact other_object
24
+ if @center[0] - @size < other_object.top_limit[0] and other_object.bottom_limit[0] < @center[0] + @size and
25
+ @center[1] - @size < other_object.bottom_limit[1] and other_object.top_limit[1] < @center[1] + @size
26
+ #Calculate new velocity, after the hit
27
+ if other_object.type == :vertical
28
+ @velocity[0] -= 2 * @velocity[0]
29
+ else
30
+ @velocity[1] -= 2 * @velocity[1]
31
+ end
32
+ return true
33
+ end
34
+ return false
35
+ end
36
+
37
+ def draw
38
+ @image.draw(@position[0], @position[1], @z)
39
+ end
40
+ end
41
+
42
+ class StillObject
43
+ attr_accessor :bottom_limit, :top_limit
44
+ attr_reader :type
45
+ def initialize(window, file_name, p0, p1, z)
46
+ @image = Gosu::Image.new(window, file_name)
47
+ @z = z
48
+ @top_limit = Array.new p0
49
+ @bottom_limit = Array.new p1
50
+
51
+ if(@bottom_limit[0] > @top_limit[0] or @bottom_limit[1] < @top_limit[1])
52
+ @top_limit, @bottom_limit = @bottom_limit, @top_limit
53
+ end
54
+
55
+ if @bottom_limit[0] == @top_limit[0]
56
+ @type = :vertical
57
+ elsif @bottom_limit[1] == @top_limit[1]
58
+ @type = :horizontal
59
+ end
60
+
61
+ end
62
+
63
+ def draw(x,y,z = @z)
64
+ @image.draw(x,y,z)
65
+ end
66
+ end
67
+
3
68
  class GameWindow < Gosu::Window
4
69
  def initialize
5
70
  super 600, 480, false, 50
6
71
  self.caption = "Gosu Pong Game"
7
- self.physics_manager.gravity_y = 0
8
- @p1score = 0
9
- @p2score = 0
72
+ @player1_score = 0
73
+ @player2_score = 0
10
74
  @song = Gosu::Song.new(self, Ruboto::R::raw::chriss_onac_tempo_red)
11
75
  @beep = Gosu::Sample.new(self, Ruboto::R::raw::beep)
12
- @p1x = 0
76
+ @player1_x = 0
13
77
  # 25 is to compesate square size of the ball
14
- @p1y = 250 + 25
15
- @p3x = 593
16
- @p3y = 100 + 25
78
+ @player1_y = 250 + 25
79
+ @player2_x = 593
80
+ @player2_y = 100 + 25
17
81
  @size = 110
18
82
  @size2 = @size/2 - 25
19
- @squ = Gosu::Square.new(self, Ruboto::R::drawable::ball, 100, 200, 0, 50, 20, 100, 100)
20
- #Left plane
21
- @p1 = Gosu::Plane.new(self, Ruboto::R::drawable::bar, [@p1x,@p1y], [@p1x, @p1y + @size] ,0)
83
+ @ball = Ball.new(self, Ruboto::R::drawable::ball, 100, 200, 0, 50, 100, 100)
84
+ @stillObjects = Array.new
85
+ #Left player
86
+ @player1 = StillObject.new(self, Ruboto::R::drawable::bar, [@player1_x, @player1_y], [@player1_x, @player1_y + @size] ,0)
87
+ #Right player
88
+ @player2 = StillObject.new(self, Ruboto::R::drawable::bar, [@player2_x,@player2_y + @size], [@player2_x,@player2_y], 0)
22
89
  #Top plane
23
- @p2 = Gosu::Plane.new(self, Ruboto::R::drawable::bar, [600,0], [0,0], 0 )
24
- #Right plane
25
- @p3 = Gosu::Plane.new(self,Ruboto::R::drawable::bar, [@p3x,@p3y + @size], [@p3x,@p3y], 0)
90
+ @top_plane = StillObject.new(self, Ruboto::R::drawable::bar, [600,0], [0,0], 0 )
26
91
  #Bottom plane
27
- @p4 = Gosu::Plane.new(self,Ruboto::R::drawable::bar, [0,480], [600,480], 0)
28
- self.apply_physics @squ
29
- self.apply_physics @p1
30
- self.apply_physics @p2
31
- self.apply_physics @p3
32
- self.apply_physics @p4
92
+ @bottom_plane = StillObject.new(self, Ruboto::R::drawable::bar, [0,480], [600,480], 0)
93
+
94
+ @stillObjects.push @player1, @player2, @top_plane, @bottom_plane
95
+
33
96
  @font = Gosu::Font.new(self, Gosu::default_font_name, 20)
34
97
  @song.play true
35
98
  end
36
99
 
37
100
  def update
38
- if @squ.center[0] < 0
101
+
102
+ @stillObjects.each do |obj|
103
+ if @ball.generate_contact obj
104
+ @beep.play
105
+ end
106
+ end
107
+
108
+ @ball.update
109
+
110
+ if @ball.center[0] < 0
39
111
  #Player 1 lost
40
- @p1score += 1
112
+ @player1_score += 1
41
113
  #Reset the ball
42
- @squ.position[0] = 300
43
- @squ.velocity[0] = -@squ.velocity[0]
114
+ @ball.position[0] = 300
115
+ @ball.velocity[0] = -@ball.velocity[0]
44
116
  @beep.play
45
117
  else
46
- if @squ.center[0] > 600
118
+ if @ball.center[0] > 600
47
119
  #Player2 lost
48
- @p2score += 1
120
+ @player2_score += 1
49
121
  #Reset the ball
50
- @squ.position[0] = 300
51
- @squ.velocity[0] = -@squ.velocity[0]
122
+ @ball.position[0] = 300
123
+ @ball.velocity[0] = -@ball.velocity[0]
52
124
  @beep.play
53
125
  end
54
126
  end
55
127
  end
56
128
 
57
- def object_collided( x, y, other_object )
58
- @beep.play
59
- end
60
-
61
129
  def touch_moved(touch)
62
130
  touch.y = touch.y - @size2
63
131
  if touch.x < 300
64
132
  #Player1
65
- @p1y = touch.y
66
- @p1.bottom_limit[1] = @p1y + @size
67
- @p1.top_limit[1] = @p1y
133
+ @player1_y = touch.y
134
+ @player1.bottom_limit[1] = @player1_y + @size
135
+ @player1.top_limit[1] = @player1_y
68
136
  else
69
137
  #Player2
70
- @p3y = touch.y
71
- @p3.bottom_limit[1] = @p3y + @size
72
- @p3.top_limit[1] = @p3y
138
+ @player2_y = touch.y
139
+ @player2.bottom_limit[1] = @player2_y + @size
140
+ @player2.top_limit[1] = @player2_y
73
141
  end
74
142
  end
75
143
 
76
144
  def draw
77
- @squ.draw
78
- @p1.draw(@p1x,@p1y,0)
79
- @p3.draw(@p3x,@p3y,0)
80
- @font.draw("Score: A #{@p1score} B #{@p2score} ", 10, 10, 3, 1.0, 1.0, 0xffffff00)
145
+ @ball.draw
146
+ @player1.draw(@player1_x,@player1_y,0)
147
+ @player2.draw(@player2_x,@player2_y,0)
148
+ @font.draw("Score: A #{@player1_score} B #{@player2_score} ", 10, 10, 3, 1.0, 1.0, 0xffffff00)
81
149
  end
82
150
 
83
151
  end