Your SlideShare is downloading. ×
Qe Reference
Upcoming SlideShare
Loading in...5

Thanks for flagging this SlideShare!

Oops! An error has occurred.

Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Qe Reference


Published on

  • Be the first to comment

  • Be the first to like this

No Downloads
Total Views
On Slideshare
From Embeds
Number of Embeds
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

No notes for slide


  • 1. QE Reference Joe Linhoff Overview QE stands for the quarter engine. Development Environment DirectX & OpenGL QE uses OpenGL for graphics and DirectX for input, sounds, and other operations on Windows. For best results, update your OpenGL drivers (from your video card manufacturer's website) and install the latest DirectX (search for dxwebsetup.exe on Microsoft's site). Microsoft Visual Studio C++ Express Edition 2008 All the solutions are built using Express Edition 2008. Directories ● (solution root) -- your application ● starter -- starter kit with hello world Directories in the tree (and some of the files in those directories) ● lib -- library files ● bin -- executables ○ qeblue.dll -- qe ○ freeglut.dll -- glut-like gl utility toolkit ● inc -- qe include files ○ qe.h -- the main interface file for the engine ○ qec.h -- engine class definitions for C++ ○ qebase.h -- base types Files config.h -- a user created file that defines how the solution builds ● qeStartup.c -- startup file for environment, not a user file ● .h files are added from the inc directory as needed ● Hello World // Copyright (C) 2007 Joe Linhoff, All Rights Reserved // e_hello.c #include quot;config.hquot; #if BUILD_HELLO // compile this app #include quot;qe.hquot; // qeMain() // JFL 05 Jan 07 int qeMain(int argc,chr *argv[])
  • 2. { // print hello world & version information qePrintf(quot;%s / %s / %snquot;,__FILE__,glGetString(GL_VERSION),qeVersion()); qePrintf(quot;Hello Worldnquot;); // turn control over to the engine until the user closes the program qeForever(); return 0; } // qeMain() #endif // compile this app // EOF Console and Log File The function qePrintf() follows most of the same formatting rules from printf(). In addition, all the messages printed are added to the log file. The log file is qelog.txt in your project's root directory. Use qeLogf() to send messages to the log file and not to the screen. Reference QE_API int qeForever(void); // does not return until closed QE_API chr *qeVersion(void); // get version QE_API int qePrintf(chr *fmt,...); ///< print a message QE_API int qeLogf(chr *fmt,...); ///< log a message Base Types, Definitions, Macros Base Types The file qebase.h contains the base type definitions for the engine. base type definition and use bit smallest unit available, use 1 or 0 chr 8 bit character for ASCII strings and internal naming char environment defined character int8 8 bit signed integer, MIN_INT8..MAX_INT8 uns8 8 bit unsigned integer, 0..MAX_UNS8 int16 16 bit signed integer, MIN_INT16..MAX_INT16 uns16 16 bit unsigned integer, 0..MAX_UNS16 int32 32 bit signed integer, MIN_INT32..MAX_INT32 uns32 32 bit unsigned integer, 0..MAX_UNS32 int environment defined integer, MIN_INT..MAX_INT uns unsigned version of environmentally defined integer, 0..MAX_UNS flt32 32 bit float flt64 64 bit float float environment defined float
  • 3. int64 64 bit signed integer uns64 64 bit unsigned integer Defines define definition notes, usage PI 3.1415.. TWOPI (2.0*PI) EPSILON 0.00001 NUL 0L, a null pointer Macros define definition notes, usage BRK() debugger breakpoint when DEBUG is defined during compile QE_DEGTORAD(_deg_) convert degree to radians QE_RADTODEG(_rad_) convert radians to degrees NUM(_a_) number of elements in a static array PTR_ADD(_p_,_i_) add _i_ bytes to pointer _p_ PTR_SUB(_p_,_i_) subtract _i_ bytes from pointer _p_ C1(_a_) combine a single 8 bit value C2(_a_,_b_) combine two 8 bit values, used for character-based constants C3(_a_,_b_,_c_) combine three 8 bit values, used for character-based constants C4(_a_,_b_,_c_,_d_) combine four 8 bit values, used for character-based constants SET2(_d_,_s1_,_s2_) set array, i.e. _d_[0]=_s1_, _d_[1]=_s2_ SET3(_d_,_s1_,_s2_,_s3_) set array, i.e. _d_[0]=_s1_, _d_[1]=_s2_ SET4(_d_,_s1_,_s2_,_s3_,_s4_) set array, i.e. _d_[0]=_s1_, _d_[1]=_s2_ CPY2(_d_,_s_) copy array entries from source _s_ to destination _d_ CPY3(_d_,_s_) copy array entries from source _s_ to destination _d_ CPY4(_d_,_s_) copy array entries from source _s_ to destination _d_ Function Pointers Typedefs for function pointers are defined such that the first letter signals the return type and the next letters signal the parameter types: v = void, i = int, u = uns, p = pointer, a = variable argument. The partial table below shows a few examples. typedefs definition notes, usage fnc_vv void function(void) fnc_iv int function(void) fnc_ii int function(int)
  • 4. fnc_ipi int function(pointer,int) fnc_ipa int function(pointer,...) Control QE presents a single list to the user. In qeMain(), the application setups a list of functions and objects and then passes control to QE with qeForever(). Each game loop, QE performs various internal operations, and then begins processing the application-created list. Because the engine processes this list, it is called the engine list. Function Objects The function qeObjAddFnc() adds a C function with the signature int function(void) to the engine object list. This function will be called when it's node is processed. If the function returns a negative number, the node is removed from the engine's list and the function is not called again. // Copyright (C) 2006-2008 Joe Linhoff, All Rights Reserved // e_simplefunction.c #include quot;config.hquot; // include the 'config' file first #if BUILD_SIMPLEFUNCTION // compile this app #include quot;qe.hquot; // JFL 12 Aug 06 int fncEveryLoop(void) { qePrintf(quot;Frame %d time %fnquot;,qeLoopFrame(),qeTimeFrame()); return 0; // function must return a value, 0 indicates success } // fncEveryLoop() // qeMain() // JFL 05 Aug 06 int qeMain(int argc,chr *argv[]) { qePrintf(quot;%s / %s / %snquot;, __FILE__,glGetString(GL_VERSION),qeVersion()); // add a function to the engine's object loop if(!qeObjAddFnc(fncEveryLoop)) BRK(); // turn control over to qe until the user closes the program qeForever(); return 0; } // qeMain() #endif // compile this app // EOF Extended Operations Many functions have a variable argument interface which starts with a string parameter. The
  • 5. string parameter specifies the remaining arguments. For example, to specify the name for the function node added above, use qeObjAddFncSP() as follows. // add a simple C function, static name, not copied if(!qeObjAddFncSP(fncEveryLoop,quot;Nquot;,quot;f-everyLoopquot;)) BRK(); // add a simple C function, dynamic name, copied if(!qeObjAddFncSP(fncEveryLoop,quot;nquot;,name)) BRK(); F8 Console QE has a built in console. Press F8 to toggle the console input on/off. Type the command and hit enter. Press F9 to toggle the background color and clear the console screen. Commands ● list -- lists the engine objects ● step -- single step the engine, forward & backward arrows to step ● run -- exit single step mode Break Macro When DEBUG is defined, the BRK() macro expands to a debugger breakpoint. When DEBUG is not defined, or defined to be zero, the BRK() macro expands into a null statement. Names Internally, names are truncated to 11 characters and are case sensitive. QE Update Base Class The preferred way to add a C++ object to the engine list is by deriving from the base class qeUpdateBase. This base class is defined in qec.h. Objects inheriting from qeUpdateBase are linked into the engine list and sorted against each other using the sort value. The gameid must be greater than zero and should be unique among all engine objects. Id value 1 is usually reserved for underdefined objects. // Copyright (C) 2006-2008 Joe Linhoff, All Rights Reserved // e_simpleclass.c #include quot;config.hquot; // include the 'config' file first #if BUILD_SIMPLECLASS // compile this app #include quot;qec.hquot; /////////////////////////////////////////////////////////////////////////////// // Plane class Plane : public qeUpdateBase { public: Plane::Plane(chr *name); int draw(void); // override virtual void final(void); // override virtual }; // class Plane
  • 6. // JFL 11 Nov 07 Plane::Plane(chr *name) : qeUpdateBase(name,0,1) // name, sort, gameid { } // Plane::Plane() // JFL 11 Nov 07 int Plane::draw(void) { qefnDrawGrid(10,1); qefnDrawAxes(1); return 0; } // Plane::draw() // JFL 11 Nov 07 void Plane::final(void) { delete this; } // Plane::final() // qeMain() // JFL 05 Aug 06 int qeMain(int argc,chr *argv[]) { qePrintf(quot;%s / %s / %snquot;, __FILE__,glGetString(GL_VERSION),qeVersion()); new Plane(quot;plane1quot;); // turn control over to qe until the user closes the program qeForever(); return 0; } // qeMain() #endif // compile this app // EOF Deriving from qeUpdateBase defines and adds nodes for: ● control() -- application definable ● update() -- application definable ● draw() -- application definable ● final() -- must delete this; QE base class The qe base class overrides the new and delete operators to provide integration with the engine without adding memory overhead to your objects. Reference QE_API int qeForever(void); // does not return until closed QE_API uns qeLoopFrame(void); ///< loop count since reset QE_API float qeTimeFrame(void); ///< game time for the frame QE_API qeObj* qeObjAddFnc(fnc_iv fnc); // add C function obj QE_API qeObj* qeObjAddFncSP(ptr adr,chr *sp,...); // add C func w/sp
  • 7. BRK(); class qeUpdateBase Input Button Input Button counts are used to report the current state of each button. Odd button counts signal the button is currently down. The keyboard is initially setup as buttons. // JFL 21 Sep 06 int fncEveryLoop(void) { uns upCount; // read the button count for the up button upCount=qeInpButton(QEINPBUTTON_UP); // print all the values qePrintf(quot;upCount=%dnquot;,upCount); return 0; // function must return a value, 0 indicates success } // fncEveryLoop() Default Key to Button Mappings Z - QEINPUTBUTTON_A up - QEINPUTBUTTON_UP pageup - QEINPUTBUTTON_UP2 X - QEINPUTBUTTON_B down - QEINPUTBUTTON_DOWN pagedown - QEINPUTBUTTON_DOWN2 C - QEINPUTBUTTON_X left - QEINPUTBUTTON_LEFT V - QEINPUTBUTTON_Y right - QEINPUTBUTTON_RIGHT Remapping The Keyboard Buttons To remap the keys to different buttons, or to map multiple keys to the same button, use qeInpOp(QEINPOP_SETKEYMAP,gameKeymap) where the gameKeymap is the remapping table. This mapping table replaces the default table. int gameKeymap[] = { // remap QEINPBUTTON_ to keys QEINPBUTTON_UP,'W',0, QEINPBUTTON_LEFT,'A',0, QEINPBUTTON_RIGHT,'D',0, QEINPBUTTON_DOWN,'S',0, QEINPBUTTON_A,'Z',0, QEINPBUTTON_B,'X',0, QEINPBUTTON_X,'C',0, QEINPBUTTON_Y,'V',0, QEINPBUTTON_START,'1','r',0, // multiple mappings GAMEINPBUTTON_SPECIAL,'G','H','8',0, // multiple mappings 0 // term }; // gameKeymap[] .. remap the keys in the setup ..
  • 8. // remap the keys -- gameKeymap must remain valid while it is mapped qeInpOp(QEINPOP_SETKEYMAP,gameKeymap); The Keyboard As A Keyboard Instead of treating the keyboard as a set of buttons, keys can also be captured into a buffer. Setup a buffer for QE to fill with keystrokes between frames, and then empty that buffer each frame. // Copyright (C) 2006-2008 Joe Linhoff, All Rights Reserved // #include quot;config.hquot; #if BUILD_KEYBOARD // compile this app #include quot;qe.hquot; struct { // create local storage record uns keyBuf[32]; } game; // JFL 12 Aug 06 // JFL 24 Sep 06 int fncEveryLoop(void) { chr buf[32]; // copy the chrs typed out of the keyBuf and into 'buf' buf[0]=0; // force a terminating 0 -- will be replaced if chrs are copied qeInpOp(QEINPOP_CPYCHRBUF,buf,sizeof(buf)); // print all the values captured this loop qePrintf(quot;'%s'nquot;,buf); return 0; // function must return a value, 0 indicates success } // fncEveryLoop() // qeMain() // JFL 05 Aug 06 int qeMain(int argc,chr *argv[]) { MEMZ(game); // zero structure // print information qePrintf(quot;%s / %s / %snquot;,__FILE__,qeVersion(),glGetString(GL_VERSION)); // add a function to the engine's object loop if(!qeObjAddFnc(fncEveryLoop)) qePrintf(quot;** qeObjAddFnc failednquot;); // setup the keyBuf to record keys as they are typed -- must remain valid qeInpKeyBuf(game.keyBuf,sizeof(game.keyBuf)); // turn control over to engine until the user closes the program qeForever(); return 0; } // qeMain() #endif // compile this app
  • 9. // EOF Turn off keyboard button mappings with qeInpOp(QEINPOP_KEYBOARDMAPPINGS_OFF). And turn them back on with qeInpOp(QEINPOP_KEYBOARDMAPPINGS_ON). Joysticks QE supports DirectX joysticks, Xbox360 joysticks, and Wii-motes. Use qeInpJoyNum() to find the current number of joysticks attached. Buttons and axes are then read using qeInpJoyButton() and qeInpJoyAxis(). The axis value ranges from QEINP_JOYAXIS_MIN to QEINP_JOYAXIS_MAX. int fncEveryLoop(void) { uns b1,b2,b3,b4; int xyLeft[2]; int xyRight[2]; // read joystick buttons and axes b1=qeInpJoyButton(0,QEJOYBUTTON_A); b2=qeInpJoyButton(0,QEJOYBUTTON_X); b3=qeInpJoyButton(0,QEJOYBUTTON_LSHOULDER); b4=qeInpJoyButton(0,QEJOYBUTTON_LTHUMB); xyLeft[0]=qeInpJoyAxis(0,QEJOYAXIS_LEFT_X); xyLeft[1]=qeInpJoyAxis(0,QEJOYAXIS_LEFT_Y); xyRight[0]=qeInpJoyAxis(0,QEJOYAXIS_RIGHT_X); xyRight[1]=qeInpJoyAxis(0,QEJOYAXIS_RIGHT_Y); // print the values qePrintf(quot;number of joysticks=%d A=%d X=%d LS=%d LT=%d (%d, %d) (%d, %d)nquot;, qeInpJoyNum(),b1,b2,b3,b4,xyLeft[0],xyLeft[1],xyRight[0],xyRight[1]); return 0; // function must return a value, 0 indicates success } // fncEveryLoop() Reference QE_API uns qeInpButton(uns inpb); // QEINPBUTTON_ QE_API int qeInpOp(uns op,...); // QEINPOP_ QE_API uns qeInpJoyNum(void); // joysticks attached -- valid after qeOpen() QE_API int qeInpJoyAxis(uns joy,uns axis); // get, use QEJOYAXIS_ QE_API uns qeInpJoyButton(uns joy,uns button); // get, use QEJOYBUTTON_ Sounds Supported Formats A limited number of .wav formats are currently supported. Channels Sounds play on software defined channels. There are currently 8 channels, which means you may play up to 8 sounds at the same time. A sound can range from a short pop to an
  • 10. endlessly looping song. The game engine manages the mixing of the currently playing channels. Loading And Playing Sounds Register sounds with qeSndNew(). Play a sound with qeSndPlay(). To pre-load a sounds, use qeSndLoad(). QE_API int qeSndNew(chr *name,uns flags,uns tProtect,chr *path); QE_API int qeSndPlay(chr *name); // returns play id on success The name parameter is the name of the sound and will be used to play or manipulate the loaded sound. The flags parameter contains track and priority information as well as other information. The tProtect parameter is a millisecond time parameter. And path is the file path to the sound file. Channel Assignment Algorithm When qeSndPlay() is called, the engine: 1. Looks through all the channels indicated in the channel mask for an empty (no sound currently playing) channel. If there is an empty channel, the engine starts the sound on that channel. 2. If there is not an empty channel, the engine looks through the channels indicated in the channel mask for a channel with a sound that it can stop playing and replace with the new sound. If the new sound's priority is higher than a currently playing sound, the oldest, currently playing sound is replaced. If there are no open channels, and the new sound's priority is lower than all the currently playing sounds, the new sound will not be played. When the new sound's priority matches currently playing sounds, the oldest sound that is not protected will be replaced. Age of a sound is determined by the time after a sound's protection expires. A Typical Channel Plan Every game has its own sound requirements. You must design a channel plan for how each game will use channels. Here is a simple example: ch0 ch1 ch2 ch3 ch4 ch5 ch6 ch7 background announcer, world player weapons,
  • 11. music music effects, critical reactions, extras reactions effects Reference QE_API int qeSndNew(chr *name,uns flags,uns tProtect,chr *path); QE_API int qeSndPlay(chr *name); // returns play id on success Options Turning Options On And Off QE is intended to be configurable. Use qeOptionTurnOff() or qeOptionTurnOn() to turn options on or off. Set options before qeForever() or qeOpen(). #define M_QEOPTION_CLEARSCREEN 0x000001 // clear screen every loop #define M_QEOPTION_AUTOCAM 0x000002 // add first (arcball) camera #define M_QEOPTION_DRAWCONSOLE 0x000100 // draw console #define M_QEOPTION_INITGL 0x000200 // init OpenGL #define M_QEOPTION_DRAWMODE 0x000400 // black on white #define M_QEOPTION_FIRSTLIGHT 0x000800 // add first light #define M_QEOPTION_LOGPRINTF 0x002000 // qePrintf() output also to log #define M_QEOPTION_CHECKLOGSIZE 0x004000 // check & delete log if too big #define M_QEOPTION_INERNALSLEEP 0x008000 // sleep inside the engine loop #define M_QEOPTION_CLEARSTENCIL 0x010000 // clear stencil buffer every loop #define M_QEOPTION_PAGEFLIP 0x010000 // flip pages For example, to request the engine to no add the default camera or first light, and to clear the stencil buffer when it clears the screen: // qeMain() // JFL 05 Jan 07 int qeMain(int argc,chr *argv[]) { qeOptionTurnOff(M_QEOPTION_AUTOCAM|M_QEOPTION_FIRSTLIGHT); qeOptionTurnOn(M_QEOPTION_CLEARSTENCIL); qePrintf(quot;%s / %s / %snquot;,__FILE__,glGetString(GL_VERSION),qeVersion()); ... Window Size, Full Screen Use qeWindowSize() to change the window size. Use qeGetWindowSize() to get the current window size. float w,h; if(qeGetWindowSize(&w,&h)>=0)
  • 12. ; // success Fullscreen mode is managed with qeFullscreen().