Galga 우주 슈팅 게임
🎯 학습 목표:
- 캐릭터를 생성하고 컨트롤러로 조종합니다.
- 일정한 시간마다 적을 생성하고 랜덤한 위치에서 나타나게 합니다.
- 발사체(총알)를 만들어 적을 공격하고 점수를 얻습니다.
1
우주선 출격 준비!
먼저 우리가 조종할 멋진 우주 비행기를 만들어 봅시다.
||sprites:스프라이트||카테고리에서||variables(sprites):[mySprite]를 스프라이트는 []로, 종류는 [player]로 설정||블록을 가져옵니다.- 변수 이름을 spacePlane(우주선)으로 바꾸고 비행기를 그립니다.
||controller:컨트롤러||의||controller:[mySprite]를 버튼으로 이동||블록을 연결하고, ⊕를 눌러 속도(vx, vy)를 200으로 빠르게 설정하세요.- 비행기가 화면 밖으로 도망가지 못하도록
||sprites:[mySprite]를 화면에 머무르기||를 <켬>으로 설정합니다. - 마지막으로
||info:정보||에서||info:생명치 정하기 [3]||을 추가해 생명을 3개로 만듭니다.
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
공격! 총알 발사하기
적을 물리치려면 무기가 필요하겠죠?
||controller:컨트롤러||에서||controller:[A] 버튼을 [누를 때]||블록을 빈 공간에 꺼냅니다.- 그 안에
||sprites:스프라이트||카테고리의||variables(sprites):[projectile]를 발사체로...||블록을 넣습니다. - 총알 이미지를 그리고, vx는 200, vy는 0으로 설정하여 총알이 앞으로 빠르게 날아가게 합니다.
🚀 발사체(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
적의 습격 (생성 및 이동)
이제 적들이 몰려오게 만들어봅시다.
||game:게임||카테고리의||game:게임 업데이트시 [500] ms 마다||블록을 가져와 시간을 1000ms(1초)로 늘려줍니다.- 새로운 스프라이트를 만들고 변수 이름을 bogey(적), 종류를 Enemy로 설정하세요.
||sprites:[bogey] 속도 설정||블록으로 vx -100, vy 0을 주어 왼쪽으로 날아오게 합니다.- 매번 다른 위치에서 나타나도록
||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
적 격추하기 (충돌 처리)
우리가 쏜 총알이 적에게 맞았을 때 적을 파괴해야 합니다.
||sprites:스프라이트||카테고리에서||sprites:... [sprite]가 ... [otherSprite]와 닿았을 때||블록을 빈 공간에 꺼내세요.- 스프라이트 종류를 각각 Projectile(발사체)과 Enemy(적)로 변경합니다.
- 이제 빈 ~닿았을 때 컨테이너 안에
||sprites:mySprite 파괴||블록을 끌어 넣으세요. - 중요: 닿았을 때 블록의 헤더(제목 부분)에 있는 빨간색
||variables(noclick):otherSprite||값을 드래그해서, 파괴 블록의 mySprite 자리에 끼워 넣으세요. (즉, 닿은 대상인 적을 파괴한다는 뜻입니다) - 파괴 블록 오른쪽의 ⊕를 클릭하고 화염(fire) 효과를 선택해 멋지게 터뜨려보세요.
- 마지막으로
||info:점수 변화 값 [1]||블록을 추가해 점수를 얻게 합니다.
sprites.onOverlap(SpriteKind.Projectile, SpriteKind.Enemy, function (sprite, otherSprite) {
// @highlight
otherSprite.destroy(effects.fire, 500)
info.changeScoreBy(1)
})
5
충돌과 게임 오버
만약 적이 우리 비행기와 부딪히면 어떻게 될까요?
- 새로운
||sprites:... 닿았을 때||블록을 추가하고, 이번엔 Player(플레이어)와 Enemy(적)로 설정합니다. - 위와 마찬가지로 헤더의 otherSprite를 드래그하여,
||sprites:[otherSprite] 파괴||블록을 만듭니다. (부딪힌 적을 없앱니다) - 충격 효과를 위해
||scene:카메라 흔들기||블록을 추가합니다. ||info:생명치 변화 값 [-1]||로 생명을 하나 줄입니다. 생명이 0이 되면 게임 오버가 됩니다.
sprites.onOverlap(SpriteKind.Player, SpriteKind.Enemy, function (sprite, otherSprite) {
otherSprite.destroy()
scene.cameraShake(4, 500)
info.changeLifeBy(-1)
})
🎉
완성!
축하합니다! Galga 게임을 완성했습니다.
이제 시뮬레이터에서 A 버튼(키보드 Z 또는 스페이스바)을 눌러 적들을 무찌르세요!
아래는 전체 완성 코드입니다.
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)
})