Code Sketch
sniper
Category: Art
// Clear canvas and configure stage setup
cleari()
disablePanAndZoom()
val cb = canvasBounds
drawStage(ColorMaker.black)
// 1. Create Field Elements using correct Kojo Picture constructors
val pitch = Picture.rectangle(120, 400).withFillColor(ColorMaker.tan).withPenColor(ColorMaker.white)
pitch.setPosition(cb.x + cb.width / 2 - 60, cb.y + 50)
val stumps = Picture.rectangle(30, 15).withFillColor(ColorMaker.yellow)
stumps.setPosition(cb.x + cb.width / 2 - 15, cb.y + 70)
val batsman = Picture {
setPenColor(ColorMaker.blue)
setFillColor(ColorMaker.blue)
circle(12) // Head
setPenColor(ColorMaker.brown)
setPenThickness(6)
forward(30) // Bat handle/blade
}
batsman.setPosition(cb.x + cb.width / 2, cb.y + 110)
val ball = Picture.circle(6).withFillColor(ColorMaker.red).withPenColor(ColorMaker.white)
var ballX = cb.x + cb.width / 2
var ballY = cb.y + cb.height - 50
var ballVelY = 0.0 // Ball starts stationary until you bowl
var isBallActive = false
var score = 0
// Draw everything onto the Kojo stage
draw(pitch, stumps, batsman, ball)
// State flags for gameplay mechanics
var isBatting = false
// 2. Main Animation & Game Loop
animate {
// Check if user presses SPACE or W to bowl/release the ball
if (!isBallActive && (isKeyPressed(Kc.VK_SPACE) || isKeyPressed(Kc.VK_W))) {
ballX = cb.x + cb.width / 2 + (scala.util.Random.nextInt(40) - 20)
ballY = cb.y + cb.height - 60
ballVelY = -6.0 // Start bowling action
isBallActive = true
}
// Move the ball if it is active
if (isBallActive) {
ballY = ballY + ballVelY
ball.setPosition(ballX, ballY)
}
// Handle Batsman Swing Interaction via Up Arrow Key
if (isKeyPressed(Kc.VK_UP)) {
if (!isBatting) {
isBatting = true
batsman.rotate(45) // Swing bat forward
}
} else {
if (isBatting) {
batsman.rotate(-45) // Return bat to original stance
isBatting = false
}
}
// Collision Detection / Shot Evaluation (Batsman hits ball)
val distanceToBat = Math.hypot(ballX - batsman.position.x, ballY - batsman.position.y)
if (isBallActive && distanceToBat < 35 && isBatting && ballVelY < 0) {
ballVelY = 8.0 // Hit back up the ground!
score = score + 4
println(s"Current Score: $score - Great Shot!")
}
// Reset ball if it goes past the limits
if (ballY < cb.y || ballY > cb.y + cb.height) {
isBallActive = false
ballVelY = 0.0
ball.setPosition(-100, -100) // Hide ball until next press
}
}