Code Sketch


sniper car game
By: Mhalsakant School
Category: Art
cleari()

// --- Game Dimensions ---
val canvasWidth = 800 //> val canvasWidth: Int = 800
val canvasHeight = 600 //> val canvasHeight: Int = 600
val roadWidth = 340 //> val roadWidth: Int = 340

// --- Realistic Terrain Background ---
val bg = Picture.rectangle(canvasWidth, canvasHeight) //> val bg: net.kogics.kojo.picture.RectanglePic = Picture with Id: 78923640
bg.setFillColor(Color(10, 25, 10, 255))
bg.setPenColor(noColor)
bg.setPosition(-canvasWidth / 2, -canvasHeight / 2)
bg.draw()

val road = Picture.rectangle(roadWidth, canvasHeight) //> val road: net.kogics.kojo.picture.RectanglePic = Picture with Id: 502328057
road.setFillColor(Color(35, 35, 38, 255))
road.setPenColor(noColor)
road.setPosition(-roadWidth / 2, -canvasHeight / 2)
road.draw()

// --- Road Boundary Marking Lines ---
val lineLeft = Picture.rectangle(6, canvasHeight) //> val lineLeft: net.kogics.kojo.picture.RectanglePic = Picture with Id: 589196569
lineLeft.setFillColor(white)
lineLeft.setPenColor(noColor)
lineLeft.setPosition(-roadWidth / 2 + 5, -canvasHeight / 2)
lineLeft.draw()

val lineRight = Picture.rectangle(6, canvasHeight) //> val lineRight: net.kogics.kojo.picture.RectanglePic = Picture with Id: 909552495
lineRight.setFillColor(white)
lineRight.setPenColor(noColor)
lineRight.setPosition(roadWidth / 2 - 11, -canvasHeight / 2)
lineRight.draw()

// --- Fast Animated Lane Markers ---
val dashCount = 8 //> val dashCount: Int = 8
val dashHeight = 40 //> val dashHeight: Int = 40
val dashGap = 50 //> val dashGap: Int = 50
var dashOffset = 0.0 //> var dashOffset: Double = 0.0

val yellowDashesL = Array.fill(dashCount) {
  val d = Picture.rectangle(4, dashHeight)
  d.setFillColor(Color(255, 204, 0, 255))
  d.setPenColor(noColor)
  d.draw()
  d
} //> val yellowDashesL: Array[net.kogics.kojo.picture.RectanglePic] = Array(Picture with Id: 803395409, Picture with Id: 1997543536, Picture with Id: 9987635, Picture with Id: 953997638, Picture with Id: 20830547, Picture with Id: 1989771932, Picture with Id: 896781186, Picture with Id: 1807426179)

val yellowDashesR = Array.fill(dashCount) {
  val d = Picture.rectangle(4, dashHeight)
  d.setFillColor(Color(255, 204, 0, 255))
  d.setPenColor(noColor)
  d.draw()
  d
} //> val yellowDashesR: Array[net.kogics.kojo.picture.RectanglePic] = Array(Picture with Id: 855525343, Picture with Id: 970057547, Picture with Id: 793624280, Picture with Id: 1298788316, Picture with Id: 233408785, Picture with Id: 993315928, Picture with Id: 2043485848, Picture with Id: 2069371250)

def updateDashes(): Unit = {
  dashOffset = (dashOffset - 45) % (dashHeight + dashGap)
  for (i <- 0 until dashCount) {
    val yPos = (canvasHeight / 2) - (i * (dashHeight + dashGap)) + dashOffset
    yellowDashesL(i).setPosition(-5, yPos)
    yellowDashesR(i).setPosition(1, yPos)
  }
} //> def updateDashes(): Unit

// --- Night Overlay ---
val nightOverlay = Picture.rectangle(canvasWidth, canvasHeight) //> val nightOverlay: net.kogics.kojo.picture.RectanglePic = Picture with Id: 1769224982
nightOverlay.setFillColor(Color(0, 0, 0, 160))
nightOverlay.setPenColor(noColor)
nightOverlay.setPosition(-canvasWidth / 2, -canvasHeight / 2)
nightOverlay.draw()

