Code Sketch
sniper
Category: Art
cleari()
// --- Game Dimensions ---
val canvasWidth = 800
val canvasHeight = 600
val roadWidth = 360
// --- Background Terrain ---
val bg = Picture.rectangle(canvasWidth, canvasHeight)
bg.setFillColor(Color(10, 25, 10, 255))
bg.setPenColor(noColor)
bg.setPosition(-canvasWidth / 2, -canvasHeight / 2)
bg.draw()
val road = Picture.rectangle(roadWidth, canvasHeight)
road.setFillColor(Color(35, 35, 38, 255))
road.setPenColor(noColor)
road.setPosition(-roadWidth / 2, -canvasHeight / 2)
road.draw()
// --- Road Boundary Lines ---
val lineLeft = Picture.rectangle(6, canvasHeight)
lineLeft.setFillColor(white)
lineLeft.setPenColor(noColor)
lineLeft.setPosition(-roadWidth / 2 + 5, -canvasHeight / 2)
lineLeft.draw()
val lineRight = Picture.rectangle(6, canvasHeight)
lineRight.setFillColor(white)
lineRight.setPenColor(noColor)
lineRight.setPosition(roadWidth / 2 - 11, -canvasHeight / 2)
lineRight.draw()
// --- 2-Way Road Central Double Yellow Line ---
val centerDivider1 = Picture.rectangle(3, canvasHeight)
centerDivider1.setFillColor(Color(255, 204, 0, 255))
centerDivider1.setPenColor(noColor)
centerDivider1.setPosition(-4, -canvasHeight / 2)
centerDivider1.draw()
val centerDivider2 = Picture.rectangle(3, canvasHeight)
centerDivider2.setFillColor(Color(255, 204, 0, 255))
centerDivider2.setPenColor(noColor)
centerDivider2.setPosition(1, -canvasHeight / 2)
centerDivider2.draw()
// --- Animated Lane Markers ---
val dashCount = 8
val dashHeight = 40
val dashGap = 50
var dashOffset = 0.0
val whiteDashesL = Array.fill(dashCount) {
val d = Picture.rectangle(3, dashHeight)
d.setFillColor(Color(200, 200, 200, 150))
d.setPenColor(noColor)
d.draw()
d
}
val whiteDashesR = Array.fill(dashCount) {
val d = Picture.rectangle(3, dashHeight)
d.setFillColor(Color(200, 200, 200, 150))
d.setPenColor(noColor)
d.draw()
d
}
def updateDashes(moveSpeed: Double): Unit = {
dashOffset = (dashOffset - moveSpeed) % (dashHeight + dashGap)
for (i <- 0 until dashCount) {
val yPos = (canvasHeight / 2) - (i * (dashHeight + dashGap)) + dashOffset
whiteDashesL(i).setPosition(-roadWidth / 4, yPos)
whiteDashesR(i).setPosition(roadWidth / 4, yPos)
}
}
// --- Side Destination: Right Side Hotel & Parking Spot ---
var destinationY = 700.0
val hotelWidth = 110
val hotelHeight = 90
val hotelBuilding = Picture.rectangle(hotelWidth, hotelHeight)
hotelBuilding.setFillColor(Color(70, 40, 90, 255))
hotelBuilding.setPenColor(white)
val hotelRoof = Picture.rectangle(hotelWidth + 10, 15)
hotelRoof.setFillColor(Color(200, 50, 50, 255))
hotelRoof.setPenColor(noColor)
val hotelSign = Picture.text("HOTEL DELUXE", 11)
hotelSign.setFillColor(yellow)
val parkingSpotX = (roadWidth / 2 + 15).toDouble
val parkingSpotWidth = 70
val parkingSpotHeight = 100
val parkingSpot = Picture.rectangle(parkingSpotWidth, parkingSpotHeight)
parkingSpot.setFillColor(Color(50, 50, 55, 255))
parkingSpot.setPenColor(white)
val parkingSign = Picture.text("P", 30)
parkingSign.setFillColor(Color(0, 230, 255, 255))
def updateDestination(): Unit = {
hotelBuilding.setPosition(parkingSpotX, destinationY + 110)
hotelRoof.setPosition(parkingSpotX - 5, destinationY + 110 + hotelHeight)
hotelSign.setPosition(parkingSpotX + 5, destinationY + 110 + hotelHeight - 20)
parkingSpot.setPosition(parkingSpotX, destinationY)
parkingSign.setPosition(parkingSpotX + 22, destinationY + 32)
}
hotelBuilding.draw()
hotelRoof.draw()
hotelSign.draw()
parkingSpot.draw()
parkingSign.draw()
updateDestination()
// --- Night Overlay ---
val nightOverlay = Picture.rectangle(canvasWidth, canvasHeight)
nightOverlay.setFillColor(Color(0, 0, 0, 140))
nightOverlay.setPenColor(noColor)
nightOverlay.setPosition(-canvasWidth / 2, -canvasHeight / 2)
nightOverlay.draw()
// --- Player Car ---
val playerBody = Picture.rectangle(52, 95)
playerBody.setFillColor(Color(245, 245, 250, 255))
playerBody.setPenColor(black)
val playerRoof = Picture.rectangle(46, 34)
playerRoof.setFillColor(Color(230, 230, 235, 255))
playerRoof.setPenColor(gray)
val playerGlass = Picture.rectangle(44, 20)
playerGlass.setFillColor(Color(20, 40, 60, 255))
playerGlass.setPenColor(noColor)
val playerTailL = Picture.rectangle(8, 6)
playerTailL.setFillColor(Color(220, 20, 20, 255))
playerTailL.setPenColor(noColor)
val playerTailR = Picture.rectangle(8, 6)
playerTailR.setFillColor(Color(220, 20, 20, 255))
playerTailR.setPenColor(noColor)
val playerHeadL = Picture.rectangle(9, 6)
playerHeadL.setFillColor(gray)
playerHeadL.setPenColor(noColor)
val playerHeadR = Picture.rectangle(9, 6)
playerHeadR.setFillColor(gray)
playerHeadR.setPenColor(noColor)
val beamL = Picture.fromPath { p =>
p.moveTo(0, 0)
p.lineTo(-45, 170)
p.lineTo(20, 170)
p.lineTo(9, 0)
}
beamL.setFillColor(Color(245, 245, 255, 140))
beamL.setPenColor(noColor)
val beamR = Picture.fromPath { p =>
p.moveTo(0, 0)
p.lineTo(-20, 170)
p.lineTo(45, 170)
p.lineTo(9, 0)
}
beamR.setFillColor(Color(245, 245, 255, 140))
beamR.setPenColor(noColor)
playerBody.draw()
playerRoof.draw()
playerGlass.draw()
playerTailL.draw()
playerTailR.draw()
playerHeadL.draw()
playerHeadR.draw()
// --- Enemy Car (Opposing Right Lane) ---
val enemyBody = Picture.rectangle(52, 95)
enemyBody.setFillColor(Color(200, 30, 30, 255))
enemyBody.setPenColor(gray)
val enemyRoof = Picture.rectangle(44, 34)
enemyRoof.setFillColor(Color(120, 20, 20, 255))
enemyRoof.setPenColor(noColor)
val enemyGlass = Picture.rectangle(44, 18)
enemyGlass.setFillColor(Color(50, 50, 70, 255))
enemyGlass.setPenColor(noColor)
val enemyHeadL = Picture.rectangle(8, 6)
enemyHeadL.setFillColor(yellow)
enemyHeadL.setPenColor(noColor)
val enemyHeadR = Picture.rectangle(8, 6)
enemyHeadR.setFillColor(yellow)
enemyHeadR.setPenColor(noColor)
enemyBody.draw()
enemyRoof.draw()
enemyGlass.draw()
enemyHeadL.draw()
enemyHeadR.draw()
// --- Same-Lane Traffic Car (Left Lane) ---
val leftTrafficBody = Picture.rectangle(52, 95)
leftTrafficBody.setFillColor(Color(30, 140, 200, 255))
leftTrafficBody.setPenColor(gray)
val leftTrafficRoof = Picture.rectangle(44, 34)
leftTrafficRoof.setFillColor(Color(15, 80, 130, 255))
leftTrafficRoof.setPenColor(noColor)
val leftTrafficGlass = Picture.rectangle(44, 18)
leftTrafficGlass.setFillColor(Color(40, 60, 80, 255))
leftTrafficGlass.setPenColor(noColor)
val leftTrafficTailL = Picture.rectangle(8, 6)
leftTrafficTailL.setFillColor(Color(220, 20, 20, 255))
leftTrafficTailL.setPenColor(noColor)
val leftTrafficTailR = Picture.rectangle(8, 6)
leftTrafficTailR.setFillColor(Color(220, 20, 20, 255))
leftTrafficTailR.setPenColor(noColor)
leftTrafficBody.draw()
leftTrafficRoof.draw()
leftTrafficGlass.draw()
leftTrafficTailL.draw()
leftTrafficTailR.draw()
// --- Game Control Variables ---
var carX = -100.0
var carY = -220.0
val carSteerSpeed = 6.0
var currentPlayerSpeed = 0.0
var enemyX = 40.0
var enemyY = 380.0
var enemySpeed = 6.0
var leftTrafficX = -100.0
var leftTrafficY = 500.0
var leftTrafficSpeed = 3.0
var isLightActive = false
var currentLevel = 1
var levelDistance = 0.0
val targetDistancePerLevel = 600.0
var gameOver = false
var gameWon = false
var score = 0
def updatePlayerPos(): Unit = {
playerBody.setPosition(carX, carY)
playerRoof.setPosition(carX + 3, carY + 28)
playerGlass.setPosition(carX + 4, carY + 58)
playerTailL.setPosition(carX + 2, carY + 2)
playerTailR.setPosition(carX + 42, carY + 2)
playerHeadL.setPosition(carX + 2, carY + 88)
playerHeadR.setPosition(carX + 41, carY + 88)
if (isLightActive) {
beamL.setPosition(carX + 2, carY + 94)
beamR.setPosition(carX + 41, carY + 94)
}
}
def updateEnemyPos(): Unit = {
enemyBody.setPosition(enemyX, enemyY)
enemyRoof.setPosition(enemyX + 4, enemyY + 28)
enemyGlass.setPosition(enemyX + 4, enemyY + 20)
enemyHeadL.setPosition(enemyX + 2, enemyY + 2)
enemyHeadR.setPosition(enemyX + 42, enemyY + 2)
}
def updateLeftTrafficPos(): Unit = {
leftTrafficBody.setPosition(leftTrafficX, leftTrafficY)
leftTrafficRoof.setPosition(leftTrafficX + 4, leftTrafficY + 28)
leftTrafficGlass.setPosition(leftTrafficX + 4, leftTrafficY + 58)
leftTrafficTailL.setPosition(leftTrafficX + 2, leftTrafficY + 2)
leftTrafficTailR.setPosition(leftTrafficX + 42, leftTrafficY + 2)
}
def resetEnemy(): Unit = {
enemyX = random(20, (roadWidth / 2 - 65).toInt)
enemyY = canvasHeight / 2 + 120
enemySpeed = currentLevel match {
case 1 => 6.0
case 2 => 9.0
case 3 => 13.0
}
updateEnemyPos()
}
def resetLeftTraffic(): Unit = {
leftTrafficX = random((-roadWidth / 2 + 15).toInt, -65)
leftTrafficY = canvasHeight / 2 + 200
leftTrafficSpeed = currentLevel match {
case 1 => 2.0
case 2 => 4.0
case 3 => 6.0
}
updateLeftTrafficPos()
}
resetEnemy()
resetLeftTraffic()
updatePlayerPos()
// --- Top-Right Mini-Map ---
val mapWidth = 110
val mapHeight = 110
val mapX = canvasWidth / 2 - mapWidth - 15
val mapY = canvasHeight / 2 - mapHeight - 15
val miniMapBg = Picture.rectangle(mapWidth, mapHeight)
miniMapBg.setFillColor(Color(15, 20, 25, 240))
miniMapBg.setPenColor(white)
miniMapBg.setPosition(mapX, mapY)
miniMapBg.draw()
val mapRoad = Picture.rectangle(20, mapHeight - 16)
mapRoad.setFillColor(Color(50, 50, 55, 255))
mapRoad.setPenColor(noColor)
mapRoad.setPosition(mapX + mapWidth / 2 - 10, mapY + 8)
mapRoad.draw()
val mapPlayerIcon = Picture.rectangle(6, 8)
mapPlayerIcon.setFillColor(Color(0, 230, 255, 255))
mapPlayerIcon.setPenColor(noColor)
mapPlayerIcon.draw()
val mapHotelIcon = Picture.rectangle(8, 8)
mapHotelIcon.setFillColor(Color(255, 50, 50, 255))
mapHotelIcon.setPenColor(noColor)
mapHotelIcon.setPosition(mapX + mapWidth / 2 + 15, mapY + mapHeight - 20)
mapHotelIcon.draw()
val mapTitleText = Picture.text("MINI MAP", 10)
mapTitleText.setFillColor(white)
mapTitleText.setPosition(mapX + 28, mapY + mapHeight - 14)
mapTitleText.draw()
// --- HUD Displays ---
val hudText = Picture.text("", 15)
hudText.setFillColor(white)
hudText.setPosition(-canvasWidth / 2 + 15, canvasHeight / 2 - 35)
hudText.draw()
val helpControlsText = Picture.text("Drive: SPACE | Reverse: DOWN | Brake: B | Steer: LEFT/RIGHT", 13)
helpControlsText.setFillColor(Color(0, 230, 255, 255))
helpControlsText.setPosition(-canvasWidth / 2 + 15, -canvasHeight / 2 + 20)
helpControlsText.draw()
val statusText = Picture.text("", 24)
statusText.setPosition(-240, 0)
def updateUI(): Unit = {
val speedKmh = (currentPlayerSpeed * 12).toInt
val levelLabel = currentLevel match {
case 1 => "1 (EASY)"
case 2 => "2 (MEDIUM)"
case 3 => "3 (HARD)"
}
hudText.update(s"LEVEL: $levelLabel | SCORE: $score | SPEED: $speedKmh KM/H")
}
def updateMapProgress(): Unit = {
val totalProgress = ((currentLevel - 1) * targetDistancePerLevel) + levelDistance
val maxProgress = 3 * targetDistancePerLevel
val ratio = Math.min(1.0, Math.max(0.0, totalProgress / maxProgress))
val iconY = mapY + 12 + (ratio * (mapHeight - 35))
mapPlayerIcon.setPosition(mapX + mapWidth / 2 - 7, iconY)
if (currentLevel == 3 && levelDistance > targetDistancePerLevel * 0.7) {
if (destinationY > -100) {
destinationY -= currentPlayerSpeed * 0.4
updateDestination()
}
}
}
// --- Game Loop ---
animate {
if (!gameOver && !gameWon) {
// --- Controls ---
if (isKeyPressed(Kc.VK_SPACE)) { // Accelerate
currentPlayerSpeed = 7.0 + (currentLevel * 2.0)
} else if (isKeyPressed(Kc.VK_DOWN)) { // Reverse
currentPlayerSpeed = -4.0
} else if (isKeyPressed(Kc.VK_B)) { // Brake
currentPlayerSpeed = 0.0
} else {
if (currentPlayerSpeed > 0) currentPlayerSpeed = Math.max(0.0, currentPlayerSpeed - 0.5)
if (currentPlayerSpeed < 0) currentPlayerSpeed = Math.min(0.0, currentPlayerSpeed + 0.5)
}
// Steering
if (isKeyPressed(Kc.VK_LEFT)) carX -= carSteerSpeed
if (isKeyPressed(Kc.VK_RIGHT)) carX += carSteerSpeed
val minX = -canvasWidth / 2 + 20
val maxX = canvasWidth / 2 - 70
if (carX < minX) carX = minX
if (carX > maxX) carX = maxX
updateDashes(currentPlayerSpeed)
if (currentPlayerSpeed != 0.0) {
levelDistance += currentPlayerSpeed * 0.2
if (levelDistance < 0) levelDistance = 0.0
}
updateMapProgress()
updateUI()
// Level Check
if (levelDistance >= targetDistancePerLevel) {
if (currentLevel < 3) {
currentLevel += 1
levelDistance = 0.0
}
}
// Exact Parking Spot Verification (Level 3 Required)
if (currentLevel == 3 && destinationY <= -50) {
val isInsideSpotX = carX >= (parkingSpotX - 10) && (carX + 52) <= (parkingSpotX + parkingSpotWidth + 10)
val isInsideSpotY = carY >= (destinationY - 20) && (carY + 95) <= (destinationY + parkingSpotHeight + 20)
if (isInsideSpotX && isInsideSpotY && currentPlayerSpeed == 0.0) {
gameWon = true
statusText.setFillColor(Color(50, 255, 50, 255))
statusText.update("PERFECTLY PARKED! GAME WON! Press 'R'")
statusText.draw()
}
}
// Light Dipper Control
if (isKeyPressed(Kc.VK_A)) {
if (!isLightActive) {
isLightActive = true
playerHeadL.setFillColor(Color(245, 245, 255, 255))
playerHeadR.setFillColor(Color(245, 245, 255, 255))
beamL.draw()
beamR.draw()
}
} else {
if (isLightActive) {
isLightActive = false
playerHeadL.setFillColor(gray)
playerHeadR.setFillColor(gray)
beamL.erase()
beamR.erase()
}
}
updatePlayerPos()
// Right Lane Traffic
enemyY -= (enemySpeed + currentPlayerSpeed * 0.5)
if (enemyY < -canvasHeight / 2 - 120) {
if (currentPlayerSpeed > 0) score += 10
resetEnemy()
}
updateEnemyPos()
// Left Lane Traffic
leftTrafficY -= (currentPlayerSpeed - leftTrafficSpeed)
if (leftTrafficY < -canvasHeight / 2 - 120) {
if (currentPlayerSpeed > 0) score += 15
resetLeftTraffic()
}
updateLeftTrafficPos()
// Collision Check
val crashEnemy = Math.abs((carX + 26) - (enemyX + 26)) < 44 && Math.abs((carY + 47) - (enemyY + 47)) < 82
val crashLeftTraffic = Math.abs((carX + 26) - (leftTrafficX + 26)) < 44 && Math.abs((carY + 47) - (leftTrafficY + 47)) < 82
if (crashEnemy || crashLeftTraffic) {
gameOver = true
statusText.setFillColor(Color(255, 50, 50, 255))
statusText.update("CRASHED! Press 'R' to Restart")
statusText.draw()
}
} else {
if (isKeyPressed(Kc.VK_R)) {
gameOver = false
gameWon = false
currentLevel = 1
levelDistance = 0.0
score = 0
currentPlayerSpeed = 0.0
destinationY = 700.0
updateDestination()
statusText.erase()
carX = -100.0
carY = -220.0
resetEnemy()
resetLeftTraffic()
updatePlayerPos()
}
}
}