Sign in to follow this  
  • entries
    298
  • comments
    1135
  • views
    231060

A quick look through BaseCamp.

Sign in to follow this  
HopeDagger

140 views

Just what does the BaseCamp API look like?

Good question, Billy.

I've been aiming to keep BaseCamp as simple as possible, while still offering plenty of behind-the-scene flexibility -- largely via function overloads and optional parameters. Inspiration for the structure of BCGL has been mainly drawn from libraries like Omega, GTGE, and Slick2D.

For kicks, let's go through a few code snippets.

Let's say we want to go and get a new game started. Maybe draw a primitive or two on the screen for the heck of it. We do this by deriving a class from the Game class, from which all games are base'd (har, pun?) off of.


class MyGame : public Game
{
void startup()
{
getLogger()->write("And so it begins!", LOG_INFO); // full logging system, including multiple channels and console+HTML output

getGraphics()->setLineWidth(3);
getGraphics()->setLineAntiAliasing(true);
}

void update()
{
// Nothin'..
}

void render(Graphics *gfx)
{
gfx->drawCircle(150,150, 64, Colour::red(), true); // radius-64 circle at 150,150 that is red and filled-in

gfx->setBlendMode( BLEND_ALPHA ); // many blending modes
gfx->drawLine( Vector2D(10,10), Vector2D(350,80), Colour(255,0,255,128)); // Can use X/Y points, or supply vectors
}
};

int main(int argc, char *argv[])
{
MyGame *MG = new MyGame();
MG->launch(640, 480, false); // screen size 640x480, windowed
delete MG;

return 0;
}




I'm naturally biased since I wrote it, but I found this fairly straight-forward to use. A user is to derive a class from Game, and then launch it in the main() method. From there, s/he can override the startup(), update(), render(), and also the shutdown() methods to do their bidding.

BaseCamp uses a Java-like 'Graphics' object, which can manipulate anything from the transformation matrix, to the current colour, to the blending mode, to the clear-screen colour, to the Z-layer, and so forth.

Let's play with some images!


class ImageFun : public Game
{
Image *thor;
Image *boxman;

void startup()
{
// Top window text/caption
setTitle("Fun with Images");
setVersion("Beta 1");

// Colour masking (using fuchsia here)
getGraphics()->useColourMasking(true);
getGraphics()->setMaskColour( Colour(255,0,255) );

// Load Images, which use Textures automatically for you
thor = new Image( getGraphics(), "thor.png" );
thor->setFrameWidth(16); // Set frame sizes for animations

// Able to access textures directly for low-level access
Texture *tex = new Texture( getGraphics(), "box.jpg" );
// tex->getPixelAt(10,10); // texture reading (for pixel-based collision);
boxman = new Image( getGraphics(), tex );
}

void update()
{
// Nothin'..
}

void render(Graphics *gfx)
{
// Draw Thor at 100,100 at Z-layer 25, and have his frame go through each of his 6 frames
thor->draw( 100, 100, 25, getTick() % 6 );
// Z-layers use the Z-buffer to make sure that everything gets drawn properly, so you don't need
// to worry about sorting sprites.

// Lots of options -- Z-layer, centre-of-sprite coords (for pivoting), scaling coefficients, image tint,
// and blending style.
boxman->draw( 300,450, 10, 0.5,0.5, 1,1, Colour::white(), BLEND_ADD );
}
};

int main(int argc, char *argv[])
{
ImageFun *MG = new ImageFun();
MG->launch(640, 480, false);
delete MG;

return 0;
}




As you can see, image loading, manipulation, and drawing is fairly straight-forward. There's 8 overloads for draw(), all with optional parameters included, so you should be able to do whatever you need to do. [smile]

However, manual image drawing can get a little tedious. And so the Sprite class (and SpriteGroup and SpriteManager) are introduced. These are essentially 'game entities' that have their own set of properties, and handle drawing, updating, and detecting collisions by themselves.

The idea is that the Game class (behind the scenes) has a Sprite Manager that manages all of the Sprite Groups in the game. A Sprite Group is somesort of collection of game entities that have something in common for logic handling, like enemies, players, projectiles, and so forth. Using them isn't mandatory, but used properly they can speed things up.


class SpriteFun : public Game
{

void startup()
{
// Colour masking (using fuchsia here)
getGraphics()->useColourMasking(true);
getGraphics()->setMaskColour( Colour(255,0,255) );
Image *img = new Image("boxman.png");

SpriteGroup *group = new SpriteGroup();
group->setName("Box Men");

for(int i=0; i < 50; i++)
{
BoxMan *man = new BoxMan();
// Handy Utils class for commonly needed functions, like int->string conversions, oscillation, lerp'ing,
// and others.
man->setName("BoxMan #" + Utils::IntToStr(i+1) );
man->setImage(img);
man->setPosition( Vector2D( Utils::Random(640), Utils::Random(480) ) );
man->detectCollisions(true); // By default, bounding box collisions are used
man->setPixelCheck(true); // Pixel-perfect collisions can be enabled at any time
man->setColour( Colour::green() ); // Green Box-men!

group->addSprite(man); // Add this sprite to the group
}

group->addCollisionGroup( group ); // Add itself to its collision list, so collisions will be checked for
// within the group
getSpriteManager()->addSpriteGroup(group); // Add group to the game
}

void update()
{
// Nothin'..
}

void render(Graphics *gfx)
{
// Draw Thor at 100,100 at Z-layer 25, and have his frame go through each of his 6 frames
thor->draw( 100, 100, 25, getTick() % 6 );
// Z-layers use the Z-buffer to make sure that everything gets drawn properly, so you don't need
// to worry about sorting sprites.

// Lots of options -- Z-layer, centre-of-sprite coords (for pivoting), scaling coefficients, image tint,
// and blending style.
boxman->draw( 300,450, 10, 0.5,0.5, 1,1, Colour::white(), BLEND_ADD );
}
};

int main(int argc, char *argv[])
{
SpriteFun *MG = new SpriteFun();
MG->launch(640, 480, false);
delete MG;

return 0;
}




There's a lot to digest here -- hopefully the comments are somewhat helpful.


Anyways, I'm mostly curious how you generally find the intuitiveness of the library. Obviously I'm throwing a lot around in these examples, and I'm quite biased, so I'd like to know how others see it, and where I can improve on the functionality and user-friendliness. Thanks! [smile]
Sign in to follow this  


2 Comments


Recommended Comments

That looks alot (alot) like how you use my engine - which is a good thing so well done :P

The only difference is I use static classes so you dont have to go 'getGraphics()->Set...' etc.

I find this kind of design every Intuitive which is why I wrote my engine like it too.

--

Btw are you going to be making a resource manager? Thats about the only thing i'd add as you'll beable to potentially beable to access your resources globally without making them global - It'll also be easier to manage your memory.

Share this comment


Link to comment
Thanks!

Quote:
Original post by diablo_tk
Btw are you going to be making a resource manager? Thats about the only thing i'd add as you'll beable to potentially beable to access your resources globally without making them global - It'll also be easier to manage your memory.


There's no real 'real' resource management yet -- well, at least not on a global scale. Each *Manager class (SpriteManager, AudioManager, etc) handles creating and disposing of its own resources.

Share this comment


Link to comment

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