GETTING STARTED by mikesanye

VIEWS: 2 PAGES: 7

									     JGC Library Version 2.0 DarkGDK C++ OOP Source Code A leg-up for Game Developers



                                  Getting Started!

GETTING STARTED
      To get started, download the latest version of the library, unzip it so the directory
      structure remains in tact, and highlight any demo in the tree view control so its selected
      and in bold, followed by clicking the debug “RUN” button. Note: I found ending
      applications via the ESCAPE key and clicking the “X” on DarkGDK windows takes a LONG
      time in debug mode. I recommend “ALT-TAB” back to Visual Studio and pressing SHIFT-
      F5 (stop Debugging). Both ways work fine, just the normal method takes a long time. All
      the source code in this article has been included in the JGC released archive file!

HOW IT WORKS – THE BASICS
     There is the JGC_DADDY class which is in the JGC name space and its job is to tie
     everything together and serve as the “point man”. The JGC_DADDY class starts,
     updates and shuts down JGC properly.

        There are two names spaces JFC (Jegas Foundation Classes – Not DarkGDK dependent)
        and JGC (Jegas Game Classes – DarkGDK dependent). Visual Studio’s Intellisense and
        “right click” menus in the source code windows will prove indispensable in learning about
        all the functions and data members that are in here.

        Here is how a JGC “Hello World” program might look:
#include <DarkGDK.h>
#include "jfc_common.h"
#include "jgc_configuration.h"
#include "jgc_common.h"
void DarkGDK(void){
  JGC::Daddy = new JGC_DADDY();

  // Here you can tweak some default values before the engine starts
  JGC::Daddy->D_DISPLAY_WIDTH=640;
  JGC::Daddy->D_DISPLAY_HEIGHT=480;
  JGC::Daddy->D_DISPLAY_DEPTH=32;
  JGC::Daddy->D_DISPLAY_WINDOWED=true;

  // Then you say... Ok START!
  JGC::Daddy->Init();

  // now all the classes in the JGC NameSpace are Alive and Instantiated
  // a couple default images are created in memory, and a couple objects
  // Default Bitmap fonts are loaded (Arial, Arial Bold)

  //Now I know I created an object (three actually) Called Toy, Angle Finder, and
  // anchor. Two are excluded, anchor remains visible... so
  JGC::ObjAnchor->Exclude_Set(true);

  // I use JGC::ObjAnchor to mark the center of 3d world space
  // I use JGC::ObjToy as a 3d cursor, and JGC::ObjAngleFinder to help me get positions in 3d
  // space.. like I'll position the object angle finder where some game thing is, rotate to match
  // the game thing, move it a little, and then read the new position of this
  // angle finder... I usually don't want to see them so they default to excluded.
  // but if I needed to:
  //JGC::ObjAngleFinder->Exclude_Set(true); //used for finding positions and angles in space
  //JGC::ObjToy->Exclude_Set(true);//used as a cursor when selecting 3d things


  // Let's make an object
  JGC_OBJECT *Obj=new JGC_OBJECT();
  Obj->Make_Cube(10);
     Obj->Move(50);

     // How about a bitmap font? We already have an array with two.. arial and Arial Bold Right?
     // You'd see in the source code for the DADDY class how they are loaded when that
     // Init() is called.
     JGC_BITMAPTEXT *BitmapText = new JGC_BITMAPTEXT();

     // this will “stick” because its using sprites, but you can render to images too!
     BitmapText->String_Write(100,100,"Hello World!",JGC::BitmapFontIndex_Default);

     while(LoopGDK()){
        JGC::Daddy->Update();
     };
     delete BitmapText;
     delete Obj;
     delete JGC::Daddy;
};




Integration with Existing Code

           One of the things about this library that is important to note is that it doesn’t need a ton
           of changes to your existing code to utilize! I was answering a forum message and I
           wrote this little example to show how to utilize the file logging system:

