gosu_android 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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