// --- Player Fortuner ---
val playerBody = Picture.rectangle(52, 95) //> val playerBody: net.kogics.kojo.picture.RectanglePic = Picture with Id: 504923649
playerBody.setFillColor(Color(245, 245, 250, 255))
playerBody.setPenColor(black)

val playerRoof = Picture.rectangle(46, 34) //> val playerRoof: net.kogics.kojo.picture.RectanglePic = Picture with Id: 1556910576
playerRoof.setFillColor(Color(230, 230, 235, 255))
playerRoof.setPenColor(gray)

val playerGlass = Picture.rectangle(44, 20) //> val playerGlass: net.kogics.kojo.picture.RectanglePic = Picture with Id: 363207207
playerGlass.setFillColor(Color(20, 40, 60, 255))
playerGlass.setPenColor(noColor)

val playerTailL = Picture.rectangle(8, 6) //> val playerTailL: net.kogics.kojo.picture.RectanglePic = Picture with Id: 1813230771
playerTailL.setFillColor(Color(220, 20, 20, 255))
playerTailL.setPenColor(noColor)

val playerTailR = Picture.rectangle(8, 6) //> val playerTailR: net.kogics.kojo.picture.RectanglePic = Picture with Id: 1435696716
playerTailR.setFillColor(Color(220, 20, 20, 255))
playerTailR.setPenColor(noColor)

val playerHeadL = Picture.rectangle(9, 6) //> val playerHeadL: net.kogics.kojo.picture.RectanglePic = Picture with Id: 1305308460
playerHeadL.setFillColor(gray)
playerHeadL.setPenColor(noColor)

val playerHeadR = Picture.rectangle(9, 6) //> val playerHeadR: net.kogics.kojo.picture.RectanglePic = Picture with Id: 1448691588
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)
} //> val beamL: net.kogics.kojo.picture.PathPic = Picture with Id: 295414095
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)
} //> val beamR: net.kogics.kojo.picture.PathPic = Picture with Id: 317209106
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 Traffic Cars ---
val enemyBody = Picture.rectangle(52, 95) //> val enemyBody: net.kogics.kojo.picture.RectanglePic = Picture with Id: 1656628606
enemyBody.setFillColor(Color(20, 20, 25, 255))
enemyBody.setPenColor(gray)

val enemyRoof = Picture.rectangle(44, 34) //> val enemyRoof: net.kogics.kojo.picture.RectanglePic = Picture with Id: 1808006837
enemyRoof.setFillColor(Color(30, 30, 35, 255))
enemyRoof.setPenColor(noColor)

val enemyGlass = Picture.rectangle(44, 18) //> val enemyGlass: net.kogics.kojo.picture.RectanglePic = Picture with Id: 418528165
enemyGlass.setFillColor(Color(50, 50, 70, 255))
enemyGlass.setPenColor(noColor)

val enemyTailL = Picture.rectangle(8, 6) //> val enemyTailL: net.kogics.kojo.picture.RectanglePic = Picture with Id: 247658462
enemyTailL.setFillColor(red)
enemyTailL.setPenColor(noColor)

val enemyTailR = Picture.rectangle(8, 6) //> val enemyTailR: net.kogics.kojo.picture.RectanglePic = Picture with Id: 911192081
enemyTailR.setFillColor(red)
enemyTailR.setPenColor(noColor)

enemyBody.draw()
enemyRoof.draw()
enemyGlass.draw()
enemyTailL.draw()
enemyTailR.draw()

// --- Movement Variables ---
var carX = -26.0 //> var carX: Double = -26.0
val carY = -220.0 //> val carY: Double = -220.0
val carSteerSpeed = 55.0 //> val carSteerSpeed: Double = 55.0

