본문 바로가기
앱인벤터/앱인벤터 코딩따라하기

앱인벤터 오마이스파이크 게임 앱-코딩편

by flycoding 2022. 12. 20.
반응형

앱인벤터 오마이스파이크 게임 앱-코딩편

앱인벤터 오마이스파이크 게임 앱의 코딩편이다. 설계편을 읽지 않았다면, 아래 글을 꼭 읽기를 추천한다.

 

앱인벤터 오마이스파이크 앱-설계편

 

앱인벤터 오마이스파이크 앱-설계편

앱인벤터 오마이스파이크 앱-설계편 앱인벤터 홈페이지에 나와 있는 튜터리얼을 참고해서 작성한 것이다. 튜터리얼의 목적은 앱인벤터의 많은 블록은 이해하고 활용할 수 있도록 도와주는 프

flycoding.tistory.com

 

코딩블럭

블록 코딩은 내가 하고자 하는 내용을 문장으로 만들어 보라. 그것을 그대로 코딩하면 된다.

 

우리가 무엇을 할 것인지 생각해보라. 간단하다.

먼저 변수 및 프로그램 환경에 대해 초기화를 한다.

아래 전역변수와 초기화 절차를 보자...

꼭 변수의 사용 용도와 의미를 잘살펴두자.

코딩할 때, 가장 많이 사용되고 이유를 알아야 하니까 말이다.

 

. 전역변수

DB_SCORE_TAG : BEST_SCORE

. TinyDB에 저장하고 읽기 위해 TAG값을 위해 사용한다.

 

STATE_MENU : 0, STATE_READY : 1, STATE_GAME : 2

. 게임 상태를 나타낸다.

. 사용자가 메뉴 스크린 상에 있으면 state변수에 STATE_MENU, 게임이 준비가 되면 STATE_READY, 그리고 사용자가 게임중이면 STATE_GAME 상태값을 갖는다.

. 상기 변수는 대문자로 constant변수이다.('값이 변하지 않는다'는 의미이다.)

 

state : 0

. 현재 사용자의 상태를 저장하는 변수이다.

. 값으로는 위에 STATE_MENU, STATE_READY, STATE_GAME 값을 갖는다.

 

isFalling : False

. 사용자가 스크린을 터치하지 않으면 새는 아래로 떨어지기 시작한다.

. 떨어지기 시작하면 값은 true값이 된다.

 

score : 0

. 현재 게임의 점수를 저장하는 변수이다.

 

bestScore : 0

. 사용자의 최고 점수를 기록하는 변수이다.

 

HeadingLeft : False

. x축 상에서 새의 방향으로 왼쪽 혹은 오른쪽인지를 저장한다.

 

temp : true

. 임시 변수이다.

 

isOnLeft : False

. 장애물이나 스파이크가 캔버스 상에 왼쪽에 있으면 true이고 아니면 false값이다ㅣ.

 

SPKES_Y_POS

. 이 변수는 리스트들의 리스트가 포함된다. 

.  우리는 새의 방향에 따라 양쪽에 배치된 4개의 이미지 스프라이트(장애물 스파이크)를 가지고 있다. 스파이크를 왼쪽에 배치하려면 0을 x로 사용할 수 있다. 오른쪽에 배치하려면 캔버스의 너비에서 스파이크의 너비를 뺀 값을 x에 사용할 수 있다. 장애물의 x 위치는 왼쪽이나 오른쪽에 있으므로 y축에 대한 값만 있으면 된다.

. 그런 다음 설계 뷰에서 Y 값을 SPICSKES_Y_POS 변수로 복사한다. 장애물 스프라이트가 4개이기 때문에 각 스프라이트에 하나씩 y축에 4개의 값을 선택한다. 이것이 각 목록에 4개의 항목이 포함된 이유이다. 첫 번째는 스프라이트 1, 두 번째는 스프라이트 2 등입이다. 더 추가하거나 랜덤화할 수 있다. 미리 정의된 리스트 대신 빈 리스트를 생성한 다음 나중에 해당 리스트에 항목을 추가할 수 있다. 만약 여러분이 왜 그들 중 일부가 -100을 가지고 있는지 궁금하다면, 그것은 우리가 항상 4개의 장애물 스프라이트를 모두 보여주고 싶지 않기 때문이다. 그래서 우리는 그것들을 스크린에서 내려놓았다. 각 스파이크의 높이는 30픽셀이므로 -30을 사용할 수 있습니다. 어떤 이유에서인지 테스트 중에 Blocks 창에서 더 눈에 잘 띄기 때문에 -100을 선택했다.

 

