굴착 소년 쿵이 어떤 게임인지 아래 링크를 참고 하시기 바랍니다.
비슷한 게임 링크들은 아래와 같습니다.
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
댓글 없음:
댓글 쓰기