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

Galga 우주 슈팅 게임

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

🎯 학습 목표:

  • 캐릭터를 생성하고 컨트롤러로 조종합니다.
  • 일정한 시간마다 적을 생성하고 랜덤한 위치에서 나타나게 합니다.
  • 발사체(총알)를 만들어 적을 공격하고 점수를 얻습니다.
1

우주선 출격 준비!

먼저 우리가 조종할 멋진 우주 비행기를 만들어 봅시다.

  1. ||sprites:스프라이트|| 카테고리에서 ||variables(sprites):[mySprite]를 스프라이트는 []로, 종류는 [player]로 설정|| 블록을 가져옵니다.
  2. 변수 이름을 spacePlane(우주선)으로 바꾸고 비행기를 그립니다.
  3. ||controller:컨트롤러||||controller:[mySprite]를 버튼으로 이동|| 블록을 연결하고, 를 눌러 속도(vx, vy)를 200으로 빠르게 설정하세요.
  4. 비행기가 화면 밖으로 도망가지 못하도록 ||sprites:[mySprite]를 화면에 머무르기||<켬>으로 설정합니다.
  5. 마지막으로 ||info:정보||에서 ||info:생명치 정하기 [3]||을 추가해 생명을 3개로 만듭니다.
Game animation
let spacePlane = sprites.create(img`
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . 8 2 . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . 1 1 1 . . . . . 9 9 9 9 9 . . . . . . . . . . . . . . .
    . . . . 2 2 2 2 . . . 9 9 9 9 9 9 9 . . . . . . . . . . . . . .
    . 4 4 4 f 8 6 6 6 6 6 6 9 9 9 9 9 6 6 6 . . . . . . . . . . . .
    4 4 4 f 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 . . . . . . . . .
    . 4 4 f 6 8 8 8 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 . . . . . . . .
    . . 4 4 f 8 8 . . . . . 8 8 8 8 6 6 6 6 6 6 6 . . . . . . . . .
    . . . . . . . . . . . 8 8 8 8 8 8 2 . . . . . . . . . . . . . .
    . . . . . . . . . . . 8 8 8 8 8 2 . . . . . . . . . . . . . . .
    . . . . . . . . . . 8 8 8 8 8 2 . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
`, SpriteKind.Player)
controller.moveSprite(spacePlane, 200, 200)
spacePlane.setStayInScreen(true)
info.setLife(3)
2

공격! 총알 발사하기

적을 물리치려면 무기가 필요하겠죠?

  1. ||controller:컨트롤러||에서 ||controller:[A] 버튼을 [누를 때]|| 블록을 빈 공간에 꺼냅니다.
  2. 그 안에 ||sprites:스프라이트|| 카테고리의 ||variables(sprites):[projectile]를 발사체로...|| 블록을 넣습니다.
  3. 총알 이미지를 그리고, vx200, vy0으로 설정하여 총알이 앞으로 빠르게 날아가게 합니다.
🚀 발사체(Projectile)란?
특정 위치에서 시작해 일정한 속도로 날아가는 스프라이트입니다. 화면 밖으로 나가면 자동으로 사라져 게임 성능을 지켜줍니다.
let spacePlane: Sprite = null
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
    let projectile = sprites.createProjectileFromSprite(img`
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . 5 a a 2 . . . . . . . . .
        . . 5 5 a 2 2 2 2 4 4 4 . . . .
        . . . 5 a a 2 . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
    `, spacePlane, 200, 0)
})
3

적의 습격 (생성 및 이동)

이제 적들이 몰려오게 만들어봅시다.

  1. ||game:게임|| 카테고리의 ||game:게임 업데이트시 [500] ms 마다|| 블록을 가져와 시간을 1000ms(1초)로 늘려줍니다.
  2. 새로운 스프라이트를 만들고 변수 이름을 bogey(적), 종류를 Enemy로 설정하세요.
  3. ||sprites:[bogey] 속도 설정|| 블록으로 vx -100, vy 0을 주어 왼쪽으로 날아오게 합니다.
  4. 매번 다른 위치에서 나타나도록 ||sprites:[bogey] 위치 설정|| 블록을 사용합니다. X는 160, Y는 ||math:[0]부터 [10]까지의 정수 랜덤값|| 블록을 넣어 5~115 사이로 설정합니다.
💡 팁: ||sprites:[bogey]의 [자동 파괴]를 <켬>|| 블록을 마지막에 추가하면, 우리를 지나친 적이 메모리에서 삭제되어 게임이 느려지는 것을 방지합니다.
game.onUpdateInterval(1000, function () {
    let bogey = sprites.create(img`
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . 9 9 . . . . . 5 . . . .
        . . . 9 9 9 9 . . . 5 5 . . . .
        2 2 2 2 9 9 2 2 2 2 2 f 4 4 . .
        . . 2 2 2 2 5 5 5 2 2 f 4 4 4 .
        . . . . . . 5 5 5 . . . . . . .
        . . . . . . . 5 5 . . . . . . .
        . . . . . . . . 5 . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
    `, SpriteKind.Enemy)
    bogey.setVelocity(-100, 0)
    bogey.setPosition(160, randint(5, 115))
    bogey.setFlag(SpriteFlag.AutoDestroy, true)
})
4

