CoRサンプル集: Reversi
シンプルなリバーシゲームです
ルール
PCでもスマホでも遊べます
全画面表示ボタンを試験的に追加(2021.4.4)
ルール
- 黒が先手、白が後手です
- 自分の色のコマで相手の色のコマを挟むと自分の色にできます
- コマを置ける場所がなくなった場合はスキップになります
- どちらも置ける場所がなくなった時点で自分の色のコマが多かった方が勝利です
PCでもスマホでも遊べます
全画面表示ボタンを試験的に追加(2021.4.4)
プレー:262
(人数:55)
クリア: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
プレー内容を公開する
プレー履歴
-
レン:
WIN: (●) 53-11 ○
(11/20 03:24)
-
kazamironari...:
WIN: (●) 42-22 ○
(04/02 14:16)
-
レン:
WIN: ● 28-36 (○)
(04/14 23:39)
-
レン:
WIN: (●) 58-6 ○
(04/14 23:38)
-
aoihikawa:
WIN: (●) 47-17 ○
(02/18 00:35)
-
井戸乃博士:
WIN: ● 20-44 (○)
(02/14 20:36)
-
mochi3kan:
WIN: (●) 41-23 ○
(02/14 13:07)
-
光楼(114):
WIN: (●) 46-18 ○
(02/13 13:10)
-
muga:
WIN: ● 20-44 (○)
(02/13 11:42)
-
shainy:
WIN: ● 0-54 (○)
(02/13 09:12)
新着レビュー
レビューはまだ投稿されていません。 作品の感想を作者に伝えるためにレビューを投稿してみませんか?
フォロー/シェア
タイトルのアニメーションの気合の入り方がすごいですね!
タイトルのアニメーションは自分でも無駄に凝りました