var enemyX = 40.0 //> var enemyX: Double = 40.0
var enemyY = 380.0 //> var enemyY: Double = 380.0
var enemySpeed = 35.0 //> var enemySpeed: Double = 35.0

var isLightActive = false //> var isLightActive: Boolean = false

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 updatePlayerPos(): Unit

def updateEnemyPos(): Unit = {
  enemyBody.setPosition(enemyX, enemyY)
  enemyRoof.setPosition(enemyX + 4, enemyY + 28)
  enemyGlass.setPosition(enemyX + 4, enemyY + 20)
  enemyTailL.setPosition(enemyX + 2, enemyY + 88)
  enemyTailR.setPosition(enemyX + 42, enemyY + 88)
} //> def updateEnemyPos(): Unit

def resetEnemy(): Unit = {
  val laneChoice = random(0, 2)
  if (laneChoice == 0) enemyX = -roadWidth / 2 + 25
  else enemyX = roadWidth / 2 - 75

  enemyY = canvasHeight / 2 + 120
  enemySpeed = random(32, 45)
  updateEnemyPos()
} //> def resetEnemy(): Unit

resetEnemy()
updatePlayerPos()

// --- HUD / Score Board ---
var score = 0 //> var score: Int = 0
var gameOver = false //> var gameOver: Boolean = false

val scoreText = Picture.text(s"SPEED: 220 KM/H  |  SCORE: $score", 18) //> val scoreText: net.kogics.kojo.picture.TextPic = TextPic (Id: 1684867852)
scoreText.setFillColor(white)
scoreText.setPosition(-canvasWidth / 2 + 20, canvasHeight / 2 - 40)
scoreText.draw()

val helpText = Picture.text("Steer: Left/Right Arrow | Dipper Flash: Hold 'A'", 15) //> val helpText: net.kogics.kojo.picture.TextPic = TextPic (Id: 111744548)
helpText.setFillColor(Color(0, 230, 255, 255))
helpText.setPosition(-canvasWidth / 2 + 20, -canvasHeight / 2 + 20)
helpText.draw()

val gameOverText = Picture.text("CRASHED! Press 'R' to Restart", 26) //> val gameOverText: net.kogics.kojo.picture.TextPic = TextPic (Id: 92471409)
gameOverText.setFillColor(Color(255, 50, 50, 255))
gameOverText.setPosition(-180, 0)

// --- Game Loop ---
animate {
  if (!gameOver) {
    updateDashes()

    if (isKeyPressed(Kc.VK_LEFT)) {
      carX -= carSteerSpeed
    }
    if (isKeyPressed(Kc.VK_RIGHT)) {
      carX += carSteerSpeed
    }

    val minX = -roadWidth / 2 + 12
    val maxX = roadWidth / 2 - 64
    if (carX < minX) carX = minX
    if (carX > maxX) carX = maxX

    // Flash Dipper Light on 'A' Press
    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()

    // High Speed Enemy Movement
    enemyY -= enemySpeed
    if (enemyY < -canvasHeight / 2 - 120) {
      score += 10
      scoreText.update(s"SPEED: 220 KM/H  |  SCORE: $score")
      resetEnemy()
    }
    updateEnemyPos()

    // Collision Detection
    val collision = Math.abs((carX + 26) - (enemyX + 26)) < 44 && Math.abs((carY + 47) - (enemyY + 47)) < 82
    if (collision) {
      gameOver = true
      gameOverText.draw()
    }
  } else {
    if (isKeyPressed(Kc.VK_R)) {
      gameOver = false
      score = 0
      scoreText.update(s"SPEED: 220 KM/H  |  SCORE: $score")
      gameOverText.erase()
      carX = -26.0
      resetEnemy()
      updatePlayerPos()
    }
  }
} //> val res72: java.util.concurrent.Future[edu.umd.cs.piccolo.activities.PActivity] = net.kogics.kojo.util.FutureResult@3fa052f3