Reader small image

You're reading from  Game Physics Cookbook

Product typeBook
Published inMar 2017
Reading LevelIntermediate
PublisherPackt
ISBN-139781787123663
Edition1st Edition
Languages
Tools
Concepts
Right arrow
Author (1)
Gabor Szauer
Gabor Szauer
author image
Gabor Szauer

Gabor Szauer has been making games since 2010. He graduated from Full Sail University in 2010 with a bachelor's degree in game development. Gabor maintains an active Twitter presence, and maintains a programming-oriented game development blog. Gabor's previously published books are Game Physics Programming Cookbook and Lua Quick Start Guide, both published by Packt.
Read more about Gabor Szauer

Right arrow

Chapter 4. 2D Primitive Shapes

Now that we have covered the necessary linear algebra, it is time to delve into some geometry. We are going to start with 2D primitive shapes. In this chapter, we are going to cover:

  • 2D points

  • 2D line segments

  • Circle

  • Rectangle

  • Oriented rectangle

  • Point containment tests

  • Line intersection tests

Introduction


Collisions play a large role in physics, determining if two objects touch is half the work. To determine if collisions are happening, we need to cover some basic geometry. In this chapter, we define what the geometry being used for collision tests will be and even implement some basic containment tests.

In this chapter we will implement primitive two-dimensional shapes. In the following chapters which follow we will combine multiple primitive shapes to create more complex shapes. After we have mastered two-dimensional collisions, we will create three-dimensional geometry and collision tests.

2D points


A point is the simplest two-dimensional primitive we can implement. It is infinitely small; it has x and y coordinates. A good way to think of a 2D point is like an alternate representation of a 2D vector. A vector points to somewhere in space; a point is where the vector points to:

Getting ready

Since this is the first geometry object we are creating, we also need to create a new header file, Geometry2D.h. All future 2D geometry and intersection tests will be added to this file. Because a point has the same definition as a 2D vector, we're not going to create a new structure; instead we will redefine the vec2 struct as Point2D.

How to do it…

Follow these steps to create a new header file in which we will define 2D geometry:

  1. Create a new C++ header file; call this file Geometry2D.h.

  2. Add standard header guards to the file, and include vectors.h.

    #ifndef _H_2D_GEOMTRY_
    #define _H_2D_GEOMETRY_
    
    #include "vectors.h"
    
    #endif
  3. Because a point is practically the same thing as a 2D vector, we are...

2D lines


A line is the shortest straight path that connects two points. A line can be defined by a point on the line and a slope; this is called the slope intercept form. An actual line has no ends; it extends infinitely in both directions. This is not what we intuitively think of as a line. Instead, we want to define a line using a Start Point and an End Point. This is called a Line Segment:

Getting ready

Even though we are implementing a line segment, in code we are going to refer to it as a line. We rarely, if ever, use real lines to detect collisions, but we often use line segments. The Line2D structure we are about to create will consist of two points, where the line starts and where it ends.

How to do it…

