{"id":139,"date":"2011-09-16T21:19:59","date_gmt":"2011-09-16T21:19:59","guid":{"rendered":"http:\/\/www.drmop.com\/?p=139"},"modified":"2011-09-25T10:06:54","modified_gmt":"2011-09-25T10:06:54","slug":"marmalade-sdk-tutorial-loading-bitmaps-and-rendering-sprites-with-iw2d","status":"publish","type":"post","link":"http:\/\/www.drmop.com\/index.php\/2011\/09\/16\/marmalade-sdk-tutorial-loading-bitmaps-and-rendering-sprites-with-iw2d\/","title":{"rendered":"Marmalade SDK Tutorial &#8211; Loading bitmaps and rendering sprites with Iw2D"},"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>Carrying on from my previous Marmalade SDK tutorial that covered creating a basic game loop, I promised that I would move onto something a little more interesting. Well I was going to write this some other day, but I wanted to get it out of the way. As usual if your here just for the code then you can <a title=\"DrawSprite Marmalade SDK Iw2D tutorial source code\" href=\"http:\/\/www.drmop.com\/wp-content\/uploads\/2011\/09\/DrawSprite_Iw2D.zip\">download it from here<\/a><\/p>\n<p>Ok, in this tutorial we are going to cover drawing a sprite using Marmalade\u2019s Iw2D module. if you do not know what Iw2D is then its Marmalade\u2019s simple 2D drawing API that you can use for drawing a whole host of simple 2D objects, including:<\/p>\n<ul>\n<li>Lines<\/li>\n<li>Arcs<\/li>\n<li>Rectangles<\/li>\n<li>Polygons<\/li>\n<li>Images<\/li>\n<li>Text<\/li>\n<\/ul>\n<p>Primitives can be rotated, translated, scaled and flipped. You can also set the colour and opacity.<\/p>\n<p>Its worth noting at this point that Iw2D is context (or state) based (like Open GL). which means that if you modify a parameter within the context, such as a transform or a colour then it will be applied to all rendered primitives until you change the parameter again. So for example, if you set the current colour to red using Iw2DSetColour(0xff0000ff) then all primitives will have a red tint until you change the colour.<\/p>\n<p>Ok, so lets get to some code. I put together some quick sprite rendering code that renders two sprites using rotation, scaling and translation:<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/ Marmalade headers<\/span>\r\n#include \"s3e.h\"\r\n#include \"Iw2D.h\"\r\n#include \"IwGx.h\"\r\n\r\nvoid DrawSprite(CIw2DImage* image, int at_pos_x, int at_pos_y, iwangle angle = 0, iwfixed scale = IW_GEOM_ONE)\r\n{\r\n    <span style=\"color: #008000;\">\/\/ Set the rotation transform<\/span>\r\n    CIwMat2D m;\r\n    m.SetRot(angle);\r\n\r\n    <span style=\"color: #008000;\">\/\/ Scale the transform<\/span>\r\n    m.ScaleRot(scale);\r\n\r\n    <span style=\"color: #008000;\">\/\/ Translate the transform<\/span>\r\n    m.SetTrans(CIwSVec2(at_pos_x, at_pos_y));\r\n\r\n    <span style=\"color: #008000;\">\/\/ Set this transform as the active transform for Iw2D<\/span>\r\n    Iw2DSetTransformMatrix(m);\r\n\r\n    <span style=\"color: #008000;\">\/\/ Render the sprite<\/span>\r\n    int x = -(image-&gt;GetWidth() \/ 2);\r\n    int y = -(image-&gt;GetHeight() \/ 2);\r\n    Iw2DDrawImage(image, CIwSVec2(x, y));\r\n}\r\n\r\nint main()\r\n{\r\n    <span style=\"color: #008000;\">\/\/ Initialise Marmalade graphics system and Iw2D module<\/span>\r\n    IwGxInit();\r\n    Iw2DInit();\r\n\r\n    <span style=\"color: #008000;\">\/\/ Set the default background clear colour<\/span>\r\n    IwGxSetColClear(0x40, 0x40, 0x40, 0);\r\n\r\n    <span style=\"color: #008000;\">\/\/ Create two images from PNG files<\/span>\r\n    CIw2DImage* image1 = Iw2DCreateImage(\"test1.png\");\r\n    CIw2DImage* image2 = Iw2DCreateImage(\"test2.png\");\r\n\r\n    <span style=\"color: #008000;\">\/\/ Get the display surface width and height<\/span>\r\n    int surface_width = Iw2DGetSurfaceWidth();\r\n    int surface_height = Iw2DGetSurfaceHeight();\r\n\r\n    <span style=\"color: #008000;\">\/\/ Dynamic variables<\/span>\r\n    iwangle angle = 0;\r\n\r\n   <span style=\"color: #008000;\"> \/\/ Main Game Loop<\/span>\r\n    while (!s3eDeviceCheckQuitRequest())\r\n    {\r\n        <span style=\"color: #008000;\">\/\/ Update keyboard system<\/span>\r\n        s3eKeyboardUpdate();\r\n        if (s3eKeyboardGetState(s3eKeyAbsBSK) &amp; S3E_KEY_STATE_DOWN)    \/\/ Back key is used to exit on some platforms\r\n            break;\r\n\r\n        <span style=\"color: #008000;\">\/\/ Update pointer system<\/span>\r\n        s3ePointerUpdate();\r\n\r\n        <span style=\"color: #008000;\">\/\/ Clear the screen<\/span>\r\n        IwGxClear(IW_GX_COLOUR_BUFFER_F | IW_GX_DEPTH_BUFFER_F);\r\n\r\n       <span style=\"color: #008000;\"> \/\/ Draw two sprites<\/span>\r\n        DrawSprite(image1, surface_width \/ 2, surface_height \/ 2, -angle, (iwfixed)(IW_GEOM_ONE * 2));\r\n        DrawSprite(image2, surface_width \/ 2, surface_height \/ 2, angle, IW_GEOM_ONE);\r\n\r\n        <span style=\"color: #008000;\">\/\/ Spin our awesome sprite<\/span>\r\n        angle += IW_ANGLE_2PI \/ 60;\r\n\r\n        <span style=\"color: #008000;\">\/\/ Show the surface<\/span>\r\n        Iw2DSurfaceShow();\r\n\r\n        <span style=\"color: #008000;\">\/\/ Yield to the opearting system<\/span>\r\n        s3eDeviceYield(0);\r\n    }\r\n\r\n    <span style=\"color: #008000;\">\/\/ Safely cleanup images<\/span>\r\n    if (image2 != NULL)\r\n        delete image2;\r\n    if (image1 != NULL)\r\n        delete image1;\r\n\r\n    <span style=\"color: #008000;\">\/\/ Shut down Marmalade graphics system and the Iw2D module<\/span>\r\n    Iw2DTerminate();\r\n    IwGxTerminate();\r\n\r\n    return 0;\r\n}<\/blockquote>\r\n<\/pre>\n<p>The main() function code looks pretty much the same as in our BasicMKB example except for a few additions (marked in bold). The additions are:<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/ Create two images from PNG files<\/span>\r\nCIw2DImage* image1 = Iw2DCreateImage(\"test1.png\");\r\nCIw2DImage* image2 = Iw2DCreateImage(\"test2.png\");<\/blockquote>\r\n<\/pre>\n<p>These two lines basically create two images from PNG files that I have added to our projects MKB file. if you open up the DrawSprite_Iw2D.mkb file and take a look, you will notice that the following two lines have appeared in the assets section:<\/p>\n<p>test1.png<br \/>\ntest2.png<\/p>\n<p>This instructs Marmalade to include these files when we deploy our app or game to a phone, tablet or TV<\/p>\n<p>Its worth noting at this point that if I had forgotten to add these two lines then my awesome sprites would not have been included in the build when I go to deploy it to an actual device, but it would still work on the emulator no problem (I\u2019ve fallen for this many times)<\/p>\n<p>We also added new code to get the width and height of the drawing surface that we are going to draw our sprites to using:<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/ Get the display surface width and height<\/span>\r\nint surface_width = Iw2DGetSurfaceWidth();\r\nint surface_height = Iw2DGetSurfaceHeight();<\/blockquote>\r\n<\/pre>\n<p>We will later use these values to centre our sprite on the display because it looks much nicer than being stuck in the top left hand corner.<\/p>\n<p>Because we want our sprites to do something a little more interesting than just sitting there in the middle of the screen, we are going to spin them (spinning stuff usually impresses people). In order to do that we need track an angle and change it every game frame.<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/ Dynamic variables<\/span>\r\niwangle angle = 0;<\/blockquote>\r\n<\/pre>\n<p>We create our angle variable of type iwangle. You could just use int if you like but, then the variable would lose some of its meaning. Angles in Marmalade are integer and the range of 360 degrees is defined by the constant IW_ANGLE_2PI<\/p>\n<p>In the main loop we use the following two lines of code to render our sprites:<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/ Draw two sprites<\/span>\r\nDrawSprite(image1, surface_width \/ 2, surface_height \/ 2, -angle, (iwfixed)(IW_GEOM_ONE * 2));\r\nDrawSprite(image2, surface_width \/ 2, surface_height \/ 2, angle, IW_GEOM_ONE);<\/blockquote>\r\n<\/pre>\n<p>I decided to stick all of the sprite rendering code into a nice easy to use re-usable function so that you just whip off with it and use it. It also keeps my code nice and readable.<\/p>\n<p>Lastly, we update the angle of the sprites using:<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/ Spin our awesome sprite<\/span>\r\nangle += IW_ANGLE_2PI \/ 60;<\/blockquote>\r\n<\/pre>\n<p>This spins our sprites 6 degrees every game frame (pretty fast in other words)<\/p>\n<p>Ok, now those bits are out of the way, we will move onto the DrawSprite() function. Unfortunately, you do bump into matrices at this point, if you do not know what they are then do not worry as long as you know how to use them. In a nutshell, A matrix is a mathematical object that allows you to transform a set of coordinates. In our case we are using it to rotate, scale and then translate (move) the coordinates of our sprite. The important parts of code in DrawSprite() that I want to point out are:<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/ Set this transform as the active transform for Iw2D<\/span>\r\nIw2DSetTransformMatrix(m);<\/blockquote>\r\n<\/pre>\n<p>Here we tell Iw2D to set the \u201ccurrent\u201d transform to use when drawing \u201canything\u201d. Remember that Iw2D is context based and this transform will be remembered, so if you attempt to draw something else without again changing the transform then it will be drawn in the same position, at the same angle and at the same scale. Note that you can reset the current transform back to normal using Iw2DSetTransformMatrix(CIwMat2D::g_Identity). The identity matrix is the default transformation matrix that has no rotation, no translation and no scaling.<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/ Render the sprite<\/span>\r\nint x = -(image-&gt;GetWidth() \/ 2);\r\nint y = -(image-&gt;GetHeight() \/ 2);\r\nIw2DDrawImage(image, CIwSVec2(x, y));<\/blockquote>\r\n<\/pre>\n<p>This section of code draws our sprite on screen. Note that we offset the sprite up and to the left by half its height and width so that it is positioned using its centre point rather than its top-left hand corner. This allows out sprite to be rotated and scaled around its centre.<\/p>\n<p>The final result should look something l like this:<\/p>\n<figure id=\"attachment_144\" aria-describedby=\"caption-attachment-144\" style=\"width: 332px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.drmop.com\/wp-content\/uploads\/2011\/09\/DrawSprite_Shot.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-144\" title=\"DrawSprite_Shot\" src=\"http:\/\/www.drmop.com\/wp-content\/uploads\/2011\/09\/DrawSprite_Shot.png\" alt=\"DrawSprite example shot\" width=\"332\" height=\"557\" srcset=\"http:\/\/www.drmop.com\/wp-content\/uploads\/2011\/09\/DrawSprite_Shot.png 332w, http:\/\/www.drmop.com\/wp-content\/uploads\/2011\/09\/DrawSprite_Shot-178x300.png 178w\" sizes=\"auto, (max-width: 332px) 100vw, 332px\" \/><\/a><figcaption id=\"caption-attachment-144\" class=\"wp-caption-text\">DrawSprite screenshot for Marmalade SDK Iw2D Tutorial<\/figcaption><\/figure>\n<p>Like anything to do with game development you will eventually come to the point where you need to squeeze every last drop of power out of your rendering engine. Each time you render a different image a new state change is sent to the underlying hardware (this is not efficient by any stretch of the imagination). To help you, Marmalade built an automated batching system into Iw2D so that multiple draw calls using the same image are collected together and batched. Batched is a term used to describe sticking lots of data together and sending it to the hardware in one go. This process is not totally automated however, you will need to draw images by group. For example, lets say you have 10 trees and 5 balls in your scene. The most optimal way would be to draw all of the trees then all of the balls, not 2 trees, 1 ball, 2 trees, 2 balls etc..The astute among you will have noticed a simple problem with batching and that is the problem of draw order. Sometimes it is not practical to draw all trees then all balls because sometimes a ball may appear behind a particular tree.<\/p>\n<p>So how do we solve this problem other than using a z-buffer, which I believe is not supported by Iw2D? The solution is to arrange the ball and tree image on a single bitmap (usually called a sprite atlas or sprite sheet). When you want to draw the tree, you simply render the portion of the image that represents the tree and when you want to draw a ball, you simply render the portion of the image that represents the ball. This way, you are always rendering the same image (albeit different potions of the image) and never have to worry about batching optimisations.<\/p>\n<p>As usual you can download the source code for this tutorial from <a title=\"DrawSprite Marmalade SDK Iw2D tutorial source code\" href=\"http:\/\/www.drmop.com\/wp-content\/uploads\/2011\/09\/DrawSprite_Iw2D.zip\">here<\/a><\/p>\n<p>Happy coding and until next time, be careful crossing roads!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial is part of the Marmalade SDK tutorials collection. To see the tutorials index\u00a0click here Carrying on from my previous Marmalade SDK tutorial that covered creating a basic game loop, I promised that I would move onto something a little more interesting. Well I was going to write this some other day, but I [&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,43,44,42,28,3,45,1],"tags":[50,718,52,51,46],"class_list":["post-139","post","type-post","status-publish","format-standard","hentry","category-airplay-sdk","category-android-app-development","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-iw2d","tag-marmalade-sdk","tag-rendering","tag-sprites","tag-tutorial"],"_links":{"self":[{"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/posts\/139","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=139"}],"version-history":[{"count":9,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/posts\/139\/revisions"}],"predecessor-version":[{"id":146,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/posts\/139\/revisions\/146"}],"wp:attachment":[{"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/media?parent=139"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/categories?post=139"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/tags?post=139"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}