Sce-Engine Interface
Engine entry point:
Render-Buffer handling
Input
Camera
2d Rendering
3d Rendering
This document tries to help you getting started with the main-engine interface. The main-engine interface is a collection of C functions that allows you to use the engine in an easy way. The only C++ code that is expected to understand, is the use of basic classes like sce::Colorf or sce::Vec3. These classes help to produce easy "write and readable code" and are very comfortable to use. The engine itself is written in C++ and its' components can be used individually. (The Sce-Edit editor uses the core engine code, and its classes.)
You as the game programmer use the engine like a painter. The engine gives you several tools for painting: camera, buffer, rendering functions for 2d and 3d graphics.
The engine uses a double buffer system for rendering. (See the section: "Concepts, Definitions and Setup" , to get more information about the double-buffer system) You start the rendering by clearing the backbuffer. Then you define a rectangular region (=viewport) in the window that will be used for rendering. After that you call all necessary functions that render the 2d and 3d graphics. Now it is time to make the buffer visible, this is done by switching the buffers.
With resources i mean graphics and sound data. To access and use these resources, the engine uses a handle based approach. (No classes are given to the game programmer!) Here is a simple example how to play a sound resource:
int backgroundMusic = -1; // handle for the sound resource, -1 = invalid handle void init() { // register the sound resource and store its id backgroundMusic = sce::registerSound("bkgSong1"); if( backgroundMusic == -1 ) { /* write some message */ } } void run() { if( /* entering menu mode */ ) { sce::playSound(backgroundMusic); // start playing the music if entering the menu } else if( /* entering game mode */ ) { sce::stopSound(backgroundMusic); // stop playing the music if leaving the menu } }
#include <windows.h> #include "../../sce_sdk/headers/sce_engine.h" void init() { // allocate all needed resources (graphics, sounds, ...) } void run() { // do the rendering und updating here } void shutdown() { // free game resources, engine objects are deleted automatically } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { sce::engineStart(init, run, shutdown); return 0; }
void update() { // update input if( /* user wants to exit game */ ) { sce::engineShutDown(); } // update game // update rendering }
void init() { sce::setAppName("PACKMAN"); // do initialisation }
void init() { if( /* screen mode 800*600 windowed mode set */ ) sce::resetRenderingDevice(800, 600, false); else if( /* screen mode 1024*768 windowed mode set */ ) sce::resetRenderingDevice(1024, 768, false); else if( /* screen mode 1024*768 fullscreen mode set */ ) sce::resetRenderingDevice(1024, 768, true); }
The example shows a simple rendering loop, that handles the rendering buffers.
void run() { sce::Colorf backgroundColor(1,0,0); sce::clearBackBuffer(backgroundColor); // clear the backbuffer and make it completely red // render everything... sce::swapBuffers(); // make the back buffer visible, and the front buffer ready // for rendering }
To push you into the right direction the code snippet shows you how a 2d game can handle the keyboard input for a spaceship moving up, down, left and right.
void run() { // update input if( sce::isButtonDown(sce::KEY_RIGHT) ) { // move the ship right } else if( sce::isButtonDown(sce::KEY_LEFT) ) { // move the ship left } else if( sce::isButtonDown(sce::KEY_UP) ) { // move the ship up } else if( sce::isButtonDown(sce::KEY_DOWN) ) { // move the ship down } }
A good example how to use this function could be, a spaceship firing a missle. You do not want the ship to fire continously, only one shot per button push.
void run() { // update input if( sce::isButtonUpToDown(sce::KEY_SPACE) ) { // fire missle } }
The exmaple shows you how getMouseAxis() can be used to change the viewing angles of a free cam.
float horizontalViewAngle = 0.0f; float verticalViewAngle = 0.0f; void run() { // update input if( sce::getMouseAxis().x_ != 0 ) { horizontalViewAngle += sce::DEG_TO_RAD(sce::getMouseAxis().x_); } if( sce::getMouseAxis().y_ != 0 ) { verticalViewAngle += sce::DEG_TO_RAD(sce::getMouseAxis().y_); } }
void run() { sce::Vec2i cursorPos = sce::getMouseCursorPos(); // use "cursorPos" to do picking, handle user input for the menu, ... }
The camera is used to do 2d and 3d rendering. A camera is handled like a resource object. You ask the engine for an instance, by calling function: registerCam, and retrieve a handle for this camera instance.
The example demonstrates how to register a camera, and what has to be done to do 2d and 3d rendering.
int camaId = -1; // handle for the camera object void init() { cameraId = sce::registerCam(1024, 768); // ask the engine for a camera object // the params 1024*768 define the viewport extensions } void run() { sce::clearBackBuffer(sce::Colorf(0,0,0)); // clear the backbuffer with color black sce::setCamViewport(cameraId, sce::Colorf(0,0,0)); // prepare the scene to do rendering sce::setCam3d(camaId); // prepare for 3d rendering /* do 3d rendering here */ sce::setCam2d(cameraId); // prepare the engine for 2d rendering /* do 2d rendering */ sce::swapBuffers(); // make the backbuffer visible } void shutdown() { sce::unregisterCam(cameraId); // tell the engine to release the camera // (note: the engine does this by itself on shutdown, // so this is not a must!) }
The camera object can also be released. This is not a must, since the engine deletes all allocated objects automatically on shutdown.
See function int registerCam(int, int) .
Using the camera frame you are able to position the camera in space and make it aim into the wanted direction.
See section "Concepts, Definitions and Setup", to learn more about frames and cameras.
int cameraId = -1; // handle for the camera object void init() { cameraId = sce::registerCam(1024, 768); // register camera // place the cam 10 units on the negative y-axis, facing the world origin sce::setCamFrame(cameraId, sce::Vec3(0,-10,0), sce::Vec3(0,1,0), sce::Vec3(0,0,1)); } void run() { // update free cam }
This function is just for convenience. The example below shows you, how a free cam can be realized using keyboard and mouse input.
int cameraId = -1; // handle for the camera object sce::Vec3 ypr(0,0,0) // holds yaw, pitch, roll void init() { cameraId = sce::registerCam(1024, 768); // register camera } void run() { // update free cam sce::Frame f = sce::getCamFrame(cameraId); // get current frame of this camera if( sce::isButtonDown(sce::KEY_W) ) // cam moves foreward f.pos() = f.pos() + f.dir(); if( sce::isButtonDown(sce::KEY_S) ) // cam moves back f.pos() = f.pos() - f.dir(); if( sce::isButtonDown(sce::KEY_A) ) // cam moves left f.pos() = f.pos() - f.right(); if( sce::isButtonDown(sce::KEY_D) ) // cam moves right f.pos() = f.pos() + f.right(); if( sce::getMouseAxis().y_ != 0 ) // cam changes pitch ypr_ += sce::Vec3(0,sce::DEG_TO_RAD(-sce::getMouseAxis().y_),0); if( sce::getMouseAxis().x_ != 0 ) // cam changes roll ypr_ += sce::Vec3(sce::DEG_TO_RAD(-sce::getMouseAxis().x_),0,0); f.setRotation(ypr_); // change the camera's rotation sce::setCamFrame(cameraId, f); // pass new calulated frame to camera }
Using this function you can access the current frame (the 4*4 matrix) of the camera. In most 3d applications the camera changes its position and orientation, so this function gives you information about the current placing of the cam.
See section "Concepts, Definitions and Setup" for more information about the frustum.
The frustum has to be set carefully. The engine uses the cam frustum for rendering optimizations. Remember, nearly all geometry that is within the frustum will be rendered. Having this is mind, it does not make sense to use the same frustum size for game acting in a dungeon and a game simulating a flight. The far value for the camera in the dungeon has to be 10-100 units. The far value for the flight game will have to be 1000-50000 units.
Get the values of the frustum for this camera. The six parameters are passed by referenz!
Using the viewport concept, you can define multiple regions on screen, that display different scenes, or the same scene from different camera positions.
You can use multiple cameras in a scene, define different viewports for them, and do things like: splitscreens. The example shows you how to create a splitscreen window with two cameras.
int cam_1 = -1; int cam_2 = -1; void init() { cam_1 = sce::registerCam(); // register a cam for the upper splitscreen cam_2 = sce::registerCam(); // register a cam for the lower splitscreen sce::setCamViewportExt(cam_1, 0, 0, 1024, 384); // define the viewport for cam_1 sce::setCamViewportExt(cam_2, 0, 384, 1024, 384); // define the viewport for cam_2 } void run() { sce::clearBackBuffer(sce::Colorf(0,0,0)); // clear the backbuffer with color black // render cam_1 viewport sce::setCamViewport(cam_1, sce::Colorf(0,0,0)); // prepare the scene to do rendering sce::setCam3d(cam_1); // prepare for 3d rendering /* do 3d rendering here */ sce::setCam2d(cam_1); // prepare the engine for 2d rendering /* do 2d rendering */ // render cam_1 viewport sce::setCamViewport(cam_2, sce::Colorf(0,0,0)); // prepare the scene to do rendering sce::setCam3d(cam_2); // prepare for 3d rendering /* do 3d rendering here again! */ sce::setCam2d(cam_2); // prepare the engine for 2d rendering /* do 2d rendering */ sce::swapBuffers(); // make the backbuffer visible }
Just a simple accessor function to get the current viewport values for a given camera. Note the values are passed by referenz!
When doing the rendering, you have to tell the engine which viewport is the current one. Have a look at the example given in function: void setCamViewportExt()
A camera is used for 2d and 3d drawing. You have to tell the engine what kind of rendering you will do. So "setCam3d has()" to be called, before 3d rendering is done. (Basically calling this function tells the rendering hardware how the graphics data should be projected on the screen.)
See function: void setCamViewportExt()
See function: void setCam3d(int).
Returns the current game application time in seconds. When the engine is started and all components and managers are initialized, a timer is also started that handles synchronization. The timer starts with time: 0 seconds.
Use this function to print something on screen.
Because the character size can be variable and the character set is not "monospace", the string lengths can change. This function returns the length of a string for a given character size.
This function can be used to align strings to the left or right border in a menu or in the HUD (head-up-display).
Retruns the height of a given character size.
This function is only used in debug mode. The function only takes effect for one frame (rendering loop). It is design to print values on screen, that are not fixed. For example: if you need to know the position of a character and the character moves between sectors.
Placing this function in the 2d rendering code is not a must! It can be called from anywhere!
You can pass as many strings as you want to this function. You can not control the string position. They are
printed starting in the lower left corner.
To effectively render the strings you have to call: render2dRetainedMode().
Render function that prints the current frames per second, in the lower right corner. The function has to be placed in the 2d rendering code!
This function should be called after you are finished with the 2d rendering. It collects all retained 2d data, and prints it on screen. For example: if you have used dbgPrint(), now is the time that these strings are made visible.
Renders a simple spot on the virtual screen.
Renders a 2d line with a start and an end point on the virtual screen.
Renders a 2d retangle on the virtual 2d screen.
Renders a 3d point.
Renders a 3d line with a start and end point.
Renders a sphere.
Renders an axis aligned bounding box.
Renders a frame (=coordinate system).
Renders the world coordinate system and a grid. The grid shows the xy-plane. One cell is 10*10 units.
Renders the frustum of a camera. Can be used to do some ai things. Enemy can see you or not...
Print some text to the engine console.
Has to be called in the 2d rendering code. Just displays the console.
Flag to check if the console is visible or not.