Code Sketch
sniper new cricket game
Category: Art
import scala.util.Random
// Clear canvas and set speed
clear()
invisible()
setSpeed(fast)
// --- Game Settings ---
val maxBalls = 12 // 2 Overs = 12 Balls
val maxWickets = 10
// --- Match State Variables ---
var currentInning = 1 // 1 = Player Batting, 2 = AI Batting
var ballsBowled = 0
var runs = 0
var wickets = 0
var targetRuns = 0
var aiRuns = 0
var aiWickets = 0
var ballX = -200.0
var ballY = 0.0
var ballHeight = 0.0
var ballVx = 0.0
var ballVy = 0.0
var swingFactor = 0.0
var isBowled = false
var isHit = false
// --- Bowler Run-Up Variables ---
var bowlerX = -260.0
var bowlerY = 0.0
var isRunningUp = false
var strideState = 0
var bowlingPhase = "RUNUP"
// --- Fast Bat Swing Animation Variables ---
var isSwinging = false
var swingTimer = 0
// --- Stump Light Variables ---
var stumpLightTimer = 0
var isStumpGlowing = false
// --- Over Log ---
var overLog = scala.collection.mutable.ListBuffer[String]()
// Celebration & Status
var showCelebration = false
var celebrationTimer = 0
var statusMessage = "INNING 1: You are Batting First! Press SPACE to Bowl & hit 'S','D','W'!"
// ==========================================
// ?? HIGH-DETAIL REALISTIC STADIUM & CROWD
// ==========================================
val ground = Picture.rectangle(600, 400)
ground.setFillColor(Color(34, 139, 34))
ground.setPenColor(noColor)
ground.setPosition(-300, -200)
ground.draw()
// Outfield Turf Grass Pattern Lines
for (i <- -300 to 300 by 40) {
val grassStrip = Picture.rectangle(20, 400)
grassStrip.setFillColor(Color(46, 160, 46))
grassStrip.setPenColor(noColor)
grassStrip.setPosition(i, -200)
grassStrip.draw()
}
// Crowd Stand Background (Top Boundaries)
val topStand = Picture.rectangle(600, 25)
topStand.setFillColor(Color(70, 70, 70))
topStand.setPosition(-300, 175)
topStand.draw()
for (cx <- -290 to 290 by 12) {
val spectator = Picture.circle(4)
spectator.setFillColor(Color(Random.nextInt(200) + 55, Random.nextInt(200) + 55, Random.nextInt(200) + 55))
spectator.setPosition(cx, 185)
spectator.draw()
}
// ? Realistic Turf Pitch Base
val pitchBase = Picture.rectangle(420, 84)
pitchBase.setFillColor(Color(160, 120, 80))
pitchBase.setPenColor(noColor)
pitchBase.setPosition(-210, -42)
pitchBase.draw()
val pitch = Picture.rectangle(400, 76)
pitch.setFillColor(Color(218, 190, 145))
pitch.setPenColor(noColor)
pitch.setPosition(-200, -38)
pitch.draw()
// Wear Patch
val wearPatch = Picture.rectangle(120, 50)
wearPatch.setFillColor(Color(205, 175, 130))
wearPatch.setPenColor(noColor)
wearPatch.setPosition(-60, -25)
wearPatch.draw()
// White Crease Lines
def createCreaseLine(w: Int, h: Int, x: Int, y: Int): Picture = {
val line = Picture.rectangle(w, h)
line.setFillColor(cm.white)
line.setPenColor(noColor)
line.setPosition(x, y)
line.draw()
line
}
// Creases
createCreaseLine(3, 76, -180, -38)
createCreaseLine(35, 2, -200, 30)
createCreaseLine(35, 2, -200, -32)
createCreaseLine(3, 76, 180, -38)
createCreaseLine(35, 2, 165, 30)
createCreaseLine(35, 2, 165, -32)
// ==========================================
// ? BOWLER DESIGN
// ==========================================
val bowlerShadow = Picture.ellipse(28, 10)
bowlerShadow.setFillColor(Color(20, 80, 20))
bowlerShadow.setPenColor(noColor)
bowlerShadow.draw()
val shoeL = Picture.rectangle(6, 4); shoeL.setFillColor(cm.white); shoeL.draw()
val shoeR = Picture.rectangle(6, 4); shoeR.setFillColor(cm.white); shoeR.draw()
val legL = Picture.rectangle(5, 16); legL.setFillColor(Color(220, 220, 220)); legL.draw()
val legR = Picture.rectangle(5, 16); legR.setFillColor(Color(220, 220, 220)); legR.draw()
val torsoBase = Picture.rectangle(16, 22); torsoBase.setFillColor(Color(255, 82, 82)); torsoBase.draw()
val torsoHighlight = Picture.rectangle(8, 22); torsoHighlight.setFillColor(Color(255, 128, 128)); torsoHighlight.setPenColor(noColor); torsoHighlight.draw()
val armL = Picture.rectangle(4, 18); armL.setFillColor(Color(220, 220, 220)); armL.draw()
val armR = Picture.rectangle(4, 20); armR.setFillColor(Color(220, 220, 220)); armR.draw()
val head = Picture.circle(7); head.setFillColor(Color(240, 190, 150)); head.draw()
val cap = Picture.circle(7); cap.setFillColor(Color(180, 0, 0)); cap.draw()
def updateBowlerPosition(x: Double, y: Double, phase: String): Unit = {
bowlerShadow.setPosition(x - 14, -22)
shoeL.setPosition(x - 6, -18 + y)
shoeR.setPosition(x + 4, -18 + y)
legL.setPosition(x - 5, -14 + y)
legR.setPosition(x + 5, -14 + y)
torsoBase.setPosition(x - 8, 0 + y)
torsoHighlight.setPosition(x - 8, 0 + y)
phase match {
case "JUMP" =>
armL.setHeading(90); armR.setHeading(-120); legL.setHeading(20); legR.setHeading(-20)
case "RELEASE" =>
armL.setHeading(-45); armR.setHeading(110); legL.setHeading(-10); legR.setHeading(30)
case "FOLLOW_THROUGH" =>
armL.setHeading(-60); armR.setHeading(20); legL.setHeading(0); legR.setHeading(0)
case _ =>
if (strideState % 2 == 0) {
armL.setHeading(55); armR.setHeading(-55); legL.setHeading(15); legR.setHeading(-15)
} else {
armL.setHeading(-40); armR.setHeading(70); legL.setHeading(-15); legR.setHeading(15)
}
}
armL.setPosition(x - 12, 10 + y)
armR.setPosition(x + 4, 12 + y)
head.setPosition(x, 20 + y)
cap.setPosition(x, 24 + y)
}
updateBowlerPosition(bowlerX, bowlerY, "RUNUP")
// ==========================================
// ? BATSMAN & SINGLE RIGID BAT
// ==========================================
val batsman = Picture.circle(12)
batsman.setFillColor(cm.blue)
batsman.setPosition(180, 0)
batsman.draw()
val batBlade = Picture.rectangle(11, 32)
batBlade.setFillColor(Color(245, 230, 175))
batBlade.setPenColor(Color(180, 150, 90))
val batSpine = Picture.rectangle(3, 32)
batSpine.setFillColor(Color(230, 210, 150))
batSpine.setPenColor(noColor)
val batShoulder = Picture.rectangle(7, 4)
batShoulder.setFillColor(Color(230, 215, 160))
batShoulder.setPenColor(Color(180, 150, 90))
val batHandle = Picture.rectangle(4, 14)
batHandle.setFillColor(Color(15, 15, 15))
batHandle.setPenColor(Color(50, 50, 50))
def updateBatPosition(angleDeg: Double): Unit = {
val rad = math.toRadians(angleDeg)
val pivotX = 178.0
val pivotY = 12.0
def setPartPosition(pic: Picture, offsetX: Double, offsetY: Double): Unit = {
pic.setHeading(angleDeg)
val rotatedX = pivotX + (offsetX * math.cos(rad) - offsetY * math.sin(rad))
val rotatedY = pivotY + (offsetX * math.sin(rad) + offsetY * math.cos(rad))
pic.setPosition(rotatedX, rotatedY)
}
setPartPosition(batBlade, -5, -40)
setPartPosition(batSpine, -1, -40)
setPartPosition(batShoulder, -3, -10)
setPartPosition(batHandle, -2, -6)
}
batBlade.draw()
batSpine.draw()
batShoulder.draw()
batHandle.draw()
updateBatPosition(0.0)
// ==========================================
// ? STUMPS & BALL
// ==========================================
val stumpShadow = Picture.ellipse(22, 6)
stumpShadow.setFillColor(Color(160, 130, 90))
stumpShadow.setPenColor(noColor)
stumpShadow.setPosition(215, -22)
stumpShadow.draw()
val stumpBase = Picture.rectangle(18, 4)
stumpBase.setFillColor(Color(100, 100, 100))
stumpBase.setPenColor(noColor)
stumpBase.setPosition(217, -20)
stumpBase.draw()
val stump1 = Picture.rectangle(3, 30)
val stump2 = Picture.rectangle(3, 30)
val stump3 = Picture.rectangle(3, 30)
val defaultStumpColor = Color(245, 222, 179)
val defaultStumpBorder = Color(139, 69, 19)
stump1.setFillColor(defaultStumpColor); stump1.setPenColor(defaultStumpBorder); stump1.setPosition(217, -18); stump1.draw()
stump2.setFillColor(defaultStumpColor); stump2.setPenColor(defaultStumpBorder); stump2.setPosition(224, -18); stump2.draw()
stump3.setFillColor(defaultStumpColor); stump3.setPenColor(defaultStumpBorder); stump3.setPosition(231, -18); stump3.draw()
val bail1 = Picture.rectangle(7, 3)
val bail2 = Picture.rectangle(7, 3)
bail1.setFillColor(defaultStumpColor); bail1.setPenColor(defaultStumpBorder); bail1.setPosition(217, 12); bail1.draw()
bail2.setFillColor(defaultStumpColor); bail2.setPenColor(defaultStumpBorder); bail2.setPosition(224, 12); bail2.draw()
val stumpGlow = Picture.ellipse(32, 45)
stumpGlow.setFillColor(Color(0, 191, 255))
stumpGlow.setPenColor(noColor)
stumpGlow.setPosition(210, -20)
stumpGlow.draw()
stumpGlow.setOpacity(0.0)
def triggerStumpBlueLight(): Unit = {
isStumpGlowing = true
stumpLightTimer = 25
stumpGlow.setOpacity(0.85)
val glowColor = Color(0, 238, 255)
val glowBorder = Color(255, 255, 255)
stump1.setFillColor(glowColor); stump1.setPenColor(glowBorder)
stump2.setFillColor(glowColor); stump2.setPenColor(glowBorder)
stump3.setFillColor(glowColor); stump3.setPenColor(glowBorder)
bail1.setFillColor(glowColor); bail1.setPenColor(glowBorder)
bail2.setFillColor(glowColor); bail2.setPenColor(glowBorder)
}
def turnOffStumpLight(): Unit = {
isStumpGlowing = false
stumpGlow.setOpacity(0.0)
stump1.setFillColor(defaultStumpColor); stump1.setPenColor(defaultStumpBorder)
stump2.setFillColor(defaultStumpColor); stump2.setPenColor(defaultStumpBorder)
stump3.setFillColor(defaultStumpColor); stump3.setPenColor(defaultStumpBorder)
bail1.setFillColor(defaultStumpColor); bail1.setPenColor(defaultStumpBorder)
bail2.setFillColor(defaultStumpColor); bail2.setPenColor(defaultStumpBorder)
}
val ballShadow = Picture.ellipse(12, 4)
ballShadow.setFillColor(Color(150, 130, 100))
ballShadow.setPenColor(noColor)
ballShadow.draw()
val ball = Picture.circle(6)
ball.setFillColor(Color(255, 255, 255))
ball.setPenColor(Color(180, 180, 180))
ball.draw()
def updateBallPosition(x: Double, y: Double, h: Double): Unit = {
ball.setPosition(x, y + h)
ballShadow.setPosition(x - 6, y - 12)
}
updateBallPosition(ballX, ballY, ballHeight)
// Confetti Particles (Set off-screen)
val confetti1 = Picture.circle(8); confetti1.setPosition(-1000, -1000); confetti1.draw(); confetti1.setOpacity(0.0)
val confetti2 = Picture.circle(10); confetti2.setPosition(-1000, -1000); confetti2.draw(); confetti2.setOpacity(0.0)
val confetti3 = Picture.circle(7); confetti3.setPosition(-1000, -1000); confetti3.draw(); confetti3.setOpacity(0.0)
val confetti4 = Picture.circle(9); confetti4.setPosition(-1000, -1000); confetti4.draw(); confetti4.setOpacity(0.0)
// ==========================================
// ? HUD & DISPLAY
// ==========================================
val boxPlayer = Picture.rectangle(260, 55); boxPlayer.setFillColor(Color(20, 20, 20)); boxPlayer.setPenColor(Color(0, 230, 118)); boxPlayer.setPenThickness(2); boxPlayer.setPosition(-285, 115); boxPlayer.draw()
val textPlayer = Picture.text("", 11); textPlayer.setFillColor(cm.white); textPlayer.setPosition(-275, 160); textPlayer.draw()
val boxAI = Picture.rectangle(260, 55); boxAI.setFillColor(Color(20, 20, 20)); boxAI.setPenColor(Color(255, 82, 82)); boxAI.setPenThickness(2); boxAI.setPosition(25, 115); boxAI.draw()
val textAI = Picture.text("", 11); textAI.setFillColor(cm.white); textAI.setPosition(35, 160); textAI.draw()
val statusText = Picture.text("", 11); statusText.setFillColor(cm.yellow); statusText.setPosition(-280, -180); statusText.draw()
def getOversString(balls: Int): String = s"${balls / 6}.${balls % 6} Ov"
def updateScoreDisplay(): Unit = {
val crrVal = if (ballsBowled > 0) (runs.toDouble / ballsBowled) * 6 else 0.0
val crr = f"$crrVal%.2f"
val lastOverStr = overLog.takeRight(6).mkString(" ")
if (currentInning == 1) {
textPlayer.update(s"TEAM SNIPER (Batting)\nRuns: $runs/$wickets | ${getOversString(ballsBowled)} | CRR: $crr\nLog: [$lastOverStr]")
textAI.update(s"TEAM AI (Bowling)\nYet to Bat (Target: TBD)")
} else {
textPlayer.update(s"TEAM SNIPER (Batting Done)\nScore: $runs/$wickets in 2.0 Ov")
textAI.update(s"TEAM AI (Chasing)\nRuns: $aiRuns/$aiWickets | Target: $targetRuns | ${getOversString(ballsBowled)}\nLog: [$lastOverStr]")
}
statusText.update(statusMessage)
}
updateScoreDisplay()
def triggerCelebration(): Unit = {
showCelebration = true; celebrationTimer = 40
confetti1.setPosition(0, 50)
confetti2.setPosition(-80, 80)
confetti3.setPosition(80, 70)
confetti4.setPosition(-120, 20)
confetti1.setOpacity(1.0); confetti2.setOpacity(1.0); confetti3.setOpacity(1.0); confetti4.setOpacity(1.0)
}
def hideCelebration(): Unit = {
showCelebration = false
confetti1.setOpacity(0.0); confetti2.setOpacity(0.0); confetti3.setOpacity(0.0); confetti4.setOpacity(0.0)
confetti1.setPosition(-1000, -1000)
confetti2.setPosition(-1000, -1000)
confetti3.setPosition(-1000, -1000)
confetti4.setPosition(-1000, -1000)
}
def switchInnings(): Unit = {
currentInning = 2; targetRuns = runs + 1; ballsBowled = 0; overLog.clear()
isBowled = false; isHit = false; isRunningUp = false
bowlerX = -260.0; bowlerY = 0.0; bowlingPhase = "RUNUP"
updateBowlerPosition(bowlerX, bowlerY, bowlingPhase)
statusMessage = s"INNING 2: AI Chasing Target of $targetRuns Runs! Press SPACE to Bowl."
updateScoreDisplay()
}
def checkMatchEnd(): Unit = {
if (currentInning == 2) {
if (aiRuns >= targetRuns) {
statusMessage = s"MATCH OVER! TEAM AI WON BY ${maxWickets - aiWickets} WICKETS!"
} else if (ballsBowled >= maxBalls || aiWickets >= maxWickets) {
if (aiRuns < targetRuns - 1) {
statusMessage = s"? CONGRATS! TEAM SNIPER WON BY ${targetRuns - 1 - aiRuns} RUNS! ?"
triggerCelebration()
} else {
statusMessage = "MATCH TIED! Equal Scores."
}
}
}
}
def startRunUp(): Unit = {
if (currentInning == 1 && (ballsBowled >= maxBalls || wickets >= maxWickets)) { switchInnings(); return }
if (currentInning == 2 && (ballsBowled >= maxBalls || aiWickets >= maxWickets || aiRuns >= targetRuns)) { checkMatchEnd(); updateScoreDisplay(); return }
if (!isBowled && !isRunningUp) {
isRunningUp = true; bowlerX = -260.0; bowlerY = 0.0; bowlingPhase = "RUNUP"
statusMessage = "Bowler running in..."
updateScoreDisplay()
}
}
def releaseBall(): Unit = {
isBowled = true; isHit = false
ballsBowled += 1; ballX = -190.0; ballY = 0.0; ballHeight = 4.0
ballVx = 7.0 // Ball speed set to 7
swingFactor = if (Random.nextBoolean()) 0.025 else -0.025
ballVy = -swingFactor * 18
val swingType = if (swingFactor > 0) "IN-SWING ?" else "OUT-SWING ?"
statusMessage = if (currentInning == 1) s"$swingType! Hit 'S', 'D', or 'W'!" else s"Ball Bowled ($swingType)!"
updateScoreDisplay()
}
// Player Bat Swing
def swingBat(shotType: String): Unit = {
if (currentInning != 1 || wickets >= maxWickets) return
isSwinging = true
swingTimer = 3
updateBatPosition(-50.0)
if (isBowled && !isHit) {
if (ballX >= 70 && ballX <= 195) {
isHit = true
val timing = math.abs(ballX - 150)
if (timing > 35) {
wickets += 1
overLog += "W"
statusMessage = "EDGE & CAUGHT IN SLIPS! OUT!"
ballVx = 2.0; ballVy = 4.0
triggerStumpBlueLight()
} else {
shotType match {
case "STRAIGHT" =>
if (timing < 20) { runs += 6; overLog += "6"; statusMessage = "GREAT SHOT! SIXER!"; ballVx = -(11.0 + Random.nextDouble() * 2.0); ballVy = 0.0 }
else { runs += 4; overLog += "4"; statusMessage = "FOUR! Straight Drive!"; ballVx = -(9.0 + Random.nextDouble() * 2.0); ballVy = 0.5 }
case "COVER" =>
if (timing < 20) { runs += 6; overLog += "6"; statusMessage = "COVER DRIVE! SIX!"; ballVx = -(10.5 + Random.nextDouble() * 2.0); ballVy = -(5.0 + Random.nextDouble() * 2.0) }
else { runs += 4; overLog += "4"; statusMessage = "FOUR! Cover Shot!"; ballVx = -(8.5 + Random.nextDouble() * 2.0); ballVy = -(3.5 + Random.nextDouble() * 2.0) }
case _ =>
if (timing < 20) { runs += 6; overLog += "6"; statusMessage = "PULL SHOT! SIX!"; ballVx = -(10.5 + Random.nextDouble() * 2.0); ballVy = 5.0 + Random.nextDouble() * 2.0 }
else { runs += 4; overLog += "4"; statusMessage = "FOUR! Pull Shot!"; ballVx = -(8.5 + Random.nextDouble() * 2.0); ballVy = -2.5 - Random.nextDouble() * 2.0 }
}
}
if (ballsBowled >= maxBalls || wickets >= maxWickets) switchInnings()
} else {
statusMessage = "MISSED THE TIMING!"
}
updateScoreDisplay()
}
}
// AI Play
def aiAutoPlay(): Unit = {
if (currentInning == 2 && isBowled && !isHit && ballX >= 100 && ballX <= 180) {
val chance = Random.nextInt(100)
if (chance < 55) {
isSwinging = true; swingTimer = 3; updateBatPosition(-50.0); isHit = true
val shotType = Random.nextInt(100)
if (shotType < 25) { aiRuns += 6; overLog += "6"; statusMessage = "AI Hit a SIX!"; ballVx = -(10.5 + Random.nextDouble() * 2.0); ballVy = 3.5 + Random.nextDouble() * 2.0 }
else if (shotType < 65) { aiRuns += 4; overLog += "4"; statusMessage = "AI Hit a FOUR!"; ballVx = -(8.5 + Random.nextDouble() * 2.0); ballVy = -2.5 - Random.nextDouble() * 2.0 }
else { aiRuns += 1; overLog += "1"; statusMessage = "AI Took 1 Run!"; ballVx = -(6.0 + Random.nextDouble() * 1.0); ballVy = -1.0 }
checkMatchEnd()
}
updateScoreDisplay()
}
}
def resetGame(): Unit = {
currentInning = 1; ballsBowled = 0; runs = 0; wickets = 0; targetRuns = 0; aiRuns = 0; aiWickets = 0; overLog.clear()
isBowled = false; isHit = false; isRunningUp = false
bowlerX = -260.0; bowlerY = 0.0; bowlingPhase = "RUNUP"
isSwinging = false; updateBatPosition(0.0)
updateBowlerPosition(bowlerX, bowlerY, bowlingPhase)
turnOffStumpLight(); hideCelebration()
statusMessage = "Game Reset! Inning 1: Press SPACE to Bowl."
updateScoreDisplay()
}
// Key Listeners
onKeyPress { key =>
key match {
case ' ' => startRunUp()
case 's' | 'S' => if (currentInning == 1) swingBat("STRAIGHT")
case 'd' | 'D' => if (currentInning == 1) swingBat("COVER")
case 'w' | 'W' => if (currentInning == 1) swingBat("PULL")
case 'r' | 'R' => resetGame()
case _ =>
}
}
// Main Game Loop
animate {
if (showCelebration) {
celebrationTimer -= 1
confetti1.setFillColor(Color(Random.nextInt(255), Random.nextInt(255), Random.nextInt(255)))
confetti2.setFillColor(Color(Random.nextInt(255), Random.nextInt(255), Random.nextInt(255)))
confetti3.setFillColor(Color(Random.nextInt(255), Random.nextInt(255), Random.nextInt(255)))
confetti4.setFillColor(Color(Random.nextInt(255), Random.nextInt(255), Random.nextInt(255)))
if (celebrationTimer <= 0) hideCelebration()
}
if (isStumpGlowing) {
stumpLightTimer -= 1
if (stumpLightTimer <= 0) turnOffStumpLight()
}
// Bowler Movement
if (isRunningUp) {
if (bowlerX < -220.0) { bowlerX += 7.0; strideState += 1; bowlingPhase = "RUNUP" }
else if (bowlerX < -205.0) { bowlerX += 6.0; bowlerY = 10.0; bowlingPhase = "JUMP" }
else if (bowlerX < -195.0) { bowlerX += 5.0; bowlerY = 3.0; bowlingPhase = "RELEASE" }
else { isRunningUp = false; bowlerY = 0.0; bowlingPhase = "FOLLOW_THROUGH"; releaseBall() }
updateBowlerPosition(bowlerX, bowlerY, bowlingPhase)
}
// Bat Swing Reset
if (isSwinging) {
swingTimer -= 1
if (swingTimer <= 0) {
isSwinging = false
updateBatPosition(0.0)
}
}
// Direct Swing Ball Movement (No Pitch Bounce)
if (isBowled) {
ballX += ballVx
if (!isHit) {
ballVy += swingFactor
if (ballY > 25.0) ballY = 25.0
if (ballY < -25.0) ballY = -25.0
}
ballY += ballVy
updateBallPosition(ballX, ballY, ballHeight)
if (currentInning == 2) aiAutoPlay()
// Bowled Check
if (!isHit && ballX > 213) {
isBowled = false
triggerStumpBlueLight()
if (currentInning == 1) {
wickets += 1; overLog += "W"
statusMessage = s"BOWLED OUT! ? ($wickets/$maxWickets Wkts)"
if (wickets >= maxWickets || ballsBowled >= maxBalls) switchInnings()
} else {
aiWickets += 1; overLog += "W"
statusMessage = s"OUT! AI WICKET TAKEN! ? ($aiWickets/$maxWickets Wkts)"
checkMatchEnd()
}
updateScoreDisplay()
}
if (ballX < -340 || ballX > 340 || ballY < -200 || ballY > 200) {
if (!isHit && currentInning == 1) overLog += "."
isBowled = false
if (currentInning == 1 && (ballsBowled >= maxBalls || wickets >= maxWickets)) switchInnings()
else if (currentInning == 2) checkMatchEnd()
}
}
}