Development/Tutorials/Games/KGLEngine2d
Tutorial Series | KGLEngine2d developement |
Prerequisites | None |
What's Next | Nothing at the moment |
Further Reading | KGLEngine2d's code |
Abstract
KGLEngine2d is a recent try to develop a 2D games engine using openGL, and powerful enough to deliver complex and beautiful games. As of now, version 1.0 is not even out, but the API is stable enough for anyone to start playing with the engine. Through this tutorial I will explain how to use a great part of the engine, included but not limited to : sprites creation, rotation and deplacement and collision detection.
The example : kglPong
Anyone who have followed the KGLEngine2d developement a bit will have seen some kglPong screenshot, as this is the way new features are shown, using this simple game to showcase them.
Starting Point : the main.cpp
Every application need one, so let's start with it, as it really is simple.
- include <KApplication>
- include <KAboutData>
- include <KCmdLineArgs>
- include "pongengine.h"
int main( int argc, char **argv)
{
KAboutData aboutData( "kglpong", 0,
ki18n("kglpong"), "0.1",
ki18n("Classic pong game using KGLEngine2d"),
KAboutData::License_GPL,
ki18n("Copyright (c) 2008 Developer") );
KCmdLineArgs::init( argc, argv, &aboutData );
KCmdLineOptions options;
KCmdLineArgs::addCmdLineOptions(options);
KApplication app;
pongEngine pong;
pong.show();
return app.exec();;
}
So, what are we doing ?
Initializing the KApplication, and creating an instance of our main class, the one that surclasses KGLEngine2d. Then we tell him to show himself, and that's all. I told you there was nothing exciting in here :)
The KGLEngine2d pong engine
Now, as we want a bit of sophisticated features, we will have to surclass the KGLEngine2d.
Namely, those sophisticated actions, that forces us to surclass are the keyboard interactions. As of now, those are managed in the engine's mainLoop, and there are no alternatives to use them otherwise. Everything else could have been done in the main, or anywhere else, using a simple slot and the engine power.
This code is subject to change, as the KGLSpriteItem constructor is not fixed in the API right now. This is why i don't explain the meaning of the args.
const double wallThickness = 0.1;
KGLSpriteItem *NWall = new KGLSpriteItem("", QRectF(-1, ratio(), 2, wallThickness), WALL_TYPE, QPointF(20, 1));
addGLItem(NWall);
KGLSpriteItem *SWall = new KGLSpriteItem("", QRectF(-1, -ratio()-wallThickness, 2, wallThickness), WALL_TYPE, QPointF(20, 1));
addGLItem(SWall);
KGLSpriteItem *background = new KGLSpriteItem("sprites/wall.png", QRectF(-1, -ratio(), 2, 2*ratio()), BACKGROUND_TYPE);
addGLItem(background);
KGLSpriteItem *player1Goal = new KGLSpriteItem("", QRectF(-1, -ratio()+wallThickness, wallThickness, 2*(ratio()-wallThickness)), GOAL_TYPE, QPointF(20, 1));
player1Goal->setColor(Qt::black);
addGLItem(player1Goal);
KGLSpriteItem *player2Goal = new KGLSpriteItem("", QRectF(1-wallThickness, -ratio()+wallThickness, wallThickness, 2*(ratio()-wallThickness)), GOAL_TYPE, QPointF(20, 1));
player2Goal->setColor(Qt::black);
addGLItem(player2Goal);
So, what happens there ? We create and add items to the engine, more specifically sprites. The first two ones are there so the ball will bounce when it reaches the border of the screen. The third one is the background image, just here for the bling. Fourth and fifth ones are the goals, so we can detect when the ball's gone past a player's racket. The goals are set to be black, this should not be done this way, they should be given an image instead, but, hey, this is a code example and i wanted to show you how to draw a simple colored rectangle.
const double thickness = 0.05;
const double wallDistance = 0.2;
const double height = 0.25;
player1Racket = new Racket();
player1Racket->setPosition(POINT(-1+wallDistance, 0));
addGLItem(player1Racket);
player2Racket = new Racket();
player2Racket->rotate(M_PI);
player2Racket->setPosition(POINT(1-wallDistance-thickness, 0));
addGLItem(player2Racket);
ball = new Ball();
ball->setPosition(POINT(0, 0));
addGLItem(ball);
Now we create the player's rackets and the ball. These are special classes that will be explained a bit later. They might have been simple KGLSprites, and the collisions would have been managed in another function connected to the KGLItem::colliding(PhysicsItem*) function. I'll explain the two ways later.