root/lang/ruby/starframe/samples/stg/main.rb @ 27389

Revision 27389, 11.4 kB (checked in by isaisstillalive, 4 years ago)

linear,accelerate,decelerateメソッドをIntegerからAnimationクラスに移動させ、
アニメーションフレーム定義中にしか使用できないようにした。

Line 
1$LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "lib"))
2
3require "starruby"
4require "starframe"
5
6# スプライト定義
7#   キャラクタ(自機および敵機)
8class Character < StarFrame::Sprite
9  include StarFrame::Sprite::Animatable
10  include StarFrame::Sprite::Collidable
11 
12  def init options
13    @scene            = options[:scene]
14    @shot_collection  = options[:shot_collection]
15    @smoke_collection = options[:smoke_collection]
16  end
17 
18  # 発射
19  # 指定された弾を追加
20  def shot shot_sprite
21    @shot_collection << shot_sprite
22  end
23 
24  # 撃墜
25  # 爆煙を追加して消滅
26  def crash
27    @smoke_collection << Smoke.new(@x, @y)
28    StarRuby::Audio.play_se @crash_se
29    @scene.score += @score
30    vanish
31  end
32end
33#     自機
34class Player < Character
35  @texture = StarRuby::Texture.load("player")
36  @center_x = 16
37  @center_y = 16+6
38 
39  attr_accessor :stelth_ready, :readying, :stelth
40 
41  animation :burner do
42    frames [0, 32], 2 do |c|
43      # このアニメーション方式は定型に?
44      self.src_y = c
45    end
46  end
47  animation :shot, :loop => false, :start => false do
48    frames 3, 2 do
49      shot Shot::Player.new(@x-8, @y-16)
50      shot Shot::Player.new(@x+8, @y-16)
51    end
52  end
53  animation :ready, :loop => false, :start => false do
54    frame do
55      @x = 160
56      @y = 520
57      @readying = true
58      @stelth = true
59      self.alpha = 0xFF
60      animation(:stelth).stop
61    end
62    frames decelerate(40) do |c|
63      @y = 520-c*2
64    end
65    frame do
66      @y = 440
67      @readying = false
68      self.stelth = @stelth_ready
69    end
70    wait 60
71    frame do
72      self.stelth = false
73    end
74  end
75  animation :stelth, :start => false do
76    frames [0x00, 0xFF] do |c|
77      self.alpha = c
78    end
79  end
80 
81  collision :damage, StarFrame::Sprite::Collision::Rect, -2, -2, 4, 4 do |other|
82    crash
83  end
84  collision :graze, StarFrame::Sprite::Collision::Rect, -8, -8, 16, 16 do |other|
85    @scene.score += 5
86    # カスリアニメーションを動的に生成できるようにしたい
87    @scene.foreground.render_rect other.x-3, other.y-3, 7, 7, StarRuby::Color.new(0xFF, 0xFF, 0xFF)
88    StarRuby::Audio.play_se "tm2_shoot000" if StarRuby::Audio.playing_se_count < 4
89  end
90 
91  def init *args
92    self.src_height = 32
93    @crash_se = "tm2r_bom34"
94    @score = -1000
95    super
96    ready false
97  end
98 
99  def update
100    if @x < 0
101      @x = 0
102    elsif @x > 320
103      @x = 320
104    end
105    if @y < 0
106      @y = 0
107    elsif @y > 480
108      @y = 480
109    end
110  end
111 
112  # 無敵モードON/OFF
113  def stelth= value
114    if value
115      animation(:stelth).restart
116    else
117      animation(:stelth).stop
118      self.alpha = 0xFF
119    end
120    @stelth = value
121  end
122 
123  # 発射
124  def fire
125    animation(:shot).start
126    StarRuby::Audio.play_se "tm2_gun001"
127  end
128 
129  # 準備
130  def ready stelth_ready = true
131    @stelth_ready = stelth_ready
132    animation(:ready).restart
133  end
134 
135  # 撃墜
136  def crash
137    super
138    ready
139  end
140end
141#     敵機
142class Enemy < Character
143  attr_accessor :score
144 
145  def init options
146    @target = options[:target]
147    @crash_se = "tm2_bom001"
148   
149    @shot_point_x =  0
150    @shot_point_y = 24
151    super
152  end
153 
154  def update
155    @to_target_angle = nil
156  end
157 
158  # 自機との角度
159  def to_target_angle
160    unless @to_player_angle
161      @to_target_angle = Math.atan((shot_y - @target.y).quo(shot_x - @target.x))
162      @to_target_angle += 180.degrees if @target.x < shot_x
163    end
164    @to_target_angle
165  end
166  def shot_x
167    @x + @shot_point_x
168  end
169  def shot_y
170    @y + @shot_point_y
171  end
172 
173  # 自機狙い弾
174  def fire_to_player speed = 3, add_angle = 0
175    enemy_shot = Shot::Enemy.new(shot_x, shot_y)
176    shot_angle = to_target_angle + add_angle
177    enemy_shot.movement_x = Math.cos(shot_angle) * speed
178    enemy_shot.movement_y = Math.sin(shot_angle) * speed
179    shot enemy_shot
180  end
181 
182  # 敵機名:ディスク
183  class Disc < Enemy
184    @texture = StarRuby::Texture.load("enemy")
185    @center_x = 16
186    @center_y = 16
187   
188    animation :burner do
189      frames [0, 32], 2 do |c|
190        self.src_y = c
191      end
192    end
193    animation :move, :loop => false do
194      frames decelerate(128) do |c|
195        @y = -32+c
196      end
197      frame do
198        @y = 96
199      end
200     
201      3.times do |i|
202        wait 18 unless i.zero?
203        frames 3, 4 do
204          fire
205        end
206      end
207     
208      parallel do
209        frame do
210          @score = 200
211        end
212        frames accelerate(32) do |c|
213          @y = 96-c*4
214        end
215        frames 32 do
216          @x += 1
217        end
218      end
219      frame do
220        vanish
221      end
222    end
223   
224    collision :body, StarFrame::Sprite::Collision::Rect, -16, -16, 32, 32 do |other|
225      # @scene.render_number @scene.foreground, @x-32, @y-32, score
226      crash
227    end
228   
229    def fire
230      # fire_to_player 3,  10.degrees
231      fire_to_player 3
232      # fire_to_player 3, -10.degrees
233    end
234   
235    def init *args
236      @score = 100
237      @shot_speed = 3
238      self.src_height = 32
239      self.tone_red  =  0x33
240      self.tone_blue = -0x33
241      super
242    end
243  end
244end
245
246class Smoke < StarFrame::Sprite
247  @texture = StarRuby::Texture.load("smoke")
248  @center_x = 16
249  @center_y = 16
250 
251  include StarFrame::Sprite::Animatable
252  animation :smoke do
253    frames Array.new(18){ |i| i*32 }, 2 do |c|
254      self.src_x = c
255    end
256    frame do
257      vanish
258    end
259  end
260 
261  include StarFrame::Sprite::Collidable
262  collision :attack, StarFrame::Sprite::Collision::Rect, -16, -16, 32, 32
263 
264  def init *args
265    self.src_width = 32
266  end
267end
268
269class Shot < StarFrame::Sprite
270  @texture = StarRuby::Texture.load("shot")
271  @center_x = 4
272  @center_y = 4
273 
274  include StarFrame::Sprite::Animatable
275  animation :rolling do
276    frames (0...8), 2 do |c|
277      self.src_x = c*8
278    end
279  end
280 
281  include StarFrame::Sprite::Collidable
282  collision :attack, StarFrame::Sprite::Collision::Rect, -4, -4, 8, 8 do |other|
283    vanish
284  end
285  collision :graze, StarFrame::Sprite::Collision::Rect, -4, -4, 8, 8
286 
287  def init *args
288    self.src_width = 8
289  end
290 
291  def update
292    if @x < -64 || @x > 384 ||
293       @y < -64 || @y > 544
294      vanish
295    end
296  end
297 
298  class Player < Shot
299    def init *args
300      self.movement_y = -4
301      super
302    end
303  end
304 
305  class Enemy < Shot
306    def init *args
307      self.tone_blue =  0x99
308      self.tone_red  = -0x66
309      super
310    end
311  end
312end
313
314# シーン定義
315class MainScene < StarFrame::Scene
316  attr_reader :foreground
317 
318  include StarFrame::Sprite::Animatable
319  animation :scroll do
320    frames (0...544) do |c|
321      @bg_scroll = c
322    end
323  end
324  animation :enemy do
325    frame 30 do
326      @enemies << Enemy::Disc.new(16+rand(320-32), -64, @enemy_options)
327    end
328  end
329 
330  def init *args
331    srand 0
332   
333    @shots       = StarFrame::Sprite::Collection.new
334    @smokes      = StarFrame::Sprite::Collection.new
335    @enemies     = StarFrame::Sprite::Collection.new
336    @enemy_shots = StarFrame::Sprite::Collection.new
337   
338    @player = Player.new(-64, -64,        :scene => self, :shot_collection => @shots,       :smoke_collection => @smokes)
339    @enemy_options = {:target => @player, :scene => self, :shot_collection => @enemy_shots, :smoke_collection => @smokes}
340   
341    @score = 0
342    @frame = 0
343    @pause = false
344   
345    @numbers = StarRuby::Texture.load("numbers")
346    @background = StarRuby::Texture.load("bg")
347    @foreground = StarRuby::Texture.new(@screen.width, @screen.height)
348   
349    @pause_screen = StarRuby::Texture.new(@screen.width, @screen.height)
350    @pause_screen.fill StarRuby::Color.new(0, 0, 0)
351    pause_logo = StarRuby::Texture.load("pause")
352    @pause_screen.render_texture pause_logo, (@screen.width-pause_logo.width)/2, (@screen.height-pause_logo.height)/2
353  end
354 
355  def update
356    # ゲーム終了・ポーズ・無敵モードON/OFF
357    exit_scene if StarRuby::Input.keys(:keyboard).include? :escape
358    input_special_keys = StarRuby::Input.keys(:gamepad, :duration => 1)
359    if input_special_keys.include? 9
360      @pause = !@pause
361      if @pause
362        animation(:scroll).stop
363        animation(:enemy).stop
364      else
365        animation(:scroll).start
366        animation(:enemy).start
367      end
368    end
369    @player.stelth = !@player.stelth if input_special_keys.include? 10
370    return if @pause
371   
372    @foreground.clear
373   
374    # 自弾と敵機(敵機に二つの自弾が当たってしまわないように)
375    @shots.collide @enemies, :attack, :body
376    # 爆煙と敵機
377    @smokes.collide @enemies, :attack, :body
378    # 自機と
379    unless @player.stelth
380      catch :vanished do
381        # 敵機
382        @enemies.each do |enemy|
383          throw :vanished if enemy.collide @player, :body, :damage
384        end
385        # 敵弾
386        @enemy_shots.each do |enemy_shot|
387          # 命中
388          throw :vanished if @player.collide enemy_shot, :damage, :attack
389          # カスり
390          @player.collide enemy_shot, :graze, :graze
391        end
392      end
393    end
394   
395    # 自機移動
396    movement_x = 0
397    movement_y = 0
398    angle = 0
399    scale_x = 1
400    unless @player.readying
401      input_move_keys = StarRuby::Input.keys(:gamepad)
402      # 高速/低速移動
403      if (input_move_keys & [5, 6, 7, 8]).empty?
404        speed = 3
405      else
406        speed = 1
407      end
408      # Up Down
409      if input_move_keys.include? :up
410        movement_y = -speed
411      elsif input_move_keys.include? :down
412        movement_y = speed
413      end
414      # Left Right
415      if input_move_keys.include? :left
416        movement_x = -speed
417        angle = -4.degrees
418        scale_x = 0.90
419      elsif input_move_keys.include? :right
420        movement_x = speed
421        angle = 4.degrees
422        scale_x = 0.90
423      end
424      # Shot::Player
425      input_shot_keys = StarRuby::Input.keys(:gamepad, :duration => 1, :delay => 8, :interval => 8)
426      @player.fire unless (input_shot_keys & [1, 2, 3, 4]).empty?
427    end
428    @player.movement_x = movement_x
429    @player.movement_y = movement_y
430    @player.angle = angle
431    @player.scale_x = scale_x
432   
433    # 各種更新
434    @player.call
435    @shots.call
436    @enemy_shots.call
437    @enemies.call
438    @smokes.call
439  end
440 
441  def render
442    @screen.render_texture @background, 0, @bg_scroll
443    @screen.render_texture @background, 0, @bg_scroll-544
444   
445    @enemies.render_to @screen
446    @player.render_to @screen
447   
448    @shots.render_to @screen
449    @enemy_shots.render_to @screen
450    @smokes.render_to @screen
451   
452    render_number @screen, 96, 8, @score
453    render_number @screen, 304, 8, @game.real_fps.to_i
454   
455    @screen.render_texture @foreground, 0, 0
456   
457    @screen.render_texture @pause_screen, 0, 0, :alpha => 0x7F if @pause
458  end
459 
460  def render_number screen, x, y, number
461    digit = 0
462    loop do
463      score_digit = number%10
464      screen.render_texture @numbers, x-(8*digit), y, :src_x => (8*score_digit), :src_width => 8
465      digit += 1
466      number /= 10
467      break if number == 0
468    end
469  end
470 
471  attr_accessor :score
472  def score= score
473    @score = score
474    @score = 0 if @score < 0
475  end
476end
477
478StarFrame.start :width => 320, :height => 480,
479                :title => "STG", :fps => 60, :fullscreen => false
Note: See TracBrowser for help on using the browser.