Saturday, December 8, 2012

Safe_Printf

Making a safe printf().
This is quickly stubbed in so I can get the code up for the Ultracode meet up. I'll write a detailed explanation soon. There also seems to be a Microsoft bug in this, so std::string doesn't properly convert to a c style string. This is not a complete example, but finishing it would be a pretty easy task.

#pragma once
#include <type_traits>
#include <string>
#include <exception>
#include <assert.h>
#include <cstdio>
#include <iostream>

template<class _Ty>
struct _is_char : std::false_type {};

template<>
struct _is_char<char> : std::true_type {};

template <class _Ty>
struct _is_c_string : std::false_type {};

template<class _Ty>
struct _is_c_string<_Ty *> : _is_char<typename std::remove_cv<_Ty>::type> {};

template<class _Ty>
struct is_c_string : _is_c_string<typename std::remove_cv<_Ty>::type> {};

template <typename T>
typename std::enable_if<std::is_integral<T>::value, long>::type normalizeArg(T arg)
{std::cout << "LongType/n"; arg;}

template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, double>::type normalizeArg(T arg)
{std::cout << "FloatType/n";return arg;}

template <typename T>
typename std::enable_if<std::is_pointer<T>::value, T>::type normalizeArg(T arg)
{std::cout << "PointerType/n";return arg;}

const char* normalizeArg(const std::string& arg)
{std::cout << "StringType/n";return arg.c_str();}

void check_printf(const char* f)
{
 for (; *f; ++f)
 {
  if (*f != '%' || *++f == '%') continue;
  throw std::exception("Too many format specifiers");
 }
}

template <typename T, typename... Ts>
void check_printf(const char* f, const T& t, const Ts&... ts)
{
 for (; *f; ++f)
 {
  if (*f != '%' || *++f == '%') continue;

  switch (*f)
  {
  default: throw std::exception("Invalid format");
  case 'd':
   if(!std::is_integral<T>::value)
   {
    throw std::exception("T is not an integral");
   }
   break;
  case 'f': case 'g':
   if(!std::is_floating_point<T>::value)
   {
    throw std::exception("T is not a float");
   }
   break;
  case 's':
   if(!is_c_string<T>::value)
   {
    throw std::exception("T is not a c string");
   }
   break;
  }
  return check_printf(++f, ts...);
 }
 throw std::exception("Too few format specifiers");
}

template <typename... Ts>
int safe_printf(const char* f, const Ts&... ts)
{
 check_printf(f, normalizeArg(ts)...);
 return printf(f, normalizeArg(ts)...);
}

Here is how to use it. Pretty basic.

#include "SafePrintf.h"
#include <string>
#include <iostream>

void main()
{
 std::string str("Try this out.");
 const int i = 5;
 float f = 0.123f;

 try
 {
  safe_printf("This is from safe printf. int %d, string %s, and a float %f", i, str, f);
 }
 catch(std::exception e)
 {
  std::cout << e.what();
 }
}


Wednesday, December 5, 2012

Move Semantics and ctors and assignment


Move Semantics

OK, so what are they? Consider this example.

const BigThing bigThing = makeBigThing();

Anyone worried about performance is going to cringe. Look at the wasted temporaries. We create data on the heap in the function, data in the intermediate temporary, and finally data again in the bigThing.So we do this instead.

BigThing bigThing;
makeBigThing(bigThing);

But that's not what we want at all, and it's harder to understand. Of course we could do this all with pointers, but that causes huge problems and syntax often looks weird, especially when using operators.

C++ now has move semantics, and perfect forwarding. This is a perfect example of why it was created. What do we know about those temporary objects? Well, they're temporary. So why not steal their guts? Turn them into organ donors. That's what move semantics does. Today I'll explain one of the ways we can use move semantics using rValue references. I'll show how we can take advantage of them to make a highly efficient assignment operator.

So how do we write them? What do they look like? What is an rValue anyway?

Let's go through these and others with a very common example. Let's do an rValue reference copy constructor. We will assume a class Foo that holds a class Bar by pointer and we want everything to be deep copies. Here is our class Bar:

class Bar
{
    SomeBigThing m_Big;
public:
    Bar() = default;
    Bar(const& Bar) = default;
    ~Bar() = default;
    Bar& operator=(const Bar&) = default;
};

We're using the default keyword here. It may seem a bit strange to say you are using the functions that are created for you anyway, but on the other hand, isn't it nice that you now know what I intend that class to do? It's an efficient way to tell everyone you want those default functions. delete removes the function so you can easily prevent copying.

