User Tools

Site Tools


en:tutorials:orxscroll:binding-orxscroll

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
en:tutorials:orxscroll:binding-orxscroll [2020/08/31 14:11 (5 years ago)] – ↷ Links adapted because of a move operation 76.14.89.164en:tutorials:orxscroll:binding-orxscroll [2024/05/06 18:10 (11 months ago)] (current) – Update to match project renaming from binding-of-objects to BindingOfObjects hcarty
Line 1: Line 1:
 ====== The Binding of Objects in orx/Scroll ====== ====== The Binding of Objects in orx/Scroll ======
  
-I keep a github repository for the code in this tutorial at https://github.com/fmahnke/OrxScroll-ObjectBinding. I like to keep the coding social, so please feel free to fork off my repo and create your own interesting projects!+The code for this tutorial is available at https://github.com/orx/scroll-tutorial
  
 ===== What is "Object Binding"? ===== ===== What is "Object Binding"? =====
Line 11: Line 11:
 For instance, you want game objects to do certain things every frame. You want enemies to move on a path, or possibly attack. You want the player's character to be moved based on user input. For instance, you want game objects to do certain things every frame. You want enemies to move on a path, or possibly attack. You want the player's character to be moved based on user input.
  
-Additionally, binding objects to classes makes it easy to handle Orx events on an object-specific basis. For example, each type of object can have its own OnCreate function which is called whenever an object of that type is created. OnDelete is called when the object is deleted, etc.+Additionally, binding objects to classes makes it easy to handle Orx events on an object-specific basis. For example, each type of object can have its own ''OnCreate'' function which is called whenever an object of that type is created. ''OnDelete'' is called when the object is deleted, etc.
  
 {{:tutorials:orxscroll:character_boy.png?nolink|}} {{:tutorials:orxscroll:enemy_bug.png?nolink|}} {{:tutorials:orxscroll:character_boy.png?nolink|}} {{:tutorials:orxscroll:enemy_bug.png?nolink|}}
  
-In this tutorial, we're going to create a small game with two specific examples of object binding. We'll create an Enemy Bug object and a Hero object and bind them to classes. Our enemy bugs will move semi-randomly across the screen. Our Hero will be controlled by the player. He'll flash red if he collides with an enemy bug, showing that he'hurt.+In this tutorial, we're going to create a small game with two specific examples of object binding. We'll create an Enemy Bug object and a Hero object and bind them to classes. Our enemy bugs will move semi-randomly across the screen. Our Hero will be controlled by the player. The Hero flashes red on collision with an enemy bug as an example of FX to indicate getting hurt.
  
 First, some preparation... First, some preparation...
Line 21: Line 21:
 ===== Trouble? ===== ===== Trouble? =====
  
