1 / 36

Sage Demo 3 Objects

Sage Demo 3 Objects. SAGE Lecture Notes Ian Parberry University of North Texas. SAGE Demo 3. The goal of this demo is to add four types of objects into the game A plane A crow A silo A windmill. Key Topics. Game Objects Game Object Management Generators. Game Objects Overview.

zamir
Télécharger la présentation

Sage Demo 3 Objects

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Sage Demo 3Objects SAGE Lecture Notes Ian Parberry University of North Texas

  2. SAGE Demo 3 • The goal of this demo is to add four types of objects into the game • A plane • A crow • A silo • A windmill

  3. Key Topics • Game Objects • Game Object Management • Generators

  4. Game Objects Overview • Base Object – Defines an interface for creating new objects, and manages some of the features • Derived Objects – These are the actually objects. They inherit the base object and implement its classes

  5. Base Game Object • Parts – The game objects are split into 1 or more parts. This allows you to animate individual parts of a model • Example: The plane is made up of two parts, the body and the propellers. This is done so that the propellers can spin independently of the plane

  6. Base Game Object Cont. • Process and Move – Virtual functions used to handle the positioning and moving of an object • process() – Implement non-movement logic by overriding the process function • AI is a good example of what to do here • move() – Should handle the updating of the objects position • The move functions handles normal forward motion for you, but you’ll want to override it if you want to handle more complex movement such as strafing void GameObject::move(float dt, bool savePreviousState)

  7. Base Game Object Cont. • move() Cont – The default implementation performs the following functions • Saves the previous state • Sets the orientation and displacement if(savePreviousState) { m_oldPosition = m_v3Position[0]; m_oldOrient = m_eaOrient[0]; } //orientation float rotStep = dt; for(int i=0; i<m_nNumParts; i++){ m_eaOrient[i].heading += m_eaAngularVelocity[i].heading * rotStep; m_eaOrient[i].pitch += m_eaAngularVelocity[i].pitch * rotStep; m_eaOrient[i].bank += m_eaAngularVelocity[i].bank * rotStep; } //displacement Vector3 bDisplacement(0, 0, 20.0f * dt * m_fSpeed); RotationMatrix Matrix; Matrix.setup(m_eaOrient[0]); Vector3 addend = Matrix.objectToInertial(bDisplacement); m_v3Position[0] += Matrix.objectToInertial(bDisplacement);

  8. Base Game Object Cont. • move() Cont – The default implementation performs the following functions • Animates the object if there is more then one frame if(m_nNumFrames > 1) { m_fCurFrame += dt * ((AnimatedModel*)m_pModel)->numFramesInAnimation() * m_animFreq; Matrix4x3 world, modelOrient; world.setupLocalToParent(m_v3Position[0], m_eaOrient[0]); modelOrient.setupLocalToParent(Vector3::kZeroVector,m_modelOrient); world = modelOrient * world; ((AnimatedModel*)m_pModel)->selectAnimationFrame(m_fCurFrame, 0, *m_vertexBuffer, m_boundingBox, world); }

  9. Base Game Object Cont. • render() – Handles basic rendering of the object based on the following assumptions • If there is no model associated with the object, nothing is drawn • If there are multiple parts to the object, the object is assumed to be articulated • If there are multiple frames associated with the object, it is assumed that the object is animated • If these assumptions don’t work for you, then you need to override the render function with your own functionality. if (m_nNumParts > 1)//articulated model ((ArticulatedModel*)m_pModel)->renderSubmodel(0); else if (m_nNumFrames > 1)// animated model ((AnimatedModel*)m_pModel)->render(m_vertexBuffer); else m_pModel->render(); //vanilla model for (int i=1; i<m_nNumParts; i++){ gRenderer.instance(m_v3Position[i], m_eaOrient[i]); ((ArticulatedModel*)m_pModel)->renderSubmodel(i); gRenderer.instancePop(); // submodel i }

  10. Base Game Object Cont. • AABB – At any time, you can query the object for its bounding box. AABBs will be covered in the next demo • Name and ID – You can set the name and id of an object manually or you can let the object manager do it for you • Note: Every object must have a unique id and a unique name • The name and ID Generators will be covered later

  11. Base Game Object Cont. • Type (Class ID) – Identifies the type/class of an object at runtime. The values shown in the following enumerations can be assigned to an objects m_Type value to specify its type. • Life State – Used by the object manager to manager the object. namespace ObjectTypes { enum ObjectType { PLANE = 0, CROW, TERRAIN, WATER, SILO, WINDMILL }; };

  12. Derived Game Objects • The following derived objects are currently implemented in the Ned3D game. • Silo – Static game object otherwise known as furniture • process() – Overwritten to do nothing since the silo does nothing • move() – Calls the base move class to put the silo in its position • Windmill – Same as the Silo except one key difference. The fan on the windmill moves • Crow – A moveable game object • process() – Overwritten to determine the flight path of the crow • move() – Overwritten to move the crow along its flight path

  13. Derived Game Objects Cont. • Silo – Static game object otherwise known as furniture • process() – Overwritten to do nothing since the silo does nothing • move() – Calls the base move class to put the silo in its position • Windmill – Same as the Silo except one key difference. The fan on the windmill moves

  14. Derived Game Objects Cont. • Crow – Moves around the screen using simple AI and uses an animated model • move() – The move functions has been overridden to implement the flight path for the crow. • Circular flight path • Straight flight path – Requires only a call to the move() base class Vector3 right(m_v3Position[0].x - m_circleCenter.x, m_circleCenter.y, m_v3Position[0].z - m_circleCenter.z); const Vector3 &up = Vector3::kUpVector; Vector3 forward = up.crossProduct(right); if(!m_circleLeft) { forward *= -1.0f; right *= -1.0f; }

  15. Derived Game Objects Cont. • Plane – The plane needs to able to respond to input in order to perform the following actions • Turn Left • Turn Right • Climb • Dive • Change Speed • Each of these actions is handled by a separate function

  16. Derived Game Objects Cont. • Plane Cont. – Three other functions exists to handle the planes movement. • inputStraight – Straightens out the plane • inputLevel – Levels out the plane • inputStop – Stops the plane

  17. Derived Game Objects Cont. • Plane Cont. • process() – Checks for keyboard and joystick input and process it before passing the data along to the move function • move() – Updates the planes position based on the information saved by the process function. switch(m_turnState) { case TS_LEFT: { planeOrient.heading -= m_maxTurnRate * m_turnRate * dt; if(planeOrient.bank < kPi * 0.25f) planeOrient.bank += m_maxBankRate * m_turnRate * dt; } break; case TS_RIGHT: { planeOrient.heading += m_maxTurnRate * m_turnRate * dt; if(planeOrient.bank > kPi * -0.25f) planeOrient.bank -= m_maxBankRate * m_turnRate * dt; } }

  18. Derived Game Objects Cont. • Special Objects – The terrain and water objects don’t benefit much from being objects, but it lets object manager manage them and results in a cleaner design.

  19. Base Object Manager • The base object manager performs the following functions • Add/Remove objects • Process/Move objects • Render objects • Track objects

  20. Add/Remove Objects • addObject() – Adds an object to the manager using the following parameters • GameObject *object – A pointer to the object being added • bool canMove – Specifies whether this is a movable object • bool canProcess – Specifies whether this object should be processed • bool canRender – Specifies whether this object should be rendered • std::string* name – The name given to the object unsignedint GameObjectManager::addObject(GameObject *object, bool canMove, bool canProcess, bool canRender, const std::string *name)

  21. Add/Remove Objects Cont. • addObject() Cont. • Inserts the object into the process lists based on the Booleans specified unsignedint GameObjectManager::addObject(GameObject *object, bool canMove, bool canProcess, bool canRender, const std::string *name) { assert(object != NULL); if(object->m_manager == this) return object->m_id; assert(object->m_manager == NULL); object->m_manager = this; m_objects.insert(object); if(canMove) m_movableObjects.insert(object); if(canProcess) m_processableObjects.insert(object); if(canRender) m_renderableObjects.insert(object);

  22. Add/Remove Objects Cont. • addObject() Cont. • Checks if there is a name, and creates one if there isn’t, otherwise it checks for a conflicting name. If a conflicting name is found, a name generator determines a new name for it based on the name given. • Return the unique unsigned integer ID assigned to the object by the object manager if(name == NULL || name->length() == 0) object->m_name = m_objectNames.generateName(object->m_className); elseif(m_objectNames.requestName(*name)) object->m_name = *name; // Requested name accepted else object->m_name = m_objectNames.generateName(*name); // Append number to requested name // Ensure new object status object->m_lifeState = GameObject::LS_NEW; // Add id and name mappings m_nameToID[object->m_name] = object->m_id; m_idToObject[object->m_id] = object; return object->m_id; }

  23. Add/Remove Objects Cont. • deleteObject() – Removes the object from the object manager void GameObjectManager::deleteObject(GameObject *object) { if(object == NULL) return; m_nameToID.erase(object->m_name); m_idToObject.erase(object->m_id); m_objectIDs.releaseID(object->m_id); m_objectNames.releaseName(object->m_name); m_objects.erase(object); m_movableObjects.erase(object); m_processableObjects.erase(object); m_renderableObjects.erase(object); object->m_manager = NULL; delete object; }

  24. Ned3D Object Manager • The Ned3DObjectManager is derived from the base object manager, and is responsible for spawning the specific objects in Ned3D using the following functions • spawnPlane() • spawnCrow() • spawnSilo() • spawnWindmill() • spawnWater() • spawnTerrain()

  25. spawnPlane unsigned int Ned3DObjectManager::spawnPlane( const Vector3 &position, const EulerAngles &orientation) { if(m_plane != NULL) return 0;// Only one plane allowed if (m_planeModel == NULL) m_planeModel = m_models->getModelPointer("Plane");// Cache plane model if (m_planeModel == NULL) return 0;// Still NULL? No such model m_plane = new PlaneObject(m_planeModel); m_plane->setPosition(position); m_plane->setOrientation(orientation); unsigned int id = addObject(m_plane, "Plane"); return id; }

  26. spawnCrow • There are two spawn crow functions, one to spawn a straight flying crow, and one to spawn a circling crow. unsigned int Ned3DObjectManager::spawnCrow(const Vector3 &position, const EulerAngles &orientation, float speed) { if(m_crowModel == NULL) m_crowModel = m_models->getModelPointer("Crow");// Cache crow model if(m_crowModel == NULL) return 0; // Still NULL? No such model CrowObject *crow =new CrowObject(m_crowModel); crow->setSpeed(speed); crow->setPosition(position); crow->setOrientation(orientation); crow->setMovementPattern(CrowObject::MP_STRAIGHT); unsigned int id = addObject(crow); m_crows.insert(crow); return id; }

  27. spawnTerrain/Water unsigned int Ned3DObjectManager::spawnTerrain(Terrain *terrain) { m_terrain = new TerrainObject(terrain); return addObject(m_terrain, false, false, false, "Terrain"); } unsigned int Ned3DObjectManager::spawnWater(Water *water) { m_water = new WaterObject(water); return addObject(m_water, false, false, false, "Water"); }

  28. spawnSilo unsigned int Ned3DObjectManager::spawnSilo(const Vector3 &position, const EulerAngles &orientation) { static const std::string silos[] = {"Silo1","Silo2","Silo3","Silo4"}; static int whichSilo = 0; m_siloModel = m_models->getModelPointer(silos[whichSilo]);// Cache silo model if (m_siloModel == NULL) return 0;// Still NULL? No such model SiloObject *silo =new SiloObject(m_siloModel); silo->setPosition(position); silo->setOrientation(orientation); unsigned int id = addObject(silo); m_furniture.insert(silo); whichSilo = ++whichSilo % 4; return id; }

  29. spawnWindmill unsigned int Ned3DObjectManager::spawnWindmill( const Vector3 &position, const EulerAngles &orientation) { if (m_windmillModel == NULL) m_windmillModel = m_models->getModelPointer("Windmill");// Cache windmill if (m_windmillModel == NULL) return 0;// Still NULL? No such model WindmillObject *windmill =new WindmillObject(m_windmillModel); windmill->setPosition(position); windmill->setPosition(Vector3(0,27.0f,-0.5f),1); windmill->setRotationSpeedBank(kPiOver2,1); windmill->setOrientation(orientation); unsigned int id = addObject(windmill); m_furniture.insert(windmill); return id; }

  30. Tether Camera • When a camera is made to follow specific object, it is called a tether camera • Our tether camera is made to always be the same distance from any object • The process() functions handles the positioning of the camera based on the position of the object it is attached to

  31. Tether Camera Cont. • process() • First, we get the position of our targeted object • We increment the y value by 3.0 to keep the object from blocking our view of the rest of the screen targetHeading = obj->getOrientation().heading; target = obj->getPosition(); target.y += 3.0f;

  32. Tether Camera Cont. • process() Cont. • Next we compute the vector from the camera to the target and the distance of that vector • Using this information, we can compute the cameras position // Compute current vector to target Vector3 iDelta = target - cameraPos; // Compute current distance float dist = iDelta.magnitude(); // Get normalized direction vector Vector3 iDir = iDelta / dist;

  33. Tether Camera Cont. • process() Cont. • Now we clamp the distance within our limits and compute the camera’s position • Then we just need to re-compute the camera heading, pitch, and bank // Clamp within desired range to get distance // for next frame if (dist < minDist) dist = minDist; if (dist > maxDist) dist = maxDist; // Recompute difference vector iDelta = iDir * dist; // Compute camera's position cameraPos = target - iDelta; // Compute heading/pitch to look in given direction cameraOrient.heading = atan2(iDir.x, iDir.z); cameraOrient.pitch = -asin(iDir.y); cameraOrient.bank = 0.0f;

  34. Generators • The generators are used to create unique identifiers and names for the objects in the game • There are two generators used in the SAGE engine • ID Generator – Generates a unique identifier. These numbers are stored in a hash set to make it easier to determine when numbers have already been used • Name Generator – Generates a unique name based on a base name given to the generator • Ex: Every time the name generator is asked to generate a name, it appends a number to the end of that name. A counter is kept for all the name bases to keep these numbers unique. • So, if you generated 4 objects with the name crow, their names would be “Crow”, “Crow1”, “Crow2”, and “Crow3”

More Related