So now we get to the rValue copy constructor.

class Foo
{
    Bar* m_Bar;
public:
    Foo(Foo&& rhs) : m_bar(rhs.m_bar) { rhs.m_bar = nullptr; }
};

So what the hell is Foo&& ?????
That is the rValue reference. OK. It looks a bit weird, but it's not too bad. The real question is what is an rValue. The full, 100% correct answer is a bit tedious, but fortunately the concept is easy enough to grasp with a few examples and applying to questions to an object. First some examples.

    int i; // lValue
    int j = i; // lValue
    int k = someFunc(); // k is an lValue, 
                        // the return value of someFunc is an rValue
    42; // rValue
    4 * 5; // rValue

rValues are the temporary, unnamed objects we are trying to get rid of. That leads to a very easy way of thinking about rValues. They have two properties that are simple to test for.
  • They do not have a name.
  • You cannot get their address.
Simple.

OK? There is one slight hitch, and I promise I'm not trying to make this difficult. The parameter coming in to Foo(Foo&&) is an rValue, but... rhs is an lValue. How do we know this? It has a name and you can get its address. But it's OK. We know it came in as an rValue so we can use it as an organ donor. 

So let's look at that code again.

class Foo
{
    Bar* m_Bar;
public:
    Foo(Foo&& rhs) : m_bar(rhs.m_bar) { rhs.m_bar = nullptr; }
};


What's going on here? Well, we simply make a shallow copy of the pointer and set rhs.m_Bar to null. This is important! The destructor WILL be called on rhs and if m_Bar is not set to null, it will be deleted, destroying the whole point of doing the rValue copy in the first place.

In the last post, I talked about the assignment operator. I also wrote that that old paradigm was now different because of rValue references and move semantics. If you remember we created a temporary and then immediately deleted it. What a waste, but in the past there really was no way around it. But what is

    Foo(rhs); 

It's an rValue! And what do we know about rValues? They are temporary and you can steal from them. So our assignment operator becomes this:

    Foo& operator=(Foo rhs)
    {
        *this = std::move(rhs);
        return *this;
    }

Now all that's left is is to write the rValue ref version of the assignment operator.

    Foo& operator=(Foo&& rhs)
    {
        delete m_bar;
        m_bar = rhs.m_bar;
        rhs.m_bar = nullptr;
        return *this;
    }

We know that calling delete on a nullptr is fine. It won't do anything, so we don't need a conditional. We steal something that is temporary anyway, so that is fast. And we make sure what we have isn't deleted by setting where we stole it from to nullptr. Now we have exception safe code with no extra copies.

We just need an lValue copy constructor (remember, we can't use rValue because we're stealing).

    Foo(const Foo& rhs) : m_bar((rhs.m_bar) ? new Bar(*rhs.m_bar) : nullptr) {;} 

And here's everything together.

class Bar
{
    int i;
public:
//     Bar() = default;
};

class Foo
{
    Bar* m_Bar;
public:
    Foo() : m_bar(new Bar()) {;}

    Foo(const Foo& rhs) : m_bar((rhs.m_bar) ? new Bar(*rhs.m_bar) : nullptr) {;}

    Foo(Foo&& rhs) : m_bar(rhs.m_bar) { rhs.m_bar = nullptr; }

    Foo& operator=(Foo&& rhs)
    {
        delete m_bar;
        m_bar = rhs.m_bar;
        rhs.m_bar = nullptr;
        return *this;
    }

    Foo& operator=(Foo rhs)
    {
        *this = std::move(rhs);
        return *this;
    }
    ~Foo() { delete m_bar; }
};

Saturday, December 1, 2012

Rule of Three, or how not to blow your leg off.


It's been far too long and there has been too much good stuff not to write about. This is going to be all about Move semantics. Writing safe, clean, fast code can be easy if you follow some basic principles. Memory leaks are very often minimized or eliminated if some basic principles are applied. The first is to use shared_ptr and make_shared instead of new and raw pointers. shared_ptr is such an old pattern that compiler writers and chip designers already account for it. Now that it is standard they can do even more.

Sometimes we need raw pointers. Maybe we need to make our own container or represent a bitmap. That being said, my use of raw pointers is extremely rare. However, if you do need them, or want to ignore the advice and use them anyway, you should be aware of the "rule of three."

Rule of Three