#include <DarkGDK.h>
#include "jfc_common.h"
#include "jgc_configuration.h"
#include "jgc_common.h"
void DarkGDK(void){
  JGC::Daddy = new JGC_DADDY();
  // Here you can tweak some default values before the engine starts
  // any Value here: JGC::Daddy->D_?????????
  JGC::Daddy->D_CAMERA_AUTOCAM=false;
  // Then you say... Ok START!
  JGC::Daddy->Init();
  // now all the classes in the JGC NameSpace are Alive and Instantiated
  // a couple default images are created in memory, and a couple objects
  // Default Bitmap fonts are loaded (Arial, Arial Bold)

     //Now I know I created some objects (three actually) Called Toy, Angle Finder, and
     // anchor. Two are excluded, anchor remains visible... so .. let's hide.
     JGC::ObjAnchor->Exclude_Set(true);

     JGC::File->Log(1,"SomeLogCode","Some Message! :)");


     while(LoopGDK()){
        JGC::Daddy->Update(); // Not needed just to use log file.
     };
     delete JGC::Daddy;

};


           Now, you could even trim this up more by ripping out the specific code you need out the
           source, but that’s more work than this was. The Output log file from the above example
           created this:

;==============================================================================
;|     _________ _______ _______ ______ _______       Jegas, LLC               |
;|    /___ ___// _____/ / _____/ / __ / / _____/      JasonPSage@jegas.com     |
;|       / /    / /__     / / ___ / /_/ / / /____                              |
;|      / /    / ____/ / / / / / __ / /____ /                                  |
;|____/ /     / /___    / /__/ / / / / / _____/ /                              |
;/_____/     /______/ /______/ /_/ /_/ /______/                                |
;|                    Under the Hood                                           |
;==============================================================================
;               Copyright(c)2008 Jegas, LLC
;==============================================================================
  IF YOU ARE VIEWING THIS FROM INSIDE VISUAL STUDIO NOTE:
  Visual Studio can not successfuly reload files in use by DarkGDK.
  STOP Your debugger, close the 'tab' with this file in it, and reopen manually!
;==============================================================================
                Jegas Dark GDK Log File.
;==============================================================================
YYYYMMDDHHmm, Priority, LOGENTRYCODE, "Log Entry Text"
;==============================================================================
200805161505, 1, "SomeLogCode", "Some Message! :)"
;==============================================================================
; EOF
;==============================================================================


        Important: Creating the instance of the JGC_DADDY class doesn’t actually start the
        system. This two step initialization was created to allow changing many of the default
        values (declared in jgc_configuration.h) programmatically before the initialization
        routines are launched. You can see these default values in JGC::Daddy-> where ever
        there is a D_<some name here>. This design allows reading and changing default
        values before the initialization is fired which can be used for example to prevent setting a
        video mode that the user’s card does not support for if you added a graphics card
        checklist poll to your application.

        After you have changed any default values in the JGC_DADDY class, you instantiate the
        system with JGC::Daddy->Init();. Here your video mode is set, some three objects are
        created (2 excluded, one visible) , 2 default bitmap fonts are loaded (Arial, Arial Bold),
        The Clock is started, the user input class is started, a few images are created for “stock
        textures” – one pixel of red, one green, one blue, and one test texture with a
        symmetrical design useful when debugging things like meshes.

        In your main loop, you call the JGC::Daddy->Update(); to do things like call dbSync(),
        update the JGC_USERINPUT class, the JGC_CLOCK class, update objects registered
        in the frustrum culling system, and also record Camera 0’s (JGC::Cam0) current position
        so that you can reference these coordinates and angles without needed to call the
        dbCameraPositionX() function repeatedly incurring overhead (reading a variable is
        faster than calling a function). There is even a new JGC::Cam0->Update() function
        that can re-syncronize JGC’s maintained camera position and angles with GDK’s. Saves
        ya from having to write all this dbCameraPositionX() functions.

        Another area that is very important to understand for integration with existing programs
        is how to work with the various DarkGDK ID’s. I purposely did not create one “ID”
        factory function and use it for everything because in practice I found there are so many
        different rules about ID’s from one DarkGDK entity to the next: 1-32 Bitmaps, 1-257
        Memblocks, 60000+ for Objects, etc. Instead, I did a cut-n-paste of a basic system, and
        tailored to suit. I used constants in the source code to limit the ID # that are sought for
        each entity type and I made a 2 tier system. The first time through the ID range, a
        simple COUNTER is used, and no checking is done to see if the entity already exists. (i.e.
        dbObjectExists(NewID);) After the first time through the ID’s, the system is more
        careful about creating ID numbers with respect to whether they exist or not. Now you
        can go into the constructor for each entity and make changes to suit which often is just
        adjusting the predefined constants.

        Another trick you can do to make this 2 tiered approach single tier is to make the
        JGC_OBJECT private member AutoGenIDCounterHasRolled set to true rather than
        false in the constructor. This would make the system ALWAYS check to make sure an
        object ID was not in use before settling on that ID value.

        The REAL neat thing about many of the JGC classes is that you can instantiate them and
        actually pass the ID of something that already exists without doing anything to it!
        (Deleting classes such as JGC_OBJECT is less forgiving… if the Object with that ID
        exists, it is deleted when the class is.) But even this can be overridden by just setting
