{"id":459,"date":"2011-10-28T14:37:40","date_gmt":"2011-10-28T14:37:40","guid":{"rendered":"http:\/\/www.drmop.com\/?p=459"},"modified":"2011-10-29T22:52:46","modified_gmt":"2011-10-29T22:52:46","slug":"marmalade-sdk-tutorial-actors-scenes-and-cameras-make-the-world-go-round","status":"publish","type":"post","link":"http:\/\/www.drmop.com\/index.php\/2011\/10\/28\/marmalade-sdk-tutorial-actors-scenes-and-cameras-make-the-world-go-round\/","title":{"rendered":"Marmalade SDK Tutorial &#8211; Actors, Scenes and Cameras Make the World Go Round"},"content":{"rendered":"<p>This tutorial is part of the Marmalade SDK tutorials collection. To see the tutorials index <a title=\"Marmalade SDK Tutorials\" href=\"http:\/\/www.drmop.com\/index.php\/marmalade-sdk-tutorials\/\" target=\"_self\">click here<\/a><\/p>\n<p>In our previous tutorial we created an extensible animation system that allowed us to create discrete frame based image animation as well as other types of animations. This week we will continue on our quest to create an easy to use, extensible cross platform 2D game engine. In order to do this effectively we need to get organised and organised we will be. If you just want the code to this tutorial then <a title=\"Marmalade SDK Tutorial - Actor, Scene and camera source code\" href=\"http:\/\/www.drmop.com\/wp-content\/uploads\/2011\/10\/IwGame1.zip\">download it from here<\/a>.<\/p>\n<p>Ok, so how do we organise things in a 2D engine? What sort of things do we want our 2D engine to do? Here&#8217;s a brief list:<\/p>\n<ul>\n<li>We want sprites and animations obviously, these we already covered in previous tutorials<\/li>\n<li>We want sprite creation \/ handling to be automated so that we do not have to worry about creating, updating and destroying sprites<\/li>\n<li>We want to define specific types of game objects (players, bombs, aliens, pickups etc..) modelled on a single game object type<\/li>\n<li>We want scenes that contain our game objects, managing their life times and updates<\/li>\n<li>We want cameras that we can move around in our scene to view different parts of the scene.<\/li>\n<li>We want our game objects to recognise when they collide with each other and react to each other<\/li>\n<\/ul>\n<p>To manage all of the above we are going to create a Camera, Actor, Scene (CAS) system.<\/p>\n<h2>Cameras, Actors and Scenes<\/h2>\n<p>The camera, actor and scene system (CAS) constitutes the logical implementation of our game engine. The scene represents our finite gaming world, whilst actors represent our individual game objects that live within our gaming world. The scene manages all of our actors for us, taking care of updating them and deleting them when they are no longer needed. The camera represents a view into the gaming world that can be moved around, rotated and scaled to view different parts of the world.<\/p>\n<h2>CIwGameActor \u2013 Our game objects are really just actors on a stage<\/h2>\n<p>Ok, we will begin by taking a look at the CIwGameActor class:<\/p>\n<pre>\r\n<blockquote>\r\n\r\nclass CIwGameActor\r\n{\r\nprotected:\r\n    \/\/ Properties\r\n    CIwGameScene*       Scene;                   <span style=\"color: #008000;\">\/\/ Scene that actor lives in<\/span>\r\n    bool                Used;                   <span style=\"color: #008000;\"> \/\/ Used is used when actors pooled to reduce memory fragmentation<\/span>\r\n    bool                Managed;                 <span style=\"color: #008000;\">\/\/ Marks this actor as being managed by another object so we do not delete it<\/span>\r\n    unsigned int        NameHash;                <span style=\"color: #008000;\">\/\/ Name of Actor (stored as an hash for speed)<\/span>\r\n    int                 Type;                    <span style=\"color: #008000;\">\/\/ Type of Actor (use to distinguish beteeen different actor types)<\/span>\r\n    CIwFVec2            OriginalPosition;        <span style=\"color: #008000;\">\/\/ Original position of actor in the scene (when actor was first spawned)<\/span>\r\n    CIwFVec2            Position;               <span style=\"color: #008000;\"> \/\/ Current position of actor in the scene<\/span>\r\n    CIwFVec2            Velocity;                <span style=\"color: #008000;\">\/\/ Current velocity of actor<\/span>\r\n    CIwFVec2            VelocityDamping;         <span style=\"color: #008000;\">\/\/ Dampens the velocity<\/span>\r\n    float               OriginalAngle;           <span style=\"color: #008000;\">\/\/ Original angle in scene (when first spawned)<\/span>\r\n    float               Angle;                   <span style=\"color: #008000;\">\/\/ Orientation in scene (degrees)<\/span>\r\n    float               AngularVelocity;         <span style=\"color: #008000;\">\/\/ Angular velocity<\/span>\r\n    float               AngularVelocityDamping;  <span style=\"color: #008000;\">\/\/ Angular velocity damping<\/span>\r\n    float               Scale;                   <span style=\"color: #008000;\">\/\/ Scale<\/span>\r\n    CIwColour           Colour;                  <span style=\"color: #008000;\">\/\/ Colour<\/span>\r\n    bool                IsActive;                <span style=\"color: #008000;\">\/\/ Active state of actor<\/span>\r\n    bool                IsVisible;               <span style=\"color: #008000;\">\/\/ Visible state of actor<\/span>\r\n    bool                IsCollidable;            <span style=\"color: #008000;\">\/\/ Collidable state of actor<\/span>\r\n    CIwGameSprite*      Visual;                  <span style=\"color: #008000;\">\/\/ Visual element that represents the actor<\/span>\r\n    CIwGameAnimManager* VisualAnimManager;       <span style=\"color: #008000;\">\/\/ Visuals animation manager, used to control the actors visual componen animations<\/span>\r\n    int                 CollisionSize;           <span style=\"color: #008000;\">\/\/ Size of collision area<\/span>\r\n    CIwRect             CollisionRect;           <span style=\"color: #008000;\">\/\/ Spherical collision size<\/span>\r\n    float               PreviousAngle;           <span style=\"color: #008000;\">\/\/ Previous updates angle<\/span>\r\n    CIwFVec2            PreviousPosition;        <span style=\"color: #008000;\">\/\/ Previous updates position<\/span>\r\npublic:\r\n    void                setUsed(bool in_use)                     { Used = in_use; }\r\n    bool                isUsed() const                           { return Used; }\r\n    void                setManaged(bool managed)                 { Managed = managed; }\r\n    bool                isManaged() const                        { return Managed; }\r\n    void                setScene(CIwGameScene* scene)            { Scene = scene; }\r\n    CIwGameScene*       getScene()                               { return Scene; }\r\n    void                setName(const char* name)                { NameHash = IwHashString(name); }\r\n    unsigned int        getNameHash()                            { return NameHash; }\r\n    void                setType(int type)                        { Type = type; }\r\n    int                 getType() const                          { return Type; }\r\n    void                setOriginalPosition(float x, float y)    { OriginalPosition.x = x; OriginalPosition.y = y; }\r\n    CIwFVec2            getOriginalPosition()                    { return OriginalPosition; }\r\n    void                setPosition(float x, float y)            { Position.x = x; Position.y = y; }\r\n    CIwFVec2            getPosition()                            { return Position; }\r\n    void                setOriginalAngle(float angle)            { OriginalAngle = angle; }\r\n    float               getOriginalAngle()                       { return OriginalAngle; }\r\n    void                setAngle(float angle)                    { Angle = angle; }\r\n    float               getAngle()                               { return Angle; }\r\n    void                setVelocity(float x, float y)            { Velocity.x = x;  Velocity.y = y; }\r\n    CIwFVec2            getVelocity()                            { return Velocity; }\r\n    void                setVelocityDamping(float x, float y)     { VelocityDamping.x = x;  VelocityDamping.y = y; }\r\n    void                setAngularVelocity(float velocity)       { AngularVelocity = velocity; }\r\n    float               getAngularVelocity() const               { return AngularVelocity; }\r\n    void                setAngularVelocityDamping(float damping) { AngularVelocityDamping = damping; }\r\n    void                setScale(float scale)                    { Scale = scale; }\r\n    float               getScale() const                         { return Scale; }\r\n    void                setColour(CIwColour&amp; colour)             { Colour = colour; }\r\n    CIwColour           getColour() const                        { return Colour; }\r\n    void                setActive(bool active)                   { IsActive = active; }\r\n    bool                isActive() const                         { return IsActive; }\r\n    void                setVisible(bool visible)                 { IsVisible = visible; }\r\n    bool                isVisible() const                        { return IsVisible; }\r\n    void                setCollidable(bool collidable)           { IsCollidable = collidable; }\r\n    bool                isCollidable() const                     { return IsCollidable; }\r\n    void                getVisual(CIwGameSprite* visual)         { Visual = visual; }\r\n    CIwGameSprite*      getVisual()                              { return Visual; }\r\n    void                setVisualAnimManager(CIwGameAnimManager* anim_manager) { VisualAnimManager = anim_manager; }\r\n    CIwGameAnimManager* getVisualAnimManager()                   { return VisualAnimManager; }\r\n    void                setCollisionRect(CIwRect&amp; rect);\r\n    CIwRect             getCollisionRect() const                 { return CollisionRect; }\r\n    int                 getCollisionSize() const                 { return CollisionSize; }\r\n    void                setPreviousPosition(float x, float y)    { PreviousPosition.x = x; PreviousPosition.y = y; }\r\n    CIwFVec2            getPreviousPosition() const              { return PreviousPosition; }\r\n    void                setPreviousAngle(float angle)            { PreviousAngle = angle; }\r\n    float               getPreviousAngle() const                 { return PreviousAngle; }\r\n    \/\/ Properties end\r\n\r\n    CIwGameActor() : Used(false), Managed(false), Scene(NULL)    { Reset();  }\r\n    virtual            ~CIwGameActor();\r\n\r\n    <span style=\"color: #008000;\">\/\/ Reset the actor (used by memory pooling systems to save actor re-allocation, usually called after re-allocation to reset the object to a default state)<\/span>\r\n    virtual void    Reset();\r\n\r\n    <span style=\"color: #008000;\">\/\/ Update the actor (called by the scene every frame)<\/span>\r\n    virtual bool    Update(float dt);\r\n\r\n    <span style=\"color: #008000;\">\/\/ Update the visual that represents this actor on screen<\/span>\r\n    virtual bool    UpdateVisual();\r\n\r\n    <span style=\"color: #008000;\">\/\/ Actors are responsible for carrying out there own collision checks. Called after all actor updates to check and resolve any collisions<\/span>\r\n    virtual void    ResolveCollisions() = 0;\r\n\r\n    <span style=\"color: #008000;\">\/\/ NotifyCollision is called by another actor when it collides with this actor<\/span>\r\n    virtual void    NotifyCollision(CIwGameActor* other) = 0;\r\n\r\n    <span style=\"color: #008000;\">\/\/ Call to see if this actor was tapped by the user<\/span>\r\n    virtual bool    CheckIfTapped();\r\n\r\n    <span style=\"color: #008000;\">\/\/ Checks to see if another actor is colliding with this actor<\/span>\r\n    bool            CheckCollision(CIwGameActor* other);\r\n};<\/blockquote>\r\n<\/pre>\n<p>Hmm, I agree, its a bit on the BIG side, but if you look carefully our CIwGameActor class provides a lot of functionality built in, which in the long run will save us lots of coding time. Again, you never create a direct instance of this class as it is abstract, you dervice your own different actor types from CIwGameActor.<\/p>\n<p>We handle a lot of functionality with this base class including:<\/p>\n<ul>\n<li>Position, orientation, scale, angular velocity, velocity damping and angular velocity damping \u2013 Physical attributes of our actor<\/li>\n<li>Visibility state, active state, collide-able state \u2013 Used to hide, disable and mark as collide-able objects<\/li>\n<li>Object type identifier, object name (used to search for specific types of objects or named objects). These are very useful as they allow you to create actors and forget about them, no need to store a pointer to them to reference them later, you simply ask the scene to find the object by name or type to access it again.<\/li>\n<li>Visual, colour and animation manager \u2013 We will use these variables to give our object a visual representation in our world<\/li>\n<li>Collision size and collision rectangle are used for collision detection<\/li>\n<\/ul>\n<p>Note that eventually we will be replacing the physical components in this class with the Box2D physics engine.<\/p>\n<p>I would like to point out a few important methods in this class:<\/p>\n<ul>\n<li>Update() \u2013 When you implement your own actor types you override this method to provide the implementation of your game object specific behaviour. For example, if you create a player actor then you may check and move the player, maybe fire of different animations \/ sound effects. The default implementation of Update() will update the basic physics for the actor, any attached playing animations as well as add the actor to the collision check list if it is collision enabled. You should call CIwGameActor::Update() in your own Update() implementation, if you want to keep this functionality.<\/li>\n<li>UpdateVisual() \u2013 You do not generally need to override and provide your own implementation of this method as this method will automatically update the actors associated visual for you.<\/li>\n<li>ResolveCollisions() \u2013 When the scene has finished calling all of its actor updates it will then call ResolveCollisions() on each of the actors. You provide the implementation of this method to check for collisions with other actors. We implement collision checking this way as it allows us to optimise which collision checks to make. For example, lets say we are creating the old game Asteroids. The scene consists of 10 asteroids, 10 bullets and our ship. Our ship actor only needs to check for collisions with the asteroids and not the bullets or the ship.<\/li>\n<li>NotifyCollision() \u2013 When an actor collides with another actor we need some mechanism for letting the other actor know that we have collided with them. When an actor collides with this actor it will call its NotifyCollision() method to let it know, this gives the actor a chance to respond to the collision event<\/li>\n<li>CheckIfTapped() \u2013 Whilst this method is not currently implemented it will eventually allow us to check and see if the actor was tapped by the user. This is good for allowing the user to interact with our actors<\/li>\n<li>CheckCollision() \u2013 Helper method for checking if two actors bounding circles overlap<\/li>\n<\/ul>\n<p>One important note about Actors is there coordinate system. As far as our scene is concerned, the worlds centre is the the middle of the scene (0, 0), which corresponds to the centre of the screen for a scene that has not been moved.<\/p>\n<h2>CIwGameActorImage \u2013 An image based actor helper class<\/h2>\n<p>I suspect that many of you will want to simply get up and running quickly with your game and not have to worry about deriving your own actor class. With that in mind I created an image based actor that allows you to quickly set up a basic image based actor, complete with a sprite atlas, a base animation and a size. Lets take a quick look at the code in that class as I thin it will prove helpful when it comes to you designing your own actors:<\/p>\n<pre>\r\n<blockquote>\r\n\r\nbool CIwGameActorImage::Init(CIwGameScene* scene, CIw2DImage* image, CIwGameAnimImage* anim, int width, int height)\r\n{\r\n    <span style=\"color: #008000;\">\/\/ Reset the actor<\/span>\r\n    CIwGameActor::Reset();\r\n\r\n    <span style=\"color: #008000;\">\/\/ Set the scene<\/span>\r\n    Scene = scene;\r\n\r\n    <span style=\"color: #008000;\">\/\/ Create sprite<\/span>\r\n    if (image != NULL)\r\n    {\r\n        CIwGameBitmapSprite* sprite = new CIwGameBitmapSprite();\r\n        if (sprite == NULL)\r\n            return false;\r\n\r\n        <span style=\"color: #008000;\">\/\/ Set sprite image<\/span>\r\n        sprite-&gt;setImage(image);\r\n        sprite-&gt;setDestSize(width, height);\r\n\r\n        <span style=\"color: #008000;\">\/\/ Set sprite as visual<\/span>\r\n        Visual = sprite;\r\n\r\n        <span style=\"color: #008000;\">\/\/ Add sprite to the sprite manager so it can be managed and drawn<\/span>\r\n        Scene-&gt;getSpriteManager()-&gt;addSprite(sprite);\r\n    }\r\n\r\n    <span style=\"color: #008000;\">\/\/ Create an animation manager and add the animation to it<\/span>\r\n    if (anim != NULL)\r\n    {\r\n        VisualAnimManager = new CIwGameAnimManager();\r\n        VisualAnimManager-&gt;setUpdateAll(false);\r\n        if (VisualAnimManager == NULL)\r\n            return false;\r\n        VisualAnimManager-&gt;addAnimation(anim);\r\n\r\n        <span style=\"color: #008000;\">\/\/ Set the first animation in the animation manager as the current animation<\/span>\r\n        VisualAnimManager-&gt;setCurrentAnimation(0);\r\n    }\r\n\r\n    return true;\r\n}<\/blockquote>\r\n<\/pre>\n<p>Our Init() method is pretty simple, it resets the actors internal data to default, creates a bitmapped sprite visual from the image and actor size then creates an animation manager and adds our default animation to it.<\/p>\n<pre>\r\n<blockquote>\r\n\r\nbool CIwGameActorImage::UpdateVisual()\r\n{\r\n    if (CIwGameActor::UpdateVisual())\r\n    {\r\n        <span style=\"color: #008000;\">\/\/ Update the sprite<\/span>\r\n        if (VisualAnimManager != NULL)\r\n        {\r\n            <span style=\"color: #008000;\">\/\/ Get the animations current image frame data and copy it to the bitmapped sprite<\/span>\r\n            CIwGameAnimImage* anim = (CIwGameAnimImage*)VisualAnimManager-&gt;getAnimation(0);\r\n            if (Visual != NULL)\r\n                ((CIwGameBitmapSprite*)Visual)-&gt;setSrcRect(anim-&gt;getCurrentFrameData());\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    return false;\r\n}<\/blockquote>\r\n<\/pre>\n<p>Our UpdateVisual() method simply moves the image animation frame data to our sprite to update its image.<\/p>\n<p>Unfortunately you will still need to derive your own actor from CIwGameActorImage() in order to create an actor object<\/p>\n<h2>CIwGameScene \u2013 A place for actors to play<\/h2>\n<p>The scene is the place where we put actors. When you add an actor to a scene the scene will take care of calling game logic update and visual update methods and building a list of potential colliding actors, as well as cleaning up the actors when the game is finished.<br \/>\nThe scene also takes care of updating the camera and fitting our game across different sized screens with different aspect ratios. Look as the scene as the driving force that manages much of our game processes for us, so we can get on with coding up cool actors and other game logic.Lets take a quick look at the CIwGameScene class:<\/p>\n<pre>\r\n<blockquote>\r\n\r\nclass CIwGameScene\r\n{\r\npublic:\r\n    <span style=\"color: #008000;\">\/\/ Public access to actor iteration<\/span>\r\n    typedef CIwList::iterator _Iterator;\r\n    _Iterator                begin() { return Actors.begin(); }\r\n    _Iterator                end() { return Actors.end(); }\r\n\r\n    \/\/ Properties\r\nprotected:\r\n    CIwGameSpriteManager*    SpriteManager;        <span style=\"color: #008000;\">\/\/ Manages sprites for the whole scene<\/span>\r\n    CIwGameAnimFrameManager* AnimFrameManager;     <span style=\"color: #008000;\">\/\/ Manages the allocation and clean up of animation frames<\/span>\r\n    unsigned int             NameHash;             <span style=\"color: #008000;\">\/\/ Hashed name of this scene<\/span>\r\n    CIwVec2                  ScreenSize;           <span style=\"color: #008000;\">\/\/ Native screen size<\/span>\r\n    CIwVec2                  VirtualSize;          <span style=\"color: #008000;\">\/\/ The virtual size is not the actual size of the scene. but a static pretend size that we can use to render to without having to cater for different sized displays<\/span>\r\n    CIwMat2D                 VirtualTransform;     <span style=\"color: #008000;\">\/\/ Virtual transform is used to scale, translate and rotate scene to fit different display sizes and orientations<\/span>\r\n    CIwMat2D                 Transform;            <span style=\"color: #008000;\">\/\/ Scene transform<\/span>\r\n    CIwList                  Actors;               <span style=\"color: #008000;\">\/\/ Collection of scene actors<\/span>\r\n    CIwRect                  Extents;              <span style=\"color: #008000;\">\/\/ Extents of scenes world<\/span>\r\n    CIwGameCamera*           Camera;               <span style=\"color: #008000;\">\/\/ Current camera<\/span>\r\n    CIwGameActor**           Collidables;          <span style=\"color: #008000;\">\/\/ List of collidable objects built this frame<\/span>\r\n    int                      MaxCollidables;       <span style=\"color: #008000;\">\/\/ Maximum allowed collidables<\/span>\r\n    int                      NextFreeCollidable;   <span style=\"color: #008000;\">\/\/ Points to next free slot in sollidables list pool<\/span>\r\npublic:\r\n    CIwGameSpriteManager*    getSpriteManager()                       { return SpriteManager; }        <span style=\"color: #008000;\">\/\/ Manages sprites for the whole scene<\/span>\r\n    CIwGameAnimFrameManager* getAnimFrameManager()                    { return AnimFrameManager; }     <span style=\"color: #008000;\">\/\/ Manages the creation and clean up of animation frames<\/span>\r\n    void                     setName(const char* name)                { NameHash = IwHashString(name); }\r\n    unsigned int             getNameHash()                            { return NameHash; }\r\n    CIwVec2                  getScreenSize() const                    { return ScreenSize; }\r\n    CIwVec2                  getVirtualSize() const                   { return VirtualSize; }\r\n    void                     setVirtualTransform(int required_width, int required_height, float angle, bool fix_aspect = false, bool lock_width = false);\r\n    CIwMat2D&amp;                getVirtualTransform()                    { return VirtualTransform; }\r\n    CIwMat2D&amp;                getTransform()                           { return Transform; }\r\n    void                     addActor(CIwGameActor *actor);\r\n    void                     removeActor(CIwGameActor* actor);\r\n    void                     removeActor(unsigned int name_hash);\r\n    CIwGameActor*            findActor(unsigned int name_hash);\r\n    CIwGameActor*            findActor(int type);\r\n    void                     clearActors();\r\n    void                     setExtents(int x, int y, int w, int h)   { Extents.x = x; Extents.y = y; Extents.w = w; Extents.h = h; }\r\n    CIwRect                  getExtents() const                       { return Extents; }\r\n    void                     setCamera(CIwGameCamera* camera)         { Camera = camera; }\r\n    CIwGameCamera*           getCamera()                              { return Camera; }\r\n    bool                     addCollideable(CIwGameActor* actor);\r\n    CIwGameActor**           getCollidables()                         { return Collidables; }\r\n    int                      getTotalCollidables() const              { return NextFreeCollidable; }\r\n    \/\/ Properties end\r\nprivate:\r\npublic:\r\n    CIwGameScene() : Collidables(NULL), SpriteManager(NULL), AnimFrameManager(NULL), NextFreeCollidable(0), Camera(NULL), MaxCollidables(0) {}\r\n    virtual ~CIwGameScene();\r\n\r\n    <span style=\"color: #008000;\">\/\/ After creating the scene, call Init() to initialise it, passing the maximum number of actors that you expect can collide<\/span>\r\n    virtual int        Init(int max_collidables = 128);\r\n\r\n    <span style=\"color: #008000;\">\/\/ Update() will update the scene and all of its contained actors<\/span>\r\n    virtual void       Update(float dt);\r\n\r\n    <span style=\"color: #008000;\">\/\/ Draw() will draw all of the scenes actors<\/span>\r\n    virtual void       Draw();\r\n\r\n    <span style=\"color: #008000;\">\/\/ Event handlers<\/span>\r\n};<\/blockquote>\r\n<\/pre>\n<p>Yep, I know, its another biggy, but again it supports lots of cool functionality such as:<\/p>\n<ul>\n<li>Handles all of our actors<\/li>\n<li>Handles our camera<\/li>\n<li>Fits our game to any sized screen \/ any aspect ratio using a virtual size display<\/li>\n<li>Tracks potential colliders<\/li>\n<li>Manages sprites and animation frames<\/li>\n<\/ul>\n<p>You will be happy to know that you do not need to derive you own scene from CIwGameScene() and you will generally instantiate and work with a version of this class directly. Our scene class does not however need a little setting up initially. Heres asome basic code on how to set up a scene:<\/p>\n<pre>\r\n<blockquote>\r\n\r\nCIwGameScene* game_scene = new CIwGameScene();\r\ngame_scene-&gt;Init();\r\ngame_scene-&gt;setVirtualTransform(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 0, true, false);<\/blockquote>\r\n<\/pre>\n<p>I think at this point I need to explain something about the virtual screen system that I use to ease the pain of cross platform development<\/p>\n<h2>Using a Virtual Screen Size to Target Any Sized Screen<\/h2>\n<p>There are quite a few different solutions knocking around that solve the problem of targeting our game at a variety of different screen resolutions, including:<\/p>\n<ul>\n<li>Scale to fit \u2013 This is a very simple scaling of the scene to match the display resolution. This is quick and simple but your game can appear stretched or squashed on displays that have a different aspect ratio to your game aspect ratio<\/li>\n<li>Bordered  \u2013 Another simple system that displays your game at its native resolution but with a border around it to fill the space that your game\u00a0doesn&#8217;t\u00a0cover. I don\u2019t like this method as you are giving up too much screen real-estate<\/li>\n<li>Unlimited screen size \u2013 This method is quite complex and involves rendering enough stuff on screen at a 1:1 pixel resolution to cover the entire screen. This disadvantage (and advantage, depends how much time you have on your hands) of using this method is that you would need to display a much larger area of the gaming world on a higher resolution display than on a lower resolution display.<\/li>\n<li>Virtual screen \u2013 This method uses a pretend screen size that best fits many resolutions (800 x 512 \/ 512 x 800 is a good choice). Your game renders everything as though it is rendering to the virtual size and not the actual phones \/ tablets native screen size. You later scale and translate the virtual canvas to fit onto the native phones screen resolution.<\/li>\n<\/ul>\n<p>We could use any of these methods in our game, but I am going to use a virtual canvas because it is the most convenient. Our CIwGameScene class has a method called setVirtualTransform() which will set this up for us, so that all of our actors will render to the virtual screen size. Heres how to use the method:<\/p>\n<p>void CIwGameScene::setVirtualTransform(int required_width, int required_height, float angle, bool fix_aspect, bool lock_width)<\/p>\n<ul>\n<li>required_width, required_height \u2013 This is the width and height we would like to use for our virtual screen<\/li>\n<li>fix_aspect \u2013 Tells the scene to fix the aspect ratio of the scene to match the native screen aspect ratio<\/li>\n<li>lock_width \u2013 Tells the scene to fix eth aspect ratio based on the width of the display instead of the height<\/li>\n<\/ul>\n<h2>CIwGameCamera \u2013 Our View Into the Gaming World<\/h2>\n<p>Many games can get away with simply one visible screen of information (such as Asteroids, Space Invaders, Pac-man etc..), but other types of games such as platformers, sports games, strategy games etc.. require the ability to move around the gaming world in some fashion. This is usually accomplished by using a camera that can move our point of view within the world. CIwGameScene supports the attachment of a camera to allow us to move our view around a larger virtual world. Lets take a quick look at the CIwGameCamera class:<\/p>\n<pre>\r\n<blockquote>\r\n\r\nclass CIwGameCamera\r\n{\r\npublic:\r\n    \/\/ Properties\r\nprotected:\r\n    unsigned int            NameHash;         <span style=\"color: #008000;\">\/\/ Hashed name of this camera<\/span>\r\n    CIwMat2D                Transform;        <span style=\"color: #008000;\">\/\/ The combined camera transform<\/span>\r\n    CIwFVec2                Position;         <span style=\"color: #008000;\">\/\/ Position of view within scene<\/span>\r\n    float                   Scale;            <span style=\"color: #008000;\">\/\/ Cameras scale<\/span>\r\n    float                   Angle;            <span style=\"color: #008000;\">\/\/ Cameras angle<\/span>\r\n    bool                    TransformDirty;   <span style=\"color: #008000;\">\/\/ Marks camera transform needs rebuilding<\/span>\r\npublic:\r\n    void                    setName(const char* name)            { NameHash = IwHashString(name); }\r\n    unsigned int            getNameHash()                        { return NameHash; }\r\n    CIwMat2D&amp;               getTransform()                       { return Transform; }\r\n    void                    setPosition(float x, float y)        { Position.x = x; Position.y = y; TransformDirty = true; }\r\n    CIwFVec2                getPosition() const                  { return Position; }\r\n    void                    setScale(float scale)                { Scale = scale; TransformDirty = true; }\r\n    float                   getScale() const                     { return Scale; }\r\n    void                    setAngle(float angle)                { Angle = angle; TransformDirty = true; }\r\n    float                   getAngle() const                     { return Angle; }\r\n    void                    forceTransformDirty()                { TransformDirty = true; }\r\n    bool                    isTransformDirty() const             { return TransformDirty; }\r\n    \/\/ Properties end\r\n\r\nprivate:\r\n\r\npublic:\r\n    CIwGameCamera() : Position(0, 0), Scale(1.0f), Angle(0), TransformDirty(true) {}\r\n    virtual ~CIwGameCamera()    {}\r\n\r\n    <span style=\"color: #008000;\">\/\/ Updates the camera<\/span>\r\n    virtual void    Update();\r\n\r\n    <span style=\"color: #008000;\">\/\/ Event handlers<\/span>\r\n};<\/blockquote>\r\n<\/pre>\n<p>Ah much better, nice and short. As you can see the camera class is quite simple, supporting position, rotation and scaling of the view. To use a camera we simply create one and attach it to the Scene, the scene will then follow the camera around. To see different areas of the game world we simply move the camera around and all of our actors will move along with it.<\/p>\n<p>Cool, I\u2019m now done with explaining the new classes. I\u2019ve been battling with trying to keep this article short and to the point, but alas I don\u2019t think its quite happening for me.<\/p>\n<h2>What\u2019s changed in IwGame Code<\/h2>\n<p><figure id=\"attachment_463\" aria-describedby=\"caption-attachment-463\" style=\"width: 335px\" class=\"wp-caption alignleft\"><a href=\"http:\/\/www.drmop.com\/wp-content\/uploads\/2011\/10\/Actor-Example.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-463\" title=\"Marmalade SDK - Actor, Scene Camera Example\" src=\"http:\/\/www.drmop.com\/wp-content\/uploads\/2011\/10\/Actor-Example.png\" alt=\"Marmalade SDK - Actor, Scene Camera Example\" width=\"335\" height=\"556\" srcset=\"http:\/\/www.drmop.com\/wp-content\/uploads\/2011\/10\/Actor-Example.png 335w, http:\/\/www.drmop.com\/wp-content\/uploads\/2011\/10\/Actor-Example-180x300.png 180w\" sizes=\"auto, (max-width: 335px) 100vw, 335px\" \/><\/a><figcaption id=\"caption-attachment-463\" class=\"wp-caption-text\">Marmalade SDK - Actor, Scene Camera Example<\/figcaption><\/figure><br \/>\n<br clear=\"all\" \/><\/p>\n<p>I will be honest, A LOT has changed since the previous article and I will try my best to walk through most of it; this is the main problem with an engine that\u2019s \u00a0in-development.<\/p>\n<p>Firstly I have had to make quite a few changes to our previous classes including:<\/p>\n<ul>\n<li>CIwGameAnim \u2013 CIwGameAnimFrameManager now handles the life time of animation frames and not the separate animation classes themselves<\/li>\n<li>CIwGameAnimFrameManager \u2013 Added the ability to retrieve allocated animation frames<\/li>\n<li>CIwGameAnimManager \u2013 setCurrentAnimation() never actually set the current animation (oops, fixed)<\/li>\n<li>CIwGameBitmapSprite \u2013 Source rectangle can now be set from a CIwGameAnimImageFrame (helper method just saves some typing)<\/li>\n<li>CInput \u2013 This class has been renamed to CIwGameInput to fit in with the frameworks naming conventions. CIwGameInput is now a singleton and not declared as a global variable (I\u2019m not generally a fan of global variables and prefer to use singletons for systems that there will only ever be one instance of). If you do not know what a singleton is then think of it as a global instance of a class.<\/li>\n<\/ul>\n<p>Now onto the changes to Main.cpp. Note that I won\u2019t be going into minor details such as \u201cOh I included these header files\u201d.<\/p>\n<p>We now accesss input using a singleton, here we have to create the IwGameInput singleton and then initialise it:<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/ Initialise the input system<\/span>\r\nCIwGameInput::Create();\r\nIW_GAME_INPUT-&gt;Init();<\/blockquote>\r\n<\/pre>\n<p>Note that IW_GAME_INPUT is just a macro that calls CIwGameInput::getInstance() (I find it more readable to use the macro)<\/p>\n<p>Next, we create and initialise a scene then create a camera and attach that to the scene<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/ Create a scene<\/span>\r\nCIwGameScene* game_scene = new CIwGameScene();\r\ngame_scene-&gt;Init();\r\ngame_scene-&gt;setVirtualTransform(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 0, true, false);\r\n\r\n<span style=\"color: #008000;\">\/\/ Create a camera and attach it to the scene<\/span>\r\nCIwGameCamera* game_camera = new CIwGameCamera();\r\ngame_scene-&gt;setCamera(game_camera);<\/blockquote>\r\n<\/pre>\n<p>Next, we allocate a bunch of image animation frames for our manic face animation. Take note that we now allocate them through the game scenes animation manager. This ensures that the game scene later cleans them up for us.<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/ Allocate animation frames for our player<\/span>\r\nCIwGameAnimImageFrame* anim_frames = game_scene-&gt;getAnimFrameManager()-&gt;allocImageFrames(8, 36, 40, 0, 0, 512, 40, 512);<\/blockquote>\r\n<\/pre>\n<p>Within our main loop we check for the player tapping the screen and if they do we explode 10 sprites into the scene at the tapped position:<\/p>\n<pre>\r\n<blockquote>\r\n\r\nif (IW_GAME_INPUT-&gt;getTouchCount() &gt; 0)\r\n{\r\n    if (!PrevTouched)\r\n    {\r\n        <span style=\"color: #008000;\">\/\/ Get tapped position in our virtual screen space<\/span>\r\n        CIwFVec2 pos = game_scene-&gt;ScreenToVirtual(IW_GAME_INPUT-&gt;getTouch(0)-&gt;x, IW_GAME_INPUT-&gt;getTouch(0)-&gt;y);\r\n\r\n        <span style=\"color: #008000;\">\/\/ Create 10 player actors<\/span>\r\n        for (int t = 0; t &lt; 10; t++)\r\n        {\r\n            <span style=\"color: #008000;\">\/\/ Create and set up our face animation<\/span>\r\n            CIwGameAnimImage* face_anim = new CIwGameAnimImage();\r\n            face_anim-&gt;setFrameData(anim_frames, 8);\r\n            face_anim-&gt;setLooped(-1);\r\n            face_anim-&gt;setPlaybackSpeed(0.2f);\r\n            face_anim-&gt;Start();\r\n\r\n            <span style=\"color: #008000;\">\/\/ Create player actor<\/span>\r\n            ActorPlayer* player = new ActorPlayer();\r\n            player-&gt;Init(game_scene, sprites_image, face_anim, 36, 40);\r\n            player-&gt;setName(\"Player\");\r\n            player-&gt;setPosition(pos.x, pos.y);\r\n\r\n            <span style=\"color: #008000;\">\/\/ Add player actor to the scene<\/span>\r\n            game_scene-&gt;addActor(player);\r\n        }\r\n    }\r\n    PrevTouched = true;\r\n}\r\nelse\r\n    PrevTouched = false;<\/blockquote>\r\n<\/pre>\n<p>Note that because we are now dealing with a virtual screen resolution and not the actual native screen resolution, our tap coordinates need converting to virtual screen coordinates. We achieve that using the ScreenToVirtual() method of the CIwGameScene class.<\/p>\n<p>Also note that we still have to create our face_anim animation, but this time we pass it to the ActorPlayer Init() method, so that the actor \/ scene can take of its management.<\/p>\n<p>Next we update and draw the scene:<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/ Update the scene<\/span>\r\ngame_scene-&gt;Update(1.0f);\r\n\r\n<span style=\"color: #008000;\">\/\/ Draw the scene<\/span>\r\ngame_scene-&gt;Draw();<\/blockquote>\r\n<\/pre>\n<p>Lastly we clean-up the camera, scene and input system:<\/p>\n<pre>\r\n<blockquote>\r\n\r\n<span style=\"color: #008000;\">\/\/ Safely clean up the camera<\/span>\r\nif (game_camera != NULL)\r\n    delete game_camera;\r\n\r\n<span style=\"color: #008000;\">\/\/ Safely cleanup game scene<\/span>\r\nif (game_scene != NULL)\r\n    delete game_scene;\r\n\r\n<span style=\"color: #008000;\">\/\/ Shut down the input system<\/span>\r\nIW_GAME_INPUT-&gt;Release();\r\nCIwGameInput::Destroy();<\/blockquote>\r\n<\/pre>\n<h2>ActorPlayer our First Derived Actor<\/h2>\n<p>ActorPlayer is our very first user defined CIwGameActor based actor and because we derived it from CIwGameActorImage (and in turn CIwGameActor) we get all of the useful functionality defined in those classes.<\/p>\n<p>The only parts of our ActorPlayer that\u2019s worth drawing out are the Init() and Update() methods:<\/p>\n<pre>\r\n<blockquote>\r\n\r\nbool ActorPlayer::Init(CIwGameScene* scene, CIw2DImage* image, CIwGameAnimImage* anim, int width, int height)\r\n{\r\n    CIwGameActorImage::Init(scene, image, anim, width, height);\r\n\r\n    FadeTimer.setDuration(1000);\r\n    Velocity.x = IwRandMinMax(-100, 100) \/ 20.0f;\r\n    Velocity.y = IwRandMinMax(-100, 100) \/ 20.0f;\r\n    AngularVelocity = IwRandMinMax(-100, 100) \/ 20.0f;\r\n\r\n    return true;\r\n}<\/blockquote>\r\n<\/pre>\n<p>Our Init() method calls the base CIwGameActorImage::Init() method to initialise the base CIwGameActorImage part of the actor. We then set up a fade timer and random velocities for position and spin.<\/p>\n<pre>\r\n<blockquote>\r\n\r\nbool ActorPlayer::Update(float dt)\r\n{\r\n    <span style=\"color: #008000;\">\/\/ If fade timer has timed out then delete this actor<\/span>\r\n    if (FadeTimer.HasTimedOut())\r\n    {\r\n        return false;    <span style=\"color: #008000;\">\/\/ Returning false tells the scene that we need to be removed from the scene<\/span>\r\n    }\r\n\r\n    <span style=\"color: #008000;\">\/\/ Calculate our opacity from time left on fade timer<\/span>\r\n    int opacity = FadeTimer.GetTimeLeft() \/ 2;\r\n    if (opacity &gt; 255) opacity = 255;\r\n    Colour.a = opacity;\r\n\r\n    return CIwGameActorImage::Update(dt);\r\n}<\/blockquote>\r\n<\/pre>\n<p>Our Update() method is called every game loop by the scene system, so keep in mind that this code will be called every single game frame. Firstly we check to see if the fade timer has timed out and if it has then we return false to the the scene system (this causes the actor to be removed from the scene \/ game) after the scene has finished updating all actors.<\/p>\n<p>We then calculate the opacity of our actor from the time left on the fade timer which causes the actor to fade out of existence.<\/p>\n<p>And that\u2019s about it for this article, hope that most of your managed to stay awake, long drawn out technical stuff can send the best of us to sleep, especially if read on a few hours sleep, which is usually the case for us programmer types. The source code that accompanies this article can be <a title=\"Marmalade SDK Tutorial - Actor, Scene and camera source code\" href=\"http:\/\/www.drmop.com\/wp-content\/uploads\/2011\/10\/IwGame1.zip\">downloaded from here<\/a><\/p>\n<p>I\u2019m quite happy with this blog as it marks the start of a real usable cross  platform game engine that we can now build upon. In our next tutorial we are  going to cover upgrading the engine to include some very basic collision  detection and response whilst building a small game using the engine to show  working collision. We will also cover handling frame rate variations and putting some audio in there.  Hopefully I will get the time to do that this weekend.<\/p>\n<p>That\u2019s it for now and don\u2019t forget HTML 5 is evil! (Just kidding, I got a book on it the other day and it looks quite good, think that I may use it to spruce up my blog)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial is part of the Marmalade SDK tutorials collection. To see the tutorials index click here In our previous tutorial we created an extensible animation system that allowed us to create discrete frame based image animation as well as other types of animations. This week we will continue on our quest to create an [&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,155,29,43,118,44,154,42,28,148,3,45,1],"tags":[182,184,185,729,718,183],"class_list":["post-459","post","type-post","status-publish","format-standard","hentry","category-airplay-sdk","category-android-app-development","category-apps","category-blackberry-playbook","category-blackberry-playbook-app-development","category-c-programming","category-game-and-app-development","category-games","category-ios-app-development","category-marmalade-sdk","category-pocketeers-limited","category-programming","category-samsung-bada-development","category-uncategorized","tag-actors","tag-cameras","tag-cross-platform-game-engine","tag-iwgame-engine","tag-marmalade-sdk","tag-scenes"],"_links":{"self":[{"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/posts\/459","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=459"}],"version-history":[{"count":11,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/posts\/459\/revisions"}],"predecessor-version":[{"id":478,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/posts\/459\/revisions\/478"}],"wp:attachment":[{"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/media?parent=459"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/categories?post=459"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/tags?post=459"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}