Bouncing Balls

I can think of a few things already, just after a quick perusal of that last source code listing, where we might move even more of the code into the engine. For example, you will always need to clear the scene and set the identity. Secondly, I would like to abstract the color system into a more generic RGBA (red-green-blue-alpha) set, rather than using the Direct3D-based color macros—something to consider for a future engine update.

Advice

A mesh is the technical term for a 3D model, but the 3D industry does not use the word model because it is not specific. You might have noticed that our Mesh class has the ability to load a .X file, which will usually contain references to texture files (included with the .X file but not embedded).


Direct3D is a state-based rendering system, which means it continues to operate as it is currently set until something is changed. When you set the current texture in the Direct3D device, it will obediently use that texture for all rendering output until it is told to change the texture.

If we were building an advanced 3D rendering system, one optimization would be to create a texture cache so that Direct3D’s state wouldn’t have to be changed so often. Basically, you figure out which textures are shared by all polygons in the scene, and you render all of those polys before changing the texture and rendering all polys that use the new texture, and so on.

Advice

Changing state in a rendering system (such as changing the current texture or shader program) is a very time-consuming process and should be done infrequently. But for the purposes of demonstration and learning, don’t be concerned with performance until later.


Our BouncingBalls program is a bit of a leap beyond the crude Cube program, as it features a C++ Standard Library container called vector to manage the balls (or rather, spheres) in this demonstration program. A vector is a good general-purpose container that mimics a C++ array in many ways, including the ability to index into the “array” using brackets and an index (for instance, spheres[1]). Instead of creating the sphere at runtime (as we did previously with the cube), the sphere will be loaded from a .X file. The sphere was created, textured, and exported using Blender, as shown in Figure 2.2.

Figure 2.2. Using Blender to create the sphere mesh used in BouncingBalls.


Advice

If you are not familiar with the C++ Standard Library, I encourage you to pick up a good book on the subject because it’s crucial to making a game engine. One good reference is C++ Standard Library Practical Tips (Charles River Media, 2005) by Greg Reese.


Since the Camera and Mesh class header files have already been included in Advanced2D.h, you will not need to include them separately in this or any other new project; you need only include Advanced2D.h. As is the common practice in this book, each new program listing assumes that it is part of a new project. If you have not already done so, create a new project (as described in the previous chapter) and name it BouncingBalls. Include the same list of linked library files shown for the previous example program.

#include <vector>
#include "..EngineAdvanced2D.h"
using namespace Advanced2D;

//we need this keyboard macro to detect Escape key
#define KEY_DOWN(vk) ((GetAsyncKeyState(vk) & 0x8000)?1:0)

//camera object
Camera *camera;

//define the number of spheres
#define SPHERES 100

//create the entity vector and iterator
typedef std::vector<Mesh*>::iterator iter;
std::vector<Mesh*> entities;

bool game_preload()
{
    g_engine->setAppTitle("BOUNCING BALLS");
    g_engine->setFullscreen(false);
    g_engine->setScreenWidth(1024);
    g_engine->setScreenHeight(768);
    g_engine->setColorDepth(32);
    return true;
}

bool game_init(HWND)
{
    srand(time(NULL));

    //set the camera and perspective
    camera = new Camera();
    camera->setPosition(0.0f, 2.0f, 10.0f);
    camera->setTarget(0.0f, 0.0f, 0.0f);
    camera->Update();

    //create ball meshes
    Mesh *ball;
    for (int n=0; n<SPHERES; n+ +)
    {
        ball = new Mesh();
        ball->Load("ball.x");
        ball->SetScale(0.3f,0.3f,0.3f);
        ball->SetPosition(0.0f,0.0f,0.0f);
        float x = (float)(rand()%8+1) / 100.0f;
        float y = (float)(rand()%8+1) / 100.0f;
        float z = (float)(rand()%8+1) / 100.0f;
        ball->SetVelocity(x,y,z);
        ball->SetRotation(0.1f,0.2f,0.01f);

        //add this ball to the vector container
        entities.push_back(ball);
    }
    return true;
}

void game_update()
{
    //update entity positions and limit the boundary
    for (iter i = entities.begin(); i != entities.end(); ++i)
    {
        (*i)->Update();
        (*i)->LimitBoundary(-5,5,4,-4,4,-4);
    }

    //escape key will terminate the program
    if (KEY_DOWN(VK_ESCAPE)) g_engine->Close();
}

void game_end()
{
    delete camera;

    //destroy all balls from the vector
    for (iter i = entities.begin(); i != entities.end(); ++i) {
        delete *i;
    }
    //empty the vector
    entities.clear();
}

void game_render3d()
{
    static DWORD start=0;

    //clear the scene using a dark blue color
    g_engine->ClearScene(D3DCOLOR_RGBA(30,30,100,0));

    //return to the origin
    g_engine->SetIdentity();

    //draw entities
    for (iter i = entities.begin(); i != entities.end(); ++i)
    {
        //remember, every entity must be moved individually!
        (*i)->Transform();
        (*i)->Draw();
    }
}

This program is far more complex than the Cube demo, and yet the source code listing is only a few lines longer! Why do you suppose that is? First of all, our engine is handling most of the details for us now, but we also benefited from the use of a standard vector, which simplified the code. Figure 2.3 shows the output from the BouncingBalls program. There is no rhyme or reason behind this program; it just sets the balls at random X,Y,Z velocities and lets them go. The Mesh class automatically updates the position of each ball based on its position and velocity when the Update() method is called.

Figure 2.3. The BouncingBalls program demonstrates how to load, manipulate, and render a mesh.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset