ソースコード:2021年度受賞作品「Titly」
2021年度受賞作品「Titly」を元に、ブラウザ上でRubyグラフィックプログラミングができる「rbCanvas/p5」(https://rbcanvas.net/p5/)に移植しました。そのソースコードの紹介をしています。
main
# 初期設定用のコード (your setup code here)
C_START = [255, 255, 0, 255] # 色(スタート地点)
C_GOAL = [255, 128, 0, 255] # 色(ゴール地点)
C_STREET = [255, 255, 255, 255] # 色(通路)
C_WALL = [ 0, 128, 0, 255] # 色(壁)
C_OBSTACLE = [ 0, 0, 0, 255] # 色(障害物)
def setup
createCanvas(400, 400)
@status = :READY
@course = CourseStatic.new
angleMode = DEGREES
selectCourse
end
# 画面描画用のコード (your draw code here)
def draw
@course.draw
check
showStatus
showClear if @status == :CLEAR
showGameOver if @status == :OVER
end
# コースの選択
def selectCourse
caption = [
'コース1(初級)',
'コース2(中級)',
'コース3(上級)',
'コース4(おまけ)'
]
sel = createSelect
sel.position(4, 4)
sel.option(caption[0])
sel.option(caption[1])
sel.option(caption[2])
sel.option(caption[3])
sel.selected(caption[0])
mySelectEvent = Proc.new {
@status = :READY
loop
case sel.value
when caption[0]
@course = CourseStatic.new
when caption[1]
@course = CourseRolling.new
when caption[2]
@course = CourseMoving.new
when caption[3]
@course = CourseCrossing.new
end
}
sel.changed(mySelectEvent)
end
# ゲームオーバーのチェック
def check
return if @status != :GO!
mx = mouseX
my = mouseY
# キャンバスの外側
if mx < 0 or mx > width or
my < 0 or my > height
@status = :OVER
end
# 壁または障害物
c = get(mx, my)
if c == C_WALL or c == C_OBSTACLE
@status = :OVER
end
end
# マウスクリック
def mouseClicked
c = get(mouseX, mouseY)
if c == C_START and @status == :READY # ゲーム開始
@status = :GO!
elsif c == C_GOAL and @status == :GO! # ゴール到達
@status = :CLEAR
elsif @status == :OVER or @status == :CLEAR # リプレイ
@status = :READY
loop
end
end
course1
# 追加のコード (your supplementary code here)
class CourseStatic
def draw
Landmark.wall(0, 0, width, height)
Landmark.street( 0, 200, 100, 30)
Landmark.street( 70, 50, 30, 150)
Landmark.street( 70, 50, 100, 30)
Landmark.street(150, 50, 30, 300)
Landmark.street(150, 320, 100, 30)
Landmark.street(220, 120, 30, 200)
Landmark.street(220, 100, 100, 30)
Landmark.street(300, 100, 30, 200)
Landmark.street(300, 300, 100, 30)
Landmark.startPoint(0, 200, 30, 30)
Landmark.goalPoint(370, 300, 30, 30)
end
end
course2
# 追加のコード (your supplementary code here)
class CourseRolling
def initialize
@rolling1 = Rolling.new(140, 215, 120, :R)
@rolling2 = Rolling.new(280, 215, 80, :L)
end
def draw
Landmark.wall(0, 0, width, height)
Landmark.street(0, 200, width, 30)
@rolling1.role(0.01)
@rolling2.role
Landmark.startPoint(0, 200, 30, 30)
Landmark.goalPoint(370, 200, 30, 30)
end
end
course3
# 追加のコード (your supplementary code here)
class CourseMoving
def initialize
@moving1 = Moving.new( 70, 200, 50, :V)
@moving2 = Moving.new(250, 200, 50, :H)
end
def draw
Landmark.wall(0, 0, width, height)
Landmark.street( 0, 200, 400, 30)
Landmark.street(200, 185, 30, 15)
Landmark.street(260, 230, 20, 15)
Landmark.wall(100, 220, 30, 10)
Landmark.wall(140, 200, 20, 15)
Landmark.wall(170, 220, 30, 10)
Landmark.wall(330, 210, 30, 10)
@moving1.move
@moving2.move(0.1)
Landmark.startPoint( 0, 200, 30, 30)
Landmark.goalPoint(370, 200, 30, 30)
end
end
course4
# 追加のコード (your supplementary code here)
class CourseCrossing
def initialize
@movings = []
@movings << Moving.new( 35, 150, 50, :V)
@movings << Moving.new( 65, 260, 50, :V, 180)
@movings << Moving.new( 95, 150, 50, :V)
@movings << Moving.new(125, 260, 50, :V, 180)
@movings << Moving.new(155, 150, 50, :V)
@movings << Moving.new(185, 260, 50, :V, 180)
@movings << Moving.new(215, 150, 50, :V)
@movings << Moving.new(245, 260, 50, :V, 180)
@movings << Moving.new(275, 150, 50, :V)
@movings << Moving.new(305, 260, 50, :V, 180)
@movings << Moving.new(335, 150, 50, :V)
@movings << Moving.new( 35, 250, 50, :V, 270)
@movings << Moving.new( 65, 150, 80, :V, 90)
@movings << Moving.new( 95, 250, 50, :V, 270)
@movings << Moving.new(125, 150, 80, :V, 90)
@movings << Moving.new(155, 250, 50, :V, 270)
@movings << Moving.new(185, 150, 80, :V, 90)
@movings << Moving.new(215, 250, 50, :V, 270)
@movings << Moving.new(245, 150, 80, :V, 90)
@movings << Moving.new(275, 250, 50, :V, 270)
@movings << Moving.new(305, 150, 80, :V, 90)
@movings << Moving.new(335, 250, 50, :V, 270)
end
def draw
Landmark.wall(0, 0, width, height)
Landmark.street( 0, 200, width, 30)
Landmark.street( 35, 60, width - (30 + 5) * 2, height - 60 * 2)
@movings.each do |m|
m.move
end
Landmark.startPoint( 0, 200, 30, 30)
Landmark.goalPoint(370, 200, 30, 30)
end
end
landmark
# 追加のコード (your supplementary code here)
module Landmark
# スタート地点の表示
def self.startPoint(x, y, w, h)
noStroke
fill(C_START)
rect(x, y, w, h)
end
# ゴール地点の表示
def self.goalPoint(x, y, w, h)
noStroke
fill(C_GOAL)
rect(x, y, w, h)
end
# 壁の表示
def self.wall(x, y, w, h)
noStroke
fill(C_WALL)
rect(x, y, w, h)
end
# 通路の表示
def self.street(x, y, w, h)
noStroke
fill(C_STREET)
rect(x, y, w, h)
end
end
message
# 追加のコード (your supplementary code here)
# ステータスの表示
def showStatus
textSize(30)
noStroke
fill("white")
text(@status, 280, 40)
end
# クリアしたときのメッセージ
def showClear
textSize(60)
noStroke
fill("gold")
textAlign(CENTER)
text("Clear!", width / 2, 100)
if @course.class == CourseCrossing
fill(255, 255, 255, 128)
rect(0, 0, width, height)
a = createElement('a', 'つぎのコンテンツに進もう!');
a.style('color', '#ff0000');
a.elt.href = 'https://www.mitaka.ne.jp/'
a.elt.target = '_parent'
# a.elt.target = '_blank'
a.position(70, 420);
a.style('font-size', '20px');
%x{
console.log(a)
console.log(a.native.elt)
}
end
noLoop
end
# ゲームオーバーのときのメッセージ
def showGameOver
textSize(60)
noStroke
fill("black")
textAlign(CENTER)
text("GameOver", width / 2, 100)
noLoop
end
obstacle
# 追加のコード (your supplementary code here)
class Rolling
def initialize(x, y, d, dir)
@x = x
@y = y
@d = d
@dir = dir
@th = 0
end
def role(delta = 0.02)
push do
translate(@x, @y)
if @dir == :R
@th -= delta
else
@th += delta
end
rotate(-@th)
noStroke
fill(C_STREET)
ellipse(0, 0, @d, @d)
fill(C_OBSTACLE)
rect(-@d / 2, -8, @d, 16)
rect(-8, -@d / 2, 16, @d)
end
end
end
# 移動する障害物の表示
class Moving
def initialize(x, y, d, dir, th = 0)
@x = x
@y = y
@d = d
@dir = dir
@th = th
end
def move(delta = 0.06)
@th += delta
push do
if @dir == :V
x = @x
y = @y + @d * sin(@th)
else
x = @x + @d * cos(@th)
y = @y
end
translate(x, y)
noStroke
fill(C_OBSTACLE)
rect(0, 0, 30, 30)
end
end
end