반응형
어제 세계 최고의 기획자로 부터 야바위 게임 스토리 보드를 전달 받았습니다.
기획자가 너무 훌륭해서 스토리 보드만 가지고도 충분히 코딩을 할 수가 있겠네요. ^^
기획자로부터 자세히 설명을 듣고 이렇게 스토리보드 까지 받았습니다.
이제 프로그래머는 나름대로 objects 들과 함수들에 대한 설계를 했을 테고 또 Flow Chart 를 그려서 어떻게 앱이 진행될지 그려 보았을 겁니다.
좀 더 완벽하게 준비하는 스타일의 개발자라면 Use Case 도 한번 정리 해 봤겠죠...
물론 이 내용들은 하나의 문서에 정리 돼 있겠구요.
이제 코딩을 시작하겠습니다.
display.setStatusBar(display.HiddenStatusBar)
-- Graphics-- [Background]
local bg = display.newImage('bg.png')
일단 아이폰에서 status bar 를 안보이도록 하구요.
백그라운드 이미지는 앱이 시작하면서 끝날때까지 유지 되니까 함수(function) 내가 아니라 이렇게 앱 시작하면서 display를 해 놓습니다.
그 다음엔 각 objects를 담을 변수들을 만듭니다.
-- [Title View]
local title; local playBtn; local creditsBtn; local titleView
여긴 게임 첫 화면에 나올 objects를 정리했습니다.
게임 제목과 플레이 버튼,크레딧 버튼이구요. 이 첫 화면 객체들을 담을 그룹으로 titleView를 사용할 겁니다.
-- [Credits]
local creditsView -- 첫 화면에서 나올 credit 이미지가 들어갈 변수입니다.
-- [Bank Credits]
local bank; local bankText
게임 화면에서 좌측 상단에 들어갈 숫자(bank)와 이미지(bankText) 변수 입니다.
-- [Shells]
local s1; local s2; local s3; local shells;
3개 shell에 대한 변수 이구요. 이 3개 shell 들을 담을 로컬그룹 변수 shells입니다.
-- [Ball]
local ball -- ball 이미지를 담을 변수입니다.
-- [Button Bar]
local buttonBar -- 아래 진한 색 네모를 표시할 이미지를 담을 변수입니다.
-- [Bet Button]
local betBtn -- 게임 시작 버튼 이미지를 담을 변수 입니다.
-- [Message Text]
local msg -- 왼쪽 아래 안내 문구를 담을 변수 입니다.
-- [GameView]
local gameView -- Game 화면에 있는 모든 변수
-- [Alert]
local alert-- alert 이미지 담을 변수
local moveSpeed = 600 -- shell 움직이는 스피드
local totalMoves = 5 -- shell 움직이는 횟수
자 여기까지 야바위 게임에서 사용할 모든 objects에 대한 변수를 선언했습니다.
세계최고의 기획자가 스토리보드에서 언급한 모든 객체를 생성했구요.
또 프로그래머가 화면 전환할 때 사용하기 위해 각 화면별 objects들의 localGroup으로 사용할 변수들도 선언했습니다.
그리고 스피드,움직이는 횟수같은 개념적인 객체에 대한 변수까지 다 선언했습니다.
변수의 갯수가 총 20개네요.
20개의 objects들이 이 게임을 만들어 나갈겁니다.
출연자들이죠. 주연도 있고 조연도 있고...
이제 스토리보드 대로 (시나리오대로) 움직임을 만들 차례입니다.
그러기 위해 함수(메소드)를 선언합니다.
-- Functions
local Main = {}
local startButtonListeners = {}
local showCredits = {}
local hideCredits = {}
local showGameView = {}
local placeBet = {}
local randomShellMove = {}
local checkMovesLeft = {}
local revealBall = {}
local alert = {}
이 앱에서는 총 10개의 메소드가 사용됩니다.
-- Main Function
function Main()
title = display.newImage('title.png', display.contentCenterX - 123, 40)
playBtn = display.newImage('playBtn.png', display.contentCenterX - 25.5, display.contentCenterY - 10)
creditsBtn = display.newImage('creditsBtn.png', display.contentCenterX - 40.5, display.contentCenterY + 45)
titleView = display.newGroup(title, playBtn, creditsBtn)
startButtonListeners('add')
end
첫번째 함수는 Main()함수입니다.
이 소스코드 맨 마지막을 보시면 이 메인 함수를 호출합니다.
Main() 부분이죠. 그러니까 이 앱은 이 Main()부터 시작합니다.
그러니까 첫화면에 display될 제목과 플레이/credit 버튼을 화면에 그립니다.
그리고 이 title화면의 객체들을 titleView라는 localGroup으로 그룹화 합니다.
(여기서 bg는 빠졌습니다. 왜냐하면 bg는 모든 화면에 다 등장할 거거든요.)
그리고 startButtonListeners()라는 함수에 add라는 인수를 전달하면서 호출합니다.
function startButtonListeners(action)
if(action == 'add') then
playBtn:addEventListener('tap', showGameView)
creditsBtn:addEventListener('tap', showCredits)
else
playBtn:removeEventListener('tap', showGameView)
creditsBtn:removeEventListener('tap', showCredits)
end
end
메인에서 호출된 함수인데요.
메인에서 add를 인수로 던졌죠?
안에 내용을 보니까 add가 인수일 경우에는 플레이버튼과 크레딧 버튼에 리스너를 답니다.
플레이버튼을 누르면 showGameView() 함수를 실행하고 크레딧버튼을 누르면 showCredits() 함수를 실행하게 됩니다.
만약 인수가 add가 아니라면 이 두 리스너를 remove합니다.
우선 크레딧 버튼을 눌렀을 때 실행될 showCredits() 함수를 보겠습니다.
function showCredits:tap(e)
playBtn.isVisible = false
creditsBtn.isVisible = false
creditsView = display.newImage('credits.png')
transition.from(creditsView, {time = 300, x = -creditsView.width, onComplete = function() creditsView:addEventListener('tap', hideCredits) creditsView.x = creditsView.x - 0.5 end})
end
메인함수에서 크레딧 버튼을 누르면 실행되는 함수입니다.
처음에 플레이 버튼과 크레딧 버튼을 안 보이도록 만듭니다.
그리고 creditsView 이미지를 만들구요. 이 이미지를 transition합니다.
0.3초동안 왼쪽에서부터 서서히 나올 겁니다.
이미지가 다 나오면 이 이미지에 리스너를 답니다.
이 creditsView 이미지를 클릭하면 hideCredits() 함수가 실행 됩니다.
function hideCredits:tap(e)
playBtn.isVisible = true
creditsBtn.isVisible = true
transition.to(creditsView, {time = 300, x = -creditsView.width, onComplete = function() creditsView:removeEventListener('tap', hideCredits) display.remove(creditsView) creditsView = nil end})
end
크레딧 이미지를 클릭하면 실행되는 함수 입니다.
아까 안 보이도록 했던 플레이버튼과 크레딧 버튼을 모두 다시 보이도록 합니다.
creditsView를 transition.to를 이용해서 왼쪽으로 사라지도록 합니다.
다 사라지면 아까 만들었던 creditsView에 대한 리스너를 remove합니다.
여기까지가 첫 화면에서 크레딧 버튼을 누르고 나서 다시 원래 화면으로 돌아오기 까지 진행시키는 함수들 입니다.
다음엔 첫 화면에서 플레이 버튼을 누르면 실행되는 showGameView() 함수입니다.
본격적으로 게임이 시작 되는 부분입니다.
function showGameView:tap(e)
transition.to(titleView, {time = 300, x = -titleView.height, onComplete = function() startButtonListeners('rmv') display.remove(titleView) titleView = nil end})
-- [Bank Credits]
bank = display.newText('5', 18, 5, native.systemFontBold, 14)
bank:setTextColor(234, 170, 12)
bankText = display.newImage('bankText.png', 7.5, 25)
-- [Ball]
ball = display.newImage('ball.png', 228, 142)
-- [Shells]
s1 = display.newImage('shell.png', 50, 114)
s2 = display.newImage('shell.png', 195, 84)
s2.name = 's2'
s3 = display.newImage('shell.png', 340, 114)
shells = display.newGroup(s1, s2, s3)
-- [Button Bar]
buttonBar = display.newImage('buttonBar.png', 0, 270)
msg = display.newText('Click Bet to start', 1, 307, native.systemFont, 9)
betBtn = display.newImage('betBtn.png', 223, 275)
betBtn:addEventListener('tap', placeBet)
gameView = display.newGroup(bank, bankText, ball, shells, buttonBar, msg, betBtn)
end
실제 게임화면으로 넘어오면 처음에 실행되는게 이전 화면의 객체들을 없애는 작업입니다.
아까 첫 화면 객체들은 titleView라는 localGroup으로 그룹화를 했었습니다.
transition.to를 이용해서 이 titleView를 왼쪽으로 이동시키고 다 이동되면 startButtonListener에 rmv라는 인수를 전달하면서 실행시킵니다.
startButtonListener는 아까 add를 인수로 전달하면서 불렀던 함수인데요.
인수가 add가 아니면 첫 화면의 플레이버튼하고 크레딧 버튼의 리스너를 remove하도록 돼 있었습니다.
그러니까 첫화면의 객체들을 사라지게 하고 이 객체들에 할당된 리스너들도 다 remove 한 겁니다.
그 다음으로는 text를 출력할 bank를 만들고 위치시켜주고 색도 지정합니다.
그리고 bankText 이미지도 지정된 위치에 display합니다.
다음은 ball 이미지를 지정된 위치에 display하구요. shell 3개를 나란히 display합니다.
여기서 ball이 들어가 있게 될 shell은 별도로 name을 s2라고 할당합니다.
그리고 이 shell들을 shells라는 변수에 그룹화 시켜 놓습니다.
다음에 하단에 buttonBar를 표시하고 msg Text를 표시합니다.
그리고 betBtn을 표시하고 이 이미지에 리스너를 답니다.
이 이미지를 누르면 paceBet() 함수가 실행됩니다.
맨 마지막에는 이 게임 화면에 있는 모든 objects를 gameView변수로 그룹화 합니다.
나중에 화면전환 할 때 사용하기 위해서 입니다.
function placeBet:tap(e)
-- Place Bet
bank.text = bank.text - 1;
-- Remove Button Listener
betBtn:removeEventListener('tap', placeBet)
-- Change Msg
msg.text = ''
-- Reset Total Moves
totalMoves = 5
-- Hide Ball
transition.to(s2, {time = moveSpeed, y = s2.y + 30, onComplete = randomShellMove})
end
betBtn을 누르면 실행 될 placeBet()함수입니다.
이 함수에서는 bank.text를 -1해서 다시 display합니다.
그리고 betBtn이미지의 리스너를 remove합니다.
다음으로는 msg.text를 아무것도 표시하지 않도록 고치구요.
shell이 몇번 움직일지 그 숫자를 다시 지정합니다.
(지금은 초기 설정값이랑 같은데 만약에 점점 더 움직이는 횟수를 늘리고 싶으면 이 부분에서 코딩해 주면 됩니다.)
다음은 s2를 아래로 내립니다. 그러면 공을 덮어서 안 보이게 됩니다.
완료 되면 randomShellMove() 함수가 호출 됩니다.
function randomShellMove()
local randm = math.floor(math.random() * 2) + 1
local shell1 = shells[randm]
local shell2
if(shell1 ~= 3) then
shell2 = shells[randm + 1]
elseif(shell1 ~= 1) then
shell2 = shells[randm - 1]
end
ball.isVisible = false
totalMoves = totalMoves -1
transition.to(shell1, {time = moveSpeed, x = shell2.x, y = shell2.y})
transition.to(shell2, {time = moveSpeed, x = shell1.x, y = shell1.y, onComplete = checkMovesLeft})
end
여기는 3개의 shell을 움직이는 로직입니다.
아마 이 앱에서의 핵심 부분일 겁니다.
이 로직은 여러분이 연구해 보세요.
이것보다 더 좋은 로직을 생각해 보셔도 되구요.
이 로직에 대한 해석은 생략하겠습니다.
하여간 로직대로 shell3개를 5회 움직입니다. 이때 ball은 안보이도록 하구요.
shell2가 다 움직이면 checkMovesLeft()를 호출합니다.
function checkMovesLeft()
if(totalMoves > 0) then
randomShellMove()
else
s1:addEventListener('tap', revealBall)
s2:addEventListener('tap', revealBall)
s3:addEventListener('tap', revealBall)
-- Change Msg
msg.text = 'Click where the ball is'
msg:setReferencePoint(display.TopLeftReferencePoint)
msg.x = -20
end
end
이 함수에서는 totalMoves를 먼저 체크합니다. 0이 아니면 randomShellMove()함수를 다시 호출합니다. 이렇게 해서 총 5번 randomShellMove()함수가 실행 될 겁니다.
totalMoves가 0 이면 각 shell에 모두 리스너를 답니다.
tap 하면 revealBall함수가 실행되도록이요.
그리고 msg.text는 Click where the ball is 로 바꿔 주시고 그 위치를 바로 잡아 줍니다.
function revealBall:tap(e)
-- Remove Shell Mouse Listeners
s1:removeEventListener('tap', revealBall)
s2:removeEventListener('tap', revealBall)
s3:removeEventListener('tap', revealBall)
-- Move Ball to correct position
ball.x = s2.x + 75
ball.y = s2.y + 150
ball.isVisible = true
-- Give credits if correct guess
if(e.target.name == 's2') then
bank.text = bank.text + 2
-- Change Msg
msg.text = 'Correct! Click Bet to play again'
msg:setReferencePoint(display.TopLeftReferencePoint)
msg.x = -20
else
msg.text = 'Wrong! Click Bet to play again'
msg:setReferencePoint(display.TopLeftReferencePoint)
msg.x = -20
end
-- Reveal Ball
transition.to(s2, {time = moveSpeed, y = s2.y - 30})
-- Add Bet button listener
betBtn:addEventListener('tap', placeBet)
-- Check for bank credits
if(bank.text == '0') then
betBtn:removeEventListener('tap', placeBet)
alert()
end
end
이 함수에서는 호출되면 일단 3개 shell에 할당된 리스너를 모두 remove합니다.
그리고 ball의 위치를 두번째 shell 즉 s2 안으로 위치시키고 이 볼이 보일 수 있게 합니다.
터치한 shell이 s2이면 즉 ball이 있는 shell이면 msg.text를 Correct! Click Bet to play again 으로 표시하고 그 위치를 바로 잡습니다. 그리고 s2가 아니면 Wrong! Click Bet to play again 을 표시하고 그 위치를 잡습니다.
그리고 s2를 transition.to를 이용해서 위로 올립니다. 그러면 ball이 나오겠죠?
이제 게임을 다시 시작할 수 있도록 betBtn에 리스너를 다시 달아줍니다.
만약 bank.text가 0 이면 그 리스너를 다시 없애고 alert() 함수를 실행합니다.
function alert()
alert = display.newImage('alert.png')
alert:setReferencePoint(display.CenterReferencePoint)
alert.x = display.contentCenterX
alert.y = display.contentCenterY
transition.from(alert, {time = 300, xScale = 0.3, yScale = 0.3})
msg.text = ''
alert:addEventListener('tap', restart)
end
이 함수에서는 alert이미지를 transition.from을 이용해서 display하구요.
msg.text를 아무것도 표시 안 합니다.
그리고 이 alert이미지에 리스너를 달아서 tap하면 restart()함수가 실행되도록 합니다.
function restart()
display.remove(gameView)
gameView = nil
display.remove(alert)
alert = nil
Main()
end
이 함수에서는 게임화면에 있는 모든 객체들(gameView)을 remove합니다.
그리고 alert화면도 remove합니다.
그리고 Main()을 실행시켜 게임을 다시 시작하도록 합니다.
Main()
이 부분은 앱이 처음 시작할 때 Main()을 호출하는 부분입니다.
이번엔 야바위게임을 같이 살펴봤습니다.
게임 설계가 아주 모범적으로 잘 돼 있는것 같습니다.
저도 이 모범적인 설계를 배우고 싶어서 공부 자료로 사용했습니다.
코딩이 아주 깔끔하네요.
아래 원래 소스 파일이 있습니다.
기획자가 너무 훌륭해서 스토리 보드만 가지고도 충분히 코딩을 할 수가 있겠네요. ^^
기획자로부터 자세히 설명을 듣고 이렇게 스토리보드 까지 받았습니다.
이제 프로그래머는 나름대로 objects 들과 함수들에 대한 설계를 했을 테고 또 Flow Chart 를 그려서 어떻게 앱이 진행될지 그려 보았을 겁니다.
좀 더 완벽하게 준비하는 스타일의 개발자라면 Use Case 도 한번 정리 해 봤겠죠...
물론 이 내용들은 하나의 문서에 정리 돼 있겠구요.
이제 코딩을 시작하겠습니다.
display.setStatusBar(display.HiddenStatusBar)
-- Graphics-- [Background]
local bg = display.newImage('bg.png')
일단 아이폰에서 status bar 를 안보이도록 하구요.
백그라운드 이미지는 앱이 시작하면서 끝날때까지 유지 되니까 함수(function) 내가 아니라 이렇게 앱 시작하면서 display를 해 놓습니다.
그 다음엔 각 objects를 담을 변수들을 만듭니다.
-- [Title View]
local title; local playBtn; local creditsBtn; local titleView
여긴 게임 첫 화면에 나올 objects를 정리했습니다.
게임 제목과 플레이 버튼,크레딧 버튼이구요. 이 첫 화면 객체들을 담을 그룹으로 titleView를 사용할 겁니다.
-- [Credits]
local creditsView -- 첫 화면에서 나올 credit 이미지가 들어갈 변수입니다.
-- [Bank Credits]
local bank; local bankText
게임 화면에서 좌측 상단에 들어갈 숫자(bank)와 이미지(bankText) 변수 입니다.
-- [Shells]
local s1; local s2; local s3; local shells;
3개 shell에 대한 변수 이구요. 이 3개 shell 들을 담을 로컬그룹 변수 shells입니다.
-- [Ball]
local ball -- ball 이미지를 담을 변수입니다.
-- [Button Bar]
local buttonBar -- 아래 진한 색 네모를 표시할 이미지를 담을 변수입니다.
-- [Bet Button]
local betBtn -- 게임 시작 버튼 이미지를 담을 변수 입니다.
-- [Message Text]
local msg -- 왼쪽 아래 안내 문구를 담을 변수 입니다.
-- [GameView]
local gameView -- Game 화면에 있는 모든 변수
-- [Alert]
local alert-- alert 이미지 담을 변수
local moveSpeed = 600 -- shell 움직이는 스피드
local totalMoves = 5 -- shell 움직이는 횟수
자 여기까지 야바위 게임에서 사용할 모든 objects에 대한 변수를 선언했습니다.
세계최고의 기획자가 스토리보드에서 언급한 모든 객체를 생성했구요.
또 프로그래머가 화면 전환할 때 사용하기 위해 각 화면별 objects들의 localGroup으로 사용할 변수들도 선언했습니다.
그리고 스피드,움직이는 횟수같은 개념적인 객체에 대한 변수까지 다 선언했습니다.
변수의 갯수가 총 20개네요.
20개의 objects들이 이 게임을 만들어 나갈겁니다.
출연자들이죠. 주연도 있고 조연도 있고...
이제 스토리보드 대로 (시나리오대로) 움직임을 만들 차례입니다.
그러기 위해 함수(메소드)를 선언합니다.
-- Functions
local Main = {}
local startButtonListeners = {}
local showCredits = {}
local hideCredits = {}
local showGameView = {}
local placeBet = {}
local randomShellMove = {}
local checkMovesLeft = {}
local revealBall = {}
local alert = {}
이 앱에서는 총 10개의 메소드가 사용됩니다.
-- Main Function
function Main()
title = display.newImage('title.png', display.contentCenterX - 123, 40)
playBtn = display.newImage('playBtn.png', display.contentCenterX - 25.5, display.contentCenterY - 10)
creditsBtn = display.newImage('creditsBtn.png', display.contentCenterX - 40.5, display.contentCenterY + 45)
titleView = display.newGroup(title, playBtn, creditsBtn)
startButtonListeners('add')
end
첫번째 함수는 Main()함수입니다.
이 소스코드 맨 마지막을 보시면 이 메인 함수를 호출합니다.
Main() 부분이죠. 그러니까 이 앱은 이 Main()부터 시작합니다.
그러니까 첫화면에 display될 제목과 플레이/credit 버튼을 화면에 그립니다.
그리고 이 title화면의 객체들을 titleView라는 localGroup으로 그룹화 합니다.
(여기서 bg는 빠졌습니다. 왜냐하면 bg는 모든 화면에 다 등장할 거거든요.)
그리고 startButtonListeners()라는 함수에 add라는 인수를 전달하면서 호출합니다.
function startButtonListeners(action)
if(action == 'add') then
playBtn:addEventListener('tap', showGameView)
creditsBtn:addEventListener('tap', showCredits)
else
playBtn:removeEventListener('tap', showGameView)
creditsBtn:removeEventListener('tap', showCredits)
end
end
메인에서 호출된 함수인데요.
메인에서 add를 인수로 던졌죠?
안에 내용을 보니까 add가 인수일 경우에는 플레이버튼과 크레딧 버튼에 리스너를 답니다.
플레이버튼을 누르면 showGameView() 함수를 실행하고 크레딧버튼을 누르면 showCredits() 함수를 실행하게 됩니다.
만약 인수가 add가 아니라면 이 두 리스너를 remove합니다.
우선 크레딧 버튼을 눌렀을 때 실행될 showCredits() 함수를 보겠습니다.
function showCredits:tap(e)
playBtn.isVisible = false
creditsBtn.isVisible = false
creditsView = display.newImage('credits.png')
transition.from(creditsView, {time = 300, x = -creditsView.width, onComplete = function() creditsView:addEventListener('tap', hideCredits) creditsView.x = creditsView.x - 0.5 end})
end
메인함수에서 크레딧 버튼을 누르면 실행되는 함수입니다.
처음에 플레이 버튼과 크레딧 버튼을 안 보이도록 만듭니다.
그리고 creditsView 이미지를 만들구요. 이 이미지를 transition합니다.
0.3초동안 왼쪽에서부터 서서히 나올 겁니다.
이미지가 다 나오면 이 이미지에 리스너를 답니다.
이 creditsView 이미지를 클릭하면 hideCredits() 함수가 실행 됩니다.
function hideCredits:tap(e)
playBtn.isVisible = true
creditsBtn.isVisible = true
transition.to(creditsView, {time = 300, x = -creditsView.width, onComplete = function() creditsView:removeEventListener('tap', hideCredits) display.remove(creditsView) creditsView = nil end})
end
크레딧 이미지를 클릭하면 실행되는 함수 입니다.
아까 안 보이도록 했던 플레이버튼과 크레딧 버튼을 모두 다시 보이도록 합니다.
creditsView를 transition.to를 이용해서 왼쪽으로 사라지도록 합니다.
다 사라지면 아까 만들었던 creditsView에 대한 리스너를 remove합니다.
여기까지가 첫 화면에서 크레딧 버튼을 누르고 나서 다시 원래 화면으로 돌아오기 까지 진행시키는 함수들 입니다.
다음엔 첫 화면에서 플레이 버튼을 누르면 실행되는 showGameView() 함수입니다.
본격적으로 게임이 시작 되는 부분입니다.
function showGameView:tap(e)
transition.to(titleView, {time = 300, x = -titleView.height, onComplete = function() startButtonListeners('rmv') display.remove(titleView) titleView = nil end})
-- [Bank Credits]
bank = display.newText('5', 18, 5, native.systemFontBold, 14)
bank:setTextColor(234, 170, 12)
bankText = display.newImage('bankText.png', 7.5, 25)
-- [Ball]
ball = display.newImage('ball.png', 228, 142)
-- [Shells]
s1 = display.newImage('shell.png', 50, 114)
s2 = display.newImage('shell.png', 195, 84)
s2.name = 's2'
s3 = display.newImage('shell.png', 340, 114)
shells = display.newGroup(s1, s2, s3)
-- [Button Bar]
buttonBar = display.newImage('buttonBar.png', 0, 270)
msg = display.newText('Click Bet to start', 1, 307, native.systemFont, 9)
betBtn = display.newImage('betBtn.png', 223, 275)
betBtn:addEventListener('tap', placeBet)
gameView = display.newGroup(bank, bankText, ball, shells, buttonBar, msg, betBtn)
end
실제 게임화면으로 넘어오면 처음에 실행되는게 이전 화면의 객체들을 없애는 작업입니다.
아까 첫 화면 객체들은 titleView라는 localGroup으로 그룹화를 했었습니다.
transition.to를 이용해서 이 titleView를 왼쪽으로 이동시키고 다 이동되면 startButtonListener에 rmv라는 인수를 전달하면서 실행시킵니다.
startButtonListener는 아까 add를 인수로 전달하면서 불렀던 함수인데요.
인수가 add가 아니면 첫 화면의 플레이버튼하고 크레딧 버튼의 리스너를 remove하도록 돼 있었습니다.
그러니까 첫화면의 객체들을 사라지게 하고 이 객체들에 할당된 리스너들도 다 remove 한 겁니다.
그 다음으로는 text를 출력할 bank를 만들고 위치시켜주고 색도 지정합니다.
그리고 bankText 이미지도 지정된 위치에 display합니다.
다음은 ball 이미지를 지정된 위치에 display하구요. shell 3개를 나란히 display합니다.
여기서 ball이 들어가 있게 될 shell은 별도로 name을 s2라고 할당합니다.
그리고 이 shell들을 shells라는 변수에 그룹화 시켜 놓습니다.
다음에 하단에 buttonBar를 표시하고 msg Text를 표시합니다.
그리고 betBtn을 표시하고 이 이미지에 리스너를 답니다.
이 이미지를 누르면 paceBet() 함수가 실행됩니다.
맨 마지막에는 이 게임 화면에 있는 모든 objects를 gameView변수로 그룹화 합니다.
나중에 화면전환 할 때 사용하기 위해서 입니다.
function placeBet:tap(e)
-- Place Bet
bank.text = bank.text - 1;
-- Remove Button Listener
betBtn:removeEventListener('tap', placeBet)
-- Change Msg
msg.text = ''
-- Reset Total Moves
totalMoves = 5
-- Hide Ball
transition.to(s2, {time = moveSpeed, y = s2.y + 30, onComplete = randomShellMove})
end
betBtn을 누르면 실행 될 placeBet()함수입니다.
이 함수에서는 bank.text를 -1해서 다시 display합니다.
그리고 betBtn이미지의 리스너를 remove합니다.
다음으로는 msg.text를 아무것도 표시하지 않도록 고치구요.
shell이 몇번 움직일지 그 숫자를 다시 지정합니다.
(지금은 초기 설정값이랑 같은데 만약에 점점 더 움직이는 횟수를 늘리고 싶으면 이 부분에서 코딩해 주면 됩니다.)
다음은 s2를 아래로 내립니다. 그러면 공을 덮어서 안 보이게 됩니다.
완료 되면 randomShellMove() 함수가 호출 됩니다.
function randomShellMove()
local randm = math.floor(math.random() * 2) + 1
local shell1 = shells[randm]
local shell2
if(shell1 ~= 3) then
shell2 = shells[randm + 1]
elseif(shell1 ~= 1) then
shell2 = shells[randm - 1]
end
ball.isVisible = false
totalMoves = totalMoves -1
transition.to(shell1, {time = moveSpeed, x = shell2.x, y = shell2.y})
transition.to(shell2, {time = moveSpeed, x = shell1.x, y = shell1.y, onComplete = checkMovesLeft})
end
여기는 3개의 shell을 움직이는 로직입니다.
아마 이 앱에서의 핵심 부분일 겁니다.
이 로직은 여러분이 연구해 보세요.
이것보다 더 좋은 로직을 생각해 보셔도 되구요.
이 로직에 대한 해석은 생략하겠습니다.
하여간 로직대로 shell3개를 5회 움직입니다. 이때 ball은 안보이도록 하구요.
shell2가 다 움직이면 checkMovesLeft()를 호출합니다.
function checkMovesLeft()
if(totalMoves > 0) then
randomShellMove()
else
s1:addEventListener('tap', revealBall)
s2:addEventListener('tap', revealBall)
s3:addEventListener('tap', revealBall)
-- Change Msg
msg.text = 'Click where the ball is'
msg:setReferencePoint(display.TopLeftReferencePoint)
msg.x = -20
end
end
이 함수에서는 totalMoves를 먼저 체크합니다. 0이 아니면 randomShellMove()함수를 다시 호출합니다. 이렇게 해서 총 5번 randomShellMove()함수가 실행 될 겁니다.
totalMoves가 0 이면 각 shell에 모두 리스너를 답니다.
tap 하면 revealBall함수가 실행되도록이요.
그리고 msg.text는 Click where the ball is 로 바꿔 주시고 그 위치를 바로 잡아 줍니다.
function revealBall:tap(e)
-- Remove Shell Mouse Listeners
s1:removeEventListener('tap', revealBall)
s2:removeEventListener('tap', revealBall)
s3:removeEventListener('tap', revealBall)
-- Move Ball to correct position
ball.x = s2.x + 75
ball.y = s2.y + 150
ball.isVisible = true
-- Give credits if correct guess
if(e.target.name == 's2') then
bank.text = bank.text + 2
-- Change Msg
msg.text = 'Correct! Click Bet to play again'
msg:setReferencePoint(display.TopLeftReferencePoint)
msg.x = -20
else
msg.text = 'Wrong! Click Bet to play again'
msg:setReferencePoint(display.TopLeftReferencePoint)
msg.x = -20
end
-- Reveal Ball
transition.to(s2, {time = moveSpeed, y = s2.y - 30})
-- Add Bet button listener
betBtn:addEventListener('tap', placeBet)
-- Check for bank credits
if(bank.text == '0') then
betBtn:removeEventListener('tap', placeBet)
alert()
end
end
이 함수에서는 호출되면 일단 3개 shell에 할당된 리스너를 모두 remove합니다.
그리고 ball의 위치를 두번째 shell 즉 s2 안으로 위치시키고 이 볼이 보일 수 있게 합니다.
터치한 shell이 s2이면 즉 ball이 있는 shell이면 msg.text를 Correct! Click Bet to play again 으로 표시하고 그 위치를 바로 잡습니다. 그리고 s2가 아니면 Wrong! Click Bet to play again 을 표시하고 그 위치를 잡습니다.
그리고 s2를 transition.to를 이용해서 위로 올립니다. 그러면 ball이 나오겠죠?
이제 게임을 다시 시작할 수 있도록 betBtn에 리스너를 다시 달아줍니다.
만약 bank.text가 0 이면 그 리스너를 다시 없애고 alert() 함수를 실행합니다.
function alert()
alert = display.newImage('alert.png')
alert:setReferencePoint(display.CenterReferencePoint)
alert.x = display.contentCenterX
alert.y = display.contentCenterY
transition.from(alert, {time = 300, xScale = 0.3, yScale = 0.3})
msg.text = ''
alert:addEventListener('tap', restart)
end
이 함수에서는 alert이미지를 transition.from을 이용해서 display하구요.
msg.text를 아무것도 표시 안 합니다.
그리고 이 alert이미지에 리스너를 달아서 tap하면 restart()함수가 실행되도록 합니다.
function restart()
display.remove(gameView)
gameView = nil
display.remove(alert)
alert = nil
Main()
end
이 함수에서는 게임화면에 있는 모든 객체들(gameView)을 remove합니다.
그리고 alert화면도 remove합니다.
그리고 Main()을 실행시켜 게임을 다시 시작하도록 합니다.
Main()
이 부분은 앱이 처음 시작할 때 Main()을 호출하는 부분입니다.
이번엔 야바위게임을 같이 살펴봤습니다.
게임 설계가 아주 모범적으로 잘 돼 있는것 같습니다.
저도 이 모범적인 설계를 배우고 싶어서 공부 자료로 사용했습니다.
코딩이 아주 깔끔하네요.
아래 원래 소스 파일이 있습니다.
반응형
'Corona SDK > 샘플 코드 분석' 카테고리의 다른 글
animation chain 소스 분석 해 보기 03 (0) | 2013.08.11 |
---|---|
animation chain 소스 분석 해 보기 02 (0) | 2013.07.22 |
animation chain 소스 분석 해 보기 01 (0) | 2013.07.15 |
코로나로 뱀 기어디니는 효과 내기 (0) | 2012.02.28 |
간단하게 눈발 흩날리는 느낌 주기 (2) | 2012.02.16 |
돈 넣고 돈 먹기(야바위) 모바일 게임 만들기 1 (2) | 2012.01.03 |
내가 그린 선으로 떨어지는 공 받아내기 (2) | 2011.12.31 |
Corona SDK 화면전환 API (Story Board) (4) | 2011.12.23 |
Level 별 Lock 기능 걸고 푸는 법 (0) | 2011.12.15 |
벽돌 깨기 게임 만들기 -3 (1) | 2011.12.01 |