2015년 11월 13일 금요일

corona sdk 굴착소년 쿵 같은거 어떻게 만들까 고민하기


굴착 소년 쿵이 어떤 게임인지 아래 링크를 참고 하시기 바랍니다.


비슷한 게임 링크들은 아래와 같습니다.

http://logstudy.tistory.com/75

http://games.yasinka.com/play/mega-miner

http://www.kongregate.com/games/matakukos/cave-explorer

공통점들은 땅을 파고(?) 그 의미는 객체가 사라지게 한다는 것입니다. 깨질 수 있는 벽을 어떤식을 만들면 될까?
반복 적인 데이터가 많으므로 tile기반으로 만들면 됩니다.
주의해야 할점은 tile갯수가 많아지면 물리기반 충돌검사시 성능적인 문제가 발생할 소지가 있습니다.

Corona SDK에서 Tile기반으로 맵을 구성하고 충돌 조건에 의해 다른 블럭으로 변환하는 방법에 대해 알아 보았습니다.
LevelDirector의 경우 Tile기반은 아닙니다. 따라서 타일형태의 게임을 제작하기에는 여간 불편한게 아닙니다. 타일기반이 아니면 충돌 검사시 물리 형태 아니면 자체적으로 만들어야 되는데 불변한 점도 있습니다. 하지만 게임 리소스로딩등 편한점이 있어서 다른 엔진들과 같이 사용하도록 할 예정입니다.


타일 기반 라이브러리 사용하기
https://github.com/GymbylCoding/Dusk-Engine
간단하게 사용할수 있는 dusk 엔진을 사용하여 예제를 제작 해보았습니다.
왼쪽 L,R 버튼을 누르면 방향이동이되고, L Drill R을 누르면 블럭이 제거가 됩니다.
맵은 Tiled로 제작하였으며, 이미지라던가 버튼은 Level Director 를 이용하여 만들었습니다.



기본적인 코드는 Dusk Demo 코드에서 가져왔습니다.

큰 문제가 있습니다. 타일을 없앨때 아래와 같은 함수를 이용하였습니다.
map.layer["Tile Layer 1"].lockTileErased(tile.tileX, tile.tileY)
이렇게 되면 tile이 한번에 사라지게 됩니다. 자연스럽게 없앨려면 다른 종류의 타일 이미지로 변경이 가능해야하는데 아무리 찾아도 방법을 모르겠어서 Dusk 엔진은 여기까지하고 접었습니다. ㅠ
다른 엔진을 연구해보도록 하겠습니다.
아래는 작업된 소스입니다.
https://drive.google.com/file/d/0B9vAKDzHthQIS3ROUEVfNmNVOEk/view?usp=sharing


--------------------------------------------------------------------------------
display.setStatusBar(display.HiddenStatusBar)

local textureFilter = "nearest"
display.setDefault("minTextureFilter", textureFilter)
display.setDefault("magTextureFilter", textureFilter)

--------------------------------------------------------------------------------
-- Localize
--------------------------------------------------------------------------------
local dusk = require("Dusk.Dusk")
local physics = require ("physics")
local LD = require("lib.LD_LoaderG2")
local intersection = require("intersection")

local myLevel = {}
local math_ceil = math.ceil
local math_abs = math.abs
local table_insert = table.insert
local map
local player = {}
local dir = 0
local drill = false
local gravity = 2
local speed = 2
local drillOffset = 20
local drillObject
local printMemUsageCount = 0
--------------------------------------------------------------------------------
-- Functions
--------------------------------------------------------------------------------
local distanceBetween = function(x1, y1, x2, y2) return (((x2 - x1) ^ 2) + ((y2 - y1) ^ 2)) ^ 0.5 end
local getPointsAlongLine = function(x1, y1, x2, y2, d) local points = {} local diffX = x2 - x1 local diffY = y2 - y1 local distBetween = math_ceil(distanceBetween(x1, y1, x2, y2) / d) local x, y = x1, y1 local addX, addY = diffX / distBetween, diffY / distBetween for i = 1, distBetween do table_insert(points, {x, y}) x, y = x + addX, y + addY end return points end
local clamp = function(v, l, h) return (v < l and l) or (v > h and h) or v end

