Jump to content
  • Advertisement
  • Remove ads and support GameDev.net for only $3. Learn more: The New GDNet+: No Ads!

  • 02/28/18 02:32 AM

    Learning
    How to write a 2D UFO game using the Orx Portable Game Engine - Part 2

    General and Gameplay Programming

    sausagejohnson

    The UFO

    This is part 2 of a series on creating a game with the Orx Portable Game Engine. Part 1 is here.

    We have a playfield, and now we need a UFO character for the player to control.

    The first step is the create the configuration for the ufo object in ufo.ini:

     

    [UfoObject] 
    Graphic  = UfoGraphic 
    Position = (0, 0, -0.1)

    This indicates that the UfoObject should use a graphic called UfoGraphic. Secondly, its position will be centered in the playfield with (x,y) = (0,0). The -0.1 is the Z-axis, and this will be placed above the BackgroundObject whose Z-axis is set to 0.

    Then the UfoGraphic which the UfoObject needs:

     

    [UfoGraphic]
    Texture = ufo.png
    Pivot   = center

     

    Unlike the background object, our ufo object will need to be assigned to a variable. This will make it possible to affect the ufo using code:

    Create the variable for our ufo object just under the orx.h include line:

     

    #include "orx.h" 
    orxOBJECT *ufo;

     

    And in the Init() function, create an instance of the ufo object with:

     

    ufo = orxObject_CreateFromConfig("UfoObject");

     

    Compile and run. You'll see a ufo object in front of the background. Excellent.

    first-ufo.jpg.68523e488bd35a2119668f8f28726870.jpg

    Time to move to something a little more fun, moving the ufo.

     

    Controlling the UFO

    The ufo is going to be controlled using the cursor arrow keys on the keyboard.

    The ufo will be moved by applying forces. Physics will be set up in the project in order to do this.

    Also, we will use a clock to call an update function regularly. This function will read and respond to key presses.

     

    Defining Direction Keys

    Defining the keys is very straight forward. In the config file, expand the MainInput section in the ufo.ini by adding the four cursor keys:

     

    [MainInput] 
    KEY_ESCAPE = Quit 
    KEY_UP     = GoUp 
    KEY_DOWN   = GoDown 
    KEY_LEFT   = GoLeft 
    KEY_RIGHT  = GoRight

     

    Each key is being given a label name, like: GoUp or GoDown. These label names are available in our code to test against.

    The next step is to create an update callback function in our code where the keys presses are checked:

     

    void orxFASTCALL Update(const orxCLOCK_INFO *_pstClockInfo, void *_pContext)
    { 
    }

     

    And in order to tie this function to a clock (the clock will execute this function over and over), add the following to bottom of the Init() function:

     

    orxClock_Register(orxClock_FindFirst(orx2F(-1.0f), orxCLOCK_TYPE_CORE), 
                      Update, orxNULL, orxMODULE_ID_MAIN, orxCLOCK_PRIORITY_NORMAL);

     

    That looks very scary and intimidating, but the only part that is important to you is the parameter with “Update”. This means, tell the existing core clock to continually call our “Update” function. Of course you can specify any function name here you like as long as it exists.

    Let's test a key to ensure that our event is working well. Add the following code into the Update function:

     

    void orxFASTCALL Update(const orxCLOCK_INFO *_pstClockInfo, void *_pContext)
    {
        if (ufo) {
     
            if (orxInput_IsActive("GoLeft")) {
                orxLOG("LEFT PRESSED!");
            }
        }
    }

     

    Every time Update is run, ufo is tested to ensure it exists, and then moves to check the input system for the label “GoLeft” (if it is active or pressed). Remember how GoLeft is bound to KEY_LEFT in the MainInput config section?

    If that condition is true, send “LEFT PRESSED!” to the console output window while the key is pressed or held down.

    Soon we'll replace the orxLOG line with a function that places force on the ufo. But before that, we need to add physics to the ufo.

    Compile and run.

    Press the left arrow key and take note of the console window. Every time you press or hold the key, the message is printed. Good, so key presses are working.

    left-press-test.jpg.0eda61ccb55bcdb1a559ecfc445ae23b.jpg

     

    Physics

    In order to affect the ufo using forces, physics need to be enabled.

    Begin by adding a Physics config section and setting Gravity with:

     

    [Physics]
    Gravity = (0, 980, 0)

     

    In order for an object in Orx to be affected by physics, it needs both a dynamic body, and at least one bodypart. Give the ufo a body with the Body property:

     

    [UfoObject]
    Graphic  = UfoGraphic
    Position = (0, 0, -0.1)
    Body     = UfoBody

     

    Next, create the UfoBody section and define the UfoBodyPart property:

     

    [UfoBody]
    Dynamic  = true
    PartList = UfoBodyPart

     

    The body part is set to Dynamic which means that it is affected by gravity and collisions. A body needs at least one part, and so we need to define the UfoBodyPart:

     

    [UfoBodyPart]
    Type  = sphere
    Solid = true

     

    The body part Type is set to be a sphere which will automatically size itself around the object's size, and the body is to be solid so that if it should collide with anything, it will not pass through it.

    Compile and Run.

    The ufo falls through the floor. This is because of the gravity setting of 980 in the y axis which simulates world gravity.

    ufo-gravity.thumb.jpg.805e06d205e306d58e734cd562d5eed1.jpg

    Our game is a top down game. So change the Gravity property to:

     

    [Physics] 
    Gravity = (0, 0, 0)

     

    Re-run (no compile needed) and the ufo should remain in the centre of the screen.

    The Physics section has another handy property available to visually test physics bodies on objects: ShowDebug. Add this property with true:

     

    [Physics]
    Gravity   = (0, 0, 0)
    ShowDebug = true

     

    Re-run, and you will see a pinkish sphere outline automatically sized around the ufo object.

    ufo-physics-on.jpg.671777abcd9b59c405a31f456e08ca12.jpg

    For now we'll turn that off again. You can do this by changing the ShowDebug value to false, adding a ; comment in front of the line or simply just deleting the line. We'll set our ShowDebug to false:

     

    [Physics]
    Gravity   = (0, 0, 0)
    ShowDebug = false

     

    Let's add some force to the ufo if the left cursor key is pressed. Change the code in the Update function to be:

     

    void orxFASTCALL Update(const orxCLOCK_INFO *_pstClockInfo, void *_pContext)
    {
      if (ufo) {
     
        const orxFLOAT FORCE = 0.8;
        orxVECTOR leftForce= { -FORCE, 0, 0 };
     
        if (orxInput_IsActive("GoLeft")) {
            orxObject_ApplyForce(ufo, &leftForce, orxNULL);
        }
      }
    }

     

    The orxObject_ApplyForce function takes an orxVECTOR facing left and applies it to the ufo object.

    Compile and re-run.

    If you press and release the left arrow key, the ufo will move to the left. If you hold the left key down, the ufo will increase its speed and move out the left hand side of the screen.

    ufo-move-left.thumb.jpg.79c3f77dae131ffa8df8a7c2b100c40f.jpg

    Even if you tap the left key once quickly, the ufo will still eventually travel out of the left of the screen. There is no friction yet to slow it down, or any barriers to stop it going out of the screen.

     

    Barrier Around The Border

    Even though the background looks it has a border, it is really only a picture. In order to create a barrier for the ufo, we will need to wrap the edges using some body parts.

    This means, the background object will also be given a body, and four body parts, one for each wall. Start with adding a body to the object:

     

    [BackgroundObject]
    Graphic  = BackgroundGraphic
    Position = (0, 0, 0)
    Body     = WallBody

     

    And then the body itself:

     

    [WallBody]
    Dynamic  = false
    PartList = WallTopPart # WallRightPart # WallBottomPart # WallLeftPart

     

    This is different from the ufo body. This body is not dynamic. This means that it is a static body, one that cannot be affected by gravity. But dynamic objects can still collide with it. Also, there are four parts to this body, unlike the ufo which only had one.

    Start with the WallTopPart first:

     

    [WallTopPart]
    Type        = box
    Solid       = true
    TopLeft     = (-400, -300, 0)
    BottomRight = (400, -260, 0)

     

    In this part, the type is a box body part. It is set to solid for collisions, ie so that a dynamic object can collide with it but not pass though it.

    Stretch the box to cover the region from (-400,-300) to (400, -260).

    At this point, it might be a good idea to turn on the physics debugging to check our work:

     

    [Physics]
    Gravity   = (0, 0, 0)
    ShowDebug = true

     

    Re-run the project.

    The top wall region should cover the top barrier squares:

    playfield-top-wall.thumb.jpg.c9895e72197fc6a806e77c0eff9c81d6.jpg

     

    Great. Next, we'll do the right hand side. But rather than copy all the same values, we'll reuse some from the top wall:

     

    [WallRightPart@WallTopPart]
    TopLeft     = (360, -260,0)
    BottomRight = (400, 260, 0)

     

    Notice the @WallTopPart in the section name? This means: copy all the values from WallTopPart, but any properties in WallRightPart will take priority.

    Therefore, use the Type, and Solid properties from WallTopPart, but use our own values for TopLeft and BottomRight for the WallRightPart section.

    This is called “Section Inheritance”. This will come in very handy soon when we tweak values or add new properties to all four wall parts.

    Re-run the project, and there will now be two walls.

    right-wall-barrier.jpg.dfc9f799de465c34418060f683845c7d.jpg

    Define the last two walls using the same technique:

     

    [WallBottomPart@WallTopPart]
    TopLeft     = (-400,260,0)
    BottomRight = (400, 300, 0)
     
    [WallLeftPart@WallTopPart]
    TopLeft     = (-400,-260,0)
    BottomRight = (-360, 260, 0)

     

    Now there are four walls for the ufo to collide with.

    Re-run and try moving the ufo left into the wall.

    no-collision.thumb.jpg.2dddd423bf7c80507e66517b699863c4.jpg

    Oops, it doesn't work. It still passes straight though. There is one last requirement for the collision to occur: we need to tell the physics system, who can collide with who.

    We'll cover that in Part 3.



      Report Article


    User Feedback


    There are no comments to display.



    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!