Code Sketch
sniper_0718
Category: Art
cleari()
// --- Game Dimensions ---
val canvasWidth = 800
val canvasHeight = 600
val roadWidth = 340
// --- Game States ---
var gameState = "MENU" // "MENU", "PLAYING", "VICTORY"
var selectedLevel = 1
var enemiesRemaining = 0
var totalEnemiesInLevel = 0
// --- Background & Road (Static) ---
val bg = Picture.rectangle(canvasWidth, canvasHeight)
bg.setFillColor(Color(10, 25, 10, 255))
bg.setPenColor(noColor)
bg.setPosition(-canvasWidth / 2, -canvasHeight / 2)
val road = Picture.rectangle(roadWidth, canvasHeight)
road.setFillColor(Color(35, 35, 38, 255))
road.setPenColor(noColor)
road.setPosition(-roadWidth / 2, -canvasHeight / 2)
val lineLeft = Picture.rectangle(6, canvasHeight)
lineLeft.setFillColor(white)
lineLeft.setPenColor(noColor)
lineLeft.setPosition(-roadWidth / 2 + 5, -canvasHeight / 2)
val lineRight = Picture.rectangle(6, canvasHeight)
lineRight.setFillColor(white)
lineRight.setPenColor(noColor)
lineRight.setPosition(roadWidth / 2 - 11, -canvasHeight / 2)
val dashCount = 8
val dashHeight = 40
val dashGap = 50
val yellowDashesL = Array.fill(dashCount) { Picture.rectangle(4, dashHeight).withFillColor(Color(255, 204, 0, 255)).withPenColor(noColor) }
val yellowDashesR = Array.fill(dashCount) { Picture.rectangle(4, dashHeight).withFillColor(Color(255, 204, 0, 255)).withPenColor(noColor) }
for (i <- 0 until dashCount) {
val yPos = (canvasHeight / 2) - (i * (dashHeight + dashGap))
yellowDashesL(i).setPosition(-5, yPos)
yellowDashesR(i).setPosition(1, yPos)
}
val nightOverlay = Picture.rectangle(canvasWidth, canvasHeight)
nightOverlay.setFillColor(Color(0, 0, 0, 140))
nightOverlay.setPenColor(noColor)
nightOverlay.setPosition(-canvasWidth / 2, -canvasHeight / 2)
// --- Menu UI Boxes (Levels: 20, 40, 50, 100) ---
val menuBg = Picture.rectangle(canvasWidth, canvasHeight).withFillColor(Color(15, 20, 30, 255)).withPenColor(noColor)
menuBg.setPosition(-canvasWidth / 2, -canvasHeight / 2)
val titleText = Picture.text("SELECT LEVEL - AK-47 SHOOTER", 24).withFillColor(white)
titleText.setPosition(-180, 180)
val box1 = Picture.rectangle(160, 80).withFillColor(Color(40, 100, 40, 255)).withPenColor(white)
val text1 = Picture.text("1. 20", 18).withFillColor(white)
box1.setPosition(-220, 50); text1.setPosition(-190, 85)
val box2 = Picture.rectangle(160, 80).withFillColor(Color(40, 60, 120, 255)).withPenColor(white)
val text2 = Picture.text("2. 40", 18).withFillColor(white)
box2.setPosition(-30, 50); text2.setPosition(0, 85)
val box3 = Picture.rectangle(160, 80).withFillColor(Color(120, 100, 40, 255)).withPenColor(white)
val text3 = Picture.text("3. 50", 18).withFillColor(white)
box3.setPosition(-220, -60); text3.setPosition(-190, -25)
val box4 = Picture.rectangle(160, 80).withFillColor(Color(120, 40, 40, 255)).withPenColor(white)
val text4 = Picture.text("4. 100", 18).withFillColor(white)
box4.setPosition(-30, -60); text4.setPosition(0, -25)
// --- Player with AK-47 ---
val charHead = Picture.circle(8).withFillColor(Color(255, 220, 177, 255)).withPenColor(noColor)
val charBody = Picture.rectangle(16, 24).withFillColor(Color(0, 122, 255, 255)).withPenColor(noColor)
val charArmL = Picture.rectangle(5, 18).withFillColor(Color(40, 40, 40, 255)).withPenColor(noColor)
val akGun = Picture.rectangle(26, 6).withFillColor(Color(60, 40, 20, 255)).withPenColor(black)
val charLegL = Picture.rectangle(6, 20).withFillColor(Color(20, 20, 20, 255)).withPenColor(noColor)
val charLegR = Picture.rectangle(6, 20).withFillColor(Color(20, 20, 20, 255)).withPenColor(noColor)
var charX = 0.0
var charY = -200.0
val moveSpeed = 5.0
def updateCharPos(): Unit = {
charHead.setPosition(charX, charY + 26)
charBody.setPosition(charX - 8, charY + 2)
charArmL.setPosition(charX - 15, charY + 2)
akGun.setPosition(charX + 3, charY + 8)
charLegL.setPosition(charX - 6, charY - 20)
charLegR.setPosition(charX + 2, charY - 20)
}
// --- Enemies Group ---
val enemyCount = 4
val enemyHeads = Array.fill(enemyCount)(Picture.circle(8).withFillColor(Color(255, 80, 80, 255)).withPenColor(noColor))
val enemyBodies = Array.fill(enemyCount)(Picture.rectangle(16, 24).withFillColor(Color(180, 20, 20, 255)).withPenColor(noColor))
var enemyX = Array.fill(enemyCount)(0.0)
var enemyY = Array.fill(enemyCount)(0.0)
var enemyActive = Array.fill(enemyCount)(false)
val enemySpeed = 2.2
def resetSingleEnemy(i: Int): Unit = {
enemyX(i) = random(-80, 80)
enemyY(i) = random(300, 450)
enemyActive(i) = true
}
def initAllEnemies(): Unit = {
for (i <- 0 until enemyCount) {
resetSingleEnemy(i)
enemyHeads(i).draw()
enemyBodies(i).draw()
}
}
// --- 5 Bullets Setup ---
val maxBullets = 5
val bulletPics = Array.fill(maxBullets)(Picture.rectangle(4, 12).withFillColor(yellow).withPenColor(noColor))
val bulletX = Array.fill(maxBullets)(0.0)
val bulletY = Array.fill(maxBullets)(-1000.0)
val bulletActive = Array.fill(maxBullets)(false)
val bulletSpeed = 22.0
for (bp <- bulletPics) {
bp.setPosition(-1000, -1000)
bp.draw()
}
// HUD Texts
val hudText = Picture.text("", 15).withFillColor(white)
hudText.setPosition(-canvasWidth / 2 + 20, canvasHeight / 2 - 40)
val victoryText = Picture.text("VICTORY! ALL LEVELS COMPLETED!", 24).withFillColor(Color(0, 255, 100, 255))
victoryText.setPosition(-220, 0)
def drawMenu(): Unit = {
menuBg.draw()
titleText.draw()
box1.draw(); text1.draw()
box2.draw(); text2.draw()
box3.draw(); text3.draw()
box4.draw(); text4.draw()
}
def eraseMenu(): Unit = {
menuBg.erase()
titleText.erase()
box1.erase(); text1.erase()
box2.erase(); text2.erase()
box3.erase(); text3.erase()
box4.erase(); text4.erase()
}
def startLevel(levelNum: Int): Unit = {
selectedLevel = levelNum
totalEnemiesInLevel = levelNum match {
case 1 => 20
case 2 => 40
case 3 => 50
case 4 => 100
case _ => 20
}
enemiesRemaining = totalEnemiesInLevel
eraseMenu()
bg.draw()
road.draw()
lineLeft.draw()
lineRight.draw()
for (d <- yellowDashesL) d.draw()
for (d <- yellowDashesR) d.draw()
nightOverlay.draw()
charHead.draw(); charBody.draw(); charArmL.draw(); akGun.draw(); charLegL.draw(); charLegR.draw()
initAllEnemies()
hudText.draw()
hudText.update(s"Level $selectedLevel | Enemies Left: $enemiesRemaining | Arrows/WASD: Move | Z: Shoot")
updateCharPos()
gameState = "PLAYING"
}
// Mouse Click for Level Selection
onMouseClick { (x, y) =>
if (gameState == "MENU") {
if (x >= -220 && x <= -60 && y >= 50 && y <= 130) startLevel(1)
else if (x >= -30 && x <= 130 && y >= 50 && y <= 130) startLevel(2)
else if (x >= -220 && x <= -60 && y >= -60 && y <= 20) startLevel(3)
else if (x >= -30 && x <= 130 && y >= -60 && y <= 20) startLevel(4)
}
}
var keyZReleased = true
drawMenu()
// --- Game Loop ---
animate {
if (gameState == "PLAYING") {
// Movement Controls (Both Arrow Keys and WASD supported)
if (isKeyPressed(Kc.VK_A) || isKeyPressed(Kc.VK_LEFT)) charX -= moveSpeed
if (isKeyPressed(Kc.VK_D) || isKeyPressed(Kc.VK_RIGHT)) charX += moveSpeed
if (isKeyPressed(Kc.VK_W) || isKeyPressed(Kc.VK_UP)) charY += moveSpeed
if (isKeyPressed(Kc.VK_S) || isKeyPressed(Kc.VK_DOWN)) charY -= moveSpeed
// Road Boundaries
if (charX < -150) charX = -150
if (charX > 150) charX = 150
if (charY < -250) charY = -250
if (charY > 100) charY = 100
updateCharPos()
// Move Enemies Downwards
for (i <- 0 until enemyCount) {
if (enemyActive(i)) {
enemyY(i) -= enemySpeed
if (enemyY(i) < charY - 50) {
enemyY(i) = random(300, 450)
enemyX(i) = random(-80, 80)
}
enemyHeads(i).setPosition(enemyX(i), enemyY(i) + 26)
enemyBodies(i).setPosition(enemyX(i) - 8, enemyY(i) + 2)
}
}
// Shoot with Z Key (5 Bullets burst)
val zCurrentlyPressed = isKeyPressed(Kc.VK_Z)
if (zCurrentlyPressed && keyZReleased) {
val offsets = Array(-30.0, -15.0, 0.0, 15.0, 30.0)
for (j <- 0 until maxBullets) {
if (!bulletActive(j)) {
bulletX(j) = charX + offsets(j)
bulletY(j) = charY + 30
bulletActive(j) = true
}
}
keyZReleased = false
}
if (!zCurrentlyPressed) {
keyZReleased = true
}
// Bullets Movement & Collision Logic
for (j <- 0 until maxBullets) {
if (bulletActive(j)) {
bulletY(j) += bulletSpeed
bulletPics(j).setPosition(bulletX(j), bulletY(j))
// Check Collision with Enemies
for (i <- 0 until enemyCount) {
if (enemyActive(i) && Math.abs(bulletX(j) - enemyX(i)) < 25 && Math.abs(bulletY(j) - enemyY(i)) < 25) {
enemiesRemaining -= 1
hudText.update(s"Level $selectedLevel | Enemies Left: $enemiesRemaining | Arrows/WASD: Move | Z: Shoot")
bulletActive(j) = false
bulletY(j) = -1000.0
bulletPics(j).setPosition(bulletX(j), bulletY(j))
if (enemiesRemaining > 0) {
resetSingleEnemy(i)
} else {
if (selectedLevel < 4) {
startLevel(selectedLevel + 1)
} else {
gameState = "VICTORY"
hudText.erase()
for (bp <- bulletPics) bp.setPosition(-1000, -1000)
for (e <- enemyHeads) e.erase()
for (e <- enemyBodies) e.erase()
victoryText.draw()
}
}
}
}
// Hide bullet if it goes off screen
if (bulletY(j) > canvasHeight / 2) {
bulletActive(j) = false
bulletY(j) = -1000.0
bulletPics(j).setPosition(bulletX(j), bulletY(j))
}
} else {
bulletPics(j).setPosition(-1000, -1000)
}
}
}
}