-If you have trouble following this tutorial, please let us know in the "Help Request" section of the Orx forums. The community is very helpful.+If you have trouble following this tutorial, please reach out in the [[https://discord.com/channels/522167736823185418/717481561783664681|#support channel]] on Discord. The community is very helpful.
  
-If your problems are related to physics (collision detection), it can be very useful to turn on physics debugging. This is done in .ini config. Just see the comments in the provided config.+If your problems are related to physics (collision detection), it can be very useful to turn on physics debugging. This is done in .ini config. See the comments in this tutorial'config and in ''SettingsTemplate.ini'' linked in [[en:orx:config:developmentversion|Latest config settings for the Development Version]].
  
 ===== Create a new Scroll Project ===== ===== Create a new Scroll Project =====
  
-Before you begin this tutorial, you need a basic Orx/Scroll project ready. For details on doing this, see the previous tutorial, [[en:tutorials:orxscroll:introduction-orxscroll|An Introduction to Scroll]].+Before you begin this tutorial, you need a basic Orx/Scroll project created with ore's ''init'' tool for initializing new projects. For details on doing this, see [[en:tutorials:orxscroll:introduction-orxscroll|An Introduction to Scroll]].
  
-This tutorial assumes you've made new Orx/Scroll project by following the instructions in the previously tutorial exactly!+This tutorial assumes you're starting from fresh ''init'' project with Scroll support included!
  
 ===== Get the Config Ready ===== ===== Get the Config Ready =====
Line 35: Line 35:
 You'll need to download these textures ((Thanks to Daniel Cook of www.lostgarden.com for the great prototyping graphics)) for use in your config: You'll need to download these textures ((Thanks to Daniel Cook of www.lostgarden.com for the great prototyping graphics)) for use in your config:
  
-{{http://acksys.orx-project.org/images/Character_Boy.png}} +{{tutorials:orxscroll:character_boy.png}} 
-{{http://acksys.orx-project.org/images/Enemy_Bug.png}}+{{tutorials:orxscroll:enemy_bug.png}}
  
-Then, you'll need to prepare this config in your main Orx .ini file for use with this tutorial:+Then, you'll need to prepare this config in your main project ''.ini'' file for use with this tutorial:
  
 <hidden> <hidden>
-<code> +<code ini
-OrxScroll - config file +BindingOfObjects Template basic config file
-; Should be used with orx v.1.3+ +
- +
-[Render] +
-ShowProfiler  = false+
  
 [Display] [Display]
-ScreenWidth   1024 +; FullScreen false + Decoration false + no dimension -> Borderless FullScreen 
-ScreenHeight  768 +Title           = The Binding of Objects 
-Title         = The Binding of Objects +FullScreen      false 
-VSync         true +Decoration      = false 
-Smoothing     = true +Smoothing       = true 
-FullScreen    false+VSync           true
  
 [Physics] [Physics]
 ; Uncomment to show object bounding boxes ; Uncomment to show object bounding boxes
-; ShowDebug = true +; ShowDebug = true
  
-[Input+[Resource
-SetList Input+Texture         bundle: # bundle:BindingOfObjects.obr # ../data/texture 
 +Sound           = bundle: # bundle:BindingOfObjects.obr # ../data/sound
  
 [Input] [Input]
-KEY_LEFT  = MoveLeft +KEY_ESCAPE      = Quit 
-KEY_RIGHT = MoveRight +KEY_LEFT        = MoveLeft 
-KEY_UP    = MoveUp +KEY_RIGHT       = MoveRight 
-KEY_DOWN  = MoveDown+KEY_UP          = MoveUp 
 +KEY_DOWN        = MoveDown
  
 [MainViewport] [MainViewport]
Line 74: Line 72:
  
 [MainCamera] [MainCamera]
-FrustumWidth  @Display.ScreenWidth +FrustumWidth    1280 
-FrustumHeight = @Display.ScreenHeight +FrustumHeight   720 
-FrustumFar    = 10 +FrustumFar      = 10 
-Position      = (512384, -2)+FrustumNear     = 0 
 +Position        = (00, -2) 
 + 
 +[Scene] 
 +ChildList       = O-Hero # O-EnemyBug # O-EnemyBug # O-EnemyBug # O-EnemyBug # O-EnemyBug # O-EnemyBug
  
 [O-Hero] [O-Hero]
-Graphic  = G-Hero +Graphic         = G-Hero 
-Position = (512384, 0) +Position        = (00, 0) 
-Body     = B-Hero+Body            = B-Hero
  
 ; Hero Class Data ; Hero Class Data
-MovementSpeed = 100.0+MovementSpeed   = 100.0
  
 [G-Hero] [G-Hero]
-Texture = ../data/Character_Boy.png+Texture         = Character_Boy.png
  
 [B-Hero] [B-Hero]
-PartList = BP-Hero +PartList        = BP-Hero 
-Dynamic  = true+Dynamic         = true
  
 [BP-Hero] [BP-Hero]
-Type      = box +Type            = box 
-SelfFlags = 0x0001 +SelfFlags       = 0x0001 
-CheckMask = 0xFFFF+CheckMask       = 0xFFFF
  
 [O-EnemyBug] [O-EnemyBug]
-Position = (0, 200, 0) ~ (1000, 200, 0) +Position        = (-600, 200, 0) ~ (600, 200, 0) 
-Graphic  = G-EnemyBug +Graphic         = G-EnemyBug 
-Body     = B-EnemyBug+Body            = B-EnemyBug
  
 ; EnemyBug Class Data ; EnemyBug Class Data
-MovementSpeed           = 25.0+MovementSpeed   = 25.0
 DirectionChangeInterval = 0.5 ~ 2.5 DirectionChangeInterval = 0.5 ~ 2.5
  
 [G-EnemyBug] [G-EnemyBug]
-Texture = ../data/Enemy_Bug.png +Texture         = Enemy_Bug.png 
-Pivot   = center+Pivot           = center
  
 [B-EnemyBug] [B-EnemyBug]
-PartList = BP-Hero+PartList        = BP-EnemyBug
  
 [BP-EnemyBug] [BP-EnemyBug]
-Type      = box +Type            = box 
-SelfFlags = 0x0002 +SelfFlags       = 0x0002 
-CheckMask = 0xFFFF+CheckMask       = 0xFFFF
  
 [FX-Flash] [FX-Flash]
-SlotList = FXS-FlashRed # FXS-Unflash+SlotList        = FXS-FlashRed # FXS-Unflash
  
 [FXS-FlashRed] [FXS-FlashRed]
-Type       = color +Type            = color 
-Curve      = smoother +Curve           = smoother 
-StartTime  = 0 +StartTime       = 0 
-EndTime    = 0.1 +EndTime         = 0.1 
-Absolute   = true +Absolute        = true 
-StartValue = (255, 255, 255) +StartValue      = (255, 255, 255) 
-Period     = 0.5 +Period          = 0.5 
-EndValue   = (255, 0, 0)+EndValue        = (255, 0, 0)
  
 [FXS-Unflash] [FXS-Unflash]
-Type       = color +Type            = color 
-Curve      = smoother +Curve           = smoother 
-StartTime  = @FXS-FlashRed.EndTime +StartTime       = @FXS-FlashRed.EndTime 
-EndTime    = 0.2 +EndTime         = 0.2 
-Absolute   = true +Absolute        = true 
-StartValue = @FXS-FlashRed.EndValue +StartValue      = @FXS-FlashRed.EndValue 
-EndValue   = (255, 255, 255)+EndValue        = (255, 255, 255)
 </code> </code>
 </hidden> </hidden>
  
 It's all the typical object, graphic, physics stuff you've seen in previous Orx tutorials. Notice, however, we've added some extra properties to our EnemyBug and Hero objects. The Orx engine doesn't use these, but we'll use them later in this tutorial. It's all the typical object, graphic, physics stuff you've seen in previous Orx tutorials. Notice, however, we've added some extra properties to our EnemyBug and Hero objects. The Orx engine doesn't use these, but we'll use them later in this tutorial.
-===== Creating Game Objects in Scroll ===== 
  
-In Orxyou define objects in config files and create them at runtime using orxObject_CreateFromConfig. With Scroll, object creation is just as easyIn your class deriving from Scroll, modify your OrxScroll::Init function as follows:+A newly created ''init'' project creates a ''Scene'' object by defaultwith other objects created as children. In the config abovewe have the Hero object and several Enemy Bug objects in the ''ChildList'' for ''Scene''.
  
-<code c> +Run your project. As you might expect, you'll see a hero and a few randomly placed enemy bugs in a gray expanse. Nothing happens since we've defined no behavior to control them. Pressing ''Esc''ape will quit the game.
-orxSTATUS OrxScroll::Init () +
-+
-    orxSTATUS result = orxSTATUS_SUCCESS;+
  
-    for (orxU32 i = 0; i < 5; i++) +Stop and think for a moment about how you might add behavior to the objects in Orx.
-    { +
- CreateObject ("O-EnemyBug"); +
-    } +
-    return result; +
-+
-</code>+
  
-Run your project. As you might expect, you'll see a few randomly placed enemy bugs in a gray expanse. Nothing happens since we've defined no behavior to control them. 
- 
-Stop and think for a moment about how you might add behavior to the objects in Orx.  
 ===== Giving the Bugs a Brain (Deriving the ScrollObject Class) ===== ===== Giving the Bugs a Brain (Deriving the ScrollObject Class) =====
  
-The first step to object binding is to create a binding class. To do that, we derive from the ScrollObject base class.+The first step to object binding is to create a binding class. To do that, we derive from the ''ScrollObject'' base class. ''init'' gives us an ''Object'' class which derives from ''ScrollObject'' and we can derive our objects from ''Object''.
  
-First, let's create the interface for our derived class. Create a file called EnemyBug.h and add it to your project. Add the following code to EnemyBug.h:+First, let's create the interface for our derived class. Create a file called ''EnemyBug.h'' and add it to your project. Add the following code to ''EnemyBug.h'':
  
-<code c> +<code c++
-#include "OrxScroll.h"+#pragma once
  
-enum Direction { NORTH, SOUTH, EAST, WEST };+#include "Object.h"
  
-class EnemyBug : public ScrollObject+enum Direction
 { {
-private: +  NORTH, 
-    //! Called on object creation. +  SOUTH, 
-    virtual void OnCreate (); +  EAST, 
-    //! Called on object deletion +  WEST, 
-    virtual void OnDelete (); +  LAST = WEST, 
-    //! Called on clock update +};
-    virtual void Update (const orxCLOCK_INFO &_rstInfo);+
  
-    //Direction of movement +class EnemyBug : public Object 
-    Direction   m_direction; +
-    //Speed of movement +public: 
-    float       m_movementSpeed; +protected: 
-    //Time since change of direction +  void OnCreate(); 
-    float       m_timeSinceDirectionChange; +  void OnDelete(); 
-    //Time interval between direction changes +  void Update(const orxCLOCK_INFO &_rstInfo); 
-    float       m_directionChangeInterval;+ 
 +private: 
 +  // Direction of movement 
 +  Direction m_direction; 
 +  // Speed of movement 
 +  orxFLOAT m_movementSpeed; 
 +  // Time since change of direction 
 +  orxFLOAT m_timeSinceDirectionChange; 
 +  // Time interval between direction changes 
 +  orxFLOAT m_directionChangeInterval;
 }; };
 </code> </code>
Line 201: Line 198:
 Let's create the class implementation. Add a file called EnemyBug.cpp to your project and add the following code to it: Let's create the class implementation. Add a file called EnemyBug.cpp to your project and add the following code to it:
  
-<code c>+<code c++>
 #include "EnemyBug.h" #include "EnemyBug.h"
  
-void EnemyBug::OnCreate ()+void EnemyBug::OnCreate()
 { {
-    // Set initial movement direction +  // Set initial movement direction 
-    m_direction = SOUTH; +  m_direction = SOUTH; 
-    // Get movement speed from config value  +  // Get movement speed from config value 
-    m_movementSpeed = orxConfig_GetFloat ("MovementSpeed"); +  m_movementSpeed = orxConfig_GetFloat("MovementSpeed"); 
-    // Get direction change interval from config value +  // Get direction change interval from config value 
-    m_directionChangeInterval = orxConfig_GetFloat ("DirectionChangeInterval");+  m_directionChangeInterval = orxConfig_GetFloat("DirectionChangeInterval");
 } }
  
-void EnemyBug::OnDelete ()+void EnemyBug::OnDelete()
 { {
-    // Do nothing when deleted+  // Do nothing when deleted
 } }
  
 void EnemyBug::Update(const orxCLOCK_INFO &_rstInfo) void EnemyBug::Update(const orxCLOCK_INFO &_rstInfo)
 { {
-    // Always initialize thy variables +  // Always initialize thy variables 
-    orxVECTOR speed = orxVECTOR_0;+  orxVECTOR speed = orxVECTOR_0;
  
-    // Set rotation, flip, and speed based on the object'+  // Set rotation, flip, and speed based on the object'
-    // current direction of movement. +  // current direction of movement. 
-    switch (m_direction) +  switch (m_direction) 
-    {+  {
     orxBOOL flipX, flipY;     orxBOOL flipX, flipY;
-    case NORTH: +  case NORTH: 
- speed.fY = -m_movementSpeed; +    speed.fY = -m_movementSpeed; 
- SetRotation (270 * orxMATH_KF_DEG_TO_RAD); +    SetRotation(270 * orxMATH_KF_DEG_TO_RAD); 
- SetFlip (false, false); +    SetFlip(false, false); 
- break; +    break; 
-    case SOUTH: +  case SOUTH: 
- speed.fY = m_movementSpeed; +    speed.fY = m_movementSpeed; 
- SetRotation (90 * orxMATH_KF_DEG_TO_RAD); +    SetRotation(90 * orxMATH_KF_DEG_TO_RAD); 
- SetFlip (false, false); +    SetFlip(false, false); 
- break; +    break; 
-    case WEST: +  case WEST: 
- speed.fX = -m_movementSpeed; +    speed.fX = -m_movementSpeed; 
- SetRotation (0 * orxMATH_KF_DEG_TO_RAD); +    SetRotation(0 * orxMATH_KF_DEG_TO_RAD); 
- SetFlip (true, false); +    SetFlip(true, false); 
- GetFlip (flipX, flipY); +    GetFlip(flipX, flipY); 
- break; +    break; 
-    case EAST: +  case EAST: 
- speed.fX = m_movementSpeed; +    speed.fX = m_movementSpeed; 
- SetRotation (0); +    SetRotation(0); 
- SetFlip (false, false); +    SetFlip(false, false); 
- GetFlip (flipX, flipY); +    GetFlip(flipX, flipY); 
- break; +    break; 
-    default: +  default: 
- orxASSERT (false); +    orxASSERT(false); 
-    }+  }
  
-    // Update object's speed of movement +  // Update object's speed of movement 
-    SetSpeed (speed);+  SetSpeed(speed);
  
-    // Time since direction change exceeds interval of direction change? +  // Time since direction change exceeds interval of direction change? 
-    if ((m_timeSinceDirectionChange += _rstInfo.fDT) >= m_directionChangeInterval) +  if ((m_timeSinceDirectionChange += _rstInfo.fDT) >= m_directionChangeInterval) 
-    +  
- // Reset time +    // Reset time 
- m_timeSinceDirectionChange = 0; +    m_timeSinceDirectionChange = 0; 
- // Pick random number between bounds of Direction enum +    // Pick random number between bounds of Direction enum 
- orxU32 randomNum = orxMath_GetRandomU32 (0, highDirection); +    orxU32 randomNum = orxMath_GetRandomU32(0, static_cast<orxU32>(LAST)); 
- // Update object's direction of movement +    // Update object's direction of movement 
- m_direction = static_cast<Direction> (randomNum); +    m_direction = static_cast<Direction>(randomNum); 
-    }+  }
 } }
 </code> </code>
Line 273: Line 270:
 This is all the code we need to bring our enemy bug to life. The code comments should explain what is happening, but note the following: This is all the code we need to bring our enemy bug to life. The code comments should explain what is happening, but note the following:
  
-  * An instance of the EnemyBug class is created for every enemy bug ScrollObject created. Recall in our OrxScroll::Init function we create 5 enemy bug objects. Therefore, 5 instances of EnemyBug are created. Each enemy bug shown on the screen has a class instance defining its behavior. +  * An instance of the ''EnemyBug'' class is created for every enemy bug object created. Recall in our ''Scene'' object we create 5 enemy bug objects as children. Therefore, 5 instances of ''EnemyBug'' are created. Each enemy bug shown on the screen has a class instance defining its behavior. 
-  * This class makes use of the SetRotation, SetFlip, and SetSpeed functions defined in the ScrollObject base class. +  * This class makes use of the ''SetRotation''''SetFlip'', and ''SetSpeed'' functions defined in the ''ScrollObject'' base class. 
-  * OnCreate is called when the object is first created. We didn't define a constructor, so data members must be initialized here. +  * ''OnCreate'' is called when the object is first created. We didn't define a constructor, so data members must be initialized here. 
-  * In OnCreate, we query values in config without pushing the object's section first. That's okay, because Scroll pushes the binding Orx object's config section as a convenience before calling OnCreate.+  * In ''OnCreate'', we query values in config without pushing the object's section first. That's okay, because Scroll pushes the binding Orx object's config section as a convenience before calling ''OnCreate''.
   * We initialize our class members using the "custom" values we defined in config. While not strictly necessary, this is good data-driven design. It means we can adjust these variables and run again without recompiling.   * We initialize our class members using the "custom" values we defined in config. While not strictly necessary, this is good data-driven design. It means we can adjust these variables and run again without recompiling.
-  * OnDelete is called when the object is deleted. We must provide a body for the function, but it does nothing in our case. +  * ''OnDelete'' is called when the object is deleted. We must provide a body for the function, but it does nothing in our case. 
-  * Update is called on every frame. This is the interesting part of EnemyBug. In our case, we update its rotation and speed based on its currently direction of travel. ((Why use SetSpeed and not SetPosition? Because the objects in this tutorial have physics bodies. Calling SetPosition on objects with physics bodies messes up the physics simulation. If you want to watch that happen, change SetSpeed to SetPosition and turn on physics debugging as described in the config.))+  * ''Update'' is called on every frame. This is the interesting part of ''EnemyBug''. In our case, we update its rotation and speed based on its currently direction of travel. ((Why use ''SetSpeed'' and not ''SetPosition''? Because the objects in this tutorial have physics bodies. Calling ''SetPosition'' on objects with physics bodies messes up the physics simulation. If you want to watch that happen, change ''SetSpeed'' to ''SetPosition'' and turn on physics debugging as described in the config.))
  
 ==== ScrollObject Callbacks and Accessors ==== ==== ScrollObject Callbacks and Accessors ====
  
-  * OnCreate, OnDelete, and Update are private callbacks from the ScrollObject class. That means these functions are called by Orx when these events occur on the object, allowing you to easily override their behavior. You should never call these functions directly. +  * ''OnCreate''''OnDelete'', and ''Update'' are protected callbacks from the ''ScrollObject'' class. That means these functions are called by Orx when these events occur on the object, allowing you to easily override their behavior. You should never call these functions directly. 
-  * SetRotation, SetFlip, and SetSpeed are public accessors from the ScrollObject class. You call them directly from other object class functions (and any other class can call them if it has a pointer to the class instance). The accessors correspond to the similar orxObject_ functions (e.g. SetPosition == orxObject_SetPosition).+  * ''SetRotation''''SetFlip'', and ''SetSpeed'' are public accessors from the ''ScrollObject'' class. You call them directly from other object class functions (and any other class can call them if it has a pointer to the class instance). The accessors correspond to the similar ''orxObject_'' functions (e.g. ''SetPosition'' == ''orxObject_SetPosition'').
  
-If you want to see all the accessors and callbacks available for overriding, see the ScrollObject class interface in the ScrollObject.h file.+If you want to see all the accessors and callbacks available for overriding, see the ''ScrollObject'' class interface in the ''ScrollObject.h'' file.
  
-We've now programmed a much more interesting bug. If you run the game, however, you'll still see nothing but still objects. That's because we haven't yet told Scroll that we want our enemy bug objects to take on the behavior in our EnemyBug class. One step remains.+We've now programmed a much more interesting bug. If you run the game, however, you'll still see nothing but still objects. That's because we haven't yet told Scroll that we want our enemy bug objects to take on the behavior in our ''EnemyBug'' class. One step remains.
  
 ===== Telling Scroll about the Enemy Bug Class (Overriding BindObjects) ===== ===== Telling Scroll about the Enemy Bug Class (Overriding BindObjects) =====
  
-The ScrollBindObject function accepts as a template parameter a class deriving from ScrollObject. It accepts as a regular parameter an Orx config section name. Then it binds any instance of the Orx object to the class.+The ''ScrollBindObject'' function accepts as a template parameter a class deriving from ''ScrollObject''. It accepts as a regular parameter an Orx config section name. Then it binds any instance of the Orx object to the class.
  
-Add the following private function declaration to your OrxScroll class in OrxScroll.h:+Include ''EnemyBug.h'' after the inclusion of ''Object.h'' in ''binding-of-objects.cpp'':
  
-<code c> +<code c++
-virtual void BindObjects ();+#include "EnemyBug.h"
 </code> </code>
  
-Now add the function's definition in OrxScroll.cpp:+Add the following lines to ''binding_of_objects::BindObjects'' in ''BindingOfObjects.cpp'' after the line for ''"Object"'':
  
 <code c> <code c>
-void OrxScroll::BindObjects () +  // Bind the EnemyBug class to the O-EnemyBug config section 
-+  ScrollBindObject<EnemyBug>("O-EnemyBug");
-    ScrollBindObject<EnemyBug> ("O-EnemyBug"); +
-}+
 </code> </code>
  
-The BindObjects function is called when the game starts. It basically says, "Whenever we create an object of O-EnemyBug as defined in Orx config, make it take on all the behavior defined in the EnemyBug class."+The order of calls to ''ScrollBindObject'' does not matter as long as all of the necessary bindings occur in ''BindObjects''
 + 
 +The ''BindObjects'' function is called when the game starts. It basically says, "Whenever we create an object of ''O-EnemyBug'' as defined in Orx config, make it take on all the behavior defined in the ''EnemyBug'' class."
  
-Of course, the EnemyBug class must exist for this to work, which is why we made it first.+Of course, the ''EnemyBug'' class must exist for this to work, which is why we made it first.
  
 Run the game and you should see all your enemy bugs come to life. Run the game and you should see all your enemy bugs come to life.
Line 317: Line 314:
 ===== Our Unfortunate Hero (Another Derived ScrollObject) ===== ===== Our Unfortunate Hero (Another Derived ScrollObject) =====
  
-The bugs in our game must be very hungry! Let's add another bound object. First, add Hero.h to your project and write its interface.+The bugs in our game must be very hungry! Let's add another bound object. First, add ''Hero.h'' to your project and write its interface.
  
-<code c> +<code c++> 
-#include "OrxScroll.h"+#pragma once 
 + 
 +#include "Object.h"
  
-class Hero : public ScrollObject+class Hero : public Object
 { {
 +public:
 +protected:
 +  void OnCreate();
 +  void OnDelete();
 +  void Update(const orxCLOCK_INFO &_rstInfo);
 +  void OnCollide(ScrollObject *_poCollider, orxBODY_PART *_pstPart, orxBODY_PART *_pstColliderPart, const orxVECTOR &_rvPosition, const orxVECTOR &_rvNormal);
 +
 private: private:
-    virtual void    OnCreate (); +  orxFLOAT m_movementSpeed;
-    virtual void    OnDelete (); +
-    virtual orxBOOL OnCollide (ScrollObject *_poCollider, +
-        const orxSTRING _zPartName, +
-        const orxSTRING _zColliderPartName, +
-        const orxVECTOR &_rvPosition, +
-        const orxVECTOR &_rvNormal); +
-    virtual void    Update (const orxCLOCK_INFO &_rstInfo); +
- +
-    orxFLOAT     m_movementSpeed;+
 }; };
 </code> </code>
  
-Hero has a similar interface, but notice we've added an override for OnCollide. This function will be called whenever Orx detects a physics collision between this object and another.+Hero has a similar interface, but notice we've added an override for ''OnCollide''. This function will be called whenever Orx detects a physics collision between this object and another.
  
 And add this code: And add this code:
  
-<code c>+<code c++>
 #include "Hero.h" #include "Hero.h"
  
-void Hero::OnCreate ()+void Hero::OnCreate()
 { {
-    // Get movement speed from config value +  // Get movement speed from config value 
-    m_movementSpeed = orxConfig_GetFloat ("MovementSpeed");+  m_movementSpeed = orxConfig_GetFloat("MovementSpeed");
 } }
  
-void Hero::OnDelete ()+void Hero::OnDelete()
 { {
-    // Do nothing when deleted+  // Do nothing when deleted
 } }
  
 void Hero::Update(const orxCLOCK_INFO &_rstInfo) void Hero::Update(const orxCLOCK_INFO &_rstInfo)
 { {
-    // Always initialize thy variables +  // Use movement input to initialize a vector to scale movement speed 
-    orxVECTOR speed = orxVECTOR_0;+  orxVECTOR speed = 
 +      // Vector's x component is right - left input strength. It will 
 +      // be 0.0 if the inputs are either inactive or both equally active. 
 +      orxInput_GetValue("MoveRight") - orxInput_GetValue("MoveLeft"), 
 +      // Vector's y component is down - up input strength. It will 
 +      // be 0.0 if the inputs are either inactive or both equally active. 
 +      orxInput_GetValue("MoveDown") - orxInput_GetValue("MoveUp"), 
 +      0.0};
  
-    if (orxInput_IsActive ("MoveLeft")) +  // Normalize the input vector if it has a length > 1 
-    +  if (orxVector_GetSquareSize(&speed> 1.0
- speed.fX = -m_movementSpeed+  
-    +    orxVector_Normalize(&speed, &speed)
-    else if (orxInput_IsActive ("MoveUp")) +  
-    { + 
- speed.fY = -m_movementSpeed; +  // Scale the raw input vector by the our movement speed 
-    } +  orxVector_Mulf(&speed, &speed, m_movementSpeed)
-    else if (orxInput_IsActive ("MoveRight")) + 
-    { +  // Update our speed 
- speed.fX = m_movementSpeed; +  SetSpeed(speed, false);
-    } +
-    else if (orxInput_IsActive ("MoveDown")) +
-    { +
- speed.fY = m_movementSpeed; +
-    } +
-    SetSpeed (speed, false);+
 } }
  
-orxBOOL Hero::OnCollide(ScrollObject *_poCollider, +void Hero::OnCollide(ScrollObject *_poCollider, orxBODY_PART *_pstPartorxBODY_PART *_pstColliderPart, const orxVECTOR &_rvPosition, const orxVECTOR &_rvNormal)
-       const orxSTRING _zPartName, +
-       const orxSTRING _zColliderPartName, +
-       const orxVECTOR &_rvPosition, +
-       const orxVECTOR &_rvNormal)+
 { {
-    // Add flash effect +  // Add flash effect 
-    AddFX ("FX-Flash")+  AddFX("FX-Flash");
- +
-    return true;+
 } }
 </code> </code>
  
-The code should be almost self-explanatory. The hero's movement speed will be pulled from its config value. The update function (called every frame) sets the speed of the character based on what keyboard arrow is pressed. The OnCollide function adds a "flash" effect to the character.+The code should be almost self-explanatory. The hero's movement speed will be pulled from its config value. The update function (called every frame) sets the speed of the character based on what keyboard arrow is pressed. The ''OnCollide'' function adds a "flash" effect to the character.
  
-Remember you need to modify the OrxScroll::Init function so it creates your O-Hero config object. Otherwise the Hero will not appear on the screen.+You have to modify the ''BindingOfObjects::BindObjects'' function to make it bind the new ''Hero'' class to the ''O-Hero'' object. Otherwisethe Hero will not be bound to its class and will just stand still in the middle of the screen!
  
-You also have to modify the OrxScroll::BindObjects function to make it bind the new Hero class to the O-Hero object. Otherwise, the Hero will not be bound to its class and will just stand still in the middle of the screen! +Try to do those things yourself. If you need help, though, here are the lines to add:
- +
-Try to do those things yourself. If you need help, though, here are the modified functions:+
  
 <hidden> <hidden>
 <code c> <code c>
-orxSTATUS OrxScroll::Init () +  // Bind the Hero class to the O-Hero config section 
-+  ScrollBindObject<Hero>("O-Hero");
-    orxSTATUS result = orxSTATUS_SUCCESS; +
- +
-    CreateObject ("O-Hero"); +
- +
-    for (orxU32 i = 0; i < 5; i++) +
-    { +
- CreateObject ("O-EnemyBug"); +
-    } +
-    return result; +
-+
- +
-void OrxScroll::BindObjects () +
-+
-    ScrollBindObject<EnemyBug> ("O-EnemyBug"); +
-    ScrollBindObject<Hero>     ("O-Hero"); +
-}+
 </code> </code>
 </hidden> </hidden>
  
-When you run the game, you'll be able to control the hero with the arrow keys. Be careful, the bugs will bite him if he gets too close and the OnCollision callback will make him "flash" red.+When you run the game, you'll be able to control the hero with the arrow keys. Be careful, the bugs will bite him if he gets too close and the OnCollide callback will make him "flash" red.
  
 {{ :tutorials:orxscroll:binding-orxscroll-screenshot.png?nolink&500 |}} {{ :tutorials:orxscroll:binding-orxscroll-screenshot.png?nolink&500 |}}
Line 432: Line 406:
 Well, you just finished making what could loosely be considered a game! Here are some additions you could make. Well, you just finished making what could loosely be considered a game! Here are some additions you could make.
  
-  * Add a "Life" property to the Hero. Modify OnCollision so the Hero loses life each time he's hit. Give him an untimely death when life reaches 0. +  * Add a "Life" property to the Hero. Modify ''OnCollide'' so the Hero loses life each time he's hit. Give him an untimely death when life reaches 0. 
-  * Give the Hero a weapon he can fire at the bugs. The OnCollision callback for the enemy bugs can be used to make them take damage from the weapon. +  * Give the Hero a weapon to fire at the bugs. The ''OnCollide'' callback for the enemy bugs can be used to make them take damage from the weapon. 
-  * Be sure to add interesting death animations in the OnDelete callback.+  * Be sure to add interesting death animations in the ''OnDelete'' callback.
   * Add a more interesting background, of course.   * Add a more interesting background, of course.
en/tutorials/orxscroll/binding-orxscroll.1598908270.txt.gz · Last modified: 2020/08/31 14:11 (5 years ago) by 76.14.89.164