カードゲームの作り方2


ポーカーの作り方
デフォルトスクリプトのゲームに組み込むには?


ポーカーの作り方

RCSSの実践に入ります。
カードゲームではもっともポピュラーなポーカーを選んでみました。
ただ、マルチプレイのポーカーだと思考ルーチンとか果てしなく面倒くさいので
一人用ポーカーとします。

まずはポーカーとはどんなものかを考えます。
何かを作ろうと思ったら自分の作ろうとしているものを
細かい動作に分けて考えることが大切です。

1. 5枚のカードを裏向きに配る
2. チップを賭ける
3. カードをオープンする
4. 持っておきたいカードを複数選択する
(全部ストックしても、1つもストックしなくても構わない)
5. ストックしなかったカードを捨て、同じ数だけ山札から補充する
6. 役に応じて配当を受け取る


プログラムするならもっと細かく分ける必要がありますが、
RCSSを使うならこのくらいのレベルで十分です。

それでは新しいプロジェクトを作成しましょう。
まずは必要な数のPictureとSEの素材をインポートします。

スクリプトエディタは真っ白になっていますか?
一番上のセクションにでもcard_script.txtの全内容をコピーして貼り付けます。
その下に新しいセクションを作って書き始めましょう。
class Scene_poker
  def main

    loop do
      Graphics.update
    end
  end
end

Scene_pokerクラスとmainメソッドを作りました。
クラスについてはシューティングの第1回でも書きましたので割愛しますね。

このシーンクラスを実行するには以下の2行を1つ下のセクションにでも置いてください。
scene = Scene_poker.new
scene.main()

この段階では当然何も起こりません。

まずはシステムの起動です。
class Scene_poker
  def main
    
    @system = Card_base.new
    
    loop do
      Graphics.update
    end
  end
end

まだ何も変わったようには見えませんね。しかし各種機能は使えるようになりました。

山札を作成します。
class Scene_poker
  def main
    @system = Card_base.new
    
    @system.make_talon()
    
    loop do
      Graphics.update
    end
  end
end

カードが裏向きに表示されましたね?
実はこの時点ですでに53枚のカードが表示されています。

ちょっと動かしてみましょうか。
class Scene_poker
  def main
    @system = Card_base.new
    @system.make_talon()
    
    @system.talon_x = 320
    @system.talon_y = 240
    @system.set_taloncards()
    @system.move_forcing()

    loop do
      Graphics.update
    end
  end
end

真ん中までスッと動いたでしょう?

@system.talon_x = 320
@system.talon_y = 240
山札の座標を設定して、

@system.set_taloncards()
山札に移動命令を出して、

@system.move_forcing()
移動完了までウエイト。

こんな風に記述していきます。

@system.set_taloncards(50)
なんて書くと移動速度が遅くなります。
@system.set_taloncards(10)
なら高速に。
いろいろと遊んでみてください。

・・・・・・・・・・・・・・・

では先へ進みましょう。
まずはこれ。

1. 5枚のカードを裏向きに配る

早速プレイヤーを作成しましょう。
これですね。

make_player([hand[, x[, y[, tip]]]])

handは最初に渡す枚数です。
5枚だから5。x,y,tipは適当に。気に入らなかったら後で調整しましょう。
class Scene_poker
  def main
    @system = Card_base.new
    @system.make_talon()
    
    @system.make_player(5, 120, 300, 1000)
    @system.move_forcing()

    loop do
      Graphics.update
    end
  end
end

山札から5枚がサッと取り出されました。

並びの間隔が気に入らなければ
@system.interval_x =
@system.interval_y =
で調整できます。

2. チップを賭ける

次は数値入力イベントです。
これも1から作ったら時間が掛かるものですが、システムに標準装備しています。

bet_tip(player[, x[, y[,min[, max]]]])

playerにはプレイヤー番号を入れます。
一番最初に作成したプレイヤーは0番です。
x,yは1桁目の座標、minは最小値、maxは最大値です。
maxをいくらにしてもプレイヤーのチップ数の方が小さければそれが最大値となります。
class Scene_poker
  def main
    @system = Card_base.new
    @system.make_talon()
    @system.make_player(5, 120, 300, 1000)
    @system.move_forcing()
    
    @system.bet_tip(0,320,200,1)
    
    loop do
      Graphics.update
    end
  end
end

入力した値だけプレイヤーのチップから@system.potへ移動します。

そういえば現在のチップ数が見えないと都合が悪いですね。
class Scene_poker
  def main
    @system = Card_base.new
    @system.make_talon()
    @system.make_player(5, 120, 300, 1000)
    @system.move_forcing()
    
    menuview = Sprite.new
    menuview.bitmap = Bitmap.new(640,480) 
    menuview.bitmap.draw_text(380,200,200,24,"$")
    menuview.bitmap.draw_text(420,200,200,24,"#{@system.player_tip(0)}")
    @system.bet_tip(0,320,200,1)
    menuview.bitmap.clear
    menuview.bitmap.draw_text(360,170,200,24,"Bet")
    menuview.bitmap.draw_text(420,170,200,24,"#{@system.pot}")
    menuview.bitmap.draw_text(380,200,200,24,"$")
    menuview.bitmap.draw_text(420,200,200,24,"#{@system.player_tip(0)}")
    
    loop do
      Graphics.update
    end
  end
