Code Sketch


sniper_0718
By: Mhalsakant School
Category: Art
// Kojo Killer Room Game - Killers Shoot Back Version

clear()
val cb = canvasBounds

// ?. ???? ?????????? ??? ??? ???? ????
val bg = Picture.rectangle(3000, 3000)
bg.setFillColor(ColorMaker.black)
bg.setPosition(cb.x - 1000, cb.y - 1000)
draw(bg)

// ?. ??????????? ??????
val pHead = Picture.circle(8)
pHead.setFillColor(ColorMaker.cyan)
pHead.setPosition(cb.x + 200, cb.y + 245)

val pBody = Picture.rectangle(18, 30)
pBody.setFillColor(ColorMaker.blue)
pBody.setPosition(cb.x + 191, cb.y + 210)

val pLeg1 = Picture.rectangle(6, 15)
pLeg1.setFillColor(ColorMaker.blue)
pLeg1.setPosition(cb.x + 191, cb.y + 195)

val pLeg2 = Picture.rectangle(6, 15)
pLeg2.setFillColor(ColorMaker.blue)
pLeg2.setPosition(cb.x + 203, cb.y + 195)

val pGun = Picture.rectangle(16, 5)
pGun.setFillColor(ColorMaker.gray)
pGun.setPosition(cb.x + 209, cb.y + 222)

draw(pBody)
draw(pHead)
draw(pLeg1)
draw(pLeg2)
draw(pGun)

var facingRight = true

// ?. ???? ??? ????????? ?????? ?????????? (Max 10 Killers & Bullets)
var currentLevel = 0 
var killersLeft = 0
val maxKillers = 10

val killerBodies = new Array[Picture](maxKillers)
val killerHeads = new Array[Picture](maxKillers)
val killerBullets = new Array[Picture](maxKillers)
val killerBulletActive = new Array[Boolean](maxKillers)
val killerBulletDirX = new Array[Double](maxKillers)
val killerBulletDirY = new Array[Double](maxKillers)

for (i <- 0 until maxKillers) {
  val kBody = Picture.rectangle(18, 30)
  kBody.setFillColor(ColorMaker.red)
  kBody.invisible()
  draw(kBody)
  killerBodies(i) = kBody

  val kHead = Picture.circle(8)
  kHead.setFillColor(ColorMaker.orange)
  kHead.invisible()
  draw(kHead)
  killerHeads(i) = kHead

  val kB = Picture.rectangle(10, 4)
  kB.setFillColor(ColorMaker.yellow)
  kB.invisible()
  draw(kB)
  killerBullets(i) = kB
  killerBulletActive(i) = false
  killerBulletDirX(i) = 0.0
  killerBulletDirY(i) = 0.0
}

def setupLevel(level: Int) {
  currentLevel = level
  for (i <- 0 until maxKillers) {
    killerBodies(i).invisible()
    killerHeads(i).invisible()
    killerBullets(i).invisible()
    killerBulletActive(i) = false
  }
  
  if (level == 1) {
    killersLeft = 3
    for (i <- 0 until 3) {
      killerBodies(i).setPosition(cb.x + 600 + (i * 70), cb.y + 100 + (i * 60))
      killerHeads(i).setPosition(cb.x + 600 + (i * 70), cb.y + 135 + (i * 60))
      killerBodies(i).visible()
      killerHeads(i).visible()
    }
    showMsg("Level 1 Started: 3 Killers! They will shoot at you! Arrow Keys: Move | Z: Shoot")
  } else if (level == 2) {
    killersLeft = 5
    for (i <- 0 until 5) {
      killerBodies(i).setPosition(cb.x + 500 + ((i % 3) * 80), cb.y + 50 + (i * 50))
      killerHeads(i).setPosition(cb.x + 500 + ((i % 3) * 80), cb.y + 85 + (i * 50))
      killerBodies(i).visible()
      killerHeads(i).visible()
    }
    showMsg("Level 2 Started: 5 Killers! Arrow Keys: Move | Z: Shoot")
  } else if (level == 3) {
    killersLeft = 10
    for (i <- 0 until 10) {
      killerBodies(i).setPosition(cb.x + 400 + ((i % 5) * 70), cb.y + 20 + ((i / 5) * 80))
      killerHeads(i).setPosition(cb.x + 400 + ((i % 5) * 70), cb.y + 55 + ((i / 5) * 80))
      killerBodies(i).visible()
      killerHeads(i).visible()
    }
    showMsg("Level 3 Started: 10 Killers! Arrow Keys: Move | Z: Shoot")
  }
}

// ?. ???????? ???? (Z Key)
val bullet = Picture.rectangle(15, 6)
bullet.setFillColor(ColorMaker.white)
bullet.invisible()
draw(bullet)

var bulletActive = false
var bulletDir = 1

// ????????? ??????
var infoText: Picture = null
def showMsg(msg: String) {
  if (infoText != null) {
    infoText.erase()
  }
  infoText = Picture {
    setPenFontSize(18)
    setPenColor(ColorMaker.yellow)
    write(msg)
  }
  infoText.setPosition(cb.x + 50, cb.y + 530)
  draw(infoText)
}