앱인벤터 오마이스파이크 게임입 변수

 

 

. 초기화

앱인벤터 오마이스파이크 게임 앱이 초기화될 때 아래 블록이 실행이 된다.

. ScoreLabel.보이기여부 : 참
. BridSprite.활성화 : 거짓
. yClock.타이머활성화여부 : 거짓
. MoveClock.타이머활성화여부 : 거짓
. FlapClock.타이머활성화여부 : 거짓
. ContinuousFlapClock.타이머활성화여부 : 거짓
. GameCanvas.높이 : Screen1.높이-30
. bestScore <- socreDB에서 'DB_SCORE_TAG
. if bestScore == 0
    scoreLabel <- "HOW_TO : TAP_TO_ASCEND
    bestScore <- 0
else
    ScoreLabel <- "BEST_SCORE : " + bestScore

SetupHeader() 함수 호출
SetupPlayButton() 함수 호출
SetupGameVisibility <- False
    

 

앱인벤터 오마이스파이크 게임 앱 초기화

 

HeaderSprite의 x,y위치값을 설정하고 보이기 설정한다.

SetupHeader()
. HeaderSprite.X <- screen1.너비/2 - HeaderSprite.너비/2
. HeaderSprite.Y <- HeaderSprite.높이
. HeaderSprite.보이기여부 <- True

앱인벤터 오마이스파이크 게임 앱 SetupHeader() 함수

 

'Play' 버튼의 x,y 위치를 설정한다.

SetupPlayButton()
. PlaySprite.X <- screen1.너비/2 - PlaySprite.너비/2
. PlaySprite.Y <- screen1.너비/2 - PlaySprite.너비/2

앱인벤터 오마이스파이크 게임 앱 SetupPlayButton() 함수

이미지 스프라이트를 보이게 설정한다.

SetupGameVisibility()
. PlaySprite. 보이기여부 <- not(visibility)
. SpikeUp. 보이기여부 <- visibility
. SpikeButton. 보이기여부 <- visibility
. BirdSprite. 보이기여부 <- visibility
. Spike1. 보이기여부 <- visibility
. Spike2. 보이기여부 <- visibility
. Spike3. 보이기여부 <- visibility
. Spike4. 보이기여부 <- visibility

 

앱인벤터 오마이스파이크 게임 앱 SetupGameVisibility() 함수

 

지금까지 변수와 초기화 관련해서 블록 코딩을 하였다.

화면에 'Play'게임을 준비가 되었다.

게임에 들어가는 과정을 블록 코딩할 것이다.

 

첫 단계는 'Start Game'을 위해 'Play' 버튼(실은 이미지 스프라이트)을 터치한다.

 

. PlayTouched

. 사용자가  play 버튼을 탭하였을 때, 먼저 click 소리를 플레이한다.
. ContinuousFlapClock이 시작한다.
. SetupGame 절차를 시작한다.

앱인벤터 오마이스파이크 게임 앱 PlaySprite() 함수

 

게임 진입에 필요한 변수, 레이블 및 캔버스에 이미지 스프라이트를 설정한다.

SetupGame()
. score <- 0
. ScoreLabel.텍스트 <- score
. state <- STATE_READY
. ScoreLabel.보이기여부 <- 참
. HeaderSprite.보이기여부 <- 거짓
. if 임의의정수(1,2) == 1
    isOnLeft <- 참
  else
    is OnLeft <- 거짓
SetupTopBottomSpire()
SetupPlacements()
SetupBirdPosition()
SetupGameVisibility(visibility(참))

 

앱인벤터 오마이스파이크 게임 앱 SetupGame() 함수

 

 

캔버스의 위와 아래의 이미지 스프라이트를 배치한다.
우리는 간단한 중간점 공식을 사용하여 상단 스프라이트와 하단 스프라이트의 X 값을 x축의 중심으로 설정한다.
SpicksUp이 맨 위에 있어야 하므로 Y를 0으로 설정하고 다른 하나의 경우 화면 높이를 설정하여 맨 아래에 표시합니다. 캔버스에서 점(0, 0)은 캔버스 왼쪽 위에 있습니다.


SetupTopBottomSpikes()
SpikesUp.X <- 스크린.너비/2 - SpikesUp.너비/2
SpikesUp.Y <- 0
SpikesBottom.X <- 스크린.너비/2 - SpikesBottom.너비/2
SpikesBottom.Y <- screen1.높이

 

앱인벤터 오마이스파이크 게임 입 SetupTopBottomSpikes() 함수

 

