A game isn’t much of a game if you can’t interact with it. In this tutorial we are going to look at how to handle touch and click events with Moai. This is however going to present a bit of a problem, you are going to need to have an Android or iOS device in order to test the touch events. The code will still run in the Windows host, but you won’t be able to test touch events.
Speaking of the code:
screenWidth = MOAIEnvironment.screenWidth screenHeight = MOAIEnvironment.screenHeight print("Starting up on:" .. MOAIEnvironment.osBrand .. " version:" .. MOAIEnvironment.osVersion) if screenWidth == nil then screenWidth =640 end if screenHeight == nil then screenHeight = 480 end MOAISim.openWindow("Window",screenWidth,screenHeight) viewport = MOAIViewport.new() viewport:setSize(screenWidth,screenHeight) viewport:setScale(screenWidth,screenHeight) layer = MOAILayer2D.new() layer:setViewport(viewport) MOAIRenderMgr.pushRenderPass(layer) sprite = MOAIGfxQuad2D.new() sprite:setTexture("smile.png") sprite:setRect(-200,-200,200,200) prop = MOAIProp2D.new() prop:setDeck(sprite) prop:setLoc(0,0) layer:insertProp(prop) MOAIGfxDevice.setClearColor(1,1,1,1) function handleClickOrTouch(x,y) prop:setLoc(layer:wndToWorld(x,y)) end if MOAIInputMgr.device.pointer then MOAIInputMgr.device.mouseLeft:setCallback( function(isMouseDown) if(isMouseDown) then handleClickOrTouch(MOAIInputMgr.device.pointer:getLoc()) end -- Do nothing on mouseUp end ) MOAIInputMgr.device.mouseRight:setCallback( function(isMouseDown) if(isMouseDown) then MOAIGfxDevice.setClearColor(math.random(0,1),math.random(0,1),math.random(0,1),1) end end ) else -- If it isn't a mouse, its a touch screen... or some really weird device. MOAIInputMgr.device.touch:setCallback ( function ( eventType, idx, x, y, tapCount ) if (tapCount > 1) then MOAIGfxDevice.setClearColor(math.random(0,1),math.random(0,1),math.random(0,1),1) elseif eventType == MOAITouchSensor.TOUCH_DOWN then handleClickOrTouch(x,y) end end ) end
Once again, we are building on our earlier example; and once again, we will not be covering those parts we already covered. We are changing the functionality slightly. Now in the event of a touch or left click, we are repositioning the happy sprite to the location the user clicked. If the user double taps or right clicks, we change the background color… what can I say, not everyone loves white or hot pink.
Here is the program in action:
Let’s take a look at the new code, starting from the top:
function handleClickOrTouch(x,y) prop:setLoc(layer:wndToWorld(x,y)) end
Touch and click events are two different events, but we want to share the same code when they happen, in this case a method called handleClickOrTouch. It takes the x and y locations of the mouse cursor or finger that the touch/click happened at. In the event of a touch, we simply want to move the happy face prop to the location of the touch. First though, we need to translate the touch coordinates from window space to world space, which is accomplished with layer:wndToWorld().
if MOAIInputMgr.device.pointer then
MOAITInputMgr is a global object containing the various input devices that host platform supports. Keep in mind, if your host does not support a given device, it will not exist in MOAIInputManager. That is exactly what we are checking here, to see if device.pointer has been defined, which will only be defined if the host supports a mouse.
The following types of input are *potentially* supported:
- MOAIButtonSensor
- MOAICompassSensor
- MOAIJoystickSensor
- MOAIKeyboardSensor
- MOAILocationSensor
- MOAIMotionSensor
- MOAIPointerSensor
- MOAITouchSensor
- MOAIWheelSensor
The official documentation for MOAIInputMgr is completely empty, so if you are looking for more details, the course file MOAIInputMgr.cpp is perhaps your best source for more information.
Once we have determined that the host device does in fact support a mouse pointer, we run the following code:
MOAIInputMgr.device.mouseLeft:setCallback( function(isMouseDown) if(isMouseDown) then handleClickOrTouch(MOAIInputMgr.device.pointer:getLoc()) end -- Do nothing on mouseUp end ) MOAIInputMgr.device.mouseRight:setCallback( function(isMouseDown) if(isMouseDown) then MOAIGfxDevice.setClearColor(math.random(0,1),math.random(0,1),math.random(0,1),1) end end )
First we register a callback function for mouseLeft, which takes a single bool parameter, indicating if the mouse button was pressed or released. In the event that the mouse button was indeed pressed, we call the handleClickOrTouch function, passing in the mouse coordinates be obtain by calling MOAIInputMgr.device.pointer:getLoc(). We simply do nothing in the event of a mouse up, um.. event.
Next we register another callback, this time for the right mouse button. In this case if the right mouse button was indeed pressed, we change the background to a random color.
So, that is what happens if we detected a mouse; if we don’t detect a mouse, we instead register a touch event handlers:
else -- If it isn't a mouse, its a touch screen... or some really weird device. MOAIInputMgr.device.touch:setCallback ( function ( eventType, idx, x, y, tapCount ) if (tapCount > 1) then MOAIGfxDevice.setClearColor(math.random(0,1),math.random(0,1),math.random(0,1),1) elseif eventType == MOAITouchSensor.TOUCH_DOWN then handleClickOrTouch(x,y) end end ) end
While the left/rightButton event callbacks were passed a simple bool, the touch callback get’s a fair bit more information. The following values are passed to the touch callback function:
eventType: The type of event that occurred. The value will be either TOUCH_UP or TOUCH_DOWN
idx: It touch index in case multiple simultaneous touches occurred
x: The x coordinates of where the touch happened on screen
y: The y coordinates of where the touch happened on screen
tapCount: the number of taps that occurred
In the event that multiple taps occurred, we change the window background color to a random RGB value. Otherwise, it was a single touch, in which case we call handleClicksOrTouch passing in the x,y value passed in the touch callback.
The parameters for the touch callback function were also not documented, so it took a little bit of digging to divine exactly what they are. If you are interested, the actual code for setting the parameters is in the method MOAITouchSensor::HandleEvent, in the file MOAITouchSensor.cpp.
Now we have the ability to be all touchy feely, we are yet another step further along in our adventures in Moai-land. Stay tuned for the next exciting episode where we journey even deeper! There may even be a prize at the end(*)!!!
(*) – the prize is a lie.