{"id":200,"date":"2011-09-24T15:21:30","date_gmt":"2011-09-24T15:21:30","guid":{"rendered":"http:\/\/www.drmop.com\/?p=200"},"modified":"2011-09-27T19:28:47","modified_gmt":"2011-09-27T19:28:47","slug":"marmalade-sdk-tutorial-touch-and-multi-touch","status":"publish","type":"post","link":"http:\/\/www.drmop.com\/index.php\/2011\/09\/24\/marmalade-sdk-tutorial-touch-and-multi-touch\/","title":{"rendered":"Marmalade SDK Tutorial &#8211; Touch and Multi-touch"},"content":{"rendered":"<p>This tutorial is part of the Marmalade SDK tutorials collection. To see the tutorials index\u00a0<a title=\"Marmalade SDK tutorials index\" href=\"http:\/\/www.drmop.com\/?page_id=91\">click here<\/a><\/p>\n<p><a title=\"Marmalade SDK tutorials index\" href=\"http:\/\/www.drmop.com\/?page_id=91\"><\/a>A little rushed this weekend but I did kind of commit myself to producing another tutorial this weekend, so here goes.<\/p>\n<p>This tutorial is going to cover handling touch and multi-touch pointer events using the Marmalade SDK. Thankfully the Marmalade SDK makes this pretty simple as you will soon see.<\/p>\n<p>As usual if you just want the code then <a title=\"Marmalade SDK Touch and Multi-touch Tutorial Source Code\" href=\"http:\/\/www.drmop.com\/wp-content\/uploads\/2011\/09\/Touch.zip\">grab it from here<\/a>. if you want the details then read on. If you just want the details on how to use the CInput class then jump straight to the \u201cUsing CInput\u201d section<\/p>\n<p>Oh its worth noting that week by week I am going to keep updating the original Iw2D DrawSprite example with the systems that we put together. This week for example, I have added a new CInput class. I like to try and keep code for separate systems in their own neat little classes because a) it makes the code easier to understand b) you can strip out the code and use it as-is with no modification c) its good programming practice. I would ordinarily create systems such as CInput using a singleton, but for the sake of readability and so that you don\u2019t have to run off finding out about the likes of singletons, I have simply declared the concrete version of CInput as a global (slap on the wrist for me, but whatever makes the code easier to understand)<\/p>\n<h2>Marmalade Events and Callbacks<\/h2>\n<p>The Marmalade pointer system handles screen touches using an event system. This means that when something happens to the pointer (the users finger or a stylus touches the phone or tablets screen for example) the system calls a function to handle it. The Marmalade SDK uses what are called <strong>Callbacks<\/strong> to implement this type of event notification system. A call back is basically a function that we define that gets called back by the Marmalade system when the event occurs. The system usually passes some parameters to the call back function to let us know what the heck it wants. Here&#8217;s a quick example:<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/\r\n\/\/ HandleSingleTouchButtonCB - The system will call this callback when the user moves their finger on the screen\r\n\/\/<\/span>\r\nvoid HandleSingleTouchButtonCB(s3ePointerEvent* event)\r\n{\r\n    <span style=\"color: #008000;\">\/\/ Please add code to do something about this important event<\/span>\r\n}<\/blockquote>\r\n<\/pre>\n<p>In this example HandleSingleTouchButtonCB gets called by the system when the user touches the screen. Behold, the system has also provided us with some data about the event by way of a pointer to the s3ePointerEvent data type. We can now query this data to find out what the system wants to tell us.<\/p>\n<p>Taking a quick look at the s3ePointerEvent data type we discover that there is some pretty interesting stuff in there that we can use:<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #0000ff;\">typedef <\/span><span style=\"color: #0000ff;\">struct <\/span><span style=\"color: #ff9900;\">s3ePointerTouchEvent<\/span>\r\n{\r\n    <span style=\"color: #008000;\">\/**\r\n     * ID of the touch. The ID given to a touch is equal to the number\r\n     * of simultaneous touches active at the time the touch began. This ID\r\n     * can be between 0 and S3E_POINTER_TOUCH_MAX-1 inclusive\r\n     *\/<\/span>\r\n    uint32 m_TouchID;\r\n    <span style=\"color: #008000;\">\/**  Whether the touch started (1) or ended (0).*\/<\/span>\r\n    uint32 m_Pressed;\r\n    <span style=\"color: #008000;\">\/** Position X. *\/<\/span>\r\n    int32  m_x;\r\n    <span style=\"color: #008000;\">\/** Position Y. *\/<\/span>\r\n    int32  m_y;\r\n} <span style=\"color: #ff9900;\">s3ePointerTouchEvent<\/span>;<\/blockquote>\r\n<\/pre>\n<p>Ok, so some of you may be thinking, how do I tell the Marmalade SDK to use my callback when such an event does occur? Because call backs are so useful the Marmalade SDK has lots of function for registering a callback with the system. The one we are interested in for the pointer is called:<\/p>\n<pre>S3E_API s3eResult s3ePointerRegister(<strong>s3ePointerCallback cbid, s3eCallback fn<\/strong>, void* userData);<\/pre>\n<ul>\n<li>cbid \u2013 This represents a constant that identifies which pointer event you would like to be notified about<\/li>\n<li>fn \u2013 The address of the callback function that you would like Marmalade to call when the event occurs<\/li>\n<\/ul>\n<p>Here\u2019s how we would set one up to listen for single touch events<\/p>\n<pre>s3ePointerRegister(S3E_POINTER_BUTTON_EVENT, (s3eCallback)HandleSingleTouchButtonCB, NULL);<\/pre>\n<p>Now that is registered, whenever the system receives a screen touched event you will know about it as HandleSingleTouchButtonCB() will be called<\/p>\n<p>Oh and be nice to the system and don\u2019t forget to unregister the call back when you are done using it with, such as when you exit the game:<\/p>\n<pre>s3ePointerUnRegister(S3E_POINTER_BUTTON_EVENT, (s3eCallback)HandleSingleTouchButtonCB);<\/pre>\n<h2>Types of Marmalade Pointer Events<\/h2>\n<p>The Marmalade SDk currently handles a number of pointer event types:<\/p>\n<ul>\n<li>Touch Event \u2013 Called when the user touches the screen (S3E_POINTER_BUTTON_EVENT)<\/li>\n<li>Motion Event \u2013 Called when the user moves their finger or stylus on the screen (S3E_POINTER_MOTION_EVENT)<\/li>\n<li>Multi-touch Touch Event \u2013 Called when the user touches the screen (S3E_POINTER_TOUCH_EVENT)<\/li>\n<li>Multi-touch Motion Event \u2013 Called when the user moves their finger or stylus on the screen (S3E_POINTER_TOUCH_MOTION_EVENT)<\/li>\n<\/ul>\n<p>To be a good Marmalade developer you should handle all four of these events<\/p>\n<h2>Handling the Four Marmalade Pointer Events<\/h2>\n<p>In the Input example (CInput.cpp) we have declared four call backs to handle all four events:<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/\r\n\/\/ HandleMultiTouchButtonCB - For multitouch devices the system will call this callback when the user touches the screen. This callback is called once for each screen touch\r\n\/\/<\/span>\r\nvoid HandleMultiTouchButtonCB(s3ePointerTouchEvent* event)\r\n{\r\n    <span style=\"color: #008000;\">\/\/ Check to see if the touch already exists<\/span>\r\n    CTouch* touch = g_Input.findTouch(event-&gt;m_TouchID);\r\n    if (touch != NULL)\r\n    {\r\n\t<span style=\"color: #008000;\">\/\/ Yes it does, so update the touch information<\/span>\r\n        touch-&gt;active = event-&gt;m_Pressed != 0;\r\n        touch-&gt;x = event-&gt;m_x;\r\n        touch-&gt;y = event-&gt;m_y;\r\n    }\r\n}\r\n<span style=\"color: #008000;\">\/\/\r\n\/\/ HandleMultiTouchMotionCB - For multitouch devices the system will call this callback when the user moves their finger on the screen. This callback is called once for each screen touch\r\n\/\/<\/span>\r\nvoid HandleMultiTouchMotionCB(s3ePointerTouchMotionEvent* event)\r\n{\r\n    <span style=\"color: #008000;\">\/\/ Check to see if the touch already exists<\/span>\r\n    CTouch* touch = g_Input.findTouch(event-&gt;m_TouchID);\r\n    if (touch != NULL)\r\n    {\r\n\t<span style=\"color: #008000;\">\/\/ Updates the touches positional information<\/span>\r\n        touch-&gt;x = event-&gt;m_x;\r\n        touch-&gt;y = event-&gt;m_y;\r\n    }\r\n}\r\n<span style=\"color: #008000;\">\/\/\r\n\/\/ HandleSingleTouchButtonCB - The system will call this callback when the user touches the screen\r\n\/\/<\/span>\r\nvoid HandleSingleTouchButtonCB(s3ePointerEvent* event)\r\n{\r\n    CTouch* touch = g_Input.getTouch(0);\r\n    touch-&gt;active = event-&gt;m_Pressed != 0;\r\n    touch-&gt;x = event-&gt;m_x;\r\n    touch-&gt;y = event-&gt;m_y;\r\n}\r\n<span style=\"color: #008000;\">\/\/\r\n\/\/ HandleSingleTouchMotionCB - The system will call this callback when the user moves their finger on the screen\r\n\/\/<\/span>\r\nvoid HandleSingleTouchMotionCB(s3ePointerMotionEvent* event)\r\n{\r\n    CTouch* touch = g_Input.getTouch(0);\r\n    touch-&gt;x = event-&gt;m_x;\r\n    touch-&gt;y = event-&gt;m_y;\r\n}<\/blockquote>\r\n<\/pre>\n<p>Eik! I know, looks a bit messy, but callbacks usually do look a bit out of place. That said I do love callbacks!<\/p>\n<p>The call back functions are very small and very simple. They basically pull the event data (pointer position and button status) and move them into a CTouch array inside the CInput class, where we can later access them in our code. Note the use of my nasty global concrete version of CInput g_Input. Ordinarily I would use a singleton for stuff like this (mental note, topic for another blog)<\/p>\n<p>Now that callbacks are more or less out of the way we will proceed with looking at the CInput class in a little more detail<\/p>\n<h2>The CInput Class<\/h2>\n<p>Firstly lets take a look at the CInput initialisation code:<\/p>\n<pre>\r\n<blockquote>\r\n\r\nbool CInput::Init()\r\n{\r\n    <span style=\"color: #008000;\">\/\/ Check to see if the device that we are running on supports the pointer<\/span>\r\n    Available = s3ePointerGetInt(S3E_POINTER_AVAILABLE) ? true : false;\r\n    if (!Available)\r\n        return false;    <span style=\"color: #008000;\">\/\/ No pointer support<\/span>\r\n\r\n    <span style=\"color: #008000;\">\/\/ Clear out the touches array<\/span>\r\n    for (int t = 0; t &lt; MAX_TOUCHES; t++)\r\n    {\r\n        Touches[t].active = false;\r\n        Touches[t].id = 0;\r\n    }\r\n\r\n    <span style=\"color: #008000;\">\/\/ Determine if the device supports multi-touch<\/span>\r\n    IsMultiTouch = s3ePointerGetInt(S3E_POINTER_MULTI_TOUCH_AVAILABLE) ? true : false;\r\n\r\n    <span style=\"color: #008000;\">\/\/ For multi-touch devices we handle touch and motion events using different callbacks<\/span>\r\n    if (IsMultiTouch)\r\n    {\r\n        s3ePointerRegister(S3E_POINTER_TOUCH_EVENT, (s3eCallback)HandleMultiTouchButtonCB, NULL);\r\n        s3ePointerRegister(S3E_POINTER_TOUCH_MOTION_EVENT, (s3eCallback)HandleMultiTouchMotionCB, NULL);\r\n    }\r\n    else\r\n    {\r\n        s3ePointerRegister(S3E_POINTER_BUTTON_EVENT, (s3eCallback)HandleSingleTouchButtonCB, NULL);\r\n        s3ePointerRegister(S3E_POINTER_MOTION_EVENT, (s3eCallback)HandleSingleTouchMotionCB, NULL);\r\n    }\r\n\r\n    return true; <span style=\"color: #008000;\">\/\/ Pointer support<\/span>\r\n}<\/blockquote>\r\n<\/pre>\n<p>Like any good programmer we are checking to ensure that the pointer system is available on the device that we are running on, with so many different handsets out there, who knows if there are some with no pointer support?<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/ Check to see if the device that we are eunning on supports the pointer<\/span>\r\nAvailable = s3ePointerGetInt(S3E_POINTER_AVAILABLE) ? true : false;<\/blockquote>\r\n<\/pre>\n<p>Its better to know up front and inform the user that your game or app is not compatible with their phone because it does not support the pointer.<\/p>\n<p>Next, we determine if the device supports multi-touch. Note that many Android phones and tablets do not support multi-touch, so you will have to think carefully about your game or apps design before targeting Android.<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/ Determine if the device supports multi-touch<\/span>\r\nIsMultiTouch = s3ePointerGetInt(S3E_POINTER_MULTI_TOUCH_AVAILABLE) ? true : false;<\/blockquote>\r\n<\/pre>\n<p>Lastly, we register two callbacks depending upon whether or not the device supports multi-touch:<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/ For multi-touch devices we handle touch and motion events using different callbacks<\/span>\r\nif (IsMultiTouch)\r\n{\r\n    s3ePointerRegister(S3E_POINTER_TOUCH_EVENT, (s3eCallback)HandleMultiTouchButtonCB, NULL);\r\n    s3ePointerRegister(S3E_POINTER_TOUCH_MOTION_EVENT, (s3eCallback)HandleMultiTouchMotionCB, NULL);\r\n}\r\nelse\r\n{\r\n    s3ePointerRegister(S3E_POINTER_BUTTON_EVENT, (s3eCallback)HandleSingleTouchButtonCB, NULL);\r\n    s3ePointerRegister(S3E_POINTER_MOTION_EVENT, (s3eCallback)HandleSingleTouchMotionCB, NULL);\r\n}<\/blockquote>\r\n<\/pre>\n<p>Ok, so now we have initialised the input system using g_Input.Init(); we need to ensure that the pointer system gets regularly updated. To do that we call g_Input.Update();<\/p>\n<p>This method is very simple:<\/p>\n<pre>\r\n<blockquote>\r\n\r\nvoid CInput::Update()\r\n{\r\n   <span style=\"color: #008000;\"> \/\/ Update the pointer if it is available<\/span>\r\n    if (Available)\r\n        s3ePointerUpdate();\r\n}<\/blockquote>\r\n<\/pre>\n<p>Update() simply calls the Marmalade SDK\u2019s s3ePointerUpdate() function to update the pointer system and call our callbacks when pointer events occur. Note that this must be called every game frame, so ensure that its placed somewhere in your main loop (near the beginning if possible)<\/p>\n<h2>Using the Cinput Class<\/h2>\n<p>If we now turn our attention towards Main.cpp, we can take a quick look at what has changed from DrawSprite_Iw2D.<\/p>\n<p>Well the first thing is the inclusion of the CInput.h header file.<\/p>\n<p>Next we initialise the Cinput class:<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/ Initialise the input system<\/span>\r\ng_Input.Init();<\/blockquote>\r\n<\/pre>\n<p>Because the example supports multi-touch we create a few variables to hold the position of our two sprites so we can move them independently<\/p>\n<pre>\r\n<blockquote>\r\n\r\nint        sprite1_pos_x = surface_width \/ 2;\r\nint        sprite1_pos_y = surface_height \/ 2;\r\nint        sprite2_pos_x = surface_width \/ 2;\r\nint        sprite2_pos_y = surface_height \/ 2;<\/blockquote>\r\n<\/pre>\n<p>In our main loop we update the sprites based on where the user touches the screen:<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/ Update pointer system<\/span>\r\ng_Input.Update();\r\nif (g_Input.getTouchCount() != 0)\r\n{\r\n    <span style=\"color: #008000;\">\/\/ Get the first touch position<\/span>\r\n    CTouch* touch = g_Input.getTouch(0);\r\n    if (touch != NULL)\r\n    {\r\n        sprite1_pos_x = touch-&gt;x;\r\n        sprite1_pos_y = touch-&gt;y;\r\n        sprite2_pos_x = sprite1_pos_x;\r\n        sprite2_pos_y = sprite1_pos_y;\r\n    }\r\n\r\n    <span style=\"color: #008000;\">\/\/ if multi-touch is available then move 2nd sprite to 2nd touch position<\/span>\r\n    if (g_Input.isMultiTouch())\r\n    {\r\n        if (g_Input.getTouchCount() &gt; 1)\r\n        {\r\n            touch = g_Input.getTouch(1);\r\n            if (touch != NULL)\r\n            {\r\n                sprite2_pos_x = touch-&gt;x;\r\n                sprite2_pos_y = touch-&gt;y;\r\n            }\r\n        }\r\n    }\r\n}<\/blockquote>\r\n<\/pre>\n<p>Ok, this bit of code is no longer a bit of code and looks a bit meaty. However, it is very simple to understand.<\/p>\n<p>Firstly we check to see if there has been any touches by getting the touch count from CInput. If there are touches present then we get the first touch and set both sprites to the position of the touch. This will move both sprites to wherever the user taps the screen.<\/p>\n<p>The second part checks to see if there has been more than one touch, if so then we get the 2nd touch and move the 2nd sprite to its position.<\/p>\n<p>Note that I am just getting the touches by their index in the touches list and not by their ID. In a proper multi-touch system you should ideally track touches by their ID and not their index in the touches list. But for this example, this way suffices.<\/p>\n<p>And finally we draw our sprites at their new positions:<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/ Draw two sprites<\/span>\r\nDrawSprite(image1, sprite1_pos_x, sprite1_pos_y, -sprite_angle, (iwfixed)(IW_GEOM_ONE * 2));\r\nDrawSprite(image2, sprite2_pos_x, sprite2_pos_y, sprite_angle, IW_GEOM_ONE);<\/blockquote>\r\n<\/pre>\n<h2>Multi-touch Simulation using the Simulator<\/h2>\n<p>The Marmalade SDK simulator will allow you to simulate multi-touch functionality in your application but you firstly need to enable it. To enable this functionality you need to:<\/p>\n<ul>\n<li>Go to the simulator menu and select Configuration Pointer<\/li>\n<li>Tick \u201cReport multi-touch available\u201d and \u201cenable multi-touch simulation mode\u201d<\/li>\n<\/ul>\n<p>Now that you have enabled multi-touch simulation you can use the middle mouse button to place touches. You can move the touches around by holding the middle mouse button down over the placed touch and move it. To  remove a multi-touch touch, simply click the middle mouse button over the touch again.<\/p>\n<p>Well that concludes this tutorial. I hope you all find it of some use. You can download the associated <a title=\"Marmalade SDK Touch and Multi-touch Tutorial Source Code\" href=\"http:\/\/www.drmop.com\/wp-content\/uploads\/2011\/09\/Touch.zip\">touch code project from here<\/a><\/p>\n<p>Happy coding and stay away from rickety old bridges!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial is part of the Marmalade SDK tutorials collection. To see the tutorials index\u00a0click here A little rushed this weekend but I did kind of commit myself to producing another tutorial this weekend, so here goes. This tutorial is going to cover handling touch and multi-touch pointer events using the Marmalade SDK. Thankfully the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,13,29,43,44,42,28,3,45,1],"tags":[55,718,54,53],"class_list":["post-200","post","type-post","status-publish","format-standard","hentry","category-airplay-sdk","category-android-app-development","category-blackberry-playbook","category-blackberry-playbook-app-development","category-game-and-app-development","category-ios-app-development","category-marmalade-sdk","category-programming","category-samsung-bada-development","category-uncategorized","tag-cinput-class","tag-marmalade-sdk","tag-multi-touch-tutorial","tag-touch-example"],"_links":{"self":[{"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/posts\/200","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/comments?post=200"}],"version-history":[{"count":7,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/posts\/200\/revisions"}],"predecessor-version":[{"id":208,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/posts\/200\/revisions\/208"}],"wp:attachment":[{"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/media?parent=200"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/categories?post=200"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/tags?post=200"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}