적 격추하기 (충돌 처리)

우리가 쏜 총알이 적에게 맞았을 때 적을 파괴해야 합니다.

  1. ||sprites:스프라이트|| 카테고리에서 ||sprites:... [sprite]가 ... [otherSprite]와 닿았을 때|| 블록을 빈 공간에 꺼내세요.
  2. 스프라이트 종류를 각각 Projectile(발사체)Enemy(적)로 변경합니다.
  3. 이제 빈 ~닿았을 때 컨테이너 안에 ||sprites:mySprite 파괴|| 블록을 끌어 넣으세요.
  4. 중요: 닿았을 때 블록의 헤더(제목 부분)에 있는 빨간색 ||variables(noclick):otherSprite|| 값을 드래그해서, 파괴 블록의 mySprite 자리에 끼워 넣으세요. (즉, 닿은 대상인 적을 파괴한다는 뜻입니다)
  5. 파괴 블록 오른쪽의 를 클릭하고 화염(fire) 효과를 선택해 멋지게 터뜨려보세요.
  6. 마지막으로 ||info:점수 변화 값 [1]|| 블록을 추가해 점수를 얻게 합니다.
sprites.onOverlap(SpriteKind.Projectile, SpriteKind.Enemy, function (sprite, otherSprite) {
    // @highlight
    otherSprite.destroy(effects.fire, 500)
    info.changeScoreBy(1)
})
5

충돌과 게임 오버

만약 적이 우리 비행기와 부딪히면 어떻게 될까요?

  1. 새로운 ||sprites:... 닿았을 때|| 블록을 추가하고, 이번엔 Player(플레이어)Enemy(적)로 설정합니다.
  2. 위와 마찬가지로 헤더의 otherSprite를 드래그하여, ||sprites:[otherSprite] 파괴|| 블록을 만듭니다. (부딪힌 적을 없앱니다)
  3. 충격 효과를 위해 ||scene:카메라 흔들기|| 블록을 추가합니다.
  4. ||info:생명치 변화 값 [-1]||로 생명을 하나 줄입니다. 생명이 0이 되면 게임 오버가 됩니다.
sprites.onOverlap(SpriteKind.Player, SpriteKind.Enemy, function (sprite, otherSprite) {
    otherSprite.destroy()
    scene.cameraShake(4, 500)
    info.changeLifeBy(-1)
})
🎉

완성!

축하합니다! Galga 게임을 완성했습니다.

이제 시뮬레이터에서 A 버튼(키보드 Z 또는 스페이스바)을 눌러 적들을 무찌르세요!

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

Game animation
let bogey: Sprite = null
let projectile: Sprite = null
let spacePlane: Sprite = null
sprites.onOverlap(SpriteKind.Player, SpriteKind.Enemy, function (sprite, otherSprite) {
    otherSprite.destroy()
    scene.cameraShake(4, 500)
    info.changeLifeBy(-1)
})
sprites.onOverlap(SpriteKind.Projectile, SpriteKind.Enemy, function (sprite, otherSprite) {
    otherSprite.destroy(effects.fire, 500)
    info.changeScoreBy(1)
})
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
    projectile = sprites.createProjectileFromSprite(img`
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . 5 a a 2 . . . . . . . . .
        . . 5 5 a 2 2 2 2 4 4 4 . . . .
        . . . 5 a a 2 . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
    `, spacePlane, 200, 0)
})
spacePlane = sprites.create(img`
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . 8 2 . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . 1 1 1 . . . . . 9 9 9 9 9 . . . . . . . . . . . . . . .
    . . . . 2 2 2 2 . . . 9 9 9 9 9 9 9 . . . . . . . . . . . . . .
    . 4 4 4 f 8 6 6 6 6 6 6 9 9 9 9 9 6 6 6 . . . . . . . . . . . .
    4 4 4 f 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 . . . . . . . . .
    . 4 4 f 6 8 8 8 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 . . . . . . . .
    . . 4 4 f 8 8 . . . . . 8 8 8 8 6 6 6 6 6 6 6 . . . . . . . . .
    . . . . . . . . . . . 8 8 8 8 8 8 2 . . . . . . . . . . . . . .
    . . . . . . . . . . . 8 8 8 8 8 2 . . . . . . . . . . . . . . .
    . . . . . . . . . . 8 8 8 8 8 2 . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
`, SpriteKind.Player)
controller.moveSprite(spacePlane, 200, 200)
spacePlane.setStayInScreen(true)
info.setLife(3)
game.onUpdateInterval(1000, function () {
    bogey = sprites.create(img`
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . 9 9 . . . . . 5 . . . .
        . . . 9 9 9 9 . . . 5 5 . . . .
        2 2 2 2 9 9 2 2 2 2 2 f 4 4 . .
        . . 2 2 2 2 5 5 5 2 2 f 4 4 4 .
        . . . . . . 5 5 5 . . . . . . .
        . . . . . . . 5 5 . . . . . . .
        . . . . . . . . 5 . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
    `, SpriteKind.Enemy)
    bogey.setVelocity(-100, 0)
    bogey.setPosition(160, randint(5, 115))
    bogey.setFlag(SpriteFlag.AutoDestroy, true)
})