#============================================================================== # ■ Stg_player #------------------------------------------------------------------------------ #  自機の管理用クラスです。 #============================================================================== class Stg_player < Sprite #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_reader :dx #横方向の当たり判定 attr_reader :dy #縦方向の当たり判定 attr_reader :life #ライフ #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize super() self.bitmap = RPG::Cache.picture("fighter") #原点を画像の中心に設定 self.ox = self.bitmap.width / 2 self.oy = self.bitmap.height / 2 self.x = 32 self.y = 240 self.z = 20 @dx = 16 @dy = 4 @life = 5 @muteki = 0 #無敵時間を計る end #-------------------------------------------------------------------------- # ● 自機の移動処理 #-------------------------------------------------------------------------- def move move_x = 0 #横方向の移動量 move_y = 0 #縦方向の移動量 #入力されたキーによって画像の移動量を決める move_y = 8 if Input.press?(Input::DOWN) move_x = -8 if Input.press?(Input::LEFT) move_x = 8 if Input.press?(Input::RIGHT) move_y = -8 if Input.press?(Input::UP) #斜め入力のときは速度を落とす if move_x * move_y != 0 move_x *= 0.7 move_y *= 0.7 end #移動量を座標に加算する self.x += move_x self.y += move_y #画面外に出たら座標を画面内に強制する self.x = 620 if self.x > 620 self.x = 20 if self.x < 20 self.y = 470 if self.y > 470 self.y = 10 if self.y < 10 #無敵時間があればカウントを減らす if @muteki > 0 @muteki -= 1 self.opacity = 255 if @muteki == 0 end end #-------------------------------------------------------------------------- # ● 自機のダメージ処理 #-------------------------------------------------------------------------- def damage #無敵状態でなければライフを減らす if @muteki == 0 @life -= 1 #無敵時間50フレーム @muteki = 50 #自機を半透明にする self.opacity = 127 if @life < 0 @life = 0 return true end end return false end end #============================================================================== # ■ Stg_bullet #------------------------------------------------------------------------------ #  弾の管理用クラスです。 #============================================================================== class Stg_bullet < Sprite #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_reader :dx #横方向の当たり判定 attr_reader :dy #縦方向の当たり判定 #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize(x, y, type = 0, target_x = 0, target_y = 0, rad = 0, rot = 0) super() @type = type case @type when 0 #自機が撃つ弾 self.bitmap = RPG::Cache.picture("bullet") self.z = 80 @dx = 8 @dy = 4 @spx = 12 @spy = 0 when 1 #敵が撃つ弾・左に直進する self.bitmap = RPG::Cache.picture("e_bullet") self.z = 100 @dx = 8 @dy = 8 @spx = -6 @spy = 0 when 2 #敵が撃つ弾・自機に向かって直進する self.bitmap = RPG::Cache.picture("e_bullet") self.z = 100 @dx = 8 @dy = 8 @spx = 6 @spy = 6 @spx = @spx*(target_x-x) / Math.sqrt((target_x-x)**2+(target_y-y)**2) @spy = @spy*(target_y-y) / Math.sqrt((target_x-x)**2+(target_y-y)**2) when 3 #敵が撃つ弾・Nウェイ弾 self.bitmap = RPG::Cache.picture("e_bullet") self.z = 100 @dx = 8 @dy = 8 @spx = 6 @spy = 6 @spx = @spx*(target_x-x) / Math.sqrt((target_x-x)**2+(target_y-y)**2) @spy = @spy*(target_y-y) / Math.sqrt((target_x-x)**2+(target_y-y)**2) @spx = @spx * Math.cos(rad) - @spy * Math.sin(rad) @spy = @spx * Math.sin(rad) + @spy * Math.cos(rad) when 4 #敵が撃つ弾・回転弾 self.bitmap = RPG::Cache.picture("e_bullet") self.z = 100 @dx = 8 @dy = 8 @spx = 6 @spy = 6 @spx = @spx * Math.cos(rot * Math::PI / 180) @spy = @spy * Math.sin(rot * Math::PI / 180) end self.ox = self.bitmap.width / 2 self.oy = self.bitmap.height / 2 self.x = x self.y = y @fx = x @fy = y end #-------------------------------------------------------------------------- # ● 弾の移動処理 #-------------------------------------------------------------------------- def move #浮動少数座標に移動量を加算 @fx += @spx @fy += @spy #浮動少数座標を座標に代入(座標には整数値が入る) self.x = @fx self.y = @fy #画面外に出たら消滅 if screenout? self.dispose return true end return false end #-------------------------------------------------------------------------- # ● 画面外判定 #-------------------------------------------------------------------------- def screenout? return true if self.x > 640 + self.bitmap.width / 2 return true if self.x < 0 - self.bitmap.width / 2 return true if self.y > 480 + self.bitmap.height / 2 return true if self.y < 0 - self.bitmap.height / 2 return false end end #============================================================================== # ■ Stg_enemy #------------------------------------------------------------------------------ #  敵キャラの管理用クラスです。 #============================================================================== class Stg_enemy < Sprite #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_reader :dx #横方向の当たり判定 attr_reader :dy #縦方向の当たり判定 attr_reader :score #点数 #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize(x, y, type) super() @type = type self.bitmap = RPG::Cache.picture("enemy"+"#{@type}") self.ox = self.bitmap.width / 2 self.oy = self.bitmap.height / 2 self.x = x self.y = y self.z = 60 case @type when 1 @spx = -2 @spy = 0 @life = 5 @score = 100 when 2 @spx = -4 @spy = 0 @life = 7 @score = 200 when 3 @spx = -3 @spy = 1 @life = 9 @score = 300 end @dx = 32 @dy = 32 @count = 0 #生存時間 end #-------------------------------------------------------------------------- # ● 敵キャラの移動処理 #-------------------------------------------------------------------------- def move #このupdateはフラッシュ処理に必要 self.update move_select() self.x += @spx self.y += @spy #画面外に出たら消滅 if screenout? self.dispose return true end return false end #-------------------------------------------------------------------------- # ● 敵キャラの種類別移動 #-------------------------------------------------------------------------- def move_select @count += 1 case @type when 2 #途中で引き返す @spx = 4 if @count == 100 when 3 #ジグザグ移動 @spy *= -1 if @count % 100 == 0 end end #-------------------------------------------------------------------------- # ● 画面外判定 #-------------------------------------------------------------------------- def screenout? return true if self.x > 640 + self.bitmap.width / 2 return true if self.x < 0 - self.bitmap.width / 2 return true if self.y > 480 + self.bitmap.height / 2 return true if self.y < 0 - self.bitmap.height / 2 return false end #-------------------------------------------------------------------------- # ● 攻撃判定 #-------------------------------------------------------------------------- def attack case @type when 1 return 2 if @count % 50 == 0 when 2 return 3 if @count % 50 == 0 when 3 return 4 if @count % 150 == 50 end return 0 end #-------------------------------------------------------------------------- # ● 敵キャラのダメージ処理 #-------------------------------------------------------------------------- def damage @life -= 1 #5フレームの間白くフラッシュ self.flash(Color.new(255, 255, 255, 255), 5) if @life == 0 return true end return false end end #============================================================================== # ■ Stg_burst #------------------------------------------------------------------------------ #  アニメーション用クラスです。 #============================================================================== class Stg_burst < Sprite #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize(x,y) super() self.bitmap = RPG::Cache.picture("burst6") self.ox = self.bitmap.width / 2 self.oy = self.bitmap.height / 2 self.x = x self.y = y self.z = 40 @time = 0 #爆発の効果音 Audio.se_play("Audio/SE/death",90) end #-------------------------------------------------------------------------- # ● アニメーション進行 #-------------------------------------------------------------------------- def move #2フレームに1回実行 if Graphics.frame_count % 2 == 0 @time += 1 if @time == 7 self.dispose return true end self.bitmap = RPG::Cache.picture("burst"+"#{@time}") end return false end end #============================================================================== # ■ Stg_background #------------------------------------------------------------------------------ #  背景の管理用クラスです。 #============================================================================== class Stg_background < Sprite #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize(x, y, z, sp, file) super() self.bitmap = RPG::Cache.picture(file) self.x = x self.y = y self.z = z @sp = sp end #-------------------------------------------------------------------------- # ● 背景スクロール #-------------------------------------------------------------------------- def move self.x -= @sp #左端に消えた画像を右端へ移動 if self.x <= -640 self.x += 1280 end end #-------------------------------------------------------------------------- # ● 背景の不透明部分との接触判定 #-------------------------------------------------------------------------- def crash(x, y) if self.bitmap.get_pixel(x, y) != Color.new(0, 0, 0, 0) return true else return false end end end #============================================================================== # ■ Scene_stg #------------------------------------------------------------------------------ #  シューティング部分を管理するシーンクラスです。 #============================================================================== class Scene_stg #-------------------------------------------------------------------------- # ● メイン処理 #-------------------------------------------------------------------------- def main #各種変数の初期設定 @shot = Array.new #自機の弾を格納 @enemy = Array.new #敵を格納 @enemyshot = Array.new #敵の弾を格納 @burst = Array.new #爆発アニメーションを格納 @shot_interval = 3 #弾の発射間隔(フレーム) @shot_count = 0 #弾の発射間隔をカウントする変数 @score = 0 #スコア @prescore = 0 #スコアの変化を監視するため前回のスコアを記録 @prelife = 0 #ライフの変化を監視するため前回のライフを記録 Graphics.frame_count = 0 #フレームカウントの初期化 #背景表示 @background1 = Stg_background.new(0, 0, 10, 2, "back") @background2 = Stg_background.new(640, 0, 10, 2, "back") @background3 = Stg_background.new(640, 320, 15, 4, "front") #自機表示 @player = Stg_player.new #スコア、ライフの表示 @menuview = Sprite.new @menuview.bitmap = Bitmap.new(640,32) @menuview.bitmap.draw_text(0, 0, 96, 32, "Score") @menuview.bitmap.draw_text(200, 0, 96, 32, "Life") @menuview.z = 200 @scoreview = Sprite.new @scoreview.bitmap = Bitmap.new(96,32) @scoreview.bitmap.draw_text(0, 0, 96, 32, "0") @scoreview.x = 64 @scoreview.z = 200 @lifeview = Sprite.new @lifeview.bitmap = Bitmap.new(96,32) @lifeview.bitmap.draw_text(0, 0, 96, 32, "★★★★★") @lifeview.x = 240 @lifeview.z = 200 #メインループ loop do #自機の操作 @player.move #自機の弾を発射 player_shot() #敵キャラの生成 make_enemy() #弾と敵の接触処理 enemy_crash() #敵のショット enemy_shot() #敵の弾と自機の接触処理 player_crash() #背景スクロール background_move() #地形と自機の接触処理 player_land_crash() #スコア書き換え change_score() #ライフ書き換え change_life() #ライフが0になるとシーンを移動 if @player.life == 0 #自機消滅 gameover() #全画像開放 allclear() #タイトル画面へ if $ranking[9][0] < @score $scene = Scene_name.new(@score) else $scene = Scene_ranking.new end return end #各種更新 Input.update Graphics.update end end #-------------------------------------------------------------------------- # ● 自機のショット #-------------------------------------------------------------------------- def player_shot if Input.press?(Input::A) and @shot.size < 10 @shot_count += 1 if @shot_count == @shot_interval @shot_count = 0 @shot.push Stg_bullet.new(@player.x + 32, @player.y) end end #弾の移動&削除 @shot.reject!{|i|i.move} end #-------------------------------------------------------------------------- # ● 敵キャラの生成 #-------------------------------------------------------------------------- def make_enemy if Graphics.frame_count % 100 == 0 @enemy.push Stg_enemy.new(672, rand(480),1) end if Graphics.frame_count % 250 == 0 && @score > 300 @enemy.push Stg_enemy.new(672, rand(480),2) end if Graphics.frame_count % 550 == 0 && @score > 1000 @enemy.push Stg_enemy.new(672, rand(280)+100,3) end if Graphics.frame_count % 300 == 150 && @score > 5000 @enemy.push Stg_enemy.new(672, rand(480),1) end if Graphics.frame_count % 600 == 300 && @score > 10000 @enemy.push Stg_enemy.new(672, rand(480),2) end if Graphics.frame_count % 900 == 450 && @score > 20000 @enemy.push Stg_enemy.new(672, rand(280)+100,3) end @enemy.reject!{|i|i.move} end #-------------------------------------------------------------------------- # ● 弾と敵の接触処理 #-------------------------------------------------------------------------- def enemy_crash @shot.each{|i| @enemy.each{|j| if crash?(i, j) i.dispose if j.damage @score += j.score @burst.push Stg_burst.new(j.x, j.y) j.dispose @enemy.delete(j) end break end } #背景と敵の当たり判定 unless i.disposed? if @background3.crash(i.x - @background3.x, i.y - @background3.y) i.dispose end end } @shot.reject!{|i|i.disposed?} @burst.reject!{|i|i.move} end #-------------------------------------------------------------------------- # ● 当たり判定 #-------------------------------------------------------------------------- def crash?(obj1, obj2) if (obj1.x - obj2.x).abs < obj1.dx + obj2.dx and (obj1.y - obj2.y).abs < obj1.dy + obj2.dy return true else return false end end #-------------------------------------------------------------------------- # ● 敵のショット #-------------------------------------------------------------------------- def enemy_shot @enemy.each{|i| type = i.attack case type when 1 @enemyshot.push Stg_bullet.new(i.x, i.y, 1) when 2 @enemyshot.push Stg_bullet.new(i.x, i.y, 2,@player.x, @player.y) when 3 @enemyshot.push Stg_bullet.new(i.x, i.y, 3, @player.x, @player.y, -0.1) @enemyshot.push Stg_bullet.new(i.x, i.y, 3, @player.x, @player.y, 0) @enemyshot.push Stg_bullet.new(i.x, i.y, 3, @player.x, @player.y, 0.1) when 4 for rot in 0..11 @enemyshot.push Stg_bullet.new(i.x, i.y, 4, 0,0,0,rot*30) end end } @enemyshot.reject!{|i|i.move} end #-------------------------------------------------------------------------- # ● 敵の弾と自機の接触処理 #-------------------------------------------------------------------------- def player_crash @enemyshot.each{|i| if crash?(i, @player) @player.damage i.dispose #背景と敵の弾の当たり判定 elsif @background3.crash(i.x - @background3.x, i.y - @background3.y) i.dispose end } @enemyshot.reject!{|i|i.disposed?} @player.update end #-------------------------------------------------------------------------- # ● 背景スクロール #-------------------------------------------------------------------------- def background_move @background1.move @background2.move @background3.move end #-------------------------------------------------------------------------- # ● 地形と自機の接触処理 #-------------------------------------------------------------------------- def player_land_crash if @background3.crash(@player.x - @background3.x, @player.y - @background3.y) @player.damage end end #-------------------------------------------------------------------------- # ● スコア書き換え #-------------------------------------------------------------------------- def change_score if @score != @prescore @scoreview.bitmap.clear @scoreview.bitmap.draw_text(0, 0, 96, 32, "#{@score}" ,2) @prescore = @score end end #-------------------------------------------------------------------------- # ● ライフ書き換え #-------------------------------------------------------------------------- def change_life if @player.life != @prelife @lifeview.bitmap.clear @lifeview.bitmap.draw_text(0, 0, 96, 32, "★"*@player.life) @prelife = @player.life end end #-------------------------------------------------------------------------- # ● ゲームオーバー #-------------------------------------------------------------------------- def gameover #自機の消滅 @burst.push Stg_burst.new(@player.x, @player.y) @player.dispose #100フレーム停滞 100.times{ @burst.reject!{|i|i.move} Graphics.update } end #-------------------------------------------------------------------------- # ● 全画像を開放 #-------------------------------------------------------------------------- def allclear @shot.each{|i|i.dispose} @enemyshot.each{|i|i.dispose} @enemy.each{|i|i.dispose} @background1.dispose @background2.dispose @background3.dispose @menuview.dispose @scoreview.dispose @lifeview.dispose end end #============================================================================== # ■ Scene_title #------------------------------------------------------------------------------ #  タイトル画面のシーンクラスです。 #============================================================================== class Scene_title #-------------------------------------------------------------------------- # ● メイン処理 #-------------------------------------------------------------------------- def main #背景の画像表示 title = Sprite.new title.bitmap = RPG::Cache.picture("title") #文字表示 press = Sprite.new press.bitmap = Bitmap.new(120,32) press.bitmap.draw_text(0, 0, 120, 24, "press Z key") press.x = 264 press.y = 220 #フレームカウントの初期化 Graphics.frame_count = 0 # メインループ loop do #ボタンが押されたらシーンを移動 if Input.trigger?(Input::A) title.dispose press.dispose $scene = Scene_stg.new break end #文字の点滅 press.flash(nil, 25) if Graphics.frame_count % 50 == 0 press.update Input.update Graphics.update end end end #============================================================================== # ■ Scene_ranking #------------------------------------------------------------------------------ #  ランキング画面のシーンクラスです。 #============================================================================== class Scene_ranking #-------------------------------------------------------------------------- # ● メイン処理 #-------------------------------------------------------------------------- def main #背景の画像表示 background = Sprite.new background.bitmap = RPG::Cache.picture("back") #ランキングデータを書くためのスプライト表示 rankingview = Sprite.new rankingview.bitmap = Bitmap.new(640,480) rankingview.bitmap.draw_text(0, 32, 640, 32, "Ranking", 1) #ランキングデータ10個の書き出し for i in 0..9 y = i * 32 + 100 rankingview.bitmap.draw_text(220, y, 32, 24, "#{i + 1}", 2) rankingview.bitmap.draw_text(220, y, 120, 24, "#{$ranking[i][0]}", 2) rankingview.bitmap.draw_text(320, y, 120, 24, "#{$ranking[i][1]}", 2) end #メインループ loop do #ボタンが押されたらシーンを移動 if Input.trigger?(Input::A) background.dispose rankingview.dispose Input.update $scene = Scene_title.new break end Input.update Graphics.update end end end #============================================================================== # ■ Scene_name #------------------------------------------------------------------------------ #  ネームエントリー画面のシーンクラスです。 #============================================================================== class Scene_name #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize(score) @score = score end #-------------------------------------------------------------------------- # ● メイン処理 #-------------------------------------------------------------------------- def main #背景の画像表示 background = Sprite.new background.bitmap = RPG::Cache.picture("back") #文字表示 scoreview = Sprite.new scoreview.bitmap = Bitmap.new(640,24) scoreview.bitmap.draw_text(0, 0, 640, 24, "Score " + "#{@score}", 1) scoreview.y = 120 #名前表示欄作成 name = Array.new(5, "_") nameview = Array.new(name.size) x = 280 y = 160 for i in 0...nameview.size nameview[i] = Sprite.new nameview[i].bitmap = Bitmap.new(24,24) nameview[i].bitmap.draw_text(0, 0, 24, 24, "_") nameview[i].x = x nameview[i].y = y x += 16 end #文字セット作成 charaset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ._" charaview = Array.new(charaset.size) width = 7 height = charaset.size / width x = 240 y = 200 for i in 0...charaset.size charaview[i] = Sprite.new charaview[i].bitmap = Bitmap.new(24,24) charaview[i].bitmap.draw_text(0, 0, 24, 24, charaset[i].chr) charaview[i].x = x charaview[i].y = y x += 24 if x > 240 + 24 * (width - 1) x = 240 y += 24 end end #メインループ number = 0 c_position = 0 loop do #ボタンAが押されたら名前欄の文字を1つ進める if Input.trigger?(Input::A) #名前欄の最後まできていたらランキングを更新してシーン移動 if number == name.size #ランキング更新 $ranking[10] = [@score,name.join] $ranking.sort! $ranking.reverse! #ランキングデータのセーブ file = File.open("date.rxdata", "wb") Marshal.dump($ranking, file) file.close Input.update #全画像の開放 background.dispose scoreview.dispose nameview.each{|i|i.dispose} charaview.each{|i|i.dispose} #ランキング画面へ移動 $scene = Scene_ranking.new break end #選択された文字を名前欄に書き込む name[number] = charaset[c_position].chr nameview[number].bitmap.clear nameview[number].bitmap.draw_text(0, 0, 24, 24, name[number]) number += 1 end #ボタンBが押されたら名前欄の文字を1つ後退する if Input.trigger?(Input::B) if number > 0 number -= 1 end end #各方向キーに合わせて文字セットの位置を変更する if Input.trigger?(Input::DOWN) c_position += width if charaview[c_position] == nil c_position -= width * height end end if Input.trigger?(Input::LEFT) c_position -= 1 if charaview[c_position] == nil c_position = charaview.size - 1 end end if Input.trigger?(Input::RIGHT) c_position += 1 if charaview[c_position] == nil c_position = 0 end end if Input.trigger?(Input::UP) c_position -= width if charaview[c_position] == nil c_position += width * height end end #名前欄の文字を点滅 if Graphics.frame_count % 20 == 0 nameview[number].flash(nil, 10) if nameview[number] != nil end nameview.each{|i|i.update} #文字セットのうち選択中の物の色を変更 charaview.each{|i|i.color = Color.new(255, 255, 255, 255)} charaview[c_position].color = Color.new(0, 255, 255, 255) #各種更新 Input.update Graphics.update end end end #============================================================================== # ■ Main #------------------------------------------------------------------------------ #  各クラスの定義が終わった後、ここから実際の処理が始まります。 #============================================================================== #フレームレート変更(1秒間に60回のペースで画面を書き換えます) Graphics.frame_rate = 60 #ランキングデータのロード #ファイルが無ければ$rankingを初期化します if FileTest.exist?("date.rxdata") file = File.open("date.rxdata", "rb") $ranking = Marshal.load(file) file.close else $ranking = Array.new(10,[0,"_____"].dup) end #タイトル画面のシーンから開始して、以後シーンクラスのmainを呼び続けます。 $scene = Scene_title.new $scene.main while(1)