• entries
298
1135
• views
231060

# A quick look through BaseCamp.

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]

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.

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.

## Create an account

Register a new account