--------------------------------------------------------------------------------
-- Load Map
--------------------------------------------------------------------------------

map = dusk.buildMap("resource/map1.json")
myLevel = LD:loadLevel("LDloadresource")

------------------------------------
local function spawnObject(pname,px,py,passetName)
------------------------------------
 local objProps = 
 {
  name  = pname, 
  x  = px,
  y  = py,
  xScale  =  1,
  yScale  =  1,
  assetName = passetName,
 }
 local object = myLevel:createObject(nil, objProps).view
 map.layer["Object Layer 1"]:insert(object)
 return object
end

------------------------------------
local YcheckTile = function(tile)
------------------------------------
 local intersectionPoint = intersection(
  -- Line segment #1: line drawn between player's current and previous positions
  player.x, player.y + player.YgroundOffset,
  player.x, player.prevY,
  -- Line segment #2: Top of tile
  tile.x - (tile.width * 0.5), tile.y - (tile.height * 0.5),
  tile.x + (tile.width * 0.5), tile.y - (tile.height * 0.5)
 )

 if intersectionPoint then
  return true, intersectionPoint
 else
  return false
 end
end

------------------------------------
local XcheckTile = function(tile)
------------------------------------
 local distance = player.XgroundOffset + tile.width/2
 local reald = 0
 if ( player.x > tile.x ) then
  reald = player.x - tile.x
 else
  reald = tile.x - player.x
 end
 local havetodis = distance - reald
 print(player.x,tile.x,havetodis,distance,reald)
 if (havetodis < 0) then
  return false
 end
 return true, {x = tile.x - dir*distance, y = 0}
end

------------------------------------
local YresolveCollision = function(point)
------------------------------------
 if player.yVel >= 0 then
  player.y = point.y - player.YgroundOffset
  player.yVel = 0
  return true
 else
  return false
 end
end

------------------------------------
local XresolveCollision = function(point)
------------------------------------
 if(dir > 0) then
  if player.xVel >= 0 then
   player.x = point.x
   player.xVel = 0
   return true
  else
   return false
  end
 end
 if(dir < 0) then
  if player.xVel <= 0 then
   player.x = point.x
   player.xVel = 0
   return true
  else
   return false
  end
 end
 return false
end

------------------------------------
local YcheckGroundPlayerCollisions = function()
------------------------------------
 --[[
 First, we do a collision check on the current position of the player. If the
 player has collided, we return before checking through all the points.
 --]]
 local tile = map.layer["Tile Layer 1"].tileByPixels(player.x, player.y + player.YgroundOffset)
 if tile then
  local collided, point = YcheckTile(tile)
  if collided then
   --print( tile.gid , tile.tilesetGID, tile.tileset)
   return YresolveCollision(point)
  end
 end
 return false
end

------------------------------------
local XcheckGroundPlayerCollisions = function()
------------------------------------
 local tile = map.layer["Tile Layer 1"].tileByPixels(player.x + dir * player.XgroundOffset, player.y)
 if tile then
  local collided, point = XcheckTile(tile)
  if collided then
  print( tile.gid , tile.tilesetGID, tile.tileset)
   return XresolveCollision(point)
  end
 end
 return false
end

------------------------------------
local monitorMem = function()
------------------------------------
 collectgarbage()
 print( "MemUsage: " .. collectgarbage("count") )
 local textMem = system.getInfo( "textureMemoryUsed" ) / 1000000
 print( "TexMem: " .. textMem )
end

------------------------------------
local gameLoop = function(event)
------------------------------------
 player.prevX, player.prevY = player.x, player.y
 player.xVel = dir * speed
 player.yVel = player.yVel + gravity

 player:translate(player.xVel, player.yVel)

 local isGrounded = YcheckGroundPlayerCollisions()
 player.isGrounded = isGrounded
 
 if( dir ~= 0 )then
  XcheckGroundPlayerCollisions()
 end
