아케이드 티딩 가이드 목록으로
🚀 직접 따라해보기

프리 드로우

💡 참고: 이 가이드는 메이크코드 아케이드 튜토리얼 Basketball Free Throw를 바탕으로 제작되었습니다.

🎯 학습 목표:

  • 배경(Background)을 설정하여 농구 코트를 만듭니다.
  • 스프라이트(Sprite)를 생성하고 속도와 위치를 설정합니다.
  • 발사체(Projectile)를 이용하여 공을 던지는 기능을 구현합니다.
  • 겹침(Overlap) 이벤트를 통해 골인 여부를 판단하고 점수를 얻습니다.
1

농구 코트 준비하기

게임을 시작하기 위해 농구 코트 배경을 깔아봅시다.

  1. ||scene:장면|| 카테고리에서 ||scene:배경 이미지 설정|| 블록을 가져와 ||loops:시작하면|| 안에 넣습니다.
  2. 회색 상자를 클릭하여 농구 코트를 그리거나 갤러리에서 선택하세요.
Game Intro
// @highlight
scene.setBackgroundImage(img`.`)
2

선수 입장 (Athlete)

공을 던질 선수를 만들어 위치를 잡아줍니다.


||sprites:스프라이트||에서 ||variables(sprites):[athlete]를 스프라이트 설정|| 블록을 가져옵니다. (변수 이름을 athlete로 바꿔주세요)

► 선수가 코트 위를 움직이도록 ||sprites:[athlete] 위치 설정|| (x: 80, y: 90)과 ||sprites:[athlete] 속도 설정|| (vx: 50, vy: 0)을 추가합니다.

||sprites:[athlete] 벽에 닿으면 튕기기||<켬>으로 설정하여 화면 밖으로 나가지 않게 하세요.

scene.setBackgroundImage(img`.`)
// @highlight
let athlete = sprites.create(img`
    . . f f . . . . . . . .
    . f f f f . . . . . . .
    . f f f f f f . . . . .
    . f 6 6 6 6 6 6 . . . .
    . . f f a a a a . . . .
    . . f f a f a f . . . .
    . . f a a a a a . . . .
    . . . a a a a a . . . .
    . . . . a a a . . . . .
    . a a 1 a a 1 a 4 4 4 a
    . a a 1 6 6 1 4 f 4 f 4
    . a a a 6 6 6 a a f 4 4
    . a a a 6 6 a a a 4 f 4
    . . a a a a a 6 4 4 4 .
    . . 6 a a a 6 6 . . . .
    . . 1 1 1 1 1 1 . . . .
    . . 6 6 6 8 6 6 . . . .
    . . 6 6 6 8 6 6 . . . .
    . . 6 6 6 8 6 6 . . . .
    . . a a . . a a . . . .
    . . a a . . a a . . . .
    . . 6 1 . . 6 1 . . . .
    . . 1 1 1 . 1 1 1 . . .
    . . . . . . . . . . . .
`, SpriteKind.Player)
// @highlight
athlete.setPosition(80, 90)
// @highlight
athlete.setVelocity(50, 0)
// @highlight
athlete.setBounceOnWall(true)
3

골대 설치 (Hoop)

공을 넣을 골대를 만들어 봅시다.


||sprites:스프라이트|| 생성 블록을 하나 더 추가하고 변수 이름을 hoop으로 변경합니다.