The rule of three is simple. Copy constructor, assignment operator, destructor; if you write one, you should write the other two or disable them by setting them to delete. delete and default are new C++11 features.

class Bar
{
public:
    Bar() = default;
    Bar(const Bar&) = delete;
};

Default says to use the plain old version and delete says don't make one. While it may seem silly to explicitly say I'm using the one that automatically gets created, it's important to let others know your intent.

The reason for this rule is simple. Generally we write the destructor because we have allocated a resource. Maybe it's a file or memory or whatever. If we do, we need to make sure it gets properly taken care of. If you don't delete the assignment operator, you're in for a rude surprise.

Writing an assignment operator is not an easy thing to do and is my standard whiteboard question. I have had very few candidates get it correct. Getting it right can be very tricky, unless you know the trick. The best news is that trick just got better with move semantics, but that will be another post.

So how hard could it be?

class Foo
{
    Bar* m_Bar;
public:
    Foo& operator=(const Foo& rhs)
    {
        m_Bar = rhs.m_Bar;
        return *this;
    }
};

This is just a shallow copy, exactly what the compiler would do only wrong. We want a deep copy. We'll pretend we didn't delete the copy constructor.

class Foo
{
    Bar* m_Bar;
public:
    Foo& operator=(const Foo& rhs)
    {
        m_Bar = new Bar(rhs.m_Bar);
        return *this;
    }
};

Well, that's a problem because we probably have a memory leak. Let's try again.

class Foo
{
    Bar* m_Bar;
public:
    Foo& operator=(const Foo& rhs)
    {
        delete m_Bar;
        m_Bar = new Bar(rhs.m_Bar);
        return *this;
    }
};

OK, but what if rhs.m_Bar = nullptr? <sigh>

class Foo
{
    Bar* m_Bar;
public:
    Foo& operator=(const Foo& rhs)
    {
        delete m_Bar;
        if(rhs.m_Bar)
        {
            m_Bar = new Bar(rhs.m_Bar);
        }
        return *this;
    }
};

What if I do something really stupid, but with references and aliases, you know it will happen.

    Foo f1;
    ... Do stuff
    f1 = f1;

<Are you kidding?>

class Foo
{
    Bar* m_Bar;
public:
    Foo& operator=(const Foo& rhs)
    {
        if (this == &rhs) return *this;
        delete m_Bar;
        if(rhs.m_Bar)
        {
            m_Bar = new Bar(rhs.m_Bar);
        }
        return *this;
    }
};

OK, but <now what?!?!?!> What if new throws an exception? <@#$*&(#@>
The whole body can be written in 3 lines of code.

class Foo
{
    Bar* m_Bar;
public:
    Foo& operator=(const Foo& rhs)
    {
        Bar temp(rhs);
        std::swap(rhs, *m_Bar);
        return *this;
    }
};

That is the second important rule

Copy and Swap

Now you know it, time to forget it because C++11 has something even better!

Saturday, March 31, 2012

Why Windows 8 will change everything.

I finally get out of bed. My alarm went off 2 hours earlier than normal. I pick up my phone and see I have a Skype call I forgot about. While getting dressed I glance down at my tablet and see how many mails and messages I have, and that I have a flight tomorrow. I also notice it's going to rain... again. I haven't even signed in yet. I sign in and continue getting ready. See who the mail and messages are from, but I'll check them later, I haven't opened a single app. I head to my PC and sign in. Skype is telling me I have a conference call. I realize Everything for the call is still at work. So I launch Photoshop and open the files from my work computer. I note the new project delivery dates and we change some product features. After the call I head off to work. With my pad I check the project status. The new tasks are in the project and I check on the project progress. There's a new web service we have to use so I create an account. Finally at work. I sign into my computer and open Chrome. I go to the web service and I am already logged into my account. I open Visual Studio and all my new tasks are ready for me to accept. Before I start I see some friends on facebook are having people for dinner. I accept. Near the end of day my phone alerts me that I have a dinner party to go to.

Maybe that doesn't seem so different to what can be done now. But the story is not what was done, but rather what was not done. I did not log into see if I had mail. I did not open mail after logging in to see who wrote me and what the subject line was. I did not even set my alarm clock. I did not copy files from my work computer to my home computer and then open them in Photoshop, I opened them in Photoshop from my work computer. Photoshop did not add new code to get this behavior. I did not tell Skype I had a call. I did not sign into a website twice even though I went to it on two different machines. I did not tell my phone that I had accepted a facebook event. This is amazing stuff and it's only going to get better.

