It's possible to use the game on your device now for some simple gameplay dodging rocks, although there's no progress or way to lose or advance. It's time to start adding more interactivity by accepting shake and touch inputs to control the player ship's laser fire and hyperspace jump.
Since we won't want the ship to be destroyed by its own lasers, we're going to include it in a collision group much as we did with the asteroids. Start by opening spaceship.lua
and adding a line to that effect in the body definition used by the player constructor. Save that file and create a new file at the top level of the project, laser.lua
, for the first stages of this task.
Also, we'll set a timer on the laser objects so that they disappear after a moment if they don't hit anything. To do this, we'll need an object that receives clock
events to track the passage of time.
This module is a constructor, so we'll create the framework for a function for it to return as follows:
return function(clock, life, origin, direction, image) end
return function(clock, life, origin, direction, image) local self = display.newImage(origin.parent, image) return self end
return function(clock, life, origin, direction, image) local self = display.newImage(origin.parent, image) self.rotation = direction direction = math.rad(direction) local dX, dY = math.cos(direction), math.sin(direction) self.x, self.y = origin.x + self.width * dX, origin.y + self.width * dY return self end
local dX, dY = math.cos(direction), math.sin(direction) self.x, self.y = origin.x + self.width * dX, origin.y + self.width * dY physics.addBody(self, "dynamic", body) self.isSensor = true return self
local body = {filter = {groupIndex = -1}}
return function(clock, life, origin, direction, image)
local self = display.newImage(origin.parent, image)
clock
events on its governing object and respond to them:self.isSensor = true clock:addEventListener('clock', self) function self:clock(event) end return self
function self:clock(event) life = life - event.delta / 1000 if life <= 0 then event.clock:removeEventListener('clock', self) self:removeSelf() end end
self:removeSelf() end end local speed = 400 self:setLinearVelocity(speed * dX, speed * dY) return self
Save laser.lua
and open game.lua
. We'll respond to physical touch events on the device by dispatching semantic touch events to the game object for the player ship to respond to.
createScene
and other scene event handlers, add a handler for touch
events:self:dispatchEvent{name='Yaw'; value = lateral * 64} end function scene:touch(event) end function scene:createScene( event )
function scene:touch(event) if event.phase == 'began' then self:dispatchEvent{name = 'Fire'; phase = 'began'} end end
if event.phase == 'began' then self:dispatchEvent{name = 'Fire'; phase = 'began'} elseif event.phase == 'ended' or event.phase == 'cancelled' then self:dispatchEvent{name = 'Fire'; phase = 'ended'} end
Runtime
. Since we only want to respond while the scene is fully loaded, we'll start and stop listening in response to enterScene
and exitScene
events:Runtime:addEventListener('Tilt', self) Runtime:addEventListener('touch', self) self:Start() end function scene:exitScene( event ) Runtime:removeEventListener('Tilt', self) Runtime:removeEventListener('touch', self) self:Stop()
Now that fire events are being transmitted, the player
object needs to respond to them. We'll use a field on the player
object, player.FireCounter
, to track whether there's an active touch being used as a Fire
command. This field will be nil when the player is not firing, and the number of seconds until the ship can fire again when the player is firing.
game.lua
and open player.lua
. After the registration for Fire
events, add a handler for them, which will toggle the player between firing and non-firing states:input:addEventListener('Fire', self) function self:Fire(event) if event.phase == 'began' then self.FireCounter = 0 elseif event.phase == 'ended' then self.FireCounter = nil end end input:addEventListener('Jump', self)
function self:clock(event) if self.FireCounter then self.FireCounter = self.FireCounter - event.delta / 1000 if self.FireCounter <= 0 then self.FireCounter = self.FireCounter + 0.5 end end local dX, dY = self:getLinearVelocity()
if self.FireCounter <= 0 then
self.FireCounter = self.FireCounter + 0.5
laser(event.clock, 1, self, self.rotation, "effect/laserGreen.png")
end
require "math.pythagorean"
local laser = require "laser"
return function(input, world, x, y)
While we're completing the controls the player can respond to, we'll take a moment to add the hyperspace function.
player.lua
, add a handler function under the listener registration for Jump
events:input:addEventListener('Jump', self) function self:Jump(event) end return self
function self:Jump(event) self.x, self.y = event.x, event.y self:setLinearVelocity(0, 0) end
player.lua
and return to game.lua
so that we can add a listener for Shake
events:self:dispatchEvent{name='Yaw'; value = lateral * 64} end function scene:Shake(event) end function scene:touch(event)
World
object, and send a Jump
event with those coordinates to move the player there:function scene:Shake(event) local x, y = self.World:Random() self:dispatchEvent{name = 'Jump'; x = x, y = y} end
Shake
events at the same times we do for Tilt
events, since they're provided by the same source.Runtime:addEventListener('Tilt', self) Runtime:addEventListener('Shake', self) Runtime:addEventListener('touch', self) self:Start() end function scene:exitScene( event ) Runtime:removeEventListener('Tilt', self) Runtime:removeEventListener('Shake', self) Runtime:removeEventListener('touch', self)
We created a module to manage temporary laser objects and destroy them cleanly after they hit something. We translated two different events about device information into their equivalent events with game significance, and programmed the player object to respond to them with suitable actions.
3.139.67.5