* 해야할 것 *
주인공 이동
무기발사
스테이지
점수 처리
시작처리
종료처리
이미지 사용할 것:http://m484games.ucoz.com/index/shoot_39_em_up_gfx/0-38
참고 소스:http://www.tandgapps.co.uk/resources/tutorial-space-shooter-in-240-lines/
주인공 이동
주인공 이미지를 로딩하고 움직이는 코드를 만들겠습니다.
기존대비 변경한 코드는 아래와 같습니다.
setup함수에서 player를 load하는데 비행기 이미지를 미리 만들어 두고 터치를 누르면 moveShip이 호출됩니다. 여기에서는 가로로만 이동되게 하였는데 중요한 부분은 transition 함수 입니다. 이동속도는 = 거리/시간 으로 여기에서는 일정한 속도로 움직이게 하기위해서 time이 속도가 일정하려면 시간이 변경되게 됩니다. 시간은=거리/상수(속도)값으로 0.2가 상수값으로 테스트로 적절한 값을 산출 합니다.
참고로 해당 내용은 참고 소스 링크의 부분과 다른 내용입니다.
local playerGroup = display.newGroup() local ship local function moveShip( event ) local phase = event.phase print(event.x,event.y,phase) if( event.x > ship.x ) then transition.cancel( ship ) transition.to( ship, {time = (event.x-ship.x)/0.2, x = event.x} ) -- t = d/k end if( event.x < ship.x ) then transition.cancel( ship ) transition.to( ship, {time = -(event.x-ship.x)/0.2, x = event.x} ) -- t = d/k end end local function loadPlayer() ship = display.newImageRect("my.png", 20, 20) ship.x = _W*0.5; ship.y = _H+30; ship.name = "ship" physics.addBody( ship, { isSensor = true } ) Runtime:addEventListener("touch",moveShip) playerGroup:insert(ship) transition.to(ship, {time = 600, y = _H-_H*0.1}) end local function setup() loadBGImg() loadPlayer() end
무기발사
휴대폰에서 조작이 쉽게하려면 총알 발사는 자동으로 이루어지는게 좋을겁니다. (드래곤 플라이트 처럼)
여기에서는 무기 발사에 대해 만들어 보겠습니다.
새로운 weapon 그룹을 만들고 bullet 이미지를 로드해서 timer를 등록하여 일정 주기마다 발사하도록 하면 됩니다 해당 내용은 loadBullet 함수로 되어 있습니다.
하지만 총알의 이동은 game loop에서 해주도록 합니다. moveWeapon 함수에서 모든 weapon들의 움직여 줍니다.
local weaponGroup = display.newGroup() local function setup() loadBGImg() loadPlayer() loadBullet() end local function loadBullet() local fireTimer local function fireNow() local bullet = display.newImageRect( "bullet.png", 10, 15 ) bullet.x = ship.x-5; bullet.y = ship.y-5; bullet.name = "laser" physics.addBody( bullet, { isSensor = true } ) weaponGroup:insert( bullet ) local bullet = display.newImageRect( "bullet.png", 10, 15 ) bullet.x = ship.x +5; bullet.y = ship.y-5; bullet.name = "laser" physics.addBody( bullet, { isSensor = true } ) weaponGroup:insert( bullet ) end fireTimer = timer.performWithDelay(850, fireNow, 0) end local function moveWeapon() --Move our lasers up each frame! for i = weaponGroup.numChildren,1,-1 do local weapon = weaponGroup[i] if weapon ~= nil and weapon.y ~= nil then weapon:translate(0, -10); end end end local function gameLoop(event) checkNSpawnEnemy() moveStarField() moveEnemy() moveWeapon() end
충돌처리
충돌은 onCollison에서 처리하게 됩니다. object 이름에 따라서 어떻게 할건지 결정합니다. 문제는 ship 주인공이 사라지게되면 그걸 기반으로 하는 좌표들에서 문제가 발생하므로 해당 처리가 필요합니다.
local function onCollision(event) if event.phase == "began" then local obj1 = event.object1; local obj2 = event.object2; if obj1.name == "laser" and obj2.name == "enemy" or obj1.name == "enemy" and obj2.name == "laser" then display.remove( obj1 ); obj1 = nil display.remove( obj2 ); obj2 = nil --score = score + 100 --Yay points! elseif obj1.name == "ship" and obj2.name == "enemy" or obj2.name == "ship" and obj1.name == "enemy" then display.remove( obj1 ); obj1 = nil display.remove( obj2 ); obj2 = nil --gameOver()--Weve died so call gameover... elseif obj1.name == "enemy" and obj2.name == "blocker" or obj2.name == "enemy" and obj1.name == "blocker"then if obj1.name == "enemy" then display.remove(obj1); obj1 = nil elseif obj2.name == "enemy" then display.remove( obj2 ); obj2 = nil end elseif obj1.name == "laser" and obj2.name == "blocker" or obj2.name == "laser" and obj1.name == "blocker"then if obj1.name == "laser" then display.remove(obj1); obj1 = nil elseif obj2.name == "laser" then display.remove( obj2 ); obj2 = nil end end end end Runtime:addEventListener( "collision", onCollision )
화면을 벗어난 객체 삭제
좌표로 벗어난 객체를 삭제하는 방식이 있겠지만 예제에서는 blocker라는 객체를 만들어 두고 충돌을 이용하여 구현 하였습니다. 위쪽과 아래쪽에 두어서 위쪽은 총알을 아래쪽은 적 객체가 충돌하는지 검사하게 됩니다.
local function loadBlocker() local laserBlock = display.newRect(0,-80,_W,2) laserBlock.name = "blocker" physics.addBody( laserBlock, { isSensor = true } ) bgGroup:insert(laserBlock) local shipBlock = display.newRect(0,_H+30,_W,2) shipBlock.name = "blocker" physics.addBody( shipBlock, { isSensor = true } ) bgGroup:insert(shipBlock) end
이번에 작성한 전체 소스입니다.
display.setStatusBar( display.HiddenStatusBar ) --Hide status bar from the beginning local physics = require ("physics") --Require physics physics.start(); physics.setGravity( 0, 0 ) --Start physics ----------------------------------------------- --*** Set up our variables and group *** ----------------------------------------------- local bgGroup = display.newGroup() local enemyGroup = display.newGroup() local weaponGroup = display.newGroup() local playerGroup = display.newGroup() local _W = display.contentWidth local _H = display.contentHeight local stars1, stars2 --Background moving stars local spawnInt = 0 --Gameloop spawn control local spawnIntMax = 30 --Gameloop max spawn local spawned = 0 --Keep track of enemies local spawnedMax = 10 --Max allowed per level local enemySpeed = 7 --How fast the enemies are local wave = 0 local ship local gameIsActive = true local fireTimer local function loadBGImg() stars1 = display.newImageRect("star1_480_800.png", 480, 800) stars1.x = _W*0.5; stars1.y = _H*0.5 bgGroup:insert(stars1) stars2 = display.newImageRect("star2_480_800.png", 480, 800) stars2.x = _W*0.5; stars2.y = _H*0.5-800 bgGroup:insert(stars2) end local function moveShip( event ) local phase = event.phase if gameIsActive == false then return end print(event.x,event.y,phase) if( event.x > ship.x ) then transition.cancel( ship ) transition.to( ship, {time = (event.x-ship.x)/0.2, x = event.x} ) -- t = d/k end if( event.x < ship.x ) then transition.cancel( ship ) transition.to( ship, {time = -(event.x-ship.x)/0.2, x = event.x} ) -- t = d/k end end local function loadPlayer() ship = display.newImageRect("my.png", 20, 20) ship.x = _W*0.5; ship.y = _H+30; ship.name = "ship" physics.addBody( ship, { isSensor = true } ) Runtime:addEventListener("touch",moveShip) playerGroup:insert(ship) transition.to(ship, {time = 600, y = _H-_H*0.1}) end local function loadBullet() local function fireNow() local bullet = display.newImageRect( "bullet.png", 10, 15 ) bullet.x = ship.x-5; bullet.y = ship.y-5; bullet.name = "laser" physics.addBody( bullet, { isSensor = true } ) weaponGroup:insert( bullet ) local bullet = display.newImageRect( "bullet.png", 10, 15 ) bullet.x = ship.x +5; bullet.y = ship.y-5; bullet.name = "laser" physics.addBody( bullet, { isSensor = true } ) weaponGroup:insert( bullet ) end fireTimer = timer.performWithDelay(850, fireNow, 0) end local function moveWeapon() --Move our lasers up each frame! for i = weaponGroup.numChildren,1,-1 do local weapon = weaponGroup[i] if weapon ~= nil and weapon.y ~= nil then weapon:translate(0, -10); end end end local function loadBlocker() local laserBlock = display.newRect(0,-80,_W,2) laserBlock.name = "blocker" physics.addBody( laserBlock, { isSensor = true } ) bgGroup:insert(laserBlock) local shipBlock = display.newRect(0,_H+30,_W,2) shipBlock.name = "blocker" physics.addBody( shipBlock, { isSensor = true } ) bgGroup:insert(shipBlock) end local function setup() loadBlocker() loadBGImg() loadPlayer() loadBullet() end local function moveStarField() --Move the starfields. stars1:translate(0,2) stars2:translate(0,2) if stars1.y >= (_H*0.5)+800 then stars1.y = (_H*0.5)-800 end if stars2.y >= (_H*0.5)+800 then stars2.y = (_H*0.5)-800 end end local function spawnEnemy() local imageInt = math.random(1,3) local enemy = display.newImageRect("ship_"..imageInt.."_20_20.png",20,20) enemy.x = math.random( 20, _W-20 ); enemy.y = -30; enemy.rotation = 90 enemy.name = "enemy"; physics.addBody( enemy, { isSensor = true } ) enemyGroup:insert( enemy ) if spawned == spawnedMax then wave = wave + 1 --Increase the wave. if wave <= 18 then --Limit max speed/spawn enemySpeed = enemySpeed + 1 spawnIntMax = math.round(spawnIntMax * 0.9) end spawned = 0 --Reset so that the next wave starts from 0 end spawnInt = 0 end local function checkNSpawnEnemy() --Increase the int until it spawns an enemy.. spawnInt = spawnInt + 1 --change spawnIntMax if you want enemies to spawn --faster or slower. if spawnInt == spawnIntMax then spawnEnemy() spawned = spawned + 1 end end local function moveEnemy() --Move the enemies down each frame! local i for i = enemyGroup.numChildren,1,-1 do local enemy = enemyGroup[i] if enemy ~= nil and enemy.y ~= nil then enemy:translate( 0, enemySpeed) end end end local function gameLoop(event) checkNSpawnEnemy() moveStarField() moveEnemy() moveWeapon() end local function gameOver() gameIsActive = false if( fireTimer ~= nil ) then timer.cancel(fireTimer) fireTimer = nil end end local function onCollision(event) if event.phase == "began" then local obj1 = event.object1; local obj2 = event.object2; if obj1.name == "laser" and obj2.name == "enemy" or obj1.name == "enemy" and obj2.name == "laser" then display.remove( obj1 ); obj1 = nil display.remove( obj2 ); obj2 = nil --score = score + 100 --Yay points! elseif obj1.name == "ship" and obj2.name == "enemy" or obj2.name == "ship" and obj1.name == "enemy" then display.remove( obj1 ); obj1 = nil display.remove( obj2 ); obj2 = nil gameOver()--Weve died so call gameover... elseif obj1.name == "enemy" and obj2.name == "blocker" or obj2.name == "enemy" and obj1.name == "blocker"then if obj1.name == "enemy" then display.remove(obj1); obj1 = nil elseif obj2.name == "enemy" then display.remove( obj2 ); obj2 = nil end elseif obj1.name == "laser" and obj2.name == "blocker" or obj2.name == "laser" and obj1.name == "blocker"then if obj1.name == "laser" then display.remove(obj1); obj1 = nil elseif obj2.name == "laser" then display.remove( obj2 ); obj2 = nil end end end end setup() Runtime:addEventListener ("enterFrame", gameLoop) Runtime:addEventListener( "collision", onCollision )
댓글 없음:
댓글 쓰기