Code Sketch
sniper_0718
Category: Art
cleari()
// --- Game Dimensions ---
val canvasWidth = 800
val canvasHeight = 600
val roadWidth = 360
// --- Background Terrain (Dynamic per level) ---
val bg = Picture.rectangle(canvasWidth, canvasHeight)
bg.setFillColor(Color(70, 160, 70, 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 (Hidden Initially) ---
val destFixedY = 120.0
val destWidth = 110
val destHeight = 90
val building = Picture.rectangle(destWidth, destHeight)
building.setFillColor(Color(70, 40, 90, 255))
building.setPenColor(white)
val roof = Picture.rectangle(destWidth + 10, 15)
roof.setFillColor(Color(200, 50, 50, 255))
roof.setPenColor(noColor)
val destSign = Picture.text("HOTEL DELUXE", 11)
destSign.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 updateDestinationPosition(): Unit = {
building.setPosition(parkingSpotX, destFixedY + 110)
roof.setPosition(parkingSpotX - 5, destFixedY + 110 + destHeight)
destSign.setPosition(parkingSpotX + 5, destFixedY + 110 + destHeight - 20)
parkingSpot.setPosition(parkingSpotX, destFixedY)
parkingSign.setPosition(parkingSpotX + 22, destFixedY + 32)
}
def hideDestination(): Unit = {
building.setPosition(-1000, -1000)
roof.setPosition(-1000, -1000)
destSign.setPosition(-1000, -1000)
parkingSpot.setPosition(-1000, -1000)
parkingSign.setPosition(-1000, -1000)
}
def showDestination(): Unit = {
updateDestinationPosition()
}
hideDestination()
// --- Realistic White Land Rover Defender (Player Car) ---
val playerBody = Picture.rectangle(54, 100)
playerBody.setFillColor(Color(245, 245, 250, 255))
playerBody.setPenColor(gray)
val playerRoof = Picture.rectangle(48, 42)
playerRoof.setFillColor(Color(215, 215, 220, 255))
playerRoof.setPenColor(gray)
val playerRack = Picture.rectangle(44, 30)
playerRack.setFillColor(Color(30, 30, 30, 255))
playerRack.setPenColor(noColor)
val playerGlassF = Picture.rectangle(42, 16)
playerGlassF.setFillColor(Color(20, 30, 45, 255))
playerGlassF.setPenColor(noColor)
val playerGlassR = Picture.rectangle(42, 18)
playerGlassR.setFillColor(Color(20, 30, 45, 255))
playerGlassR.setPenColor(noColor)
val playerSpareWheel = Picture.rectangle(16, 20)
playerSpareWheel.setFillColor(Color(40, 40, 40, 255))
playerSpareWheel.setPenColor(black)
val playerTailL = Picture.rectangle(6, 6)
playerTailL.setFillColor(Color(220, 20, 20, 255))
playerTailL.setPenColor(noColor)
val playerTailR = Picture.rectangle(6, 6)
playerTailR.setFillColor(Color(220, 20, 20, 255))
playerTailR.setPenColor(noColor)
val playerHeadL = Picture.rectangle(10, 8)
playerHeadL.setFillColor(yellow)
playerHeadL.setPenColor(noColor)
val playerHeadR = Picture.rectangle(10, 8)
playerHeadR.setFillColor(yellow)
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()
playerRack.draw()
playerGlassF.draw()
playerGlassR.draw()
playerSpareWheel.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 = 420.0
var enemySpeed = 6.0
var leftTrafficX = -100.0
var leftTrafficY = 650.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
var levelTransitionTimer = 0.0
var destinationShown = false
def updatePlayerPos(): Unit = {
playerBody.setPosition(carX, carY)
playerRoof.setPosition(carX + 3, carY + 29)
playerRack.setPosition(carX + 5, carY + 35)
playerGlassF.setPosition(carX + 6, carY + 68)
playerGlassR.setPosition(carX + 6, carY + 44)
playerSpareWheel.setPosition(carX + 19, carY + 4)
playerTailL.setPosition(carX + 4, carY + 2)
playerTailR.setPosition(carX + 44, carY + 2)
playerHeadL.setPosition(carX + 4, carY + 92)
playerHeadR.setPosition(carX + 40, carY + 92)
if (isLightActive) {
beamL.setPosition(carX + 4, carY + 98)
beamR.setPosition(carX + 40, carY + 98)
}
}
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 + 180
enemySpeed = currentLevel match {
case 1 => 6.0
case 2 => 10.0
case 3 => 15.0
}
updateEnemyPos()
}
def resetLeftTraffic(): Unit = {
leftTrafficX = random((-roadWidth / 2 + 15).toInt, -65)
leftTrafficY = canvasHeight / 2 + 380
leftTrafficSpeed = currentLevel match {
case 1 => 2.0
case 2 => 5.0
case 3 => 8.0
}
updateLeftTrafficPos()
}
def setupLevelTheme(): Unit = {
currentLevel match {
case 1 =>
// Level 1: Countryside / City Day (Green Theme)
bg.setFillColor(Color(70, 160, 70, 255))
building.setFillColor(Color(70, 40, 90, 255))
roof.setFillColor(Color(200, 50, 50, 255))
destSign.update("HOTEL DELUXE")
case 2 =>
// Level 2: Desert Highway (Sandy Orange Theme)
bg.setFillColor(Color(190, 140, 70, 255))
building.setFillColor(Color(130, 70, 40, 255))
roof.setFillColor(Color(240, 180, 40, 255))
destSign.update("SUNSET VILLA")
case 3 =>
// Level 3: Night Drive / Cyber City (Dark Navy Theme)
bg.setFillColor(Color(20, 25, 45, 255))
building.setFillColor(Color(30, 90, 110, 255))
roof.setFillColor(Color(220, 40, 120, 255))
destSign.update("BEACH CLUB")
}
hideDestination()
destinationShown = false
}
resetEnemy()
resetLeftTraffic()
updatePlayerPos()
setupLevelTheme()
// --- 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(Color(20, 20, 20, 255))
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(10, 40, 80, 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 (HOTEL)"
case 2 => "2 (VILLA)"
case 3 => "3 (CLUB)"
}
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)
}
// --- Game Loop ---
animate {
if (!gameOver && !gameWon) {
// --- Controls ---
if (levelDistance < targetDistancePerLevel) {
if (isKeyPressed(Kc.VK_SPACE)) {
currentPlayerSpeed = 7.0 + (currentLevel * 2.0)
} else if (isKeyPressed(Kc.VK_DOWN)) {
currentPlayerSpeed = -4.0
} else if (isKeyPressed(Kc.VK_B)) {
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)
}
} else {
currentPlayerSpeed = 0.0
}
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 < targetDistancePerLevel) {
levelDistance += currentPlayerSpeed * 0.2
if (levelDistance < 0) levelDistance = 0.0
}
updateMapProgress()
updateUI()
// Level Distance Complete Check -> Reveal Destination & Smoothly auto-steer towards parking
if (levelDistance >= targetDistancePerLevel) {
if (!destinationShown) {
showDestination()
destinationShown = true
}
if (carY < destFixedY) {
carY += 4.0
}
if (carX < parkingSpotX - 10) carX += 1.0
else if (carX > parkingSpotX + 10) carX -= 1.0
val isInsideSpotX = carX >= (parkingSpotX - 35) && (carX + 54) <= (parkingSpotX + parkingSpotWidth + 35)
val isInsideSpotY = carY >= (destFixedY - 40) && (carY + 100) <= (destFixedY + parkingSpotHeight + 40)
if (isInsideSpotX && isInsideSpotY) {
levelTransitionTimer += 1.0
if (levelTransitionTimer > 180.0) { // ~3 seconds delay
levelTransitionTimer = 0.0
if (currentLevel < 3) {
currentLevel += 1
levelDistance = 0.0
carY = -220.0
setupLevelTheme()
resetEnemy()
resetLeftTraffic()
} else {
gameWon = true
statusText.setFillColor(Color(50, 255, 50, 255))
statusText.update("ALL DESTINATIONS REACHED! WON! Press 'R'")
statusText.draw()
}
} else {
statusText.setFillColor(Color(0, 230, 255, 255))
statusText.update(s"PARKED! Next level in ${((180.0 - levelTransitionTimer)/60.0).toInt + 1}s...")
statusText.draw()
}
} else {
statusText.setFillColor(Color(255, 204, 0, 255))
statusText.update("PARKING IN PROGRESS...")
statusText.draw()
}
} else {
statusText.erase()
}
// 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(yellow)
playerHeadR.setFillColor(yellow)
beamL.erase()
beamR.erase()
}
}
updatePlayerPos()
// Right Lane Traffic
if (levelDistance < targetDistancePerLevel) {
enemyY -= (enemySpeed + currentPlayerSpeed * 0.5)
if (enemyY < -canvasHeight / 2 - 120) {
if (currentPlayerSpeed > 0) score += 10
resetEnemy()
}
}
updateEnemyPos()
// Left Lane Traffic
if (levelDistance < targetDistancePerLevel) {
leftTrafficY -= (currentPlayerSpeed - leftTrafficSpeed)
if (leftTrafficY < -canvasHeight / 2 - 120) {
if (currentPlayerSpeed > 0) score += 15
resetLeftTraffic()
}
}
updateLeftTrafficPos()
// Collision Check
val crashEnemy = Math.abs((carX + 27) - (enemyX + 26)) < 44 && Math.abs((carY + 50) - (enemyY + 47)) < 82
val crashLeftTraffic = Math.abs((carX + 27) - (leftTrafficX + 26)) < 44 && Math.abs((carY + 50) - (leftTrafficY + 47)) < 82
if ((crashEnemy || crashLeftTraffic) && levelDistance < targetDistancePerLevel) {
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
levelTransitionTimer = 0.0
setupLevelTheme()
statusText.erase()
carX = -100.0
carY = -220.0
resetEnemy()
resetLeftTraffic()
updatePlayerPos()
}
}
}