that class’ ID to ZERO before deleting it. This way, you can delete the class and preserve
the object itself in DarkGDK from deletion! Consider the following example:

[STOCK Snippet from JGC_OBJECT.h]
//============================================================================
//BEGIN RESERVED OBJECT ID's
//============================================================================
#define cnObject_AngleFinderID 1
#define cnObject_ToyID 2
#define cnObject_AnchorID 3
#define cnObject_JegasID 4
// For Applications to Use
#define cnObject_TempID 5
//============================================================================
// Set this to highest RESERVED Image #
#define cnObject_LastIDAtStartUp 5
#define cnObject_HighestUsableID 60000
//============================================================================


By default, the JGC_OBJECT classes’ ID factory reserve ID’s 5 thru 60000 for DarkGDK
objects (our declared object id factory range) and there are some reserved ID’s for the
default objects that are created. (the cnObject_TempID is meant so you always have a
scratch ID handy for little tasks where you might create, make a mesh from, and a
delete an object for example.) You can change the range of ID’s for the factory
So that your JGC_OBJECT class instances do not interfere with your existing object ID
numbering with a change like this example:

[MODIFIED Snippet from JGC_OBJECT.h to help integrate to existing
programs]
//============================================================================
//BEGIN RESERVED OBJECT ID's
//============================================================================
#define cnObject_AngleFinderID 10000
#define cnObject_ToyID 10001
#define cnObject_AnchorID 10002
#define cnObject_JegasID 10003
// For Applications to Use
#define cnObject_TempID 10004
//============================================================================
// Set this to highest RESERVED Image #
#define cnObject_LastIDAtStartUp 10005
#define cnObject_HighestUsableID 20000
//============================================================================


The above modified JGC_OBJECT.h snippet would allow the follow program to run
safely – showing how integration can happen smoothly:

[JGC Integration Example]
#include <DarkGDK.h>
#include "jfc_common.h"
#include "jgc_configuration.h"
#include "jgc_common.h"
void DarkGDK(void){
  JGC::Daddy = new JGC_DADDY();
  JGC::Daddy->Init();
  JGC::ObjAnchor->Exclude_Set(true);   // this is my 3d World Home Marker at position 0,0,0

 dbMakeObjectCube(100,10); // Not an ID in our modified Object ID range for JGC
 // but now I WISH I had the ease of the JGC_OBJECT class to manipulate my cube...
 // so I just pass my ID into the constructor and the object factory doesn't generate
 // anything. The ID you pass is used instead - though the object gets DELETED! AHH!
 // So Pass a ZERO in this CASE then manhandle the ID!
 JGC_OBJECT *Obj=new JGC_OBJECT(0);
 Obj->ID=100;

 // Now I can do things like...
 Obj->Emissive_Set(dbRGB(200,0,0));
 // Autocam default is off.. so I need to move our cube so we can see it
 Obj->Move(50);
     Obj->RotateX(30);

     // Now Just remember, when you delete the Obj via delete Obj; It does
     // destroy your object!
     while(LoopGDK()){
        JGC::Daddy->Update(); // Not needed just to use log file. ..
                              // but you need to sync yourself then, without it.
     };
     delete JGC::Daddy;
};