중요: 종류(Kind)를 Enemy로 설정해야 합니다. (Goal과 같은 새로운 종류를 만들어도 됩니다.

► 골대의 위치를 x: 80, y: 35로 설정하여 화면 상단에 배치합니다.

let athlete = sprites.create(img`
    . . f f . . . . . . . .
    . f f f f . . . . . . .
    . f f f f f f . . . . .
    . f 6 6 6 6 6 6 . . . .
    . . f f a a a a . . . .
    . . f f a f a f . . . .
    . . f a a a a a . . . .
    . . . a a a a a . . . .
    . . . . a a a . . . . .
    . a a 1 a a 1 a 4 4 4 a
    . a a 1 6 6 1 4 f 4 f 4
    . a a a 6 6 6 a a f 4 4
    . a a a 6 6 a a a 4 f 4
    . . a a a a a 6 4 4 4 .
    . . 6 a a a 6 6 . . . .
    . . 1 1 1 1 1 1 . . . .
    . . 6 6 6 8 6 6 . . . .
    . . 6 6 6 8 6 6 . . . .
    . . 6 6 6 8 6 6 . . . .
    . . a a . . a a . . . .
    . . a a . . a a . . . .
    . . 6 1 . . 6 1 . . . .
    . . 1 1 1 . 1 1 1 . . .
    . . . . . . . . . . . .
`, SpriteKind.Player)
athlete.setPosition(80, 90)
athlete.setVelocity(50, 0)
athlete.setBounceOnWall(true)

// @highlight
let hoop = sprites.create(img`
    . . 3 3 4 4 4 4 4 4 4 3 3 . . .
    . 3 4 4 1 1 . . . 1 1 4 4 3 . .
    3 4 4 . 1 . 1 . 1 . 1 . 4 4 3 .
    3 4 1 . 1 . . 1 . . 1 . 1 4 3 .
    4 3 4 1 1 . 1 . 1 . 1 1 4 3 4 .
    1 4 3 3 1 1 . . . 1 1 3 3 4 1 .
    1 1 4 4 3 3 3 3 3 3 3 4 4 1 1 .
    1 . 1 . 4 4 4 4 4 4 4 . 1 . 1 .
    1 . . 1 1 . 1 . 1 . 1 1 . . 1 .
    1 . 1 . 1 1 . . . 1 1 . 1 . 1 .
    1 1 . . 1 . 1 . 1 . 1 . . 1 1 .
    1 . 1 . 1 . . 1 . . 1 . 1 . 1 .
    1 . . 1 1 . 1 . 1 . 1 1 . . 1 .
    . . . . 1 1 . . . 1 1 . . . . .
    . . . . 1 . 1 . 1 . 1 . . . . .
    . . . . 1 . . 1 . . 1 . . . . .
    . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . .
`, SpriteKind.Enemy)
// @highlight
hoop.setPosition(80, 35)
4

제한 시간 설정

긴장감을 더하기 위해 제한 시간을 둡니다.


||info:정보|| 카테고리의 ||info:카운트다운 시작 [10] (s)|| 블록을 시작하면 블록의 맨 마지막에 넣고, 시간을 30초로 변경합니다.

// (이전 코드 생략 없이 전체 포함)
scene.setBackgroundImage(img`.`)
let athlete = sprites.create(img`
    . . f f . . . . . . . .
    . f f f f . . . . . . .
    . f f f f f f . . . . .
    . f 6 6 6 6 6 6 . . . .
    . . f f a a a a . . . .
    . . f f a f a f . . . .
    . . f a a a a a . . . .
    . . . a a a a a . . . .
    . . . . a a a . . . . .
    . a a 1 a a 1 a 4 4 4 a
    . a a 1 6 6 1 4 f 4 f 4
    . a a a 6 6 6 a a f 4 4
    . a a a 6 6 a a a 4 f 4
    . . a a a a a 6 4 4 4 .
    . . 6 a a a 6 6 . . . .
    . . 1 1 1 1 1 1 . . . .
    . . 6 6 6 8 6 6 . . . .
    . . 6 6 6 8 6 6 . . . .
    . . 6 6 6 8 6 6 . . . .
    . . a a . . a a . . . .
    . . a a . . a a . . . .
    . . 6 1 . . 6 1 . . . .
    . . 1 1 1 . 1 1 1 . . .
    . . . . . . . . . . . .
`, SpriteKind.Player)
athlete.setPosition(80, 90)
athlete.setVelocity(50, 0)
athlete.setBounceOnWall(true)
let hoop = sprites.create(img`
    . . 3 3 4 4 4 4 4 4 4 3 3 . . .
    . 3 4 4 1 1 . . . 1 1 4 4 3 . .
    3 4 4 . 1 . 1 . 1 . 1 . 4 4 3 .
    3 4 1 . 1 . . 1 . . 1 . 1 4 3 .
    4 3 4 1 1 . 1 . 1 . 1 1 4 3 4 .
    1 4 3 3 1 1 . . . 1 1 3 3 4 1 .
    1 1 4 4 3 3 3 3 3 3 3 4 4 1 1 .
    1 . 1 . 4 4 4 4 4 4 4 . 1 . 1 .
    1 . . 1 1 . 1 . 1 . 1 1 . . 1 .
    1 . 1 . 1 1 . . . 1 1 . 1 . 1 .
    1 1 . . 1 . 1 . 1 . 1 . . 1 1 .
    1 . 1 . 1 . . 1 . . 1 . 1 . 1 .
    1 . . 1 1 . 1 . 1 . 1 1 . . 1 .
    . . . . 1 1 . . . 1 1 . . . . .
    . . . . 1 . 1 . 1 . 1 . . . . .
    . . . . 1 . . 1 . . 1 . . . . .
    . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . .
`, SpriteKind.Enemy)
hoop.setPosition(80, 35)
// @highlight
info.startCountdown(30)
5

슛! (공 던지기)

A 버튼을 누르면 선수가 농구공을 던지게 해봅시다.


||controller:컨트롤러||에서 ||controller:[A] 버튼을 [누를 때]|| 블록을 가져옵니다.

► 그 안에 ||sprites:[projectile]을 [athlete]에서 발사하는 발사체로 설정|| 블록을 넣습니다.

► 공 이미지를 그리고, 위쪽으로 날아가도록 vy-100으로 설정합니다. (vx는 0)

let athlete: Sprite = null
let projectile: Sprite = null
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
    // @highlight
    projectile = sprites.createProjectileFromSprite(img`
        . . 4 4 4 . .
        . f 4 4 4 f .
        4 4 f 4 f 4 4
        f f f f f f f
        4 4 f 4 f 4 4
        . f 4 4 4 f .
        . . 4 4 4 . .
    `, athlete, 0, -100)
})
6

