Jump to content
  • Advertisement
  • 03/01/18 02:45 AM

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

    General and Gameplay Programming

    sausagejohnson

    Collisions

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

    There is one last requirement for the collision to occur: we need to tell the physics system, who can collide with who.

    This is done with flags and masks.

    Make a change to the ufo's body part by adding SelfFlags and CheckMask:

     

    [UfoBodyPart]
    Type      = sphere
    Solid     = true
    SelfFlags = ufo
    CheckMask = wall

     

    SelfFlags is the label you assign to one object, and CheckMask is the list of labels that your object can collide with.

    These labels don't have to match the names you give objects, however it will help you stay clean and organised.

    So in the config above, we are saying: the UfoBodyPart is a “ufo” and it is expected to collide with any bodypart marked as a “wall”.

    But we haven't done that yet, so let's do it now. We will only need to add it to the WallTopPart:

     

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

     

    Remember, that the other three wall parts inherit the values from WallTopPart. So each now carries the label of “wall” and they will collide with any other body part that carries the label of “ufo”.

    Re-run and press the left arrow key and drive the ufo into the left wall. It collides! And it stops.

    collision.thumb.jpg.849a8eeea759d1a1b32e3a4ef2a03c68.jpg

    Now that the collision is working, we can flesh out the rest of the keyboard controls and test all four walls:

     

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

     

    Now is a good time to turn off the physics debug as we did earlier on.

    Compile and run.

    Try all four keys, and you should be able to move the ufo around the screen. The ufo can also collide with each wall.

    collision-all-walls.thumb.jpg.df6000eba1a35ec169bd2078c9e2ca57.jpg

    The ufo is a little boring in the way that it doesn't spin when colliding with a wall.

    We need to ensure the UfoBody is not using fixed rotation. While this value defaults to false when not supplied, it will make things more readable if we explicitly set it:

     

    [UfoBody]
    Dynamic       = true
    PartList      = UfoBodyPart
    FixedRotation = false

     

    The active ingredient here is to ensure that both the wall bodypart and the ufo bodypart both have a little friction applied. This way when they collide, they will drag against each other and produce some spin:

     

    [UfoBodyPart]
    Type = sphere
    Solid = true
    SelfFlags = ufo
    CheckMask = wall
    Friction = 1.2
     
    [WallTopPart]
    Type = box
    Solid = true
    SelfFlags = wall
    CheckMask = ufo
    TopLeft = (-400, -300, 0)
    BottomRight = (400, -260, 0)
    Friction = 1.2

     

    Re-run that and give it a try. Run against a wall on angle to get some spin on the ufo.

    rotation-friction.jpg.f8b745ca68bddeb5f0e987fbf0dbe8fc.jpg

    The next thing to notice is that both the movement of the ufo and the spin never slow down. There is no friction to slow those down.

    We'll deal with the spin first. By adding some AngularDamping on the UfoBody, the spin will slow down over time:

     

    [UfoBody]
    Dynamic        = true
    PartList       = UfoBodyPart
    AngularDamping = 2
    FixedRotation  = false

     

    Re-run and check the spin. The ufo should be slowing down after leaving the wall.

    Now for the damping on the movement. That can be done with LinearDamping on the UfoBody:

     

    [UfoBody]
    Dynamic        = true
    PartList       = UfoBodyPart
    AngularDamping = 2
    FixedRotation  = false
    LinearDamping  = 5

     

    Re-run and the speed will slow down after releasing the arrow keys. But it's slower overall as well. Not 100% what we want.

    You can increase the FORCE value in code (ufo.cpp), in the Update function to compensate:

     

    const orxFLOAT FORCE = 1.8;

     

    Compile and run. The speed should be more what we expect.

    It would be nice for the ufo to be already spinning a little when the game starts. For this, add a little AngularVelocity :

     

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

     

    Run this and the ship will have a small amount of spin at the start until the AngularDamping on the ufo body slows it down again.

     

    Following the UFO with the camera

    While we can simply move the ufo around with the keys on a fixed background, it will be a more pleasant experience to have the ufo fixed and have the screen scroll around instead.

    This effect can be achieved by parenting the camera to the ufo so that wherever the ufo goes, the camera goes.

    Currently, our project is set up so that the viewport has a camera configured to it. But the camera is not available to our code.

    We will require the camera to be available in a variable so that it can be parented to the ufo object.

    To fix this, in the Init() function, extract the camera from the viewport into a variable by first removing this line:

    orxViewport_CreateFromConfig("Viewport");

    to:

    orxVIEWPORT *viewport = orxViewport_CreateFromConfig("Viewport");
    camera = orxViewport_GetCamera(viewport);

     

    And because the camera variable isn't defined, do so at the top of the code:

     

    #include "orx.h"
    orxOBJECT *ufo;
    orxCAMERA *camera;

     

    Now it is time to parent the camera to the ufo in the init() function using the orxCamera_SetParent function:

     

    ufo = orxObject_CreateFromConfig("UfoObject");
    orxCamera_SetParent(camera, ufo);

     

    Compile and Run.

    oops-screen-rotation.jpg.1a47bbad8faa0394fcd4383cc5747265.jpg

    Woah, hang on. That's crazy, the whole screen just rotated around when ufo. And it continues to rotate when hitting the ufo against the walls. See how the camera is a child of the ufo now? Not only does the camera move with the ufo, it rotates with it as well.

    We certainly want it to move with the ufo, but it would be nice ignore the rotation from the parent ufo. Add the IgnoreFromParent property to the MainCamera section:

     

    [MainCamera]
    FrustumWidth     = 1024
    FrustumHeight    = 720
    FrustumFar       = 2.0
    FrustumNear      = 0.0
    Position         = (0.0, 0.0, -1.0)
    IgnoreFromParent = rotation

     

    Re-run. That's got it fixed.

    Now when you move around, the playfield will appear to scroll rather than it being the ufo that moves. This makes for a more dramatic and interesting effect.

    In Part 4, we will give the ufo something to do. The goal is to collect several pickups.



      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
  • Advertisement
  • GameDev.net and Intel Contest

    GameDev.net and Intel® have partnered up to bring GameDev.net members a gamedev contest running until December 21, 2018 - Submit your game for Intel® Certification and you could win big!

    Click here to learn more and submit your game.

  • Latest Featured Articles

  • Featured Blogs

  • Advertisement
  • Popular Now

  • Similar Content

    • By Nick Griffith
      I'm making a 2d platformer game as a learning experience, and I need a character and some backgrounds.
      The idea is a person on the brink of death "running" through his memories. The background is his memories.
      This game will make minimal revenue, because it'll be a free mobile game.
      I'll give you more details if you respond.
      Thanks.
    • By SIlentOff
      Greetings to everyone, I urgently need a ready-made game or source code (compatible with Visual Studio 2017 and DirectX SDK June 2010) according to the book Vaughan Young. "Programming a multiplayer FPS in DirectX". I already found the source code: https://github.com/matt77hias/VYGE/ but I get errors when creating a project.
      Also, I found many topics on this site with a similar theme, but they were created a long time ago, most of the links do not work.
      Please help me!
    • By EnderStaffExe
      Hello! I'm new to the scene of video game developing and was wondering if anyone here has any experience developing 2D fighters and are up for making a little test demo to see if the idea would catch on to the public? I have no way of paying but I want to put the demo onto Kickstarter and I will pay a good amount if I get a good amount. Please, if you want to contact me for more info, add me on my Discord or Twitter. Thank you, and see you later!
      (Twitter: @enderstaffexe
      Discord: EnderStaffExe#3193)
    • By Hashbrown
      I purchased a nice tile set for practicing:

      ...and I'm wondering what would be the best way to tile my game world. At the moment my sprite renderer works nicely, I'm able to render only a portion of a texture given the right x,y, width and height. I can even animate my sprites:

      Question
      What's the best way to draw my environment though? I can't imagine creating a bunch of game objects just to fill the screen with floor tiles. I thought of perhaps making a few giant quads, scatter them around the world, and texture each quad with an image of the environment tiles already placed. Maybe this could avoid making so many game objects.
      Or maybe I'm wrong. Hopefully somebody can point me towards the right direction, no code is needed.
       
      I'm not using any particular engine btw, just opengl, c++, and glm for math. Thanks!
    • By Orella
      I'm creating a 2D game engine using Vulkan.
      I've been looking at how to draw different textures (each GameObject can contain its own texture and can be different from others). In OpenGL you call glBindTexture and in vulkan I have seen that there are people who say that you can create a descriptor for each texture and call vkCmdBindDescriptorSets for each. But I have read that doing this has a high cost.
      The way I'm doing it is to use only 1 descriptor for the Sampler2D and use a VkDescriptorImageInfo vector where I add each VkDescriptorImageInfo for each texture and assign the vector in pImageInfo.
      VkWriteDescriptorSet samplerDescriptorSet; samplerDescriptorSet.pNext = NULL; samplerDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; samplerDescriptorSet.dstSet = descriptorSets[i]; samplerDescriptorSet.dstBinding = 1; samplerDescriptorSet.dstArrayElement = 0; samplerDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; samplerDescriptorSet.descriptorCount = static_cast<uint32_t>(samplerDescriptors.size()); samplerDescriptorSet.pImageInfo = samplerDescriptors.data(); //samplerDescriptors is the vector Using this, I can skip creating and binding a descriptor for each texture but now I need an array of Samplers in fragment shader. I can't use sampler2DArray because each texture have different sizes so I decided to use an array of Samplers2D (Sampler2D textures[n]). The problem with this is that I don't want to set a max number of textures to use.
      I found a way to do it dynamically using:
      #extension GL_EXT_nonuniform_qualifier : enable layout(binding = 1) uniform sampler2D texSampler[]; I never used this before and don't know if is efficient or not. Anyways there is still a problem with this. Now I need to set the number of descriptor count when I create the descriptor layout and again, I don't want to set a max number you can use:
      VkDescriptorSetLayoutBinding samplerLayoutBinding = {}; samplerLayoutBinding.binding = 1; samplerLayoutBinding.descriptorCount = 999999; <<<< HERE samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; samplerLayoutBinding.pImmutableSamplers = nullptr; samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; Having said that. How can I solve this? Or which is the correct way to do this efficiently?
      If you need more information, just ask.
      Thanks in advance!
×

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!