We are now a user moving through a world of devices. Every device we sign into knows all our preferences, all our needed information. I think very soon we will not log in at all but use bio-metrics. Some already do. If I finish reading 30 pages of a book at home, my phone knows what page I'm on if I continue. I don't have to go through every level of a game because I have moved to another computer. I am a user moving through a world of devices. The devices conform to me.

On the coding side, most programs will just work like this. They don't even have to know about each other. When programmers want new interactions they provide small, simple apps that extend the functionality of every application I have. No coding required from the other apps. 

My favorite part is that no longer do we need to learn a new language for a new technology. All languages are treated equal. All languages can inter-operate. I can write a class in C++ that is called by C# or java script. I can call C# from C++. There are minor extensions to C++, and some proposed extensions to HTML5, but unlike the past, MS is working with the organizations to extend the standard rather than having MS versions of what is standard.

To some this will be a frightening threat to personal liberties. I am so glad I will no longer have to remember all the apps that need to know the same stupid piece of information, and all the devices I use and which apps are on them.

Microsoft, My baby's all grown up!

Most people who know me would never accuse me of being a Microsoft evangelist. Several would accuse me of being a Microsoft heathen. I gave MS a hard time, not because I hate MS, rather I knew they could do better but didn't. Well My Baby's All Grown Up! The excuses have been left behind, the sleazy business models have been tossed in the trash, and MS is out to kick ass!

Windows 8 is simply the best thing to happen to computers since Windows 95, and will be as big a change to all our lives. Anyone who remembers dual booting to play a game knows what I mean. To everyone else, it was a big, big deal.

I'm going to write a few posts about Windows 8 and my thoughts on what it means. I'll write about the business impact, the design impact, and the programming impact. The world is about to change. Are you ready?

Tuesday, January 17, 2012

If You Can Name It, It's An Object

This is a continuation of a previous post on creating better design.

What happens when your class becomes a giant ball of garbage and you have no idea what anything does anymore. I throw it away and start again. Let's consider a Physics World object. What does it do? What is the role of this object? Let's start from the simplest example to the more difficult. I am going to ignore the double dispatch problem for now and completely ignore the issues regarding strong types in C++, but I will be taking advantage of that behavior.

Let's go back to the old example of my simple graphics app.

void main()
{
   System system(640, 480);
   Sprite ball("Ball.PNG");
   ball.velocity(1.0f, 1.0f);
   ball.position(10.0f, 20.0f);
   PhysicsWorld world();
   Scene scene();
   world.Add(ball);
   scene.Add(ball);
   Boundary bounds(0,0,640,480);
   world.Add(bounds);

   Timer timer;
   Keyboard keys;
   Mouse mouse;

   while(!keys.AnyKey() && !mouse.RightButton())
   {
      world.update(timer);
      scene.update(timer);
      Renderer renderer;
      renderer.Render(scene);
   }
}

Let's take out everything except what relates to the Physics World object.
void main()
{
   Thing ball();
   ball.velocity(1.0f, 1.0f);
   ball.position(10.0f, 20.0f);
   PhysicsWorld world();
   world.Add(ball);
   Boundary bounds(0,0,640,480);
   world.Add(bounds);

   Timer timer;
   Keyboard keys;
   Mouse mouse;

   while(!keys.AnyKey() && !mouse.RightButton())
   {
      world.update(timer);
   }
}

Since this is not a post about how physics engines work, I'm going to ignore a lot of details. The details I'll be omitting is not relevant to this discussion, but is Critical to a proper Physics Engine!

OK. First I have changed the object from Sprite to Thing. I'll be writing about this object family in another post, but it's pretty complex and involves a lot of template meta programming. For our purposes what matters is that it has a physical body. It has physical properties like velocity and position. It has something that can be collided with, and since it moves, it can collide. That's an important concept when we consider efficiency.

Next we create a world. Really not much to say about that. Then we add the ball to the world. We're using overloaded functions so we only have the function Add(). This makes it easier to use the object because there is less to memorize. If you think you can add it to the physics world, you should be able to just Add() it. You don't have to memorize what kind of add to use. In the case of my real code the Add() is more complicated because the objects being used are collections of policy classes and the user may not know what the actual type is with regards to the Physics World object. This brings up a couple of important points.

Make your objects easy to use right and hard to use wrong.


