2015년 8월 14일 금요일

corona sdk로 벽돌깨기


특이하게 생긴 벽돌 깨기 게임이 재미있어서 벽돌깨기 게임은 어떻게 만들면 될까 고민 해봤습니다.

- 깨지기 위한 블럭이 있는데 그건 stage load 처럼 map 마다 다르게 구현합니다. (아마도 block 특성에에 따라 draw 객체를 따로 생성해야 합니다.)
- 공이 있고 공은 시작뒤에는 특정 방향으로 움직이는데 이건 물리 library를 이용합니다.
- 부딧히면 점수가 갂이거나 각도가 변하도록 합니다.
- 아래 bar가 있는데 이건 사용자가 조정할 수 있도록 하고 공과 부딧힐때 어디쯤 부딧쳤느냐에 따라 튕겨나가는 각도를 다르게 처리합니다.

여기까지가 제가 생각해 본 것이고,

인터넷 검색해보니 이미 구현된 소스도 존재해서, 구현된 소스를 분석해서 설명 하도록 하겠습니다.

투토리얼의 내용은 아래 링크 참고하고
https://coronalabs.com/blog/2011/06/07/tutorial-create-a-breakout-game-in-corona-sdk/
소스는 https://github.com/ansca/breakout GIT여기에서 받을 수 있습니다.

확인해보니까 소스가 오래된 소스라 제대로 동작되지 않아서 약간 수정하였습니다.

표현하는 좌표계에 문제가 있어서, 아래와 같이 anchorX =0, anchorY =0 추가 하였습니다.
local paddle = display.newRect( display.contentWidth / 2 - paddleWidth / 2, display.contentHeight - 50, paddleWidth, paddleHeight )
=>
local paddle = display.newRect( display.contentWidth / 2 - paddleWidth / 2, display.contentHeight - 50, paddleWidth, paddleHeight )
paddle.anchorX = 0
paddle.anchorY = 0


여기서 부터는 설명 들어갑니다.

function main()

 setUpPhysics() -- 물리 library를 사용
 createWalls()  -- 벽을 만들어 공이 벽에 부딧힘을 감지 1
 createBricks() -- 벽을 만듦 2
 createBall()   -- 공을 만듦
 createPaddle() -- 아래쪽 패들 만듦
 startGame()    -- 게임 시작

end

- 물리 library를 사용
물리 library setup에서 아래와 같은 값을 사용하는데
physics.setGravity( 0, 0 ) 
블럭 깨기라서 중력 가속도 값은 없습니다. (0,0)
기본값은 (0,9.8) 입니다.
https://docs.coronalabs.com/api/library/physics/setGravity.html

- 벽을 만들기 1
아래와 같은 형태로 만듧니다.
 local wall = display.newRect( 0, 0, wallThickness, display.contentHeight )
 wall.anchorX = 0
 wall.anchorY = 0
 physics.addBody(wall, "static", {friction=0, bounce = 1})

- 벽을 만들기 2
아래와 같은 형태로 만듧니다.
특정 위치에 numOfRows * numOfCols 개의 깨질 수 있는 벽을 만듧니다. type을 destructible을 넣습니다.
 for row = 0, numOfRows - 1 do
  for col = 0, numOfCols - 1 do
  
   -- Create a brick
   local brick = display.newRect( topLeft.x + (col * brickWidth), topLeft.y + (row * brickHeight), brickWidth, brickHeight )
   brick:setFillColor(math.random(50, 255), math.random(50, 255), math.random(50, 255), 255)
   brick.type = "destructible"
   
   physics.addBody(brick, "static", {friction=0, bounce = 1})
  end
 end

- 공을 만듦
공에만 충돌 처리 루틴을 넣습니다.
아래쪽 벽에 부딧치면 onTimerComplete 함수가 호출되면서 게임을 새로 시작합니다.
destructible 종류의 벽에 부딧치면 벽돌이 사라집니다. event.other:removeSelf()
나머지 벽들은 일반 static 벽들로서 물리작용이 일어나게 됩니다.
즉, ball은 dynamic이고 벽돌은 static으로 부딧히면 dynamic인 물체만 움직이게 됩니다.

- 아래쪽 패들 만듦
static 물체를 만들고 touch 이벤트를 등록해서 움직이도록 해줍니다.