우리는 새의 속도가 5가 되도록 한다.
그런 다음 y축 측면에서 장애물 스파이크 4개를 모두 어디에 배치해야 하는지 결정합니다. SPIKS_Y_POS 변수에 포함된 미리 정의된 위치 목록이 있으므로 목록에서 하나만 선택하면 됩니다. 그래서 우리는 목록의 첫 번째 항목의 색인인 1과 목록의 크기인 10 사이의 숫자를 생성합니다. 우리는 10개의 항목을 가지고 있기 때문에 1과 10 사이의 숫자를 얻을 수 있습니다. 그 후에 우리는 무작위로 얻은 색인에서 목록을 얻습니다.
우리가 캔버스 높이의 20에서 절반 사이의 임의의 숫자를 선택하는 이유는 스파이크를 항상 화면 위에 배치하지 않기 위해서입니다. 이렇게 하면 더 큰 화면에서 항상 화면 하단을 사용할 수 없게 됩니다. 목록 항목을 가져오기 위해 동일한 블록 집합을 여러 번 사용하지 않고 대신 GetList라는 프로시저를 만들었습니다.


이미지 스프라이트의 위치를 정하는 함수이다.
spike1~4의 왼쪽/오른쪽 위치를 정하고 x,y좌표를설정한다.

SetupPlacement()
BirdSpike.속도 <- 5
temp <- 임의의정수(1~SPIKE_Y_POS)
temp2 <- 임의의정수(20~(GameCanvas.높이/2))
spike1.Y <- temp2+GetListItem(temp, 1)
spike2.Y <- temp2+GetListItem(temp, 2)
spike3.Y <- temp2+GetListItem(temp, 3)
spike4.Y <- temp2+GetListItem(temp, 4)

if(isOnLeft==참)
  isOnLeft <- 거짓
  headingLeft <- 거짓
  BirdSprite.방향 <-0
  BirdSprite.사진 <- BirdRightOne.png
  Spike1.X <- GameCanvas.너비 - Spike1.너비 + 1
  Spike2.X <- GameCanvas.너비 - Spike2.너비 + 1
  Spike3.X <- GameCanvas.너비 - Spike3.너비 + 1
  Spike4.X <- GameCanvas.너비 - Spike4.너비 + 1
  Spike1.사진 <- SpikeLeft.png
  Spike2.사진 <- SpikeLeft.png
  Spike3.사진 <- SpikeLeft.png
  Spike4.사진 <- SpikeLeft.png
else
  isOnLeft <- 참
  headingLeft <- 참
  BirdSprite.방향 <-180
  BirdSprite.사진 <- BirdLeftOne.png
  Spike1.X <- -1
  Spike2.X <- -1
  Spike3.X <- -1
  Spike4.X <- -1
  Spike1.사진 <- SpikeRight.png
  Spike2.사진 <- SpikeRight.png
  Spike3.사진 <- SpikeRight.png
  Spike4.사진 <- SpikeRight.png

앱인벤터 오마이스파이크 SetupPlacement() 함수

 

SPIKS_Y_POS는 리스트의 리스트이므로 리스트의 값도 리스트이다. 이제 상위 리스트의 색인 1에 있는 [-100, 140, 210, 365]를 포함하는 리스트를 원한다면  parent 리스트에 인덱스는 1로, 그리고 child 리스트의 인덱스는  3을 지정하면  210이라는 숫자를 얻을 수 있다.
그런 다음 게임 설정 절차에서 결정한 isOnLeft 변수의 값을 사용하여 장애물을 왼쪽에 배치해야 하는지 확인합니다.


이제 왜 isOnLeft의 값을 반대로 다시 변경하는지 궁금할 수 있습니다. 사용자가 게임을 시작할 때 SetupGame이 한 번만 호출되지만 플레이어가 가장자리에서 튕겨나갈 때마다 이 SetupPlacement가 사용되기 때문입니다. 만약 선수가 왼쪽 가장자리에서 튕겨 나간다면, 우리는 장애물을 오른쪽에 놓아야 하고 그 반대도 마찬가지입니다. 그 후에 우리는 또한 x축에서 새의 현재 방향의 반대 방향으로 헤딩을 변경한다. 머리글을 0으로 설정하면 새가 오른쪽으로 이동합니다.