Follow these steps to define a two-dimensional line, and the helper functions we will need to work with lines:

  1. Define the Line2D structure in Geometry2D.h.

    typedef struct Line2D {
       Point2D start;
       Point2D end;
    
       inline Line2D() { }
       inline Line2D(const Point2D& s, const Point2D...

Circle


A circle is defined by a point in space and a Radius. The circle is an extremely simple shape as shown in the following diagram:

Getting ready

Intersection algorithms for the circle are as simple as its definition. For this reason, a circle is often the first choice to approximate the bounding volume of objects. Arguably, the circle is the most commonly used 2D primitive.

How to do it…

Follow these steps to implement a two-dimensional circle:

  1. Start the declaration of the Circle structure in Geometry2D.h by creating the variables that make up a circle:

    typedef struct Circle {
       Point2D position;
       float radius;
  2. Next, declare an inline constructor that will create a circle at origin with a radius of 1:

       inline Circle() : radius(1.0f) {}
  3. Finish the declaration of the Circle structure by creating an inline constructor that lets us specify the position and radius of the circle being created:

       inline Circle(const Point2D& p, float r):
          position(p), radius(r) {}
    } Circle;

How it works...

Rectangle


A rectangle has four sides; the angle between each side is 90 degrees. There are several ways to represent a rectangle: using a Min and Max point, using a Center and half-extents, or using a Position and a Size:

Getting ready

We are going to implement our rectangle structure using the origin and Size representation. However, having the Min and Max representation of a rectangle is often useful. For this reason, we are going to implement helper functions to get the Min and Max points of a rectangle, and we will to make a rectangle from a Min and Max pair.

How to do it…

Follow these steps to implement a two-dimensional rectangle and all of the support functions we will need to work with the rectangle:

  1. Add the declaration of the Rectangle2D structure to Geometry2D.h:

    typedef struct Rectangle2D {
       Point2D origin;
       vec2 size;
    
       inline Rectangle2D() : size(1, 1) { }
       inline Rectangle2D(const Point2D& o, const vec2& s) :
          origin(o), size(s) { }
    } Rectangle2D;
  2. Add the declaration...

Oriented rectangle


An oriented rectangle is very similar to a non-oriented (Axis Aligned) rectangle. They both have a Position and a size, but the oriented rectangle also has a Rotation. Rotating a rectangle will allow us to better approximate the shape of objects as shown in the following diagram:

Getting ready

Unlike the Rectangle2D, we're going to represent an OrientedRectangle using a center point and half-extents. Additionally, we're also going to store a Rotation. It makes no sense for an oriented rectangle to have a min or max, so we're not going to implement these helper functions for the OrientedRectangle structure.

The reason we represent the rectangle this way is because it will make rotating objects relative to the rectangle easier. As an added bonus, by doing this we will have covered all three methods described earlier to represent a rectangle.

How to do it…

Follow these steps to create an oriented rectangle:

  1. Start the declaration of the OrientedRectangle structure in Geometry2D...

Point containment


So far in this chapter, we have implemented the basic primitives for 2D shapes. Now we are going to implement the most basic primitive test for 2D shapes; point containment. It's often useful to know if a point is inside a shape or not.

Getting ready

We are going to implement a method to check if a point is on a line, as well as methods to check if a point is within a circle, rectangle, and oriented rectangle. These are the most basic 2D intersection tests we can perform.

How to do it…

Follow these steps to test if a point is contained within any of the two-dimensional primitives we have created so far:

  1. Declare the containment functions in Geometry2D.h:

    bool PointOnLine(const Point2D& point, const Line2D& line);
    bool PointInCircle(const Point2D& point, const Circle& c);
    bool PointInRectangle(const Point2D& point, 
       const Rectangle& rectangle);
    bool PointInOrientedRectangle(const Point2D& point,
       const OrientedRectangle& rectangle);
  2. Implement...

Line intersection


After point containment, the line intersection the is the next logical intersection test to implement. Knowing if a line intersects one of the basic 2D primitives is very useful, and in most cases rather straightforward to implement.

Getting ready

We are going to implement functions to test if a line is intersecting any of the basic 2D primitives. To keep the naming of these functions a little more convenient, we are going to use the #define macro to create aliases for each function.

How to do it…

Follow these steps to test if a line intersects any of the two-dimensional primitives we have defined so far:

  1. Declare the line test functions in Geometry2D.h:

    bool LineCircle(const Line2D& line, const Circle& circle);
    bool LineRectangle(const Line2D& l, const Rectangle2D& r);
    bool LineOrientedRectangle(const Line2D& line,
       const OrientedRectangle& rectangle);
  2. Using the #define directive, add aliases for all these functions to Geometry2D.h. These defines do not...

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Game Physics Cookbook
Published in: Mar 2017Publisher: PacktISBN-13: 9781787123663
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Gabor Szauer

Gabor Szauer has been making games since 2010. He graduated from Full Sail University in 2010 with a bachelor's degree in game development. Gabor maintains an active Twitter presence, and maintains a programming-oriented game development blog. Gabor's previously published books are Game Physics Programming Cookbook and Lua Quick Start Guide, both published by Packt.
Read more about Gabor Szauer