Creating multiple Add functions is not as easy as having everything in physics derive from a common base class, but this adds an unnecessary burden to the user of your code by requiring a tight binding that may be undesirable or impossible, and makes the add function hopelessly cluttered with conditionals.

An objects type is as valid a piece of data as anything else.


The fact that I have a Dynamic Body, information that is hidden in this example, means that I know extra processing will have to be done that is unnecessary if the object is a Static Body. While I could have an if statement or a switch statement add objects to the correct container, why not let the compiler do it? This creates two clean, simple functions rather than one god awful mess. This will become more obvious as we continue.

When we add bounds, we are doing the same thing except this time bounds is a Static Body. When we get to the update function we don't have to update the position of bounds.

OK, but what if we want to have gravity?

Too often Physics worlds include gravity as part of the world object. This makes physics worlds very complex. It's not just gravity they include, but also ground planes and up vectors, and all kinds of other crap. So how do we get the same complex behavior in a simplified system?

Let's create a Gravity Object.

void main()
{
   Thing ball();
   ball.velocity(1.0f, 1.0f);
   ball.position(10.0f, 20.0f);
   COR cor(0.7f);
   ball.Add(cor);

   PhysicsWorld world();
   world.Add(ball);
   Boundary bounds(0,0,640,480);
   world.Add(bounds);

   // Default constructor assumes gravity is 1.0f in the -Y direction. 
   Gravity gravity;
   world.Add(gravity);


   Timer timer;
   Keyboard keys;
   Mouse mouse;

   while(!keys.AnyKey() && !mouse.RightButton())
   {
      world.update(timer);
   }
}

OK. We created Gravity and added it to the world. That's pretty simple. We could have changed properties if we wanted different behavior. What the heck is that COR? It's the Coefficient Of Restitution. It makes the ball not perfectly bouncy. I actually do this a different way in my code, but without getting into how Generic Programming works it's easier to think of it this way. And if I didn't have other tools available it's how I would handle complex behaviors of physics bodies.

Let's change the code completely and have the ball floating in space with a giant planet.

void main()
{
   Thing ball();
   ball.velocity(1.0f, 1.0f);
   ball.position(10.0f, 20.0f);
   COR cor(0.7f);
   ball.Add(cor);

   PhysicsWorld world();
   world.Add(ball);
   Boundary bounds(0,0,640,480);
   world.Add(bounds);

   // Default constructor assumes gravity is 1.0f in the -Y direction. 
   PointGravity gravity(150.0f, 150.0f);
   world.Add(gravity);


   Timer timer;
   Keyboard keys;
   Mouse mouse;

   while(!keys.AnyKey() && !mouse.RightButton())
   {
      world.update(timer);
   }
}

That's all there is to it. How about we make an atmosphere to slow us down?

void main()
{
   Thing ball();
   ball.velocity(1.0f, 1.0f);
   ball.position(10.0f, 20.0f);
   COR cor(0.7f);
   ball.Add(cor);
   COD cod(0.8f);
   ball.Add(cod);

   PhysicsWorld world();
   world.Add(ball);
   Boundary bounds(0,0,640,480);
   world.Add(bounds);

   // Default constructor assumes gravity is 1.0f in the -Y direction. 
   PointGravity gravity(150.0f, 150.0f);
   world.Add(gravity);

   PointAtmosphere atmos(150.0f, 150.0f, 15.0f);
   world.Add(atmos);


   Timer timer;
   Keyboard keys;
   Mouse mouse;

   while(!keys.AnyKey() && !mouse.RightButton())
   {
      world.update(timer);
   }
}

We add a drag coefficient to the ball and add an atmosphere to the gravity source. Well, that's OK, but this is for my physics class and that really doesn't cut it.

How about this?

void main()
{
   Thing ball();
   ball.velocity(1.0f, 1.0f);
   ball.position(10.0f, 20.0f);
   COR cor(0.7f);
   ball.Add(cor);
   COD cod(0.8f);
   ball.Add(cod);

   PhysicsWorld world();
   world.Add(ball);

   Planet earth(1.0f, 6,371.0f);
   Atmosphere atmos(1.0f);
   earth.Add(atmos);
   world.Add(earth);

   Timer timer;
   Keyboard keys;
   Mouse mouse;

   while(!keys.AnyKey() && !mouse.RightButton())
   {
      world.update(timer);
   }
}

You could continue and make the whole solar system and if you get the data correct, you will have a stable system, or at least as stable as the real one is.