또한 우리는 새의 방향과 일치하는 이미지를 설정합니다. 새가 오른쪽으로 이동해야 한다는 의미로 OnLeft를 false로 설정했기 때문에 새의 X를 오른쪽 가장자리(캔버스 너비)에서 너비를 뺀 값으로 설정합니다. 우리는 추가 픽셀(+1)을 넣었습니다. 왜냐하면 저는 그런 식으로 외관이 더 낫다고 생각하기 때문입니다. 당신은 그것을 추가할 필요가 없습니다.

GetListItem(parentIndex, childIndex)
select list item(select list item list(SPIKE_Y_POS, parentIndex), childIndex)

앱인벤터 오마이스파이크 게임 앱 GetListImte() 함수 (출처:imagnity홈페이지)

 

birdSprite의 위치를 정한다.
이 위치는 실제로 장애물 스파이크를 배치한 위치의 반대쪽입니다. 내가 했던 것처럼 다른 변수(heading Left)를 사용하는 대신 원하는 경우 새의 헤딩 속성을 사용할 수 있습니다. 하지만 여러분은 비교를 해서 그것이 0(오른쪽)인지 180(왼쪽)인지 확인해야 합니다.
Y 값은 제목에 의존하지 않습니다. 우리는 그것이 바닥 스파이크에 닿아서 바로 죽는 곳에 너무 높이거나 너무 낮게 두지 않도록 해야 합니다.

SetupBirdPosition()
if headingLeft == 참
  BirdSprite.X <- GameCanvas.너비 - BirdSprite*2
else
  BirdSprite.X <- BirdSprite.너비
BirdSprite.Y <- GameCanvas.높이 - ScoreLabel.높이 - SpikeBottom-높이 - (BirdSprite.높이*2)

앱인벤터 오마이스파이크 게임 입 SetupBirdPosition() 함수

 

캔버스 위의 이미지 스프라이트의 보이기여부를 설정한다.
이제 게임을 시작할 단계이기에 PlaySprite는 off, 나머지 스프라이트는 보이기를 설정한다.

GameSetupVisibility(visibility(참))
PlaySprite.보이기여부 <- 아니다(visibility)
SpikesUp.보이기여부 <- visibility
SpikesBottom.보이기여부 <- visibility
BirdSprite.보이기여부 <- visibility
Spike1.보이기여부 <- visibility
Spike2.보이기여부 <- visibility
Spike3.보이기여부 <- visibility
Spike4.보이기여부 <- visibility

앱인벤터 오마이스파이크 게임 앱 SetupGameVisibility() 함수

 

이제 게임은 GAME_READY 상태가 되었다.

GAME_READY상태에서 해야 하는 일

새는 계속해서 퍼덕거려야 한다.
- ContinuousFlapClock이 활성화될 때마다 새가 퍼덕거리도록 처리한다. 이 간격은 300msec이다.

앱인벤터 오마이스파이크 게임 앱 ContinuousFlapClock 타이머가 작동할 때

 ChangeImage 프로시저에서 왼쪽 제목이 true로 설정된 경우 현재 이미지가 BirdLeftOne.png인지 확인하고, 그렇다면 새가 펄럭이는 것처럼 보이도록 BirdLeftTwo.png으로 변경합니다. 두 번째 이미지라면 첫 번째 이미지로 변경됩니다.
왼쪽 제목이 거짓인 경우에는 반대로 처리됩니다. 

ChangeImage()

if headingLeft == 참
  if BirdSprite.사진== BirdLeftOne.png
    BirdSprite.사진 <- BirdLeftTwo.png
  else
    BirdSprite.사진 <- BirdLeftOne.png
else
  if BirdSprite.사진== BirdRightOne.png
    BirdSprite.사진 <- BirdRightTwo.png
  else
    BirdSprite.사진 <- BirdRightOne.png

 

앱인벤터 오마이스파이크 게임 앱 ChangeImage() 함수

 

 

이제 캔버스를 터치해보자, BirdSprite를 움직여보자...

캔버스를 터치했을 때,
if state가 STATE_READY상태이면
  state <- STATE_GAME
  ContinuousFlapClock.타이머활성화여부 <- 거짓
  yClock.활성화여부 <- 참
  BirdSprite.활성화 <- 참
  JumpBird() 함수 호출
아니면
  JumpBird()호출

GameCanvas 터치했을때
JumpBird()

앱인벤터 오마이스파이크 게임 앱 GameCanvas 터치했을때

 

MoveClock, FlapClock을 참으로 설정하여 이동과 날개짓 효과를 준다.

JumpBird()
FlapSound.재생하기
isFalling <- 거짓
ChangeImage()
MoveClock.타이머활성화여부 <- 참
FlapClock.타이머활성화여부 <- 참

 

