ang 9.19.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/ang ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/ruby
2
+ require 'gosu'
3
+
4
+ Dir.chdir(File.dirname(__FILE__)+"/..")
5
+ load 'main.rb'
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/ruby
2
+ require 'gosu'
3
+
4
+ Dir.chdir(File.dirname(__FILE__)+"/../net")
5
+ load 'agent.rb'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/ruby
2
+ Dir.chdir(File.dirname(__FILE__)+"/../net")
3
+ load 'multicast_test.rb'
@@ -0,0 +1,11 @@
1
+ comments=ARGV.join(" ")
2
+ exit! if comments.size==0
3
+
4
+ version=File.read("VERSION").strip.to_f
5
+ version= ((version*100)+1).round*0.01
6
+ open("VERSION","w") { |f| f.print(version.to_s) }
7
+ puts "New Version=#{version}"
8
+
9
+ system("git","commit","-a","-m","#{comments}")
10
+ system("git push") # put your password in .git/config : http://name:passwd@github...
11
+ puts "\n\nDone"
data/main.rb ADDED
@@ -0,0 +1,379 @@
1
+ # Creative Commons BY-SA : Regis d'Aubarede <regis.aubarede@gmail.com># LGPL
2
+ ###########################################################################
3
+ # ANG.RB : planetoide game
4
+ #--------------------------------------------------------------------------
5
+ # install ruby
6
+ # install Gosu > gem install gosu
7
+ # download this > git http://github.com/rdaubarede/ang.git
8
+ # run > ruby main.rb
9
+ # do your own version :
10
+ # > loop { edit/main.rb ; ruby main.rb }
11
+ # make your disribution :
12
+ # > ocra main.rb
13
+ #
14
+ ###########################################################################
15
+ if RUBY_VERSION >= "3.0.0"
16
+ puts "Sorry, not ready for ruiby 3..."
17
+ exit(0)
18
+ end
19
+ ##################### Tuning ##########################
20
+
21
+ KK=0.5
22
+ SX=1280/KK # window size width
23
+ SY=900/KK # height
24
+ $INITIALE_SCORE=2000
25
+ $NB_STAR=35
26
+ $NB_PLANET=8
27
+ $RANGE_STAR_SIZE=(10..30) # more planet / bigger planets ==>> harder game!
28
+ $SCALE_PLAYER=0.8
29
+ $SIZE_TANK=5
30
+ $DD=false
31
+ #######################################################
32
+
33
+ require 'rubygems'
34
+ require 'gosu'
35
+
36
+ module ZOrder
37
+ Background, Stars, Player, UI = [0,1,2,3]
38
+ end
39
+ class Numeric
40
+ def minmax(min,max=nil)
41
+ (max=min;min=-min) if !max
42
+ return self if self>=min && self<=max
43
+ return(min) if self<min
44
+ return(max)
45
+ end
46
+ end
47
+ class Range ; def rand() self.begin+Kernel.rand((self.end-self.begin).abs) end ; end
48
+
49
+ # pseudo newton
50
+ def newton_xy1(p1,p2,a,b)
51
+ k1=1.5/200
52
+ k2=1.0/30000
53
+ dx,dy=[a.x-b.x,a.y-b.y]
54
+ d=Math::sqrt(dx ** 2 + dy ** 2)
55
+ f1=(k1*p1*p2/(d*d)).minmax(100)
56
+ f2=(k2*p1*p2/(d)).minmax(100)
57
+ teta=Math.atan2(dy,dx)
58
+ f=(f2<f1) ? f1 : f2
59
+ $DD=true if (f2>f1)
60
+ r=[-f*Math.cos(teta),-f*Math.sin(teta)]
61
+ r
62
+ end
63
+
64
+ # newton, with 'amortissement'
65
+ def newton_xy(p1,p2,a,b,k=1.0/300,dmin=10,dmax=10000)
66
+ dx,dy=[a.x-b.x,a.y-b.y]
67
+ d=dmin+Math::sqrt(dx ** 2 + dy ** 2)
68
+ return [0,0] if d>dmax
69
+ #f=(k*p1*p2/(d*d)).minmax(100) : k/d**2 not good for gameplay
70
+ f=(k*p1*p2/(d*d-dmin*dmin)).minmax(10)
71
+ teta=Math.atan2(dy,dx)
72
+ [-f*Math.cos(teta),-f*Math.sin(teta)]
73
+ end
74
+
75
+ # apply gravity between obj and a list l of planet
76
+ # k=coef gr&avity, >0 attraction, <0 repulsion
77
+ # dmaw : distance max, no attaction if distance>dmax
78
+ def motion(l,obj,k,dmax)
79
+ dx,dy=0,0
80
+ l.each do |o|
81
+ next if o==obj
82
+ next if block_given? && ! yield(o)
83
+ dx1,dy1= newton_xy(obj.r,o.r,obj,o,k,0,dmax)
84
+ dx+=dx1
85
+ dy+=dy1
86
+ end
87
+ obj.x+=dx
88
+ obj.y+=dy
89
+ return Math.sqrt(dx*dx+dy*dy)
90
+ end
91
+
92
+ ###########################################################################
93
+ # P l a y e r
94
+ ###########################################################################
95
+ # move by arrow keyboard acceleration commande,
96
+ # eat star, move with current speed, and attractive planets
97
+ class Player
98
+ attr_accessor :x,:y,:r,:score
99
+ def initialize(window,animation)
100
+ @animation = animation
101
+ @app=window
102
+ clear()
103
+ @r=15
104
+ self.restart()
105
+ end
106
+ def clear
107
+ @pos=1
108
+ end
109
+ def restart
110
+ @vel_x = @vel_y = @angle = @vangle = 0.0
111
+ @x = SX/2
112
+ @y = SY/2
113
+ @score = $INITIALE_SCORE
114
+ @lxy=[]
115
+ end
116
+ def warp(x, y) @x, @y = x, y ; end
117
+ def turn_left() @pos=3 ; @vangle -= 0.3 ; end
118
+ def turn_right() @pos=4 ; @vangle += 0.3 ; end
119
+ def accelerate(s)
120
+ @pos= s ? 0 : 2
121
+ @score-=3
122
+ @vel_x += 0.7*Gosu::offset_x(@angle, s ? 0.1 : -0.1)
123
+ @vel_y += 0.7*Gosu::offset_y(@angle, s ? 0.1 : -0.1)
124
+ end
125
+
126
+ def move(stars)
127
+ a=false
128
+ (a=true;@vel_x *= -1) if @x >= SX || @x <= 0
129
+ (a=true;@vel_y *= -1) if @y >= SY || @y <= 0
130
+ @x -= 10 if @x >= SX && @vel_x == 0
131
+ @y -= 10 if @y >= SY && @vel_y == 0
132
+ @x += 10 if @x <= 0 && @vel_x == 0
133
+ @y += 10 if @y <= 0 && @vel_y == 0
134
+
135
+ @angle+=@vangle
136
+ @vangle=@vangle*95.0/100
137
+ @lxy << [@x,@y] if @vel_x!=0 && @vel_y!=0
138
+ vx,vy=newton(stars)
139
+ @vel_x+=vx
140
+ @vel_y+=vy
141
+ @vel_x.minmax(-50,+50)
142
+ @vel_y.minmax(-50,+50)
143
+ @x += @vel_x
144
+ @y += @vel_y
145
+ if a
146
+ @vel_x*=1
147
+ @vel_y*=1
148
+ end
149
+
150
+ end
151
+ def newton(stars)
152
+ vx = vy = 0.0
153
+ stars.each do |star|
154
+ next if star.type
155
+ d=Gosu::distance(@x,@y,star.x,star.y)-15-star.r
156
+ dx,dy=*newton_xy1(15*15,star.r*star.r,self,star)
157
+ vx+=dx
158
+ vy+=dy
159
+ end
160
+ [vx,vy]
161
+ end
162
+
163
+ def draw(app,stars)
164
+ img = @animation[@pos]
165
+ img.draw_rot(@x, @y, ZOrder::Player, @angle, 0.5, 0.5, $SCALE_PLAYER,$SCALE_PLAYER)
166
+ x,y=newton(stars) ; app.draw_line(@x,@y, 0xffffffff,@x+x*1000,@y+y*1000,0xffffffff) # debug: mark gravity force
167
+ if app.pending?
168
+ @lxy.each_cons(2) { |p0,p1| app.draw_line(p0[0],p0[1], 0xffffff00 ,p1[0],p1[1], 0xffffff00 ) if p1} rescue nil
169
+ elsif @lxy.size>100
170
+ @lxy[(-1*[800,@lxy.size].min)..-1].each_cons(2) { |p0,p1|
171
+ app.draw_line(p0[0],p0[1], 0x33ffff00 ,p1[0],p1[1], 0x33ffff00 ) if p1
172
+ } rescue nil
173
+ end
174
+ @lxy=@lxy[-5000..-1] if @lxy.size>10000
175
+ end
176
+
177
+ def collect_stars(stars)
178
+ stars.reject! do |star|
179
+ next if star.x-@x > 200
180
+ next if star.x-@x < -200
181
+ next if star.y-@y > 200
182
+ next if star.y-@y < -200
183
+
184
+ if Gosu::distance(@x, @y, star.x, star.y) < (15+star.r) then
185
+ if star.type
186
+ @score += 120
187
+ true
188
+ else
189
+ if @vel_x !=0 || @vel_y!=0
190
+ @score -= 10
191
+ @x -= 25*@vel_x
192
+ @y -= 25*@vel_y
193
+ @x -= -2*25*@vel_x if @x >= SX && @vel_x == 0
194
+ @y -= -2*25*@vel_y if @y >= SY && @vel_y == 0
195
+ else
196
+ @x += (-10..+10).rand
197
+ @y += (-10..+10).rand
198
+ end
199
+ @vel_x=0
200
+ @vel_y=0
201
+ false
202
+ end
203
+ else
204
+ false
205
+ end
206
+ end
207
+ @app.looser if @score<=0
208
+ @app.winner(@score) if 0 == (stars.select { |s| s.type }.size )
209
+ end
210
+
211
+ end
212
+
213
+
214
+ ###########################################################################
215
+ # S t a r
216
+ ###########################################################################
217
+ class Star
218
+ attr_accessor :x, :y, :type,:r
219
+
220
+ def initialize(ls,type,animation)
221
+ @animation = animation
222
+ @ls=ls
223
+ @type=type
224
+ @r=@type ? $SIZE_TANK : $RANGE_STAR_SIZE.rand()
225
+ @no_img= type ? 1 : (rand()>0.5 && (@r>($RANGE_STAR_SIZE.max+$RANGE_STAR_SIZE.max)/2)) ? 0 : (rand(3)+2)
226
+ @rot=rand(180)
227
+ @color = Gosu::Color.new(0xff000000 )
228
+ @color.red = type ? 255 : 200
229
+ @color.green = type ? 0 : 200
230
+ @color.blue = type ? 0 : 200
231
+ @x = (SX/5..(SX-SX/5)).rand
232
+ @y = (SY/5..(SY-SY/5)).rand
233
+ end
234
+ def move(game,player,ls)
235
+ ox,oy=@x,@y
236
+ expand(game,player,ls)
237
+ @x=ox if @x>(SX-40) || @x<40
238
+ @y=oy if @y>(SY-40) || @y<40
239
+
240
+ end
241
+ def draw()
242
+ img = @animation[@no_img]
243
+ img.draw_rot(@x, @y, ZOrder::Stars, @rot, 0.5,0.5 ,@r/40.0, @r/40.0,@color)
244
+ end
245
+ def expand(game,player,ls)
246
+ return unless game.pending?(40)
247
+ motion(ls,self,-100.0,110) { |o| ! o.type} if type # Star <-> Planet
248
+ motion(ls,self,-10.0,50) { |o| o.type} # * <-> Star
249
+ motion(ls,self,-10.0,500) { |o| ! o.type } if !type # Planet <-> Planet
250
+
251
+ motion([player],self,-6,180) if type # Star <-> Player
252
+ end
253
+ end
254
+
255
+ ###########################################################################
256
+ # W i n d o w
257
+ ###########################################################################
258
+
259
+ class GameWindow < Gosu::Window
260
+ attr_reader :star,:ping
261
+ def initialize
262
+ super((SX*KK).to_i, (SY*KK).to_i, false)
263
+ self.caption = "Gosu Tutorial Game"
264
+
265
+ @lp=[]; 100.times { x=rand(SX) ; y=rand(SY); @lp<<x;@lp<<y }
266
+
267
+ @player_anim= Gosu::Image::load_tiles(self, "Starfighter.bmp", 50,50, false)
268
+ @player = Player.new(self,@player_anim)
269
+ @player.warp(320, 240)
270
+ @font = Gosu::Font.new(self, Gosu::default_font_name, (20/KK).round)
271
+ @font2 = Gosu::Font.new(self, Gosu::default_font_name, (40/KK).round)
272
+
273
+ @star_anim = Gosu::Image::load_tiles(self, "Star.bmp", 100,100, false)
274
+ @ping=0
275
+ @start=0
276
+ @mouse=nil
277
+ self.go("Start")
278
+ end
279
+
280
+ ######################## Game global state
281
+
282
+ def looser() ego("Game Over !") end
283
+ def winner(n) ego("Wiiiinner #{n}") end
284
+ def ego(text)
285
+ return if @ping < @start
286
+ puts "ego #{text}"
287
+ @text=text
288
+ @start=@ping+200
289
+ Thread.new { sleep 2 ; self.go("Start") }
290
+ end
291
+ def go(text)
292
+ @start=@ping+200
293
+ @text=text
294
+ @stars = Array.new
295
+ $NB_PLANET.times { @stars.push( Star.new(@stars,false,@star_anim) ) }
296
+ $NB_STAR.times { @stars.push( Star.new(@stars,true,@star_anim) ) }
297
+ @player.restart
298
+ end
299
+ def pending?(d=0) (@start+d > @ping) end
300
+
301
+ ######################## Global interactions : mouse/keyboard
302
+
303
+ def interactions()
304
+ @player.turn_left if button_down? Gosu::KbLeft or button_down? Gosu::GpLeft
305
+ @player.turn_right if button_down? Gosu::KbRight or button_down? Gosu::GpRight
306
+ @player.accelerate(true) if button_down? Gosu::KbUp or button_down? Gosu::GpButton0
307
+ @player.accelerate(false) if button_down? Gosu::KbDown or button_down? Gosu::GpButton1
308
+ #mouse_control
309
+ end
310
+ def mouse_control
311
+ n=[mouse_x,mouse_y]
312
+ @mouse=n unless @mouse
313
+ dx=n[0]-@mouse[0]
314
+ dy=n[1]-@mouse[1]
315
+ if Math.hypot(dx,dy)>D
316
+ @player.turn_left if dx<-D
317
+ @player.turn_right if dx>D
318
+ @player.accelerate(true) if dy<-D
319
+ @player.accelerate(false) if dx>D
320
+ end
321
+ @mouse=n
322
+ end
323
+ def button_down(id)
324
+ if id == Gosu::KbEscape
325
+ if @player.score==0
326
+ close
327
+ else
328
+ @player.score=0
329
+ end
330
+ end
331
+ end
332
+
333
+ ######################## Global draw : update()/draw() are invoked continuously by Gosu engine
334
+
335
+ def update
336
+ $DD=false
337
+ @ping+=1
338
+ @player.clear()
339
+ @stars.each { |star| star.move(self,@player,@stars) }
340
+ return if @ping<@start
341
+ interactions()
342
+ @player.move(@stars)
343
+ @player.collect_stars(@stars)
344
+ end
345
+
346
+ def draw
347
+ scale(KK,KK) {
348
+ draw_background
349
+ @player.draw(self,@stars)
350
+ @stars.each { |star| star.draw() }
351
+ draw_variable_background()
352
+ }
353
+ end
354
+ def draw_background
355
+ @lp.each_slice(2) do |x,y|
356
+ draw_triangle(
357
+ x, y, 0xAAFFFFFF,
358
+ x+(4..8).rand, y+(4..8).rand, 0xAAFFFFFF,
359
+ x+(4..8).rand, y, 0xAAFFFFFF)
360
+ end
361
+ end
362
+ def draw_variable_background()
363
+ if @ping<@start
364
+ @font2.draw(@text+ " ! !", SX/2, SY/2, ZOrder::UI, 1.0, 1.0, 0xf0f0f000)
365
+ @font.draw("", 10, 10, ZOrder::UI, 1.0, 1.0, 0xffffff00)
366
+ else
367
+ #----------- barr graph energies reserve level
368
+ h=5+(@player.score/2000.0)*(SY-10)
369
+ draw_quad(5, 5, 0xBB55FF55, 20/KK, 5, 0xBB55FF55, 20/KK, h, 0xBBFFFF55, 5 , h , 0xBBFFFF55)
370
+
371
+ #------------ textual energie reserve level
372
+ @font.draw("Score: #{@player.score}", 25/KK, 10/KK, ZOrder::UI, 1.0, 1.0, 0xffffff00)
373
+ draw_quad(20, 20, 0xFFFF00FF, 40, 20, 0xFFFF00FF, 40, 40, 0xFFFF00FF, 20 , 40 , 0xFFFF00FF) if $DD
374
+
375
+ end
376
+ end
377
+ end
378
+
379
+ GameWindow.new.show
@@ -0,0 +1,324 @@
1
+ # Creative Commons BY-SA : Regis d'Aubarede <regis.aubarede@gmail.com>
2
+ ###########################################################################
3
+ # ANG.RB : planetoide game
4
+ #--------------------------------------------------------------------------
5
+ # install ruby
6
+ # install Gosu > gem install gosu
7
+ # download this > git http://github.com/rdaubarede/ang.git
8
+ # run > ruby main.rb
9
+ # do your own version :
10
+ # > loop { edit/main.rb ; ruby main.rb }
11
+ # make your disribution :
12
+ # > ocra main.rb
13
+ #
14
+ ###########################################################################
15
+ require 'rubygems'
16
+ require 'gosu'
17
+
18
+ # KK=0.5
19
+ # SX=1280/KK
20
+ # SY=900/KK
21
+ KK=0.5
22
+ SX=640/KK
23
+ SY=480/KK
24
+
25
+ module ZOrder
26
+ Background, Stars, Player, UI = [0,1,2,3]
27
+ end
28
+ class Numeric
29
+ def minmax(min,max=nil)
30
+ (max=min;min=-min) if !max
31
+ return self if self>=min && self<=max
32
+ return(min) if self<min
33
+ return(max)
34
+ end
35
+ end
36
+ class Range ; def rand() self.begin+Kernel.rand((self.end-self.begin).abs) end ; end
37
+
38
+ def e(a,b) (20.0/(a-b)).minmax(-10,+10) end
39
+
40
+ def newton_xy(p1,p2,a,b)
41
+ k=1.0/40000
42
+ dx,dy=[a.x-b.x,a.y-b.y]
43
+ d=Math::sqrt(dx ** 2 + dy ** 2)
44
+ #f=(k*p1*p2/(d*d)).minmax(100) : k/d**2 not good for gameplay
45
+ f=(k*p1*p2/(d)).minmax(10)
46
+ teta=Math.atan2(dy,dx)
47
+ [-f*Math.cos(teta),-f*Math.sin(teta)]
48
+ end
49
+
50
+ ###########################################################################
51
+ # P l a y e r
52
+ ###########################################################################
53
+ # move by arrow keyboard acceleration commande,
54
+ # eat star, move with current speed, and attractive planets
55
+ class Player
56
+ attr_reader :x,:y,:r
57
+ attr_accessor :score
58
+ def initialize(window,animation)
59
+ @animation = animation
60
+ @app=window
61
+ @r=15
62
+ @pos=1
63
+ self.restart()
64
+ end
65
+ def restart
66
+ @vel_x = @vel_y = @angle = @vangle = 0.0
67
+ @x = SX/2
68
+ @y = SY/2
69
+ @score = 2000
70
+ @lxy=[]
71
+ end
72
+ def clear
73
+ @pos=1
74
+ end
75
+ def warp(x, y) @x, @y = x, y ; end
76
+ def turn_left() @pos=3 ; @vangle -= 0.3 ; end
77
+ def turn_right() @pos=4 ; @vangle += 0.3 ; end
78
+ def accelerate(s)
79
+ @pos= s ? 0 : 2
80
+ @score-=3
81
+ @vel_x += Gosu::offset_x(@angle, s ? 0.1 : -0.1)
82
+ @vel_y += Gosu::offset_y(@angle, s ? 0.1 : -0.1)
83
+ end
84
+
85
+ def move(stars)
86
+ @x += @vel_x
87
+ @y += @vel_y
88
+ @vel_x *= -1 if @x >= SX || @x <= 0
89
+ @vel_y *= -1 if @y >= SY || @y <= 0
90
+ @x -= 10 if @x >= SX && @vel_x == 0
91
+ @y -= 10 if @y >= SY && @vel_y == 0
92
+ @x += 10 if @x <= 0 && @vel_x == 0
93
+ @y += 10 if @y <= 0 && @vel_y == 0
94
+
95
+ #@vel_x *= 0.998
96
+ #@vel_y *= 0.998
97
+ @angle+=@vangle
98
+ @vangle=@vangle*95.0/100
99
+ @lxy << [@x,@y] if @vel_x!=0 && @vel_y!=0
100
+ vx,vy=newton(stars)
101
+ @vel_x+=vx
102
+ @vel_y+=vy
103
+ @vel_x.minmax(-50,+50)
104
+ @vel_y.minmax(-50,+50)
105
+ end
106
+ def newton(stars)
107
+ vx = vy = 0.0
108
+ stars.each do |star|
109
+ next if star.type
110
+ d=Gosu::distance(@x,@y,star.x,star.y)-15-star.r
111
+ dx,dy=*newton_xy(15*15,star.r*star.r,self,star)
112
+ vx+=dx
113
+ vy+=dy
114
+ end
115
+ [vx,vy]
116
+ end
117
+
118
+ def draw(app,stars)
119
+ img = @animation[@pos]
120
+ img.draw_rot(@x, @y, ZOrder::Player, @angle) # (@x, @y, ZOrder::Stars, 0, 0.5,0.5 ,@r/10, @r/10,@color)
121
+ #@image.draw_rot(@x, @y, ZOrder::Player, @angle)
122
+ x,y=newton(stars) ; app.draw_line(@x,@y, 0xffffffff,@x+x*1000,@y+y*1000,0xffffffff) # debug: mark gravity force
123
+ if app.is_pending
124
+ @lxy.each_cons(2) { |p0,p1| app.draw_line(p0[0],p0[1], 0xffffff00 ,p1[0],p1[1], 0xffffff00 ) if p1} rescue nil
125
+ elsif @lxy.size>100
126
+ @lxy[(-1*[300,@lxy.size].min)..-1].each_cons(2) { |p0,p1|
127
+ app.draw_line(p0[0],p0[1], 0x33ffff00 ,p1[0],p1[1], 0x33ffff00 ) if p1
128
+ } rescue nil
129
+ end
130
+ @lxy=@lxy[-5000..-1] if @lxy.size>10000
131
+ end
132
+
133
+ def collect_stars(stars)
134
+ stars.reject! do |star|
135
+ if Gosu::distance(@x, @y, star.x, star.y) < (15+star.r) then
136
+ if star.type
137
+ @score += 70
138
+ true
139
+ else
140
+ if @vel_x !=0 || @vel_y!=0
141
+ @score -= 10
142
+ @x -= 15*@vel_x
143
+ @y -= 15*@vel_y
144
+ else
145
+ @x += (-10..+10).rand
146
+ @y += (-10..+10).rand
147
+ end
148
+ @vel_x=0
149
+ @vel_y=0
150
+ false
151
+ end
152
+ else
153
+ false
154
+ end
155
+ end
156
+ @app.looser if @score<=0
157
+ @app.winner(@score) if 0 == (stars.select { |s| s.type }.size )
158
+ end
159
+
160
+ end
161
+
162
+
163
+ ###########################################################################
164
+ # S t a r
165
+ ###########################################################################
166
+ class Star
167
+ attr_reader :x, :y, :type,:r
168
+
169
+ def initialize(ls,type,animation)
170
+ @animation = animation
171
+ @ls=ls
172
+ @type=type
173
+ @r=@type ? 10 : (20..60).rand()
174
+ @color = Gosu::Color.new(0xff000000 )
175
+ @color.red = type ? 255 : 0
176
+ @color.green = type ? 0 : 200
177
+ @color.blue = type ? 0 : 200
178
+ @x = (SX/5..(SX-SX/5)).rand
179
+ @y = (SY/5..(SY-SY/5)).rand
180
+ end
181
+ def move(player)
182
+ expand(player)
183
+ end
184
+ def draw()
185
+ img = @animation[self.type ? 1 : 0 ]
186
+ img.draw_rot(@x, @y, ZOrder::Stars, 0, 0.5,0.5 ,@r/10, @r/10,@color)
187
+ end
188
+ def expand(p)
189
+ ox,oy=@x,@y
190
+ @ls.each do |s|
191
+ next if s==self
192
+ (@x+=e(@x,s.x) ; @y+=e(@y,s.y) ) if Gosu::distance(@x,@y,s.x,s.y)< ((s.type && self.type) ? 100 : 0 )
193
+ end
194
+ d=Gosu::distance(@x,@y,p.x,p.y)-@r-p.r
195
+ if @type
196
+ (@x+=-e(p.x,@x)/0.5 ; @y+=-e(p.y,@y)/0.5 ) if d> 20 && d < 180
197
+ else
198
+ (@x+=e(p.x,@x)/5.0 ; @y+=e(p.y,@y)/5.0 ) if d> 20 && d < 0
199
+ end
200
+ @x=ox if @x>600 || @x<40
201
+ @y=oy if @y>440 || @y<40
202
+ end
203
+ end
204
+
205
+ ###########################################################################
206
+ # W i n d o w
207
+ ###########################################################################
208
+
209
+ class GameWindow < Gosu::Window
210
+ attr_reader :star,:ping
211
+ def initialize
212
+ super((SX*KK).to_i, (SY*KK).to_i, false)
213
+ self.caption = "Gosu Tutorial Game"
214
+
215
+ @lp=[]; 100.times { x=rand(SX) ; y=rand(SY); @lp<<x;@lp<<y }
216
+ @player_anim= Gosu::Image::load_tiles(self, "Starfighter2.bmp", 50,50, false)
217
+ @player = Player.new(self,@player_anim)
218
+ @player.warp(320, 240)
219
+ @font = Gosu::Font.new(self, Gosu::default_font_name, (20/KK).round)
220
+ @font2 = Gosu::Font.new(self, Gosu::default_font_name, (40/KK).round)
221
+
222
+ @star_anim = Gosu::Image::load_tiles(self, "Star.png", 25,25, false)
223
+ @ping=0
224
+ @start=0
225
+ @mouse=nil
226
+ self.go("Start")
227
+ end
228
+
229
+ ######################## Game global state
230
+
231
+ def looser() ego("Loose") end
232
+ def winner(n) ego("Winne #{n}") end
233
+ def ego(text)
234
+ puts "ego #{text}"
235
+ @text=text
236
+ @start=@ping+50
237
+ Thread.new { sleep 2 ; self.go("Start") }
238
+ end
239
+ def go(text)
240
+ @start=@ping+200
241
+ @text=text
242
+ @stars = Array.new
243
+ 3.times { @stars.push( Star.new(@stars,false,@star_anim) ) }
244
+ 10.times { @stars.push( Star.new(@stars,true,@star_anim) ) }
245
+ @player.restart
246
+ end
247
+ def is_pending() (@start > @ping) end
248
+
249
+ ######################## Global interactions : mouse/keyboard
250
+
251
+ def interactions()
252
+ @player.turn_left if button_down? Gosu::KbLeft or button_down? Gosu::GpLeft
253
+ @player.turn_right if button_down? Gosu::KbRight or button_down? Gosu::GpRight
254
+ @player.accelerate(true) if button_down? Gosu::KbUp or button_down? Gosu::GpButton0
255
+ @player.accelerate(false) if button_down? Gosu::KbDown or button_down? Gosu::GpButton1
256
+ #mouse_control
257
+ end
258
+ def mouse_control
259
+ n=[mouse_x,mouse_y]
260
+ @mouse=n unless @mouse
261
+ dx=n[0]-@mouse[0]
262
+ dy=n[1]-@mouse[1]
263
+ if Math.hypot(dx,dy)>D
264
+ @player.turn_left if dx<-D
265
+ @player.turn_right if dx>D
266
+ @player.accelerate(true) if dy<-D
267
+ @player.accelerate(false) if dx>D
268
+ end
269
+ @mouse=n
270
+ end
271
+ def button_down(id)
272
+ if id == Gosu::KbEscape
273
+ if @player.score==0
274
+ close
275
+ else
276
+ @player.score=0
277
+ end
278
+ end
279
+ end
280
+
281
+ ######################## Global draw : update()/draw() are invoked continuously by Gosu engine
282
+
283
+ def update
284
+ @ping+=1
285
+ return if @ping<@start
286
+ @player.clear()
287
+ interactions()
288
+ @player.move(@stars)
289
+ @player.collect_stars(@stars)
290
+ @stars.each { |star| star.move(@player) }
291
+ end
292
+
293
+ def draw
294
+ scale(KK,KK) {
295
+ draw_background
296
+ @player.draw(self,@stars)
297
+ @stars.each { |star| star.draw() }
298
+ draw_variable_background()
299
+ }
300
+ end
301
+ def draw_background
302
+ @lp.each_slice(2) do |x,y|
303
+ draw_triangle(
304
+ x, y, 0xAAFFFFFF,
305
+ x+(3..5).rand, y+(3..5).rand, 0xAAFFFFFF,
306
+ x+(3..5).rand, y, 0xAAFFFFFF)
307
+ end
308
+ end
309
+ def draw_variable_background()
310
+ if @ping<@start
311
+ @font2.draw(@text+ " ! !", SX/2, SY/2, ZOrder::UI, 1.0, 1.0, 0xf0f0f000)
312
+ @font.draw("", 10, 10, ZOrder::UI, 1.0, 1.0, 0xffffff00)
313
+ else
314
+ #----------- barr graph energies reserve level
315
+ h=5+(@player.score/2000.0)*(SY-10)
316
+ draw_quad(5, 5, 0xBB55FF55, 20/KK, 5, 0xBB55FF55, 20/KK, h, 0xBBFFFF55, 5 , h , 0xBBFFFF55)
317
+
318
+ #------------ textual energie reserve level
319
+ @font.draw("Score: #{@player.score}", 25/KK, 10/KK, ZOrder::UI, 1.0, 1.0, 0xffffff00)
320
+ end
321
+ end
322
+ end
323
+
324
+ GameWindow.new.show