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

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