앱인벤터 오마이스파이크 게임 앱 JumpBird() 함수

 

MoveClock.타이머가작동할때
isFalling <- 참
MoveClock.타이머활성화여부 <- 거짓

 

앱인벤터 오마이스파이크 게임 앱 MoveClock타이머가작동할때

 

 

FlapClock.타이머가작동할때
ChangeImage()
FlapClock.타이머활성화여부 <- 거짓

 

앱인벤터 오마이스파이크 게임 앱 FlapClock타이머가작동할때

 

yClock().타이머가작동할때

if isFalling == 참
  BirdSprite.Y <- BridSprite.Y + 10
else
  BirdSprite.Y <- BridSprite.Y - 10

 

앱인벤터 오마이스파이크 게임 앱 yClock.타이머가작동할때

 

이제 기본적인 동작은 완료되었다.이후에는 BirdSprite에 대한 처리를 할 것이다.BirdSprite가 스크린 화면 모서리에 닿았을 때, BirdSprite가 spike 이미지 스프라이트에 닿았을 때, 죽었는지 확인한다.

 

BirdSprite가 모서리에 닿으면 점수가 카운트된다.
. ScoreSound를 재생한다.
. SetupPlacement() 호출
. score <- score + 1
. ScoreLabel.텍스트 <- score

BirdSprite.모서리에닿았을때
{
ScoreSound.재생하기
SetupPlacement()
score <- score + 1
ScoreLabel.텍스트 <- score

앱인벤터 오마이스파이크.모서리에닿았을때

 

BirdSprite.충돌했을때(다른)
{
if '다른' == SpikesUp or '다른' == 'SpikesBottom'
  EndGameState()
else if isDead()
  EndGameState()
}

 

앱인벤터 오마이스파이크 게임 앱 BirdSprite.충돌했을때

 


isDead()
{
temp <- 거짓
if headingLeft == 참 and BridSprite.X < GameCanvas.너비/2
  if BirdSprite.X < Spike1.너비/2
    BirdSprite.속도 <- 20
  else
    temp <- 참
else if headingLeft == 참 and BridSprite.X > GameCanvas.너비/2
  if BirdSprite.X > + BirdSprite.너비 >= GameCanvas.너비 - Spike1.너비/2
    BirdSpreite.속도 <- 20
  else
    temp <- 참
  return temp  

앱인벤터 오마이스파이크 게임 앱 siDeat() 함수

 

새가 죽었고, 죽음의 소리를 재생한다. 
그리고 메뉴화면을 보여줘야 한다.(PlaySprite.이미지를 RetryButton.png 으로 변경한다.)
현재 점수가 최고 점수보다 높은 경우, 현재 점수로 best Score를 설정합니다. 그런 다음 데이터베이스에 저장합니다. 
우리는 모든 게임 구성 요소를 숨깁니다. 우리는 보이지 않는 것을 비활성화합니다. (게임 상태를 STATE_MENU로 변경한다)

EndGameState()
DeathSound.재생하기
PlaySprite.사진 <- RetryButton.png
if score > bestScore
  bestScore <- score
  ScoreDB.값저장하기(DB_SCORE_TAG, score)

SetupGameVisibility(거짓)
BirdSprite.활성화 <- 거짓
MoveClock.타이머활성화여부 <- 거짓
yClock.타이머활성화여부 <- 거짓
HeaderSprite.보이기여부 <- 참
state <- STATE_MENU
if bestScore >= 0
  ScoreLabel.텍스트 <- 'SCORE : " + score, + 'BEST : ' + bestScore
else
  ScoreLabel.텍스트 <- 'SCORE : " + score

 

앱인벤터 오마이스파이크 게임 입 isDead() 함수

 

 

지금까지 오마이스파이크 게임 앱을 작성하였다. 단순하지만 고전 앱인 오마이스파이크 게임 앱을 작성해 보았다. 개인적으로 더 추가해서 작성하고 수정해도 좋다. 하나씩 블럭을 쌓아가면서 어느 새 오마이스파이크 게임 앱을 작성할 수 있는 정도의 수준이 된 것이다. 잘 모르면 지금 앱을 하나씩 분석하여 변수와 프로그램을 이해해 보는 것을 추천한다.

 

눈으로 보는 것과 직접 실행하며 하는 것은 완전히 달라요.

간단하지만 직접 해보면 이해하고 자신감이 생길거에요...

 

Just Do It!!!

Just Drag&Drop It!!!

 

 

감사합니다.

 

반응형

댓글