CoRサンプル集: Reversi

シンプルなリバーシゲームです

ルール
  • 黒が先手、白が後手です
  • 自分の色のコマで相手の色のコマを挟むと自分の色にできます
  • コマを置ける場所がなくなった場合はスキップになります
  • どちらも置ける場所がなくなった時点で自分の色のコマが多かった方が勝利です

PCでもスマホでも遊べます

全画面表示ボタンを試験的に追加(2021.4.4)
プレー:259 (人数:52) クリア:21 評価: 50 (5回)
# # ooooooooo. o8o # `888 `Y88. `"' # 888 .d88' .ooooo. oooo ooo .ooooo. oooo d8b .oooo.o oooo # 888ooo88P' d88' `88b `88. .8' d88' `88b `888""8P d88( "8 `888 # 888`88b. 888ooo888 `88..8' 888ooo888 888 `"Y88b. 888 # 888 `88b. 888 .o `888' 888 .o 888 o. )88b 888 # o888o o888o `Y8bod8P' `8' `Y8bod8P' d888b 8""888P' o888o # # Code on Rmakeで作ったゲームがタップ操作できないと見かけたので、タップ操作でも遊べるゲームを作ってみました # タップ操作できる仕組みを作ることを目的として作ったため、本来のゲーム部分は適当です # 恥ずかしいぐらい手抜きのプログラムなので、あくまで軽い参考程度に見てください # 315行あたりからタップ操作対応についてほんの少しだけ解説しています # CoRサンプルとしておきながらそれ以外はコメントアウトによる説明はありません # 使用されているすべての素材は公開しています # 作成者 Shainy # 2021.2.13 # 更新履歴 # 全画面表示ボタンを追加(試験的) # 2021.4.4 sprite :fullscreen do image :fullscreen origin :left_top end sprite :invisible do motion :wait do from params: {y: '-1'}, duration: 1000 end motion :move_1 do from params: {x: '-1'}, duration: 1000 end end sprite :logo do image :logo motion :fade_in do to params: {x: 225,y: 50, alpha: 0}, duration: 1 to params: {y: 150, alpha: 1}, duration: 2000 end motion :fade_out do to params: {y: 100}, duration: 1000 end end sprite :logo_shadow do image :logo_shadow motion :fade_in do to params: {x: 235,y: 160, alpha: 0}, duration: 1 to params: {alpha: 1}, duration: 2000 end motion :fade_out do to params: {y: 110}, duration: 1000 end end sprite :color do image :color origin :left_top motion :fade_in do to params: {alpha: 0}, duration: 1 to params: {alpha: 1}, duration: 2000 end motion :fade_out do to params: {alpha: 1}, duration: 1 to params: {x: '-1', alpha: 0}, duration: 2000 end end sprite :start do image :start motion :blink do to params: {x: 225,y: 600, alpha: 0}, duration: 1 to params: {alpha: 1}, duration: 500 to params: {}, duration: 1000 to params: {alpha: 0}, duration: 500 loop true end end sprite :piece do image :piece motion :move_33 do to params: {x: '-54'}, duration: 2000 end motion :move_34 do to params: {x: '54'}, duration: 2000 end motion :move_1 do from params: {x: '-1'}, duration: 1000 end end sprite :piece_shadow do image :piece_shadow motion :move_1 do from params: {x: '-1'}, duration: 1000 end motion :fade_in do to params: {alpha: 0}, duration: 1 to params: {alpha: 0.5}, duration: 499 end end sprite :play_black do image :play_black motion :fade_out do to params: {alpha: 0}, duration: 250 end end sprite :play_white do image :play_white motion :fade_out do to params: {alpha: 0}, duration: 250 end end sprite :map do image :map motion :invisible do to params: {alpha: 0}, duration: 1 end motion :fade_in do to params: {alpha: 1}, duration: 1000 end end sprite :number_black do image :number_black motion :invisible do to params: {alpha: 0}, duration: 1 end motion :fade_in do to params: {alpha: 1}, duration: 1000 end end sprite :number_white do image :number_white motion :invisible do to params: {alpha: 0}, duration: 1 end motion :fade_in do to params: {alpha: 1}, duration: 1000 end end sprite :result do image :result motion :invisible do to params: {alpha: 0}, duration: 1 end motion :fade_in do to params: {y: '-64'}, duration: 1 to params: {y: '64', alpha: 1}, duration: 999 end end scene :main do canvas = $window.document.querySelector "#cor_player canvas" aspect = rmake_game.screen_width / rmake_game.screen_height pointer_x = pointer_y = pointer_moved = pointer_down = pointer_is_mouse = sprites = sounds = state = map = turn = player = skipped = can_place = nil preload do image :color, id: 325474 image :logo, id: 325448 image :logo_shadow, id: 325469 image :start, id: 325475 image :piece, id: 325476, frame_size: [108, 108], frame_pattern: 2 image :piece_shadow, id: 325478 image :play_black, id: 325482 image :play_white, id: 325483 image :map, id: 325484 image :number_white, id: 325486, frame_size: [74, 61], frame_pattern: 65 image :number_black, id: 325487, frame_size: [74, 61], frame_pattern: 65 image :result, id: 325488, frame_size: [197, 61], frame_pattern: 6 image :fullscreen, id: 325707, frame_size: [60, 60], frame_pattern: 2 sound :beep, id: 325481 end render do sprites[:fullscreen].frame_index $window.eval('document.webkitFullscreenElement? 1: 0') end create do pointer_x = pointer_y = -1 pointer_moved = pointer_down = pointer_is_mouse = false sprites = {} sounds = {} state = 0 map = [] turn = 0 skipped = false can_place = [] sounds[:beep] = add_sound :beep sprites[:pointer] = put_sprite :invisible do collision_size 1, 1 end sprites[:bg] = put_sprite :color do src_rect 4, 1, 1, 1 scale 450, 800 end sprites[:fullscreen] = put_sprite :fullscreen do position 390, 740 end sprites[:white] = put_sprite :color do src_rect 1, 1, 1, 1 scale 451, 800 end sprites[:white].start_motion :fade_out sprites[:pieces] = put_sprite :invisible do position 225, 400 end sprites[:map] = put_sprite :map do scale 0, 0 end sprites[:map].start_motion :invisible sprites[:pieces].add_child sprites[:map] sprites[:number_black] = put_sprite :number_black do position 64, 700 scale 0, 0 frame_index 2 end sprites[:number_black].start_motion :invisible sprites[:number_white] = put_sprite :number_white do position 394, 700 scale 0, 0 frame_index 2 end sprites[:number_white].start_motion :invisible sprites[:result] = put_sprite :result do position 225, 700 scale 0, 0 end sprites[:result].start_motion :invisible 8.times do |y| map[y] = [] 8.times do |x| map[y][x] = -1 piece_group = put_sprite :invisible do position x * 108 - 378, y * 108 - 378 scale 0, 0 layer_index 0 end piece_shadow = put_sprite :piece_shadow do position 15, 15 layer_index 1 end piece = put_sprite :piece do frame_index 0 layer_index 2 collision_size 32, 32 end piece_group.add_child piece_shadow piece_group.add_child piece sprites[:pieces].add_child piece_group sprites["piece_group_#{x}#{y}".to_sym] = piece_group sprites["piece_shadow_#{x}#{y}".to_sym] = piece_shadow sprites["piece_#{x}#{y}".to_sym] = piece end end sprites[:piece_33].frame_index 1 sprites[:piece_43].frame_index 0 sprites[:piece_34].frame_index 0 sprites[:piece_44].frame_index 1 map[3][3] = 1 map[3][4] = 0 map[4][3] = 0 map[4][4] = 1 sprites[:logo_shadow] = put_sprite :logo_shadow do position 0, 1024 end sprites[:logo] = put_sprite :logo do position 0, 1024 end end update do aspect2 = canvas.clientWidth / canvas.clientHeight if aspect < aspect2 then pointer_x_new = (pointer.x - (canvas.clientWidth - canvas.clientHeight * aspect) / 2) / canvas.clientHeight * rmake_game.screen_height pointer_y_new = pointer.y / canvas.clientHeight * rmake_game.screen_height else pointer_x_new = pointer.x / canvas.clientWidth * rmake_game.screen_width pointer_y_new = (pointer.y - (canvas.clientHeight - canvas.clientWidth / aspect) / 2) / canvas.clientWidth * rmake_game.screen_width end pointer_x_new=pointer_x_new.floor pointer_y_new=pointer_y_new.floor # -------- ここから ---------- # # 基本的にはここでマウス操作とタップ操作を判定しています # デフォルトではタップ操作で、以下の条件でマウス操作と判定しています # A: pointer.down?メソッドが呼ばれた # B: 2フレーム連続でpointer.xかpointer.yが変動 # Aは言わずもがな。スマホなどのタップ操作だとpointer.down?メソッドはtrueを返しません # これがCode on Rmakeで作られたゲームがタップ操作できない大体の原因です # しかし、タップした時でもpointer.xとpointer.yの値(座標)は変動します # これを利用したのがBの判定方法です # タップ操作は一般的に指で操作するので、連続で全く同じ場所をタップするのは難しいと考えます # そのためpointer.x、yが変動した時に、タップしたのだと分かります # しかしこれではマウス操作時に、マウスを動かす間ずっとタップしていると誤認識してしまいます # そこでBの条件です。2フレーム(CoRでは約60分の1秒)という短い時間で2回タップ操作するのは現実的でないことを利用しています # 一度でもマウス操作だと判定された場合はそれ以降ずっと、pointer.down?による通常のクリック検知を用いています pointer_tap = pointer_down if pointer_is_mouse then pointer_down = pointer.down? else if pointer.down? then pointer_is_mouse = true pointer_down = true elsif pointer_x != pointer_x_new || pointer_y != pointer_y_new then if pointer_moved then pointer_is_mouse = true pointer_down = false else pointer_moved = true pointer_down = false end else if pointer_moved then pointer_moved = false pointer_down = true else pointer_down = false end end end # 以下のようにpointerの座標(マウスカーソルまたはタップ位置)に追従するスプライトを用意しているのも理由があります # タップ操作でpointer.down?が使えないように、スプライトのクリック検知であるtap_down?メソッドも同様に動作しません # その代わりとして、スプライト同士のcollisionによる接触判定を使っています pointer_x = pointer_x_new pointer_y = pointer_y_new sprites[:pointer].position pointer_x, pointer_y # pointer.down?はマウスの左ボタンを押している間反応するため、クリックした瞬間は分かりません # 以下ではクリックした瞬間かどうかを判定しています if pointer_tap then pointer_tap = false elsif pointer_down then pointer_tap = true end # ---------- ここまで ---------- # if pointer_tap then collision sprites[:pointer], sprites[:fullscreen] do if sprites[:fullscreen].frame_index === 0 then $window.eval 'if(document.fullscreenEnabled) document.querySelector("#cor_player canvas").requestFullscreen(); else if(document.webkitFullscreenEnabled) document.querySelector("#cor_player canvas").webkitRequestFullscreen(); else if(document.mozFullScreenEnabled) document.querySelector("#cor_player canvas").mozRequestFullScreen(); else if(document.msFullscreenEnabled) document.querySelector("#cor_player canvas").msRequestFullscreen();' else $window.eval 'if(document.fullscreenEnabled) document.exitFullscreen(); else if(document.webkitFullscreenEnabled) document.webkitCancelFullscreen(); else if(document.mozFullScreenEnabled) document.mozCancelFullScreen(); else if(document.msFullscreenEnabled) document.msExitFullscreen();' end sounds[:beep].play pointer_tap = false pointer_down=false pointer_moved = false pointer_is_mouse = false wait_time 2000 end end case state when 0 then if sprites[:white].position[0] < -0.5 then state = 1 end when 1 then if pointer_tap then sprites[:white].destroy sounds[:beep].play state = 7 elsif sprites[:white].position[0] === -1 then sprites[:white].destroy sprites[:piece_33].start_motion :move_1 state = 2 end when 2 then scale = Math.sin((sprites[:piece_33].position[0] + 1) * 90 * (Math::PI / 180)) sprites[:piece_group_33].scale scale, scale if pointer_tap then sounds[:beep].play state = 7 elsif sprites[:piece_33].position[0] === 0 then sprites[:piece_43].start_motion :move_1 state = 3 end when 3 then scale = Math.sin((sprites[:piece_43].position[0] + 1) * 90 * (Math::PI / 180)) sprites[:piece_group_43].scale scale, scale if pointer_tap then sounds[:beep].play state = 7 elsif sprites[:piece_43].position[0] === 0 then sprites[:piece_34].start_motion :move_1 state = 4 end when 4 then scale = Math.sin((sprites[:piece_34].position[0] + 1) * 90 * (Math::PI / 180)) sprites[:piece_group_34].scale scale, scale if pointer_tap then sounds[:beep].play state = 7 elsif sprites[:piece_34].position[0] === 0 then sprites[:piece_44].start_motion :move_1 state = 5 end when 5 then scale = Math.sin((sprites[:piece_44].position[0] + 1) * 90 * (Math::PI / 180)) sprites[:piece_group_44].scale scale, scale if pointer_tap then sounds[:beep].play state = 7 elsif sprites[:piece_44].position[0] === 0 then sprites[:logo].start_motion :fade_in sprites[:logo_shadow].start_motion :fade_in state = 6 end when 6 then if pointer_tap then sounds[:beep].play state = 7 elsif sprites[:logo].position[1] === 150 then state = 7 end when 7 then sprites[:logo].destroy sprites[:logo_shadow].destroy sprites[:piece_group_33].scale 1, 1 sprites[:piece_group_43].scale 1, 1 sprites[:piece_group_34].scale 1, 1 sprites[:piece_group_44].scale 1, 1 sprites[:logo_shadow] = put_sprite :logo_shadow do position 235, 160 end sprites[:logo] = put_sprite :logo do position 225, 150 end sprites[:start] = put_sprite :start do position 0, 1024 end sprites[:start].start_motion :blink state = 8 when 8 then if pointer_tap then sprites.delete(:start).destroy sounds[:beep].play sprites[:play_black] = put_sprite :play_black do position 225, 600 end sprites[:play_white] = put_sprite :play_white do position 225, 664 end state = 9 end when 9 then if pointer_tap then collision sprites[:pointer], sprites[:play_black] do sounds[:beep].play player = 0 state = 10 end collision sprites[:pointer], sprites[:play_white] do sounds[:beep].play player = 1 state = 10 end end when 10 then sprites[:logo].start_motion :fade_out sprites[:logo_shadow].start_motion :fade_out sprites[:play_black].start_motion :fade_out sprites[:play_white].start_motion :fade_out sprites[:pieces].start_motion :wait sprites[:map].scale 2, 2 sprites[:map].start_motion :fade_in sprites[:number_black].scale 1, 1 sprites[:number_black].start_motion :fade_in sprites[:number_white].scale 1, 1 sprites[:number_white].start_motion :fade_in state = 11 when 11 then scale = Math.cos((sprites[:pieces].position[1] - 399) * 180 * (Math::PI / 180)) * 0.25 + 0.75 sprites[:pieces].scale scale, scale if sprites[:pieces].position[1] === 400 then state = 12 end when 12 then can_place = [] 8.times do |y| 8.times do |x| if map[y][x] != -1 then next end place = [[x, y], [], false] can_get = [] xx = x yy = y - 1 while yy >= 0 do if map[yy][xx] === -1 then can_get = [] break elsif map[yy][xx] === turn then if can_get.size > 0 then place[1].concat(can_get) end break else can_get << [xx, yy] end yy -= 1 end can_get = [] xx = x + 1 yy = y - 1 while (xx < 8) && (yy >= 0) do if map[yy][xx] === -1 then can_get = [] break elsif map[yy][xx] === turn then if can_get.size > 0 then place[1].concat(can_get) end break else can_get << [xx, yy] end xx += 1 yy -= 1 end can_get = [] xx = x + 1 yy = y while xx < 8 do if map[yy][xx] === -1 then can_get = [] break elsif map[yy][xx] === turn then if can_get.size > 0 then place[1].concat(can_get) end break else can_get << [xx, yy] end xx += 1 end can_get = [] xx = x + 1 yy = y + 1 while (xx < 8) && (yy < 8) do if map[yy][xx] === -1 then can_get = [] break elsif map[yy][xx] === turn then if can_get.size > 0 then place[1].concat(can_get) end break else can_get << [xx, yy] end xx += 1 yy += 1 end can_get = [] xx = x yy = y + 1 while yy < 8 do if map[yy][xx] === -1 then can_get = [] break elsif map[yy][xx] === turn then if can_get.size > 0 then place[1].concat(can_get) end break else can_get << [xx, yy] end yy += 1 end can_get = [] xx = x - 1 yy = y + 1 while ((xx >= 0) && (yy < 8)) do if map[yy][xx] === -1 then can_get = [] break elsif map[yy][xx] === turn then if can_get.size > 0 then place[1].concat(can_get) end break else can_get << [xx, yy] end xx -= 1 yy += 1 end can_get = [] xx = x - 1 yy = y while xx >= 0 do if map[yy][xx] === -1 then can_get = [] break elsif map[yy][xx] === turn then if can_get.size > 0 then place[1].concat(can_get) end break else can_get << [xx, yy] end xx -= 1 end can_get = [] xx = x - 1 yy = y - 1 while (xx >= 0) && (yy >= 0) do if map[yy][xx] === -1 then can_get = [] break elsif map[yy][xx] === turn then if can_get.size > 0 then place[1].concat(can_get) end break else can_get << [xx, yy] end xx -= 1 yy -= 1 end if place[1].size > 0 then can_place << place sprites["piece_group_#{place[0][0]}#{place[0][1]}".to_sym].scale 0.4, 0.4 sprites["piece_#{place[0][0]}#{place[0][1]}".to_sym].frame_index turn end end end if can_place.size > 0 then state = (turn === player) ? 13 : 14 skipped = false else if skipped then state = 16 else state = 15 skipped = true end end when 13 then if pointer_tap then for place in can_place do selected = false collision sprites[:pointer], sprites["piece_#{place[0][0]}#{place[0][1]}".to_sym] do place[2] = true selected = true state = 15 sounds[:beep].play end if selected then break end end end when 14 then can_place.shuffle! (can_place.max_by do |place| place[1].size end)[2] = true state = 15 when 15 then for place in can_place do if place[2] then sprites["piece_group_#{place[0][0]}#{place[0][1]}".to_sym].scale 1, 1 sprites["piece_#{place[0][0]}#{place[0][1]}".to_sym].frame_index turn map[place[0][1]][place[0][0]] = turn for reverse in place[1] do sprites["piece_group_#{reverse[0]}#{reverse[1]}".to_sym].scale 1, 1 sprites["piece_#{reverse[0]}#{reverse[1]}".to_sym].frame_index turn map[reverse[1]][reverse[0]] = turn end else sprites["piece_group_#{place[0][0]}#{place[0][1]}".to_sym].scale 0, 0 end end scores = [0, 0] 8.times do |y| 8.times do |x| if map[y][x] != -1 then scores[map[y][x]] += 1 end end end sprites[:number_black].frame_index scores[0] sprites[:number_white].frame_index scores[1] turn = (turn + 1) % 2 state = 12 when 16 then scores = [0, 0] 8.times do |y| 8.times do |x| if map[y][x] != -1 then scores[map[y][x]] += 1 end end end $window.eval 'if(document.fullscreenEnabled) document.exitFullscreen(); else if(document.webkitFullscreenEnabled) document.webkitCancelFullscreen(); else if(document.mozFullScreenEnabled) document.mozCancelFullScreen(); else if(document.msFullscreenEnabled) document.msExitFullscreen();' if scores[player] === scores[player - 1] then sprites[:result].frame_index player * 3 sprites[:result].scale 1, 1 sprites[:result].start_motion :fade_in send_activity_feed "DRAW: #{player === 0 ? '(●)' : '●'} #{scores[0]}-#{scores[1]} #{player === 0 ? '○' : '(○)'}" start_scene :main elsif scores[player] > scores[player - 1] then sprites[:result].frame_index player * 3 + 1 sprites[:result].scale 1, 1 sprites[:result].start_motion :fade_in send_activity_feed "WIN: #{player === 0 ? '(●)' : '●'} #{scores[0]}-#{scores[1]} #{player === 0 ? '○' : '(○)'}" game_clear else sprites[:result].frame_index player * 3 + 2 sprites[:result].scale 1, 1 sprites[:result].start_motion :fade_in send_activity_feed "LOSE: #{player === 0 ? '(●)' : '●'} #{scores[0]}-#{scores[1]} #{player === 0 ? '○' : '(○)'}" start_scene :main end end end end start_scene :main
コード一覧
  • start.rb
投稿者:Material 315238 1 mini shainy 対象Lv1 公開日:2021年02月13日 08:59:29
プレー内容を公開する

違反を通報する

コメントする

コメントするには、ログインする必要があります。

コメント一覧

Material 303531 2 mini mochi3kan(投稿日:2021/02/14 13:08, 履歴)
タブレットでも操作できました!
タイトルのアニメーションの気合の入り方がすごいですね!
Material 315238 1 mini shainy(投稿日:2021/02/14 16:38, 履歴)
ちゃんとタッチパネル端末でも操作できているようでなによりです。
タイトルのアニメーションは自分でも無駄に凝りました
プレー履歴

全てのプレー履歴を見る

新着レビュー

レビューはまだ投稿されていません。 作品の感想を作者に伝えるためにレビューを投稿してみませんか?

全てのレビュー

フォロー/シェア

ブログ/Wiki/掲示板で共有する

Rmake内(ブログ/Wiki/掲示板)に貼り付ける場合は以下のタグを利用してください。

リンク

プレイヤー

外部ホームページに貼り付ける

外部ホームページに貼り付ける場合は以下のタグを利用してください。