Code Sketch
rider 2311 by shlok thakur
Category: Programming
// ============================================================
// RIDER 2311
// Beginner Bike Game for Learning Scala in Kojo
// AI GUIDE: ALEX
// ============================================================
cleari()
originBottomLeft()
// ------------------------------------------------------------
// GAME SCREENS
// ------------------------------------------------------------
// 0 = Start
// 1 = Bike selection
// 2 = Playing
// 3 = Game over
// 4 = Level complete
// 5 = Final screen
var screen = 0
// ------------------------------------------------------------
// PLAYER
// ------------------------------------------------------------
var riderName = "RIDER 2311"
var selectedBike = 1
// Bike positions
var bikeX = 300.0
var bikeY = 90.0
val bikeSpeed = 6.0
// Keyboard states
var moveLeft = false
var moveRight = false
var moveUp = false
var moveDown = false
// ------------------------------------------------------------
// GAME VARIABLES
// ------------------------------------------------------------
var level = 1
var score = 0
var lives = 3
var roadSpeed = 4.0
var distance = 0.0
val targetDistance = 1000.0
var fuel = 100.0
var gameOverReason = ""
// ------------------------------------------------------------
// OBSTACLES
// ------------------------------------------------------------
var obstacle1X = 150.0
var obstacle1Y = 650.0
var obstacle2X = 350.0
var obstacle2Y = 900.0
var obstacle3X = 520.0
var obstacle3Y = 1200.0
// ------------------------------------------------------------
// COINS
// ------------------------------------------------------------
var coin1X = 250.0
var coin1Y = 800.0
var coin2X = 450.0
var coin2Y = 1100.0
var coin3X = 330.0
var coin3Y = 1450.0
var coin1Taken = false
var coin2Taken = false
var coin3Taken = false
// ------------------------------------------------------------
// TIMER
// ------------------------------------------------------------
var frameCounter = 0
// ------------------------------------------------------------
// ALEX AI MESSAGE
// ------------------------------------------------------------
var alexMessage = "Hello! I am Alex."
// This function displays Alex's message.
// It is defined here, so Kojo will know what alex() means.
def alex(message: String) {
alexMessage = message
}
// ------------------------------------------------------------
// RESET GAME
// ------------------------------------------------------------
def resetGame() {
screen = 1
level = 1
score = 0
lives = 3
bikeX = cwidth / 2.0
bikeY = 90.0
distance = 0.0
fuel = 100.0
obstacle1Y = 650.0
obstacle2Y = 900.0
obstacle3Y = 1200.0
coin1Y = 800.0
coin2Y = 1100.0
coin3Y = 1450.0
coin1Taken = false
coin2Taken = false
coin3Taken = false
gameOverReason = ""
alex("Welcome to RIDER 2311! I am Alex. Let's ride!")
}
// ------------------------------------------------------------
// START LEVEL
// ------------------------------------------------------------
def startLevel(newLevel: Int) {
level = newLevel
bikeX = cwidth / 2.0
bikeY = 90.0
distance = 0.0
fuel = 100.0
frameCounter = 0
obstacle1Y = cheight + 150.0
obstacle2Y = cheight + 450.0
obstacle3Y = cheight + 750.0
coin1Y = cheight + 300.0
coin2Y = cheight + 600.0
coin3Y = cheight + 900.0
coin1Taken = false
coin2Taken = false
coin3Taken = false
if (level == 1) {
roadSpeed = 4.0
alex("Level 1! Use LEFT and RIGHT to ride.")
}
else if (level == 2) {
roadSpeed = 5.0
alex("Level 2! The road is faster. Stay focused!")
}
else {
roadSpeed = 6.0
alex("Level 3! Final race! You can do it!")
}
screen = 2
}
// ------------------------------------------------------------
// COLLISION FUNCTION
// ------------------------------------------------------------
def collision(
x1: Double,
y1: Double,
r1: Double,
x2: Double,
y2: Double,
r2: Double
): Boolean = {
val dx = x1 - x2
val dy = y1 - y2
val distanceBetween =
math.sqrt(dx * dx + dy * dy)
distanceBetween < r1 + r2
}
// ------------------------------------------------------------
// DRAW BIKE
// ------------------------------------------------------------
def drawBike(
canvas: CanvasDraw,
x: Double,
y: Double,
bikeType: Int
) {
canvas.noStroke()
// Wheels
canvas.fill(20, 20, 20)
canvas.ellipse(
x - 18,
y - 20,
25,
25
)
canvas.ellipse(
x + 18,
y - 20,
25,
25
)
// Bike body
if (bikeType == 1) {
canvas.fill(255, 50, 30)
}
else if (bikeType == 2) {
canvas.fill(30, 150, 255)
}
else {
canvas.fill(80, 255, 100)
}
canvas.rect(
x - 20,
y - 8,
40,
15
)
// Seat
canvas.fill(30, 30, 30)
canvas.rect(
x - 8,
y + 10,
20,
5
)
// Rider
canvas.fill(255, 200, 150)
canvas.ellipse(
x,
y + 25,
18,
18
)
canvas.fill(40, 40, 40)
canvas.rect(
x - 10,
y + 8,
20,
18
)
}
// ------------------------------------------------------------
// DRAW OBSTACLE
// ------------------------------------------------------------
def drawObstacle(
canvas: CanvasDraw,
x: Double,
y: Double
) {
canvas.fill(220, 40, 40)
canvas.noStroke()
canvas.rect(
x - 22,
y - 18,
44,
36
)
canvas.fill(255, 230, 0)
canvas.rect(
x - 15,
y - 5,
30,
5
)
}
// ------------------------------------------------------------
// DRAW COIN
// ------------------------------------------------------------
def drawCoin(
canvas: CanvasDraw,
x: Double,
y: Double,
taken: Boolean
) {
if (!taken) {
canvas.fill(255, 215, 0)
canvas.noStroke()
canvas.ellipse(
x,
y,
20,
20
)
canvas.fill(100, 70, 0)
canvas.text(
"$",
x - 4,
y - 5
)
}
}
// ------------------------------------------------------------
// START SCREEN
// ------------------------------------------------------------
def drawStartScreen(canvas: CanvasDraw) {
canvas.background(5, 10, 25)
canvas.fill(0, 180, 255)
canvas.text(
"RIDER 2311",
cwidth / 2.0 - 70,
cheight - 100
)
canvas.fill(255, 255, 255)
canvas.text(
"A BEGINNER SCALA BIKE GAME",
cwidth / 2.0 - 120,
cheight - 140
)
canvas.fill(0, 200, 100)
canvas.rect(
cwidth / 2.0 - 100,
cheight / 2.0 - 25,
200,
55
)
canvas.fill(255, 255, 255)
canvas.text(
"START GAME",
cwidth / 2.0 - 55,
cheight / 2.0 + 8
)
canvas.fill(255, 220, 0)
canvas.text(
"AI GUIDE: ALEX",
cwidth / 2.0 - 65,
80
)
canvas.fill(220, 220, 220)
canvas.text(
"Learn variables, if statements, functions and movement!",
70,
45
)
}
// ------------------------------------------------------------
// BIKE SELECTION
// ------------------------------------------------------------
def drawBikeSelection(canvas: CanvasDraw) {
canvas.background(10, 10, 25)
canvas.fill(255, 255, 255)
canvas.text(
"CHOOSE YOUR BIKE",
cwidth / 2.0 - 75,
cheight - 70
)
// Bike 1
canvas.fill(50, 30, 30)
canvas.rect(70, 220, 150, 190)
drawBike(
canvas,
145,
300,
1
)
canvas.fill(255, 255, 255)
canvas.text(
"RED BIKE",
115,
245
)
// Bike 2
canvas.fill(20, 40, 70)
canvas.rect(270, 220, 150, 190)
drawBike(
canvas,
345,
300,
2
)
canvas.fill(255, 255, 255)
canvas.text(
"BLUE BIKE",
310,
245
)
// Bike 3
canvas.fill(20, 60, 30)
canvas.rect(470, 220, 150, 190)
drawBike(
canvas,
545,
300,
3
)
canvas.fill(255, 255, 255)
canvas.text(
"GREEN BIKE",
500,
245
)
canvas.fill(255, 215, 0)
canvas.text(
"CLICK A BIKE",
cwidth / 2.0 - 50,
100
)
canvas.fill(180, 220, 255)
canvas.text(
alexMessage,
80,
55
)
}
// ------------------------------------------------------------
// ROAD
// ------------------------------------------------------------
def drawRoad(canvas: CanvasDraw) {
canvas.background(30, 120, 50)
// Road
canvas.fill(60, 60, 60)
canvas.rect(
70,
0,
cwidth - 140,
cheight
)
// Road edges
canvas.fill(255, 255, 255)
canvas.rect(
65,
0,
5,
cheight
)
canvas.rect(
cwidth - 70,
0,
5,
cheight
)
// Road center lines
canvas.fill(255, 230, 0)
var lineY = 0.0
while (lineY < cheight) {
canvas.rect(
cwidth / 2.0 - 4,
lineY,
8,
60
)
lineY += 120
}
}
// ------------------------------------------------------------
// GAMEPLAY SCREEN
// ------------------------------------------------------------
def drawGameScreen(canvas: CanvasDraw) {
drawRoad(canvas)
// Move obstacles downward
obstacle1Y -= roadSpeed
obstacle2Y -= roadSpeed
obstacle3Y -= roadSpeed
coin1Y -= roadSpeed
coin2Y -= roadSpeed
coin3Y -= roadSpeed
// Reset obstacles
if (obstacle1Y < -50) {
obstacle1Y = cheight + 150
obstacle1X =
100 + randomDouble(cwidth - 200)
}
if (obstacle2Y < -50) {
obstacle2Y = cheight + 400
obstacle2X =
100 + randomDouble(cwidth - 200)
}
if (obstacle3Y < -50) {
obstacle3Y = cheight + 700
obstacle3X =
100 + randomDouble(cwidth - 200)
}
// Reset coins
if (coin1Y < -30) {
coin1Y = cheight + 250
coin1Taken = false
}
if (coin2Y < -30) {
coin2Y = cheight + 500
coin2Taken = false
}
if (coin3Y < -30) {
coin3Y = cheight + 750
coin3Taken = false
}
// Draw obstacles
drawObstacle(
canvas,
obstacle1X,
obstacle1Y
)
drawObstacle(
canvas,
obstacle2X,
obstacle2Y
)
drawObstacle(
canvas,
obstacle3X,
obstacle3Y
)
// Draw coins
drawCoin(
canvas,
coin1X,
coin1Y,
coin1Taken
)
drawCoin(
canvas,
coin2X,
coin2Y,
coin2Taken
)
drawCoin(
canvas,
coin3X,
coin3Y,
coin3Taken
)
// Draw bike
drawBike(
canvas,
bikeX,
bikeY,
selectedBike
)
// --------------------------------------------------------
// COLLISION WITH OBSTACLES
// --------------------------------------------------------
if (
collision(
bikeX,
bikeY,
18,
obstacle1X,
obstacle1Y,
22
)
) {
lives -= 1
obstacle1Y = cheight + 200
alex("Watch out! You hit an obstacle.")
if (lives <= 0) {
gameOverReason =
"You ran out of lives."
screen = 3
}
}
if (
collision(
bikeX,
bikeY,
18,
obstacle2X,
obstacle2Y,
22
)
) {
lives -= 1
obstacle2Y = cheight + 350
alex("Be careful, Rider 2311!")
if (lives <= 0) {
gameOverReason =
"You ran out of lives."
screen = 3
}
}
if (
collision(
bikeX,
bikeY,
18,
obstacle3X,
obstacle3Y,
22
)
) {
lives -= 1
obstacle3Y = cheight + 500
alex("Keep your eyes on the road!")
if (lives <= 0) {
gameOverReason =
"You ran out of lives."
screen = 3
}
}
// --------------------------------------------------------
// COIN COLLISION
// --------------------------------------------------------
if (
!coin1Taken &&
collision(
bikeX,
bikeY,
18,
coin1X,
coin1Y,
10
)
) {
coin1Taken = true
score += 10
alex("Great! You collected a coin.")
}
if (
!coin2Taken &&
collision(
bikeX,
bikeY,
18,
coin2X,
coin2Y,
10
)
) {
coin2Taken = true
score += 10
alex("Excellent! Ten more points.")
}
if (
!coin3Taken &&
collision(
bikeX,
bikeY,
18,
coin3X,
coin3Y,
10
)
) {
coin3Taken = true
score += 10
alex("Amazing riding!")
}
// --------------------------------------------------------
// DISTANCE
// --------------------------------------------------------
distance += roadSpeed
// Fuel slowly decreases
fuel -= 0.025
if (fuel <= 0) {
fuel = 0
gameOverReason =
"Your bike ran out of fuel."
screen = 3
}
// Level completed
if (distance >= targetDistance) {
score += 50
if (level < 3) {
alex("Level complete! Excellent riding.")
screen = 4
}
else {
alex("Fantastic! You completed RIDER 2311!")
screen = 5
}
}
// --------------------------------------------------------
// UI
// --------------------------------------------------------
canvas.fill(0, 0, 0, 190)
canvas.rect(
0,
cheight - 80,
cwidth,
80
)
canvas.fill(255, 255, 255)
canvas.text(
s"RIDER 2311 LEVEL: $level",
20,
cheight - 25
)
canvas.text(
s"SCORE: $score",
230,
cheight - 25
)
canvas.text(
s"LIVES: $lives",
360,
cheight - 25
)
canvas.text(
s"FUEL: ${fuel.toInt}%",
470,
cheight - 25
)
// Alex message
canvas.fill(180, 220, 255)
canvas.text(
s"Alex: $alexMessage",
20,
25
)
}
// ------------------------------------------------------------
// GAME OVER
// ------------------------------------------------------------
def drawGameOver(canvas: CanvasDraw) {
canvas.background(40, 5, 5)
canvas.fill(255, 60, 60)
canvas.text(
"GAME OVER",
cwidth / 2.0 - 60,
cheight / 2.0 + 80
)
canvas.fill(255, 255, 255)
canvas.text(
gameOverReason,
cwidth / 2.0 - 100,
cheight / 2.0 + 40
)
canvas.text(
s"Final Score: $score",
cwidth / 2.0 - 65,
cheight / 2.0
)
canvas.fill(200, 50, 50)
canvas.rect(
cwidth / 2.0 - 100,
cheight / 2.0 - 80,
200,
50
)
canvas.fill(255, 255, 255)
canvas.text(
"TRY AGAIN",
cwidth / 2.0 - 50,
cheight / 2.0 - 50
)
canvas.fill(180, 220, 255)
canvas.text(
s"Alex: $alexMessage",
30,
50
)
}
// ------------------------------------------------------------
// LEVEL COMPLETE
// ------------------------------------------------------------
def drawLevelComplete(canvas: CanvasDraw) {
canvas.background(10, 60, 30)
canvas.fill(0, 255, 150)
canvas.text(
s"LEVEL $level COMPLETE!",
cwidth / 2.0 - 100,
cheight / 2.0 + 80
)
canvas.fill(255, 255, 255)
canvas.text(
s"Score: $score",
cwidth / 2.0 - 50,
cheight / 2.0 + 35
)
canvas.fill(0, 180, 100)
canvas.rect(
cwidth / 2.0 - 120,
cheight / 2.0 - 70,
240,
55
)
canvas.fill(255, 255, 255)
if (level == 1) {
canvas.text(
"PLAY LEVEL 2",
cwidth / 2.0 - 65,
cheight / 2.0 - 35
)
}
else {
canvas.text(
"PLAY LEVEL 3",
cwidth / 2.0 - 65,
cheight / 2.0 - 35
)
}
canvas.fill(180, 220, 255)
canvas.text(
s"Alex: $alexMessage",
30,
50
)
}
// ------------------------------------------------------------
// FINAL SCREEN
// ------------------------------------------------------------
def drawFinalScreen(canvas: CanvasDraw) {
canvas.background(5, 20, 40)
canvas.fill(255, 215, 0)
canvas.text(
"MISSION COMPLETE!",
cwidth / 2.0 - 100,
cheight / 2.0 + 100
)
canvas.fill(255, 255, 255)
canvas.text(
"RIDER 2311",
cwidth / 2.0 - 60,
cheight / 2.0 + 55
)
canvas.text(
s"FINAL SCORE: $score",
cwidth / 2.0 - 70,
cheight / 2.0 + 15
)
canvas.fill(0, 180, 120)
canvas.rect(
cwidth / 2.0 - 120,
cheight / 2.0 - 80,
240,
55
)
canvas.fill(255, 255, 255)
canvas.text(
"PLAY AGAIN",
cwidth / 2.0 - 55,
cheight / 2.0 - 45
)
canvas.fill(180, 220, 255)
canvas.text(
"Alex: You are becoming a Scala programmer!",
30,
50
)
}
// ------------------------------------------------------------
// KEYBOARD
// ------------------------------------------------------------
onKeyPress { key =>
if (
key == Kc.VK_LEFT ||
key == Kc.VK_A
) {
moveLeft = true
}
if (
key == Kc.VK_RIGHT ||
key == Kc.VK_D
) {
moveRight = true
}
if (
key == Kc.VK_UP ||
key == Kc.VK_W
) {
moveUp = true
}
if (
key == Kc.VK_DOWN ||
key == Kc.VK_S
) {
moveDown = true
}
}
onKeyRelease { key =>
if (
key == Kc.VK_LEFT ||
key == Kc.VK_A
) {
moveLeft = false
}
if (
key == Kc.VK_RIGHT ||
key == Kc.VK_D
) {
moveRight = false
}
if (
key == Kc.VK_UP ||
key == Kc.VK_W
) {
moveUp = false
}
if (
key == Kc.VK_DOWN ||
key == Kc.VK_S
) {
moveDown = false
}
}
// ------------------------------------------------------------
// MOUSE
// ------------------------------------------------------------
onMouseClick { (x, y) =>
// START SCREEN
if (screen == 0) {
if (
x >= cwidth / 2.0 - 100 &&
x <= cwidth / 2.0 + 100 &&
y >= cheight / 2.0 - 25 &&
y <= cheight / 2.0 + 30
) {
screen = 1
alex(
"Choose your bike! I will help you."
)
}
}
// BIKE SELECTION
else if (screen == 1) {
if (
x >= 70 &&
x <= 220 &&
y >= 220 &&
y <= 410
) {
selectedBike = 1
startLevel(1)
}
else if (
x >= 270 &&
x <= 420 &&
y >= 220 &&
y <= 410
) {
selectedBike = 2
startLevel(1)
}
else if (
x >= 470 &&
x <= 620 &&
y >= 220 &&
y <= 410
) {
selectedBike = 3
startLevel(1)
}
}
// GAME OVER
else if (screen == 3) {
if (
x >= cwidth / 2.0 - 100 &&
x <= cwidth / 2.0 + 100 &&
y >= cheight / 2.0 - 80 &&
y <= cheight / 2.0 - 30
) {
lives = 3
score = 0
startLevel(1)
}
}
// LEVEL COMPLETE
else if (screen == 4) {
if (
x >= cwidth / 2.0 - 120 &&
x <= cwidth / 2.0 + 120 &&
y >= cheight / 2.0 - 70 &&
y <= cheight / 2.0 - 15
) {
if (level == 1) {
startLevel(2)
}
else {
startLevel(3)
}
}
}
// FINAL SCREEN
else if (screen == 5) {
if (
x >= cwidth / 2.0 - 120 &&
x <= cwidth / 2.0 + 120 &&
y >= cheight / 2.0 - 80 &&
y <= cheight / 2.0 - 25
) {
lives = 3
score = 0
screen = 1
alex(
"Welcome back! Choose your bike."
)
}
}
}
// ------------------------------------------------------------
// UPDATE PLAYER
// ------------------------------------------------------------
def updatePlayer() {
if (screen == 2) {
if (moveLeft) {
bikeX -= bikeSpeed
}
if (moveRight) {
bikeX += bikeSpeed
}
if (moveUp) {
bikeY += bikeSpeed
}
if (moveDown) {
bikeY -= bikeSpeed
}
// Keep bike inside road
if (bikeX < 90) {
bikeX = 90
}
if (bikeX > cwidth - 90) {
bikeX = cwidth - 90
}
if (bikeY < 60) {
bikeY = 60
}
if (bikeY > cheight - 100) {
bikeY = cheight - 100
}
}
}
// ------------------------------------------------------------
// MAIN GAME LOOP
// ------------------------------------------------------------
animateWithCanvasDraw { canvas =>
if (screen == 0) {
drawStartScreen(canvas)
}
else if (screen == 1) {
drawBikeSelection(canvas)
}
else if (screen == 2) {
updatePlayer()
drawGameScreen(canvas)
}
else if (screen == 3) {
drawGameOver(canvas)
}
else if (screen == 4) {
drawLevelComplete(canvas)
}
else if (screen == 5) {
drawFinalScreen(canvas)
}
}