--[[
 if player.isGrounded then
  if move.jump.y <= -move.background.height and canJump then
   player.yVel = -player.jumpForce
   canJump = false
  end
 end
 ]]--
 map.updateView()

 printMemUsageCount = printMemUsageCount + 1;
 if( printMemUsageCount > 100 ) then
  printMemUsageCount = 0
  monitorMem()
 end
end

------------------------------------
local function leftPressed(event)
------------------------------------
 if( drill == true ) then
  return
 end
 print("L")
 dir = -1
end

------------------------------------
local function rightPressed(event)
------------------------------------
 if( drill == true ) then
  return
 end
 print("R")
 dir = 1
end

------------------------------------
local function btnReleased(event)
------------------------------------
 print("release")
 dir = 0
end

------------------------------------
local function drillTimerCB()
------------------------------------
 local tile = map.layer["Tile Layer 1"].tileByPixels(drillObject.x, drillObject.y)
 if( tile == nil ) then
  map.layer["Object Layer 1"]:remove(drillObject)
  drillObject=nil
  drill = false
  return
 end
 print(tile.tileX, tile.tileY)
 map.layer["Tile Layer 1"].lockTileErased(tile.tileX, tile.tileY)
 map.layer["Object Layer 1"]:remove(drillObject)
 drillObject=nil
 drill = false
end

------------------------------------
local function drillPressed(event)
------------------------------------
 print("Drill")
 if( drill == true or player.isGrounded == false ) then
  return
 end
 drill = true
 dir = 0
 drillObject = spawnObject("drill",player.x,player.y+drillOffset,"drill_down_png")

 timer.performWithDelay(500, drillTimerCB )
end

------------------------------------
local function drillRelease(event)
------------------------------------
 
end

------------------------------------
local function drillRPressed(event)
------------------------------------
 print("Drill")
 if( drill == true or player.isGrounded == false ) then
  return
 end
 drill = true
 dir = 0
 drillObject = spawnObject("drill",player.x+drillOffset,player.y,"drill_right_png")

 timer.performWithDelay(500, drillTimerCB )
end

------------------------------------
local function drillRRelease(event)
------------------------------------
 
end

------------------------------------
local function drillLPressed(event)
------------------------------------
 print("Drill")
 if( drill == true or player.isGrounded == false ) then
  return
 end
 drill = true
 dir = 0
 drillObject = spawnObject("drill",player.x-drillOffset,player.y,"drill_left_png")

 timer.performWithDelay(500, drillTimerCB )
end

------------------------------------
local function drillLRelease(event)
------------------------------------
 
end

------------------------------------
local function spawnPlayerObject()
------------------------------------
 local objProps = 
 {
  name  = "dog", 
  x  = 200,
  y  = 200,
  xScale  =  1,
  yScale  =  1,
  assetName = "dog_brown_png_1",
 }
 
 -- set the graphics 
 player = myLevel:createObject(nil, objProps).view

 player.xVel, player.yVel = 0, 0 -- Initial X and Y velocities 
 player.YgroundOffset = 10
 player.XgroundOffset = 10
 --dog:setSequence("Sequence0")
 --dog:play()

 map.layer["Object Layer 1"]:insert(player)
end
--------------------------------------------------------------------------------

Runtime:addEventListener("enterFrame", gameLoop)

spawnPlayerObject()

map.setCameraFocus(player,true,true)

btnLeft = myLevel:getLayerObject("layer1","btnL")
btnLeft.onPress = leftPressed
btnLeft.onRelease = btnReleased
btnRight = myLevel:getLayerObject("layer1","btnR")
btnRight.onPress = rightPressed
btnRight.onRelease = btnReleased
btnDrill = myLevel:getLayerObject("layer1","btnDrill")
btnDrill.onPress = drillPressed
btnDrill.onRelease = drillRelease
btnDrillR = myLevel:getLayerObject("layer1","btnDrillR")
btnDrillR.onPress = drillRPressed
btnDrillR.onRelease = drillRRelease
btnDrillL = myLevel:getLayerObject("layer1","btnDrillL")
btnDrillL.onPress = drillLPressed
btnDrillL.onRelease = drillLRelease




댓글 없음:

댓글 쓰기