end

システムとは関係ない普通のスプライト操作です。
文字を書く領域にしては大きすぎますが1つあると結構使えます。
@system.player_tip(0)がプレイヤー0番のチップ参照メソッドです。

3. カードをオープンする
class Scene_poker
  def main
    @system = Card_base.new
    @system.make_talon()
    @system.make_player(5, 120, 300, 1000)
    @system.move_forcing()
    menuview = Sprite.new
    menuview.bitmap = Bitmap.new(640,480) 
    menuview.bitmap.draw_text(380,200,200,24,"$")
    menuview.bitmap.draw_text(420,200,200,24,"#{@system.player_tip(0)}")
    @system.bet_tip(0,320,200,1)
    menuview.bitmap.clear
    menuview.bitmap.draw_text(360,170,200,24,"Bet")
    menuview.bitmap.draw_text(420,170,200,24,"#{@system.pot}")
    menuview.bitmap.draw_text(380,200,200,24,"$")
    menuview.bitmap.draw_text(420,200,200,24,"#{@system.player_tip(0)}")
    
    @system.open_allcard(0)
    @system.move_forcing()
    
    loop do
      Graphics.update
    end
  end
end

お次は?

4. 持っておきたいカードを複数選択する
5. ストックしなかったカードを捨て、同じ数だけ山札から補充する

class Scene_poker
  def main
    @system = Card_base.new
    @system.make_talon()
    @system.make_player(5, 120, 300, 1000)
    @system.move_forcing()
    menuview = Sprite.new
    menuview.bitmap = Bitmap.new(640,480) 
    menuview.bitmap.draw_text(380,200,200,24,"$")
    menuview.bitmap.draw_text(420,200,200,24,"#{@system.player_tip(0)}")
    @system.bet_tip(0,320,200,1)
    menuview.bitmap.clear
    menuview.bitmap.draw_text(360,170,200,24,"Bet")
    menuview.bitmap.draw_text(420,170,200,24,"#{@system.pot}")
    menuview.bitmap.draw_text(380,200,200,24,"$")
    menuview.bitmap.draw_text(420,200,200,24,"#{@system.player_tip(0)}")
    @system.open_allcard(0)
    @system.move_forcing()
    
    @system.nonselect_exchange_card(0)
    @system.move_forcing()
    @system.open_allcard(0)
    @system.move_forcing()
    
    loop do
      Graphics.update
    end
  end
end

はい終わり。
こういう基本的な動作はメソッド呼び出しだけでできるようにしています。

6. 役に応じて配当を受け取る

役判定の処理ですか、大変そうですね。
そう思ってポーカーの役判定メソッドも用意しておきました。

poker_fivejoker?(hand)
ファイブジョーカー判定
poker_royalflush?(hand)
ロイヤルストレートフラッシュ判定
poker_fivecard?(hand)
ファイブカード判定
poker_straightflush?(hand)
ストレートフラッシュ判定
poker_fourcard?(hand)
フォーカード判定
poker_fullhouse?(hand)
フルハウス判定
poker_flush?(hand)
フラッシュ判定
poker_straight?(hand)
ストレート判定
poker_threecard?(hand)
スリーカード判定
poker_twopair?(hand)
ツーペア判定
poker_onepair?(hand)
ワンペア判定


ファイブジョーカーて。
ジョーカーだけにジョークではなく、…(?)
@system.totalcardを57にすればジョーカーが5枚になるので十分可能です。