골인! (점수 획득)

공이 골대에 들어가면 점수를 얻어야겠죠?


||sprites:스프라이트||에서 ||sprites:스프라이트 종류가 [Projectile]인 ... [Enemy]과 닿았을 때|| 블록을 가져옵니다. (두 번째 종류를 Enemy로 꼭 바꿔주세요)

► 닿았을 때 ||info:점수 1 증가||시키고, 골대에 들어간 공(sprite)은 ||sprites:파괴||하여 사라지게 합니다.

sprites.onOverlap(SpriteKind.Projectile, SpriteKind.Enemy, function (sprite, otherSprite) {
    // @highlight
    info.changeScoreBy(1)
    // @highlight
    sprite.destroy()
})
7

게임 종료

시간이 다 되었을 때 게임을 끝내는 규칙을 확인합니다.


||info:정보|| 카테고리의 ||info:카운트다운이 종료되면|| 블록을 사용합니다.

► 그 안에 ||game:게임 종료 <승리>|| 블록을 넣어 게임을 마무리합니다.

info.onCountdownEnd(function () {
    // @highlight
    game.gameOver(true)
})
🎉

완성!

축하합니다! 프리 드로우 게임이 완성되었습니다.

30초 안에 몇 점이나 넣을 수 있는지 도전해보세요!

아래는 완성된 전체 블록 코드입니다.

Final Game
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
    projectile = sprites.createProjectileFromSprite(img`
        . . 4 4 4 . .
        . f 4 4 4 f .
        4 4 f 4 f 4 4
        f f f f f f f
        4 4 f 4 f 4 4
        . f 4 4 4 f .
        . . 4 4 4 . .
    `, athlete, 0, -100)
})
sprites.onOverlap(SpriteKind.Projectile, SpriteKind.Enemy, function (sprite, otherSprite) {
    info.changeScoreBy(1)
    sprite.destroy()
})
info.onCountdownEnd(function () {
    game.gameOver(true)
})
let projectile: Sprite = null
let athlete: Sprite = null
scene.setBackgroundImage(img`.`)
athlete = sprites.create(img`
    . . f f . . . . . . . .
    . f f f f . . . . . . .
    . f f f f f f . . . . .
    . f 6 6 6 6 6 6 . . . .
    . . f f a a a a . . . .
    . . f f a f a f . . . .
    . . f a a a a a . . . .
    . . . a a a a a . . . .
    . . . . a a a . . . . .
    . a a 1 a a 1 a 4 4 4 a
    . a a 1 6 6 1 4 f 4 f 4
    . a a a 6 6 6 a a f 4 4
    . a a a 6 6 a a a 4 f 4
    . . a a a a a 6 4 4 4 .
    . . 6 a a a 6 6 . . . .
    . . 1 1 1 1 1 1 . . . .
    . . 6 6 6 8 6 6 . . . .
    . . 6 6 6 8 6 6 . . . .
    . . 6 6 6 8 6 6 . . . .
    . . a a . . a a . . . .
    . . a a . . a a . . . .
    . . 6 1 . . 6 1 . . . .
    . . 1 1 1 . 1 1 1 . . .
    . . . . . . . . . . . .
`, SpriteKind.Player)
athlete.setPosition(80, 90)
athlete.setVelocity(50, 0)
athlete.setBounceOnWall(true)
let hoop = sprites.create(img`
    . . 3 3 4 4 4 4 4 4 4 3 3 . . .
    . 3 4 4 1 1 . . . 1 1 4 4 3 . .
    3 4 4 . 1 . 1 . 1 . 1 . 4 4 3 .
    3 4 1 . 1 . . 1 . . 1 . 1 4 3 .
    4 3 4 1 1 . 1 . 1 . 1 1 4 3 4 .
    1 4 3 3 1 1 . . . 1 1 3 3 4 1 .
    1 1 4 4 3 3 3 3 3 3 3 4 4 1 1 .
    1 . 1 . 4 4 4 4 4 4 4 . 1 . 1 .
    1 . . 1 1 . 1 . 1 . 1 1 . . 1 .
    1 . 1 . 1 1 . . . 1 1 . 1 . 1 .
    1 1 . . 1 . 1 . 1 . 1 . . 1 1 .
    1 . 1 . 1 . . 1 . . 1 . 1 . 1 .
    1 . . 1 1 . 1 . 1 . 1 1 . . 1 .
    . . . . 1 1 . . . 1 1 . . . . .
    . . . . 1 . 1 . 1 . 1 . . . . .
    . . . . 1 . . 1 . . 1 . . . . .
    . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . .
`, SpriteKind.Enemy)
hoop.setPosition(80, 35)
info.startCountdown(30)