Notice that I add a planet, but do not extract the gravity from it and add that as an additional step. Why should I? The function is customized for planets so why wouldn't the function do it? Also, I could add atmosphere to a region of space or to a planet. In either case the atmosphere is the same. I did use point instead of ambient, but the principle is the same. I could extend the concept of point atmosphere to add a hurricane to the earth.

We had a ball and rather than giving the ball properties, we instead created adverbs to append properties. So we had a "High drag bouncy ball." Rather than creating complex objects we created a noun phrase. "A planet with the same mass as earth and a radius of 6,371 km and one standard atmosphere." We could have added water and a molten core if we wanted.

I hope I made a reasonably clear case for not only creating a language to describe your problem, but also to use language constructs to build your language. 

Monday, January 16, 2012

Don't Solve The Problem. Write The Language That Lets You Define The Problem.

I've often used an example to explain why so much code is big, bloated, hard to follow, and impossible to maintain.

Imagine you have a need in code to answer the question what is 2 + 2? You sit down and write the function, after counting on both your toes and your fingers to ensure the answer is portable:

int TwoPlusTwo()
{
   return 4;
}

Feeling very pleased with the speed and efficiency of the code and how remarkably exception safe it is you continue on. And you need 3 + 5.

At first you think I'll just copy and paste that other function and make it return 7. But something inside says that's not the right approach. This one function should be able to do more than that one line. So:

int TwoPlusTwo(int val)
{
   if(val == 2)
   {
      return 4;
   }
   else
   {
      return 8;
   }
}

But you look at this and inspiration strikes!

int Equation(int val)
{
   return pow(2, val);
}

I know in this trivial example it's easy to see that this is stupid, but it is very common to write this. I've seen this code from Microsoft, EA, Sony, all the big companies have plenty of this king of code.

What's missing and why do we write this way?
We are writing the answer over and over. When we learned math we did not memorize every possible outcome of every possible equation. Instead we learned a mathematical language. What's missing then is not the solution. It's the language we need to express a solution. When I write:

2 * 35 + 64 / 3 - 125^14

I don't know the result of that, but if I entered that into a calculator I would get the answer! The guy who made the calculator didn't even know that question would ever be asked and yet it gives a result.

How about another less trivial example. I won't write the language, but I want to show how a properly written language can express complex ideas in very simple terms. I'll write in psuedo code to avoid language dependency and the C++ template arguments that would make it less clear.

Here is my cross platform graphics engine in use for a simple example:

void main()
{
   System system(640, 480);
   Sprite ball("Ball.PNG");
   ball.velocity(1.0f, 1.0f);
   ball.position(10.0f, 20.0f);
   PhysicsWorld world();
   Scene scene();
   world.Add(ball);
   scene.Add(ball);
   Boundary bounds(0,0,640,480);
   world.Add(bounds);

   Timer timer;
   Keyboard keys;
   Mouse mouse;

   while(!keys.AnyKey() && !mouse.RightButton())
   {
      world.update(timer);
      scene.update(timer);
      Renderer renderer;
      renderer.Render(scene);
   }
}

There really isn't much I left out except for some template fields. And I do usually write with many comments and I'll write a post on why and how I go about writing in another post. But the thing to note here is that it's pretty easy to see what's going on and it's pretty easy to add more things if desired. The System object turns a console app into a Windows app or a Mac app or even PS3 or Wii. There is no need for a WinMain() or Objective C.

Sprite is the object least according to it's own form. It would have a template list of everything it was composed of. It's policy classes. I'll write about that, but much later. For now just know it can be a render object or a physics object, but it inherits from nothing in the classic understanding of inheritance.

The Physics world detects and dispatches collisions, but under the hood all it really does is present close by objects to each other and let them work out if they hit or not.

Scene is an object for rendering views.

Boundary is an area that restrains physics.

Timer is the local clock with some extra abilities, and keyboard and mouse are pretty self explanatory.

Renderer is an object I put in the main loop because I wanted to point out something. When you write small, simple, and lightweight objects you don't have to worry as much about efficiency. Here it makes no difference where I put it from the point of efficiency.

So what you get is a ball bouncing around the screen like if you leave your DVD player on too long. An entire graphics application start to finish in 25 lines of code. It wouldn't take much more than that to make break out, space invaders, defender, or other arcade games because I wrote the language of arcade games. All I have to do is assemble sentences.

Let me know what you'd like to understand better and I'll make that my next post. Otherwise I'll go on to how I start a new project.