showMsg("PRESS 1 for Level 1 | PRESS 2 for Level 2 | PRESS 3 for Level 3")

var frameCount = 0

// ?. ??? ???
drawLoop {
  frameCount += 1
  if (currentLevel == 0) {
    if (isKeyPressed(Kc.VK_1)) setupLevel(1)
    if (isKeyPressed(Kc.VK_2)) setupLevel(2)
    if (isKeyPressed(Kc.VK_3)) setupLevel(3)
  } else {
    // ?????? ?????
    val speed = 4.0
    var dx = 0.0
    var dy = 0.0

    if (isKeyPressed(Kc.VK_UP)) dy = speed
    if (isKeyPressed(Kc.VK_DOWN)) dy = -speed
    
    if (isKeyPressed(Kc.VK_LEFT)) {
      dx = -speed
      if (facingRight) {
        pHead.translate(-18, 0)
        pGun.translate(-34, 0)
        facingRight = false
      }
    }
    
    if (isKeyPressed(Kc.VK_RIGHT)) {
      dx = speed
      if (!facingRight) {
        pHead.translate(18, 0)
        pGun.translate(34, 0)
        facingRight = true
      }
    }

    if (dx != 0 || dy != 0) {
      pBody.translate(dx, dy)
      pHead.translate(dx, dy)
      pLeg1.translate(dx, dy)
      pLeg2.translate(dx, dy)
      pGun.translate(dx, dy)
    }

    // Z ?? ????????? ???????? ???? ??????
    if (isKeyPressed(Kc.VK_Z) && !bulletActive) {
      bulletActive = true
      if (facingRight) {
        bullet.setPosition(pGun.position.x + 16, pGun.position.y)
        bulletDir = 1
      } else {
        bullet.setPosition(pGun.position.x - 16, pGun.position.y)
        bulletDir = -1
      }
      bullet.visible()
    }

    if (bulletActive) {
      bullet.translate(20 * bulletDir, 0)
      
      for (i <- 0 until maxKillers) {
        if (killerBodies(i).isVisible && bullet.collidesWith(killerBodies(i))) {
          killerBodies(i).invisible()
          killerHeads(i).invisible()
          killerBullets(i).invisible()
          killerBulletActive(i) = false
          bullet.invisible()
          bulletActive = false
          killersLeft -= 1
          
          if (killersLeft > 0) {
            showMsg(s"Hit! Killers left in Level $currentLevel: $killersLeft")
          } else {
            showMsg(s"Level $currentLevel Cleared! Press 1, 2 or 3 to play again.")
            currentLevel = 0
          }
        }
      }

      if (bullet.position.x > cb.x + 1500 || bullet.position.x < cb.x - 1000) {
        bullet.invisible()
        bulletActive = false
      }
    }

    // ?. ?????? ?????? ??? ?????? ???? ????? (AI Chasing & Shooting)
    val kSpeed = 0.35
    for (i <- 0 until maxKillers) {
      if (killerBodies(i).isVisible) {
        val kx = killerBodies(i).position.x
        val ky = killerBodies(i).position.y
        val px = pBody.position.x
        val py = pBody.position.y

        // ?????? ????
        if (kx < px) killerBodies(i).translate(kSpeed, 0) else killerBodies(i).translate(-kSpeed, 0)
        if (ky < py) killerBodies(i).translate(0, kSpeed) else killerBodies(i).translate(0, -kSpeed)
        
        killerHeads(i).setPosition(killerBodies(i).position.x, killerBodies(i).position.y + 35)

        // ?????? ?????????? ?????? ???? ????? (?????? ???????)
        if (!killerBulletActive(i) && frameCount % 120 == 0) {
          killerBullets(i).setPosition(kx, ky + 15)
          killerBullets(i).visible()
          killerBulletActive(i) = true
          
          val angle = math.atan2(py - ky, px - kx)
          killerBulletDirX(i) = math.cos(angle) * 6.0
          killerBulletDirY(i) = math.sin(angle) * 6.0
        }

        // ???????? ?????? ??????
        if (killerBulletActive(i)) {
          killerBullets(i).translate(killerBulletDirX(i), killerBulletDirY(i))

          // ?? ?????? ???? ???????? ?????
          if (killerBullets(i).collidesWith(pBody)) {
            showMsg(s"Ouch! Hit by killer bullet! Killers left: $killersLeft")
            killerBullets(i).invisible()
            killerBulletActive(i) = false
          }

          val kbPos = killerBullets(i).position
          if (kbPos.x > cb.x + 1500 || kbPos.x < cb.x - 1000 || kbPos.y > cb.y + 1500 || kbPos.y < cb.y - 1000) {
            killerBullets(i).invisible()
            killerBulletActive(i) = false
          }
        }

        if (killerBodies(i).collidesWith(pBody)) {
          showMsg(s"Warning! Killer touched you! Killers left: $killersLeft")
        }
      }
    }
  }
}