Page 1 of 2
Suggestions for 2D (now 3D) game framework
Posted: Tue Aug 14, 2007 5:31 am
by AndrewAPrice
If you haven't guessed by some of my previous posts, I'm writing a 2D game framework/engine. It's a C++ library - it's targeted for Windows but I making it cross platform may be a target in the future.
The current features I have so far:
* Create a game window in 1 line (including title, width, height, and optional fullscreen).
* A scene manager that contains wraps around everything within the scene.
* Sprites which can be
* - Scaled.
* - Rotated (and you can defined pivot aswell)
* - Tinted a colour.
* - Given a depth (closer sprites are drawn first).
* - Can be attached to a camera.
* A 2D camera (basically contains a 2D point which offsets a sprite at render time).
* Basic input handling (bool IsKeyDown([key]) at the moment).
This is an example program I've made with the framework so far: (it draws 2 bimaps on the screen and rotates one).
Code: Select all
#include <iostream>
#include <mgf.h>
using namespace MGF;
using namespace Core;
void Update();
Game *game;
Sprite *sampleSprite;
Sprite *sampleSprite2;
Camera2D *camera;
int main()
{
game = new Game();
if(!game->CreateGameWindow("Sample Game", 640, 480))
{
std::cout << "ERROR: Can't create game window.";
return 1;
}
sampleSprite = game->GetScene()->CreateSprite(game->GetScene()->GetTexture("test.bmp"),Vector2Di(10,10));
sampleSprite2 = game->GetScene()->CreateSprite(game->GetScene()->GetTexture("test.bmp"),Vector2Di(10,10));
camera = game->GetScene()->CreateCamera2D();
sampleSprite->SetScaling(Vector2Di(2,2));
sampleSprite->SetCentre(); // sets the pivot point to the centre (only needed since we're scaling)
sampleSprite->SetTint(Core::Colour(1.0f,1.0f,0.5f)); // tint the sprite a bright yellow
sampleSprite->AttachCamera(camera);
sampleSprite->SetDepth(0); // draw at the very front
sampleSprite2->SetDepth(.1); // draw behind
camera->SetPosition(Core::Vector2Di(-20,-20));
game->Run(Update);
delete game;
return 0;
}
void Update()
{
sampleSprite->SetRotation(game->GetTimeInMilliseconds()/500.0f);
game->GetScene()->Render();
}
And alternative way of creating a sprite is:
Code: Select all
sampleSprite = new Sprite(game->GetScene()->GetTexture("test.bmp"),Vector2Di(10,10));
game->GetScene()->AddSprite(sampleSprite);
I haven't implemented a way to remove sprites from scenes yet (it'll just be void Scene::RemoveSprite(Sprite *sprite) probably and I'll have a Scene::DeleteSprite which removes it and frees the sprite's memory). I'll work on that when I get my input handler working correctly.
I haven't released anything yet until I finish writing a sample game with it (it's a turn-based war game - a little more complex than your average Pong game). This way I'll have implemented most features a 2D game would require and have tested them in a real-world example before making a release.
I'll later be adding sound and network. Sounds will be able to be attached to cameras too (for stereo left/right). But they're not my main priorities at the moment. Once I have a stable and mature 2D game framework I'll work my way up to supporting 3D primitives, then eventually loading meshes. But I'm holding 3D off until I fully implement 2D, input, sound, and network because it'll take up most of my time when I get around to it.
Is there anything I seem to be missing from my game framework so far?
(Unrelated, I've finished a 3D variation of Pacman with rockets and destructable walls:
http://messiahandrw.netfast.org/portfol ... pacand.htm What do you guys think?)
Re: Suggestion for 2D game framework
Posted: Tue Aug 14, 2007 7:35 am
by Colonel Kernel
Sounds like fun. I started on something like that for Java once, but then my summer vacation ended.
MessiahAndrw wrote:Is there anything I seem to be missing from my game framework so far?
A generic event-handling system.
Re: Suggestion for 2D game framework
Posted: Tue Aug 14, 2007 8:00 am
by AndrewAPrice
Colonel Kernel wrote:A generic event-handling system.
How do you mean? Well, I get what an event-handling system is (like calling a function when something happens). But what would the events be for?
Posted: Tue Aug 14, 2007 9:31 am
by eboyd
I would like to see the BUFFER** handled in an #include.
Also, a more streamlined way of integrating audio would be much appreciated. I would love an API that would setup like this:
Code: Select all
#include "MyAPI.h"
#include "ScrBffr.h"
#define quit 1
int main(){
gameControl = 0;
level = 1;
initGame(myGame);
while(gameContol != quit){
loadLevel(level, status);
level++;
gameControl = status;
}
}
//the def might look like:
void loadLevel(int i, bool& q){
loadBackground(i);
loadAudiofile(i);
q = routine();
}
"Simplicity" is the mother of invention.
Re: Suggestion for 2D game framework
Posted: Tue Aug 14, 2007 11:58 am
by Colonel Kernel
MessiahAndrw wrote:How do you mean? Well, I get what an event-handling system is (like calling a function when something happens). But what would the events be for?
Simulation and animation. For simulation, take your turn-based war game for example -- each turn should be a loop that dispatches events to the objects in the game world, basically telling them to update themselves according to recent changes in game state. This scheme extends naturally from turn-based to real-time games, where each frame is an iteration of the main loop. For animation, imagine how you would add animation effects to the sprites in your war game and you'll see what I mean. Remember the old 2D version of SimCity, where buildings like power plants had animation loops that happened even if the game was idle? Same idea.
Posted: Sun Aug 19, 2007 7:36 pm
by AndrewAPrice
I started writing my turn-based war game during a 2 hour plane ride (+ another 2 hours after). I've attached a screenshot of what I've done so far. It renders a map engine with buildings (they're tinted based on the player they're associated to, red = 1, green = 2, grey = neutral). The tile under the cursor tints grey to indicate it's selected, and the map scrolls so the cursor stays in the centre (which was simple, since I associated the tile sprites with a Camera2D, so I only had to update the Camera2D position) unless the camera is near a border.
Posted: Sun Aug 19, 2007 7:37 pm
by AndrewAPrice
I started writing my turn-based war game during a 2 hour plane ride (+ another 2 hours after). I've attached a screenshot of what I've done so far. It renders a map engine with buildings (they're tinted based on the player they're associated to, red = 1, green = 2, grey = neutral). The tile under the cursor tints grey to indicate it's selected, and the map scrolls so the cursor stays in the centre (which was simple, since I associated the tile sprites with a Camera2D, so I only had to update the Camera2D position) unless the camera is near a border.
Posted: Wed Oct 03, 2007 4:08 am
by AndrewAPrice
I've added support to my framework for basic 3D (flat lighting/only basic DirectX primitives (Box, Sphere, Teapot, Torus, Pyramid), cameras). Added a few more days of programming and I'll probably have mesh support along with custom meshes. There's a lot more setup code from when I last posted, but it's necessary for the level of object orientedness I'm inspiring for.
What's basically involved in setting up the framework is:
- Create the initial MGF:Game object.
- Create a display window
- Create a game scene
- Create a camera and attach it to a display window (and/or speakers when I have sound implemented) and a scene
You can have a number of camera's all looking at the same (or different) scene from different angles/positions and they can be attached to different windows or different areas of the same window.
To render a scene, just call the Render() function of the camera you want to render. Here is my updated sample program which places a box/torus in the middle of the scene with a movable camera:
Code: Select all
#include <iostream>
#include <mgf.h>
using namespace MGF;
using namespace Core;
using namespace Input;
using namespace Scene;
// Our logic loop below
void Update();
// Some required objects
Game *game;
DisplayWindow *gameWindow;
Camera *camera;
GameScene *scene;
// our primtive's we'll use
MeshPrimitive *box;
MeshPrimitive *torus;
int main()
{
// create our game object
game = new Game();
// create our window
gameWindow = game->GetObjectFactory()->CreateDisplayWindow(640, 480, "Sample Game", false);
// create our scene
scene = game->GetObjectFactory()->CreateGameScene();
// create our camera and attach it to the scene and the window
camera = game->GetObjectFactory()->CreateCamera(scene, Vector3Df(0, 2, -10));
camera->AttachToDisplayWindow(gameWindow);
// create our box and add it to our scene
box = game->GetObjectFactory()->CreateMeshPrimitiveBox(1.0f, 1.0f, 1.0f);
scene->AddEntity(box);
// create our torus and add it to our scene
torus = game->GetObjectFactory()->CreateMeshPrimitiveTorus(1.0f, 2.0f, 3, 20);
scene->AddEntity(torus);
// place the game in the logic loop
game->Run(Update);
// everything made in our object factory must be deleted in the object factory
game->GetObjectFactory()->Destroy(box);
game->GetObjectFactory()->Destroy(torus);
game->GetObjectFactory()->Destroy(camera);
game->GetObjectFactory()->Destroy(scene);
game->GetObjectFactory()->Destroy(gameWindow);
// delete the game object
delete game;
return 0;
}
void Update()
{
// check to see if a key is down and move the camera the respective way
if(game->GetInputManager()->GetKeyboard()->IsKeyDown(MGFKEY_D))
camera->SetPosition(camera->GetPosition() + Vector3Df(0.2f,0,0));
if(game->GetInputManager()->GetKeyboard()->IsKeyDown(MGFKEY_A))
camera->SetPosition(camera->GetPosition() - Vector3Df(0.2f,0,0));
if(game->GetInputManager()->GetKeyboard()->IsKeyDown(MGFKEY_W))
camera->SetPosition(camera->GetPosition() + Vector3Df(0,0,0.2f));
if(game->GetInputManager()->GetKeyboard()->IsKeyDown(MGFKEY_S))
camera->SetPosition(camera->GetPosition() - Vector3Df(0,0,0.2f));
// render our camera
camera->Render();
}
Most methods (e.g. CreateCamera and the CreateMeshPrimitives) have about 4/5 different overloaded versions (placing their position/scale/rotation so you don't have to do it separately after).
Soon my camera will run in one of two modes; the "look at" camera (you provide a position the camera is facing), and the "rotate" camera (you provide the yaw/pitch/roll angles). And later I'm thinking about being able to 'lock' the camera position or look-at target onto on object.
Also, anything inside the GameScene inherits from SceneEntity. SceneEntity can hold a limitless about of SceneEntity children. All child position/scale/rotation is relative to it's parents (top level objects are relative to 0,0,0).
Posted: Fri Oct 05, 2007 7:57 am
by AndrewAPrice
Okay, a few updates;
- You add nodes to a scene. A node contains a link to an entity. The node is what stores the position/rotation/scale. That way you can have multiple entities in one scene.
- You can attach materials to objects. There is a default white material if no material is attached (if you load a mesh from a file, you shouldn't have to worry about manually attaching materials).
- I fixed some rendering bugs.
- Cameras can either accept a rotation, or a position to look at.
Posted: Fri Oct 05, 2007 1:58 pm
by t0xic
That sounds really neat! Care to attach another screenshot?
Michael
Posted: Sat Oct 06, 2007 1:38 am
by AndrewAPrice
I'll post another screen shot once I finish off lights, texturing, and loading meshes.
I don't have time to work on it right now (I have other college assessments too!), but those things are likely to be finished anytime from the next few days to the end of the week.
Posted: Sat Oct 06, 2007 7:03 am
by os64dev
MessiahAndrw wrote:
Code: Select all
*snip*
// everything made in our object factory must be deleted in the object factory
game->GetObjectFactory()->Destroy(box);
game->GetObjectFactory()->Destroy(torus);
game->GetObjectFactory()->Destroy(camera);
game->GetObjectFactory()->Destroy(scene);
game->GetObjectFactory()->Destroy(gameWindow);
// delete the game object
delete game;
*snip*
Why not have the object factory maintain a list of all objects created. If you add a name to the objects you can search on object name for instance. To release the resources created by the object factory you could modify the game destructor to do a GetObjectFactory()->ReleaseAll(). The Destroy method of the ObjectFactory should of course remove the object from the list.
Posted: Sat Oct 06, 2007 5:09 pm
by AndrewAPrice
Thanks, I'll consider that.
Posted: Thu Oct 25, 2007 7:40 pm
by AndrewAPrice
It's been a while since I've been on these forums (a least a week) thanks to all the work given to me at college. A lot of it involved extending my framework. I currently have:
- Multiple cameras (on same scene/many scenes/different part of the window)
Multiple windows (although only one can be used for rendering)
Multiple scene
Incomplete HTML documentation (with help from Doc-o-matic)
Texture manager
Mouse/keyboard input
Multiple instances of an object loaded once with scene nodes (saves a lot of memory) - scene nodes properties are also dependent on their parents node (rotation, position, scale).
A few different types of scene entities:
- Billboards
Mesh Primitives (boxes, spheres, toruses, etc)
Meshes (made up of mesh parts, which in term are made up of mesh indices/vertices)
Mesh X's (a quick wrapper .X meshes, I want to intergrate this into my normal mesh class)
3D Line lists
2D text boxes
Lights (spot, directional, point)
Custom mathematics code (only a small amount of matrix code uses DX, most matrix and all colour, vertex, quaternion, vector math is mine)
I have a demo program (too big to attach - it's 9.9MB IIRC - I'll send it if anyone wants it) that demonstrates matrix/vector/light/material operations visually as part of a college project. There are also billboard trees, environment effects, and a hidden secret (you can get into one of the ships). Sadly, this demo is restricted to Win32/DirectX. The demo code itself does not contain any Win32 or DirectX specific code, only the framework.
On my todo list is:
- Loose octrees (will significant speed up rendering, especially on my demo with such a populated environment)
Make the framework API independent (to support both DX and OpenGL - any suggestions on the best way to do this?) which in turn will get rid of a lot of the code that ties it down to Windows.
Posted: Fri Oct 26, 2007 2:59 am
by Combuster
Make the framework API independent (to support both DX and OpenGL - any suggestions on the best way to do this?)
You'd need some sort of abstraction. I personally used a requestmodel()/rendermodel()/freemodel() set of calls that allowed me to render whatever I wanted without being aware of the underlying functionality (which I afterwards broke by inserting dx.setrenderstate calls in the main loop and such). You could extend that with a setcamera(matrix) and setparameter(function,value) calls and map either one to either glLoadMatrix and other glxxx functions or SetTransform / SetRenderState calls. BeginDraw and EndDraw calls would also be nice to have.
I have a demo program (too big to attach - it's 9.9MB IIRC - I'll send it if anyone wants it)
I'm interested
If you want I can send you my directx engine in exchange if you want to. (its stuffed with funky directx features which you may find interesting, including some model loaders you probably won't have).