- 게임시작
공을 움직이게 합니다.
공의 x,y의 속도를 설정하면 됩니다.
ball:setLinearVelocity(75, 150) 

- 위 소스에서 안되는것
패들을 이용해서 공이 나가는 위치를 조절하는데 그 부분이 안됩니다. (즉 모서리 부분 맞출때 다른 방향으로 나가는 부분을 말합니다.)

아래는 전체 소스 입니다.
-------------------------------------------------------------

--------------------------------------------------------------------------------
-- 
-- Sample code is MIT licensed, see http://developer.anscamobile.com/code/license
-- Copyright (C) 2011 Ansca Inc. All Rights Reserved.

--------------------------------------------------------------------------------


require ("physics")


function main()

 setUpPhysics()
 createWalls()
 createBricks()
 createBall()
 createPaddle()
 startGame()

end

function setUpPhysics()
 physics.start()
 -- physics.setDrawMode("hybrid")
 physics.setGravity(0,0)
end


function createPaddle()
 
 local paddleWidth = 100
 local paddleHeight = 10
 
 local paddle = display.newRect( display.contentWidth / 2 - paddleWidth / 2, display.contentHeight - 50, paddleWidth, paddleHeight )
 paddle.anchorX = 0
 paddle.anchorY = 0
 physics.addBody(paddle, "static", {friction=0, bounce=1})

 local  movePaddle = function(event)
   paddle.x = event.x
 end

 Runtime:addEventListener("touch", movePaddle)
 
end


function createBall()

 local ballRadius = 10

 ball = display.newCircle( display.contentWidth / 2, display.contentHeight / 2, ballRadius )
 ball.anchorX = 0
 ball.anchorY = 0
 physics.addBody(ball, "dynamic", {friction=0, bounce = 1, radius=ballRadius})

 ball.collision = function(self, event)
  if(event.phase == "ended") then
   
   if(event.other.type == "destructible") then
    event.other:removeSelf()
   end
   
   if(event.other.type == "bottomWall") then
   
    self:removeSelf()
    
    local onTimerComplete = function(event)
     createBall()
     startGame()
    end
    
    timer.performWithDelay(500, onTimerComplete , 1)
   end
  end
 end

 ball:addEventListener("collision", ball)
end

function startGame()
 ball:setLinearVelocity(75, 150) 
end


function createBricks()
 
 local brickWidth = 40
 local brickHeight = 20
  
 local numOfRows = 4
 local numOfCols = 6
 
 local topLeft = {x= display.contentWidth / 2 - (brickWidth * numOfCols ) / 2, y= 50}
 
 local row
 local col
 
 for row = 0, numOfRows - 1 do
  for col = 0, numOfCols - 1 do
  
   -- Create a brick
   local brick = display.newRect( topLeft.x + (col * brickWidth), topLeft.y + (row * brickHeight), brickWidth, brickHeight )
   brick:setFillColor(math.random(50, 255), math.random(50, 255), math.random(50, 255), 255)
   brick.type = "destructible"
   
   physics.addBody(brick, "static", {friction=0, bounce = 1})
  end
 end
end


function createWalls()
 
 local wallThickness = 10
 
 -- Left wall
 local wall = display.newRect( 0, 0, wallThickness, display.contentHeight )
 wall.anchorX = 0
 wall.anchorY = 0
 physics.addBody(wall, "static", {friction=0, bounce = 1})
 
 -- Top wall
 wall = display.newRect(0,0, display.contentWidth, wallThickness)
 wall.anchorX = 0
 wall.anchorY = 0
 physics.addBody(wall, "static", {friction=0, bounce = 1})
 
 -- Right wall
 wall = display.newRect(display.contentWidth - wallThickness, 0, wallThickness, display.contentHeight)
 wall.anchorX = 0
 wall.anchorY = 0
 physics.addBody(wall, "static", {friction=0, bounce = 1})
 
 -- Bottom wall
 wall = display.newRect(0, display.contentHeight - wallThickness, display.contentWidth, wallThickness)
 wall.anchorX = 0
 wall.anchorY = 0
 physics.addBody(wall, "static", {friction=0, bounce = 1})
 
 wall.type = "bottomWall"
end


main()





댓글 없음:

댓글 쓰기