Also, another design paradigm of importance that’s advantageous is just like in native
DarkGDK you can invoke dbDeleteObject(MyID); and then use MyID again, the
JGC_OBJECT class (and most DarkGDK entity classes) has a simple delete method that
does the same exact thing. Example:

 Obj->Delete(); // just deletes the DarkGDK object, not the class itself the ID is
preserved in the class.

There is also a new flag that in many of the GDK entities in the JGC classes that can be
set to prevent the GDK object (for example) from getting deleted when you delete the
class. The default is to delete the GDK object when the class for it in JGC is destroyed.
The new flag is called: bool PreserveGDKEntityWhenThisClassDestroyed;

Example:
     MyObj-> PreserveGDKEntityWhenThisClassDestroyed=true;
     Delete MyObj;

This example would allow the JGC class to be destroyed but not the GDK object
associated with it (if there is in fact one of course – the key is the ID number naturally.)

There is one more Integration Piece we’ll cover:
                         JGC::Daddy->Update();
What does this do?
            1. Updates DarkPhysics if you have it installed
            2. Updates Objects Registered in Frustrum Culling System
            3. Updates JGC::Clock Class instantiation which keeps a copy of the time in
                both integer and float formats so you don’t need to keep doing int to
                float conversions in your code.
            4. Stores the angles and position of camera zero
            5. Polls the mouse and keyboard (Only certain keys see
                JGC_USERINPUT.cpp for details)
            6. Calls dbSync()

If you want to disable any of these sub systems, its pretty easy. Here is the JGC_DADDY
class’ Update() method found in JGC_DADDY.cpp:

//----------------------------------------------------------------------------
void JGC_DADDY::Update(void){
//----------------------------------------------------------------------------
  JGC::DarkPhysics->Update();
  JGC::Cull->Update_Cull_Objs();
  //dbUpdateTerrain();

     JGC::Clock->Update();
     JGC::Cam0->Update();
     JGC::UserInput->Update(JGC::Clock->Time_New);

     try{
        dbSync();
     }catch(...){
        int STOP=0;
     };
        };
        //----------------------------------------------------------------------------

        To summarize, you can integrate the Jegas Game Classes fairly easily, Recycle DarkGDK
        entity ID’s as well as Class Instances themselves to help enable you to have a lot of
        much flexibility and control over CPU processes.

        This is a complex and integrated code library, however it’s actually pretty easy to control
        how it works, and the design paradigm for all the DarkGDK entity classes in JGC are
        pretty consistent throughout. This makes it so getting familiar with how the
        JGC_OBJECT class works will help you using the JGC_IMAGE and other DarkGDK
        entity class wrappers.


How about the GUI!
        Well, it helps if you’ve done GUI programming before with either the Win32 API directly,
or Visual Basic, VB.Net, C#, Delphi, Lazarus or some other event driven GUI programming.
However, I’ve included a 2nd GUI demo into the release that uses each of the controls and the
source code is plugged with comments to assist you. So I recommend starting there.




        Here is a picture of the Demo GUI 2 (How To) project running


HOW DID I APPROACH THIS?
     Some of the comments I heard from the new comers who helped me test this out were
     complimentary however I perceived they were overwhelmed by the shear quantity of
        code they saw when they looked at JGC and I thought to myself that this is only a
        library, it’s not even a level editor yet let alone a game. I wouldn’t want to make any
        comment that would discourage them but what could I say to encourage them? I just
        tried to learn one thing at a time. I didn’t know C++ all that well when I started with
        DarkGDK. How do I do it? What did I do first? I Remember!

                                dbPrint(“Hello World!”);

Note: All Source code in this Getting started guide can be found in the JGC Library Version 2.0
release here: http://code.google.com/p/darkgdkoop/
                                                                  --Jason P Sage – Jegas, LLC

								
To top