この判定はサブルーチンに持ってきたいところですね。
class Scene_poker
  def main
    @system = Card_base.new
    @system.make_talon()
    @system.make_player(5, 120, 300, 1000)
    @system.move_forcing()
    menuview = Sprite.new
    menuview.bitmap = Bitmap.new(640,480) 
    menuview.bitmap.draw_text(380,200,200,24,"$")
    menuview.bitmap.draw_text(420,200,200,24,"#{@system.player_tip(0)}")
    @system.bet_tip(0,320,200,1)
    menuview.bitmap.clear
    menuview.bitmap.draw_text(360,170,200,24,"Bet")
    menuview.bitmap.draw_text(420,170,200,24,"#{@system.pot}")
    menuview.bitmap.draw_text(380,200,200,24,"$")
    menuview.bitmap.draw_text(420,200,200,24,"#{@system.player_tip(0)}")
    @system.open_allcard(0)
    @system.move_forcing()
    @system.nonselect_exchange_card(0)
    @system.move_forcing()
    @system.open_allcard(0)
    @system.move_forcing()

    name = pattern(@system.player_hand(0))
    menuview.bitmap.clear
    menuview.bitmap.draw_text(160,140,200,24,name)
    menuview.bitmap.draw_text(360,140,200,24,"Pay")
    menuview.bitmap.draw_text(420,140,200,24,"#{@system.pot}")
    @system.pay_tip(0)
    menuview.bitmap.draw_text(380,200,200,24,"$")
    menuview.bitmap.draw_text(420,200,200,24,"#{@system.player_tip(0)}")

    loop do
      Graphics.update
    end
  end
  
  def pattern(hand)
    if @system.poker_royalflush?(hand)
      @system.pot *= 250
      return "ロイヤルストレートフラッシュ" 
    elsif @system.poker_fivecard?(hand)
      @system.pot *= 100
      return "ファイブカード" 
    elsif @system.poker_straightflush?(hand)
      @system.pot *= 50
      return "ストレートフラッシュ" 
    elsif @system.poker_fourcard?(hand)
      @system.pot *= 25
      return "フォーカード" 
    elsif @system.poker_fullhouse?(hand)
      @system.pot *= 9
      return "フルハウス" 
    elsif @system.poker_flush?(hand)
      @system.pot *= 6
      return "フラッシュ" 
    elsif @system.poker_straight?(hand)
      @system.pot *= 4
      return "ストレート" 
    elsif @system.poker_threecard?(hand)
      @system.pot *= 2
      return "スリーカード" 
    elsif @system.poker_twopair?(hand)
      @system.pot *= 1
      return "ツーペア" 
    elsif @system.poker_onepair?(hand)
      @system.pot /= 2
      return "ワンペア" 
    end
    @system.pot = 0
    return "ノーペア"
  end
end

patternメソッドを追加しました。
こんな風に役の強い順に判定していくのがポイントです。
賭け金を納めた@system.potを乗算して配当を出しています。
プレイヤーへの払い出しは@system.pay_tipです。
これを使うと@system.potの中身は0に戻ります。

そうこうしてるうちに一通り処理が出来上がりました。

仕上げに何度でも遊べるように修正しましょう。
  def main
    @system = Card_base.new
    @system.make_talon()
    @system.make_player(5, 120, 300, 1000)
    @system.move_forcing()
    menuview = Sprite.new
    menuview.bitmap = Bitmap.new(640,480) 
    loop do
      menuview.bitmap.draw_text(380,200,200,24,"$")
      menuview.bitmap.draw_text(420,200,200,24,"#{@system.player_tip(0)}")
      @system.bet_tip(0,320,200,1)
      menuview.bitmap.clear
      menuview.bitmap.draw_text(360,170,200,24,"Bet")
      menuview.bitmap.draw_text(420,170,200,24,"#{@system.pot}")
      menuview.bitmap.draw_text(380,200,200,24,"$")
      menuview.bitmap.draw_text(420,200,200,24,"#{@system.player_tip(0)}")
      @system.open_allcard(0)
      @system.move_forcing()
      @system.nonselect_exchange_card(0)
      @system.move_forcing()
      @system.open_allcard(0)
      @system.move_forcing()
      name=  pattern(@system.player_hand(0))
      menuview.bitmap.clear
      menuview.bitmap.draw_text(160,140,200,24,name)
      menuview.bitmap.draw_text(360,140,200,24,"Pay")
      menuview.bitmap.draw_text(420,140,200,24,"#{@system.pot}")
      @system.pay_tip(0)
      menuview.bitmap.draw_text(380,200,200,24,"$")
      menuview.bitmap.draw_text(420,200,200,24,"#{@system.player_tip(0)}")
      @system.entry_wait()
      @system.make_talon()
      @system.move_forcing() 
      @system.take_card(0, 5)
      @system.move_forcing()
      menuview.bitmap.clear
      if @system.player_tip(0) < 1
        menuview.bitmap.draw_text(160,140,200,32,"ゲームオーバー")
        @system.entry_wait()
        @system.dispose_allcard
        menuview.dispose
        return
      end
    end
  end

これで完成です。
あとは背景を追加するなりオリジナルのルールを加えるなりして華を添えましょう。



メニューへ


デフォルトスクリプトのゲームに組み込むには?

デフォルトスクリプトで作ったRPGにミニゲームとして追加したい場合があるかもしれませんね。
シーンクラスの作り方はデフォルトに習っていますので大きな変更は必要ありません。

mainより上に新しいセクションを作ってcard_script.txtのスクリプトと
Scene_pokerクラスを張り付けます。(実行部は破棄)

後は使いたいときにイベントコマンドから
◆スクリプト:$scene = Scene_poker.new
を実行するだけです。

Scene_pokerのmainメソッドでは背景やカードなどを配置した後に
Graphics.transition
を使って画面の切り替え表示をお忘れなく。
チップ等の受け渡しにはツクール変数$game_variablesが使えます。

ゲームが終わって元のマップに戻るときは以下のように書きます。
Graphics.freeze
$scene = Scene_Map.new
return




いかがだったでしょうか?
…使える?…使えない?

これ自体が使えなくても解析するなり改造するなりして
何かの足しにでもなれば幸いです。



前のページへ
一覧へ戻る
トップページへ戻る



更新日時:2005 8/6 17:00
管理人:すっぴぃ ◆ADGYPSYxII