Lab2 The game loop and animations
In this lab is divided in three parts.
· In the first part we will explore the software design for implementing a character in your game.
· In the second part we will go trough the process of animating objects using the update method.
· In the third part we will be loading animations from the .skeleton file
Part 1: Character abstraction
For the Coursework: download this source code(demo4), and complete the classes Stats and ModelElement as it is described in each class method. In your game project implement the Player, PlayerController, PlayerModel, PlayerStats using the framework provided and suggested software design. A .uml file is contained in the archive you just downloaded, you can open it using WhitestarUML (DO NOT try to print it it will not work).
The player model must:
1. Be implemented using an instace of the ModelElement class for each part of the final model;
2. Have the same sub scene graph as at the end of the previous lab;
3. Have a method that allows to attach a node to the gun group node.
Check the Coursework notes on the Player and Player Model classes.
Part 2: Animating using the UpdateScene method
MOGRE allow us to rotate objects using three methods called yaw pitch and roll, that fill up the rotation matrices around the coordinate axes. Yaw pitch and roll correspond to rotations about coordinate axes as in the following figure:
Play with the Pitch, Roll and Yaw method in the Robot class to make the robot rotate around different axes.
So far we rotated an object around one of the coordinated axes, if you want to rotate an object around an arbitrary axes you need to use a unitary quaternionand the Rotate method of the node. Without going in too many mathematical details a unitary quaternion is a mathematical entity capable of encode rotations about arbitrary axes. MOGRE allows us to use quaternions through the Quaternion class whose constructor is overloaded to accept the direction about to which rotate and an angle.
In the Robot use the Rotate method of the node to rotate the robot about an arbitrary axis using quaternions.
Part 3: Using pre-animated meshes
Watch the following video. The source code is the same as before, just uncomment the code in the Part2 regions in the .cs files.
Play with the code provided and try to make more than one animation run at the same time activating two or more animation states together.
Coursework Notes on: the Player and PlayerModel classes
print full screen
Player Class
The player class inherits form Character and it is in charge of initializing the fields from that class (open the Character class and study it). In the constructor of the Player Class you should initialize the fields:
– model to an instance of the PlayerModel (which you have to implement. See the following);
– controller to an instance of PlayerController, the this object (self reference keyword) should be passed as parameter to the PlayerController constructor (leave it for now we will do this next lab);
– stats to an instance of PlayerStats (leave it for now we will do this next lab);
The player class also override the Update method and the Shoot method of the Character class.
In the Update method you should call the methods Animate from the model object. Leave the Shoot method empty for now.
PlayerModel Class
The PlayerModel class inherits from the CharacterModel class, it contains a ModelElement object for each node in the player scene-graph.
After you define the ModelElements you should initialize them in the LoadModelElements method which should be overridden from the CharacterModel class.
The assembling of the scene manager should happen in the AssembleModelElements method, which is again overridden from the CharacterModel class.
Once you create a ModelElement object for each node in the player scene-graph and you initialize and assemble them you should initialize the gameNode of the PlayerModel class to the gameNode in the ModelElement model object, i.e. gameNode=model.GameNode;
The PlayerModel class should have a constructor which take as parameter of type SceneManager named mSceneMgr.
In the body of the constructor you should initialize the this.mSceneMgr field to the parameter just passed and then call the methods LoadModelElements and AssembleModelElements.
You should also override the DisposeModel method form the CharacterModel class. In the body of this method you should call the Dispose method from each one of the ModelElement you created in this class.
Lab 3 – The camera and Inputs Processing
print full screen
This lab is divided in two parts:
· In the first part we will see how to customize the camera and how to change its internal parameters;
· In the second part we will see how to process keyboard and mouse inputs and apply them to models in MOGRE;
Part 1: The Camera
For the Coursework in your game project set up a camera so that it looks at the player and moves with it as explained in the demo.
Part 2: Inputs Processing
For the Coursework: Import the InputManager class in your game project and modify the ProcessInput method so that it is possible to:
· Control the player using the W, and S keys to move it forward or backward respectively;
· Control the player using the A, and D keys to move it left and right respectively;
· Rotate the player using the mouse so that the player rotate when the left button is held down and the mouse is moved left or right;
In order to do this you have to change the Robot robot field to
PlayerController playerController;
public PlayerController PlayerController
{
set { playerController = value; }
}
and then use the following scheme for the if statements in the ProcessInput method, for example to move Left using the A key:
if (mKeyboard.IsKeyDown(MOIS.KeyCode.KC_A))
playerController.Left = true;
else
playerController.Left = false;
Calling the directions field defined in the CharacterControl class. The ProcessInput method should not call the functions to move or rotate the player, it should just set the values of how much movement or rotation the player should do.
The mouse control is similar to the one you already have in the InputManager class, you only have to change angles.z into angles.y, and the pass the angle vector to the PlayerController as playerController.Angles = angles after the if statements for the mouse.
Set also the keys for shooting and swapping weapons. To do this use the Shoot and SwapGun fields of playerController in the OnKeyPressed method. You should use the spacebar to shoot and the E key to swap weapons.
The InputManager class in implemented using the singleton pattern, in order to use it you should call the static Instance field from the class
InputsManager inputsManager = InputsManager.Instance;
The class should be used in the CreateScene method of the Mogre tutorial framework. In the class which contains that method you should define and initialize the inputsManager field as previously said and then in the CreateScene method you should set the PlayerController property of the inputsManager object to player.Controller, remember to cast it to PlayerController : (PlayerController)player.Controller.
Check the Coursework notes on PlayerController and PlayerStats classes. Also implement the PlayerStats class
Coursework Notes on: the PlayerController and PlayerStats classes
print full screen
PlayerController Class
The PlayerController class inherits from the CharacterController class (open it and study it).
The constructor should get as parameter an object of type Character named player (open the Character class and study it).
In the constructor you should initialize the field speed to 100 and the character field to the parameter player.
The PlayerController class overrides the Update method inherited from the CharacterController class. In the body of the method you should call three methods:
MovementsControl(evt)
MouseControls()
ShootingControls()
You should implement these methods as follows:
Implement a private void method named MovementsControl which takes as parameter FrameEvent evt.
In the body of the method you should read the bool fields in the character controller class which represents directions. If the bool is true update the move field adding or subtracting the correct direction form the character.Modelobject, remember that the backward = – forward, right = – left, and so on…
The scheme should be:
if (forward)
move += character.Model.Forward;
where move is a local variable defined inside the method MovementsControl, move is of type Vector3 and must be initialized to the zero vector (use Vector3.ZERO).
After the if statements, update the move local variable so that it contains a normalized copy of itself (use the NormalizedCopy property of move) multiplied by the speed field.
Check also the bool field accelerate and if true multiply move by two.
Finally check the move field if it is not zero (use Vector3.ZERO) and if it is not call the Move method from character and pass the move field multiplied by evt.timeSinceLastFrame.
Implement a private void method named MouseControls(). In the body of the method retrieve the Model.GameNode of the character object and make it yaw about the value contained in angles.y using the Yaw method. Notice that the methods requires radians to work properly, you can convert the value in angles.y into radians using Mogre.Math.AngleUnitsToRadians(angles.y).
Implement a private void method ShootingControls(), leave it empty for now, it will be your responsibility to fill it later to implement the shooting.
Once you finish to implement this class go back to the Player class and initialize the field controller in the Player constructor, check the Coursework notes on Player and Player Model classes.
As parameter for the constructor of the PlayerController class pass the this keyword.
In the Update method in the Player class call the Update method from the controller object.
In the MovableElement class implement the Move and Rotate methods.
PlayerStats
The PlayerStats class inherits from CharacterStats and extends it adding a score field of type Stat (open both classes and study them) remember to add a get property for the field.
To implement the score field you should create a new class Score which inherits from Stat and override the Increase method so that the value field is increased by val without doing any check.
In the PlayerStats class override the InitStats() method making sure that the overriding method has as first line of code calls base. InitStats(). In the overriding method create a new Score object to initialize the score field, then use the InitValue method to initialize the fields score, health, shield, and lives to 0, 100, 100 and 3 respectively.
Lab 4 – Textures and Overlays
print full screen
This lab is divided in two parts:
· In part one we will see how to apply texture through MOGRE code and how to accomplish the same task using material scripts;
· In part two we will see how to generate screen overlays using MOGRE code and how to accomplish the same task using overlay scripts;
Part 1: Texturing and Material Scripts
Part 1a: Textures using C# code
Download the following Cube class, add it to the project and modify the cube adding texture coordinates in such a way that each face has texture coordinates (0,0), (1,0), (0,1), (1,1) in its vertices, draw the cube on a piece of paper to help your thinking. To assign texture coordinates to a vertex use the .TextureCoord(u, v) method of the ManualObject immediately after the vertex declaration.
In the Turorial.cs file, generate an Entity and a SceneNode to load and attach the cube to the SceneGraph. In order to do so, create a field Cube cube and in the CreateScene method write the following code:
cube = new Cube(mSceneMgr);
MeshPtr cubePtr = cube.getCube(“myCube”, “Dirt”, 10, 10, 10);
cubeEntity = mSceneMgr.CreateEntity(“Cube_Entity”, “myCube”);
cubeNode = mSceneMgr.RootSceneNode.CreateChildSceneNode(“Cube_Node”);
cubeNode.AttachObject(cubeEntity);
Apply a texture to the cube as in the video demo.
Part 1b: Textures using Material Scripts
More about material scripts:http://www.ogre3d.org/docs/manual/manual_14.html
Parameters specifications for techniques at: http://www.ogre3d.org/docs/manual/manual_15.html#Techniques
Parameters specifications for passes at: http://www.ogre3d.org/docs/manual/manual_16.html#Passes
Parameters specifications for texture_units at: http://www.ogre3d.org/docs/manual/manual_17.html#Texture-Units
For the Coursework: Modify the materials of the meshes given in the assets as you wish. You can change the diffuse color, specular value, ambient value and so on, consult the manual for a list of parameters you can change.
Part 2: Overlays and Overlay Scripts
More on Overlays at: http://www.ogre3d.org/docs/manual/manual_12.html#Overlays
More on Overlays scripts at: http://www.ogre3d.org/docs/manual/manual_41.html#Overlay-Scripts and following subsections of the OGRE manual.
More on Overlays and Overlays Scripts at: http://www.ogre3d.org/tikiwiki/Mogre+New+Basic+Tutorial+6
For the Coursework: Implement the interface for your game and link it to the game.
Coursework notes on: Enemies
print full screen
Mimicking what done with the Player class implement the enemies for your game. The suggested UML diagram shows which classes to implement for the enemies and their AI.
Lab 5 – Shaders
print full screen
This lab is divided in three parts:
· In the first part we will have a look on how to use shaders in MOGRE;
· In the second part we will having a look to simple examples of shaders;
· Finally in the third part we will see how to debug HLSL shaders;
Please note that no source code is provided for this lab.
You can find more information about HLSL at the following link: http://msdn.microsoft.com/en-us/library/windows/desktop/bb944006(v=vs.85).aspx
Watch all the demos before doing anything
Part 1: Material Scripts and Shaders
Watch now the following demo. Please be aware that this and the following are archive videos and that the demo numbering is different from the one followed until now, just ignore it.
To make it easier for you to code in HLSL download this user defined syntax highlighting, unzip it in your project folder, to install it follow these steps:
· Open Notepad++;
· In the View menu choose User-Defined Dialogue…;
· Choose Import in the window that opens;
· Choose the file you unzipped earlier;
· Click OK on the message window that appears;
· In User language choose HLSL;
· In Ext change fx to hlsl;
· Close the window;
In Notepad++ create a new file and save it in the Media\materials\scripts folder as a materialWithShadersTest.material file.
Without closing the file you just created, create now two other new files and save them respectively as vertexShaderTest.hlsl and pixelShaderText.hlsl in the Media\materials\programs folder.
In the materialWithShadersTest.material generate a new material as explained in Demo 14 setting the vertex and fragment programs references and a texture unit which refers to the Dirt.jpg texture.
Define the shaders programs at the start of the file, before the material definition, and use for the vertex program as source the vertesSaderTest.hlsl file with target vs_1_1 while for the fragment program use the pixelShaderTest.hlsl file with target ps_2_0, set the entry points for both to main.
In order to be able to pass parameters to the shaders define the default_params block in both program definitions and set for the vertex program the worldviewproj matrix.
More information about setting up shaders using material scripts at: http://www.ogre3d.org/docs/manual/manual_18.html#Declaring-Vertex_002fGeometry_002fFragment-Programs
More information about setting up HLSL shaders through material scripts at: http://www.ogre3d.org/docs/manual/manual_20.html#HLSL
More on passing parameters to shaders at: http://www.ogre3d.org/docs/manual/manual_23.html#Using-Vertex_002fGeometry_002fFragment-Programs-in-a-Pass
Geometry Shaders do not work in MOGRE (yet!)
Part 2: Vertex and Fragment shaders examples
The following is the kick-start code you need for play with The Vertex Shader
struct VS_OUTPUT {
float4 pos: POSITION;
float2 texCoord0: TEXCOORD0;
};
float4x4 worldViewProj;
VS_OUTPUT main( float4 Pos: POSITION, float3 normal: NORMAL,
float2 texCoord0: TEXCOORD0 )
{
VS_OUTPUT Out;
Out.pos = mul(viewProj, Pos);
Out.texCoord0 = texCoord0;
return Out;
}
The following is the kick-start code you need for play with The Fragment Shader
float4 main(float2 texCoord0: TEXCOORD0): COLOR0
{
return float4(1.0,0,0,0);
}
More on the compositor can be found at: http://www.ogre3d.org/docs/manual/manual_29.html#Compositor-Scripts
Try to modify the vertex and fragment shaders to reproduce what has been shown in the videos.
Part 3 – Debugging HLSL Shaders
In order to be able to debug your HLSL shaders you need to download the following file FXC, and unzip it in the folder Media\materials\programs of your project.
In the FXC folder you will find two sub-folders, if you are using a 64 bit machine, as those in the lab, you should use the file inside the folder x64. If you are working in your personal machine and it does not have a 64 bit architecture use the file in the x86 folder.
fxc.exe is a compiler for effects written in HLSL, it works using the command prompt. To debug a .hsls file you have to copy the file in the same folder of the fxc.exe program or alternatively you have to specify the full path to your shader. I suggest to make a copy of your shader in the same folder as fxc.exe.
Copy your shader in the same folder as the fxc.exe version you want to use.
Bring now up the command prompt write cmd in the Search programs and files in your start menu, navigate the folders until you reach the fxc.exe folder. To navigate so use a combination of the following DOS/Unix commands:
cd.. it allows you to go up one level, for example if you are in C:\Folder1\Folder2\ writing cd.. will bring you in C:\Folder1\;
cd
cd\ it brings you to the root of your drive, for example if you are in C:\Folder1\writing cd\ will bring you to C:\.
dir it allows you to know the content of a folder, for example if you are in the folder C:\Folder1\ writing dir will bring up the list of all the files contained in Folder1.
< Name of Drive>: it brings you inside that hard drive, for example if I am in C:\Folder1\ and I want to move to my USB drive called E, I have to type E:
You can quickly reach the folder which contains fxc.exe using the cd command followed by a space and copying and pasting the path from the window bar to the cmd window using the mouse.
Once you reached the fxc.exe folder using the command prompt you can run the compiler using the following syntax:
fxc.exe /T
for example if I want to debug a vertex shader using shader model 1.1 and my shader is in the myshader.hlsl file and the entry point is vs_main I have to type:
fxc.exe /T vs_1_1 myshader.hlsl /E vs_main
notice the use of / in front of the commands T and E.
If successful you should obtain a screen similar to the following:
fxc lists the parameters and the GPU registers used in your shader, tell you which shader profile you are using, in our case the first yellow line says vs_1_1, followed by the sequence of assembly instructions your code has been converted into.
If instead your the compiling is unsuccessful you will get an error explaining what went wrong, as for example in the following two screenshots, where in the first case the semantic for the texture coordinate has been miss-typed and in the second case a variable has been miss-typed. Notice the two numbers in brackets after the name of the file, these two numbers are respectively the line on which the error has occurred and the character in that line on which the wrong command starts.
Coursework Notes on: Collectables, Guns and Projectiles
print full screen
Implementing Collectables
Download this archive, unzip it and import the classes in your game project.
Notice that there is a UML diagram in the archive, this is an amend to the complete diagram. The projectile mechanics has been slightly simplified and an error in naming has been corrected.
The archive contains the abstract classes you should use to generate, guns, projectiles, gems and power ups.
Spend some time trying to understand them and the UML diagram. For the final assignment you need to generate concrete classes from the abstract classes.
In particular for the Basic Game you need at least one gem type, you can choose how much score the gems give when collected.
For the extra 10% you need at least one power up type, you can choose what the power up does.
For the extra 12% you need at least one gun type and one projectiles type. You can choose which model to use for the gun and the projectiles, and how much shield and health damage the projectiles inflict.
Read the following for implementation details.
Obviously the more types you implement and the more you make the game interesting the higher the mark will be.
Implementing Gems
To implement gems you need to generate a new class for each type of gem you want to create in your game.
The class should inherit from the Gem class.
The constructor of the class should take as parameters the scene manager and the player statistic the Gem changes, i.e. if the gem affects the score of the player it should receive as parameter a Stat object called score. The class constructor should call the base constructor using :base(mSceneMgr, score) immediately after the parameters list of the constructor and before its body of starts.
In the body of the constructor you should initialize the increase field inherited from Gem and call the LoadModel method.
The class should override the LoadModel method from Gem. In the LoadModel method you first call the LoadModel form the base class, base.LoadModel(), and then you should load the geometry for the power up and the scene graph nodes for it using as usual the gameNode and gameEntity.
In lab 7 in the LoadModel method in the Gem class,you should initialize the physics engine object PhysObj, and add a gravity and friction forces to it. At the end of the LoadModel of the children classes you should pass the gameNode to the physObj through the property SceneNode of the physics object.
In lab 7 still in the Gem class you should write in the the Update method the code for collision detection with the player as explained in the video, just use the remove field from Collectable setting it to true, use the method Increase from the score object to change the score and add a Dispose() call before the break statement.
Implementing Power Ups
To implement Power Ups you need to generate a new class for each type of power up you want to create in your game.
The class should inherit from the PowerUp class.
The constructor of the class should take as parameters the scene manager and the player statistic the power up changes, i.e. if the power up affects the health of the player it should receive as parameter a Stat object called Health. The class constructor should call the base constructor using :base(mSceneMgr) immediately after the parameters list of the constructor and before its body of starts.
In the body of the constructor you should initialize the stat field inherited from PowerUp and the increase field also inherited from PowerUp.
The class should override the LoadModel method from PowerUp. In the LoadModel method you should load the geometry for the power up and the scene graph nodes for it using as usual the gameNode and gameEntity.
In lab 7 you should initialize the physics engine object PhysObj, and pass the gameNode passed to it through the property SceneNode of the physics object, finally add a gravity force to it.
Also in lab 7 in the PowerUp class you should write in the the Update method the code for collision detection as explained in the video, just use the remove field from Collectable setting it to true, use the Increase method from the stat object and add a Dispose() call before the break statement.
EXTRA: You may have noticed that there is some code duplication in the PowerUp an Gem classes and their children, you may want to transfer some parts of the duplicated code into a new class which inherits from the Collectable class and make the Gem and PowerUp classes inherit from this new class.
Implementing Guns and Projectiles
Projectile types
Projectile types should inherit from the Projectile class. You need a different class for each projectile type you want to implement in your game.
The constructor of a projectile type must:
– take as parameter the mSceneMg;
– initialize the scene manager field to the parameter;
– set the value for healthDamage;
– set the value for shieldDamage;
– set the speed of the projectile;
– Call the Load method;
In the class override the Load method, in its body initialize the gameEntity, and the gameNode for the projectile, you may want to use the ModelElement class for this. You may want to scale down the size of the projectile models, you can do this using the Scale method from the gameNode.
(In lab 7 initialize the physics object add a weight force to it, set its sceneNode property to gameNode and change the initial direction setter in the projectile class to
public Vector3 InitialDirection
{
set {
initialDirection = value;
physObj.Velocity = speed * initialDirection;
}
}
).
Guns types
Implement a new class for each type of gun you want to implement in your game, each of these classes must inherit from the Gun class.
The constructor of each class must take as parameter the scene manager:
– Initialize the scene manager to the parameter you just passed;
– Initialize the maxAmmo field to a certain value;
– Initialize the field ammo to a new Stat object;
– Set the initial value of ammo to maxAmmo using the InitValue method of ammo;
– Call the LoadModel method;
Each class must:
– Override the LoadModel() method in which gameNode and gameEntity are initialized and assembled together, DO NOT attach them to the scene-graph. You may want to use the ModelElement class to do this;
– Override the Fire() method, in this method you should check whether ammo.Value is zero, if it isn’t create a new projectile of the correct type for the gun (use the inherited field for this), i.e. if you are implementing a canno then you must have a CannonBall class, if you aer implermenting a bomb dropper you should have a Bomb class, ecc. Set the projectile position as GunPosition()+ a*GunDirection() where a is a number which describes how far from the cannon the projectile will appear, decrease ammo by 1 using the Decrease function.
– Override the method ReloadAmmo(), in this method check whether the ammo.Value is less than maxAmmo, if it is it increase the value to a value of your choice, but that keep the ammo.Value less or equal to maxAmmo.
CollectableGun and Armoury classes
Complete the CollectableGun class to handle collision with the player. Open the CollectableGun class and in the constructor:
– Initialize the mSceneMgr, the gun and the playerArmoury fields to the values passed as parameters
– Initialize the gameNode, scale it by 1.5f using the Scale method, and add as its child the gameNode contained in the Gun object, and, finally, attach the gameNode to the sceneGraph.
(In lab 7 initialize the physics object and add a weight and friction force to it and pass to it the gameNode using the SceneNode property of the phys object.)
In the Update method write the code for collision detection with the player. After you set remove to true you need to write the following two lines of code (gun.GameNode.Parent).RemoveChild(gun.GameNode.Name);
playerArmoury.AddGun(gun);
to detach the gun model from the current node and add it to the player sub-scene-graph. Call Dispose() before the break.
You have noticed that the CollectableGuns uses and Armoury class. You have to implement the Armoury class, and afterwards add it to Player class as a field with a get property.
Create a new class named Armoury.
This class must have a bool field named gunChanged with get and set property, a Gun field named activeGun with get and set property, a list of gun object List
The constructor should initialize the collectedGuns list (new List
Implement a public void Dispose method which dispose of each gun in the collectedGuns list and if the activeGun is not null disposes of it as well.
Implement a public void ChangeGun method which takes as parameter a Gun and stores it in activeGun, it should also set the bool gunChanged to true.
Implement a public void SwapGun method, which takes as parameter an integer index and if the collectedGuns and the activeGun are not null calls the ChangeGun method passing the gun in the collectedGuns in the list which has the index passed as parameter to the method (use the modulo operator and the .Count property of the list to make sure that the index stays in the limits).
Finally implement a public void AddGun method which takes a Gun object named gun as parameter, set a local bool variable named add to true and then for each gun g in the collectedGuns list check whether add is true and whether the type of gun you are passing is in the collected gun list (g.GetType()==gun.GetType()), if they are both true then it calls the reloadAmmo mehtod for g, call the ChangeGun method passing g to it and then set add to false.
Once the for each loop finished check the add variable, if true then call CangeGun method, pass gun to it and add the gun to the collectedGun list, else call the Dispose method from gun.
In the PlayerModel class, if is not there yet, implement a public void AttachGun method which takes a Gun gun as parameter, and in the body checks whether the gunGroupNode has any child ( gunGroupNode.GameNode.NumChildren()!=0) and if it has children call the RemoveAllChildren() methods from its GameNode, outside the body of the if statement add the GameNode of the gun you passed as parameter as child of the GameNode of the gunGroupNode.
In the Player class create a new field playerArmoury with a get property and initialize the field in the player constructor. Override the public void method Shoot() and in its body call the Fire method from the ActiveGun property of the playerArmoury.
In the Update method check if playerArmoury.GunChanged is true and if it is write the following two lines of code
((PlayerModel)model).AttachGun(playerArmoury.ActiveGun);
playerArmoury.GunChanged = false;
try to understand what they do.
Coursework Notes on: Vertex and Fragment Shaders (up to 10 %)
print full screen
Implement a vertex shader animation (worth up to 5%) for an object in your game, for example create a model of a heart, use it for display player lives and make the hearts pulse faster and faster as the player health reduce. To update values passed to the shaders you can use the following piece of code with the appropriate modifications for the parameters and names
\\ Retrieve Material by name
using (MaterialPtr mtrPtr = (MaterialPtr)MaterialManager.Singleton.GetByName(“materialName”)) {
\\ Retrieve pass 0 form the material
Pass pass = mtrPtr.GetTechnique(0).GetPass(0);
\\ Retrieve the shader parameters form the material
GpuProgramParametersSharedPtr parameters = pass.GetFragmentProgramParameters();
\\ sets a parameter in the material (first argument) with the value passed in the second argument
parameters.SetNamedConstant(“shaderParameterName”, variableToPass);
}
In the material make sure the parameter to update is inside the default_params block in the shader program definition, for example
vertex_program shaderProgramName hlsl // or fragment_program shaderProgramName hlsl
{
source shaderSourceCodeFile.hlsl
entry_point MainFunctionName
target AppropriateShaderModel(vs_1_1 , ps_2_0, etc)
default_params
{
param_named shaderParamName paramType paramDefaultValue
}
}
Implement also a fragment shader effect (worth up to 5%).
As a rule of the thumb keep the shader model as low as possible in order to keep compatibility with old hardware so that you can cover a bigger portion of the market with your game, if you want to do something that can be done in vs_1_1 or ps_2_0 do it using those Shader models, if you wan to use a more recent feature then use the lower shader model which implements that feature.
Lab 6 – Environment, Lights and Shadows
print full screen
This lab is divided in three parts:
· In the first part we will have a look at how to create an environment for our game an how to set up a sky and some fog;
· In the second part we will look at lights and how to use the different types of lights in MOGRE;
· In the third part we will look at shadows and how to use different kind of shadows in MOGRE;
Part 1: Environment, sky and fog
For the Coursework: Complete the implementation of the GroundPlane method in the Ground class.
In order to do so you have to create two local variables. One of type Plane plane and the other of type MeshPtr groundMeshPtr.
The variable plane should be initialized to a plane object in the same fashion of the plane used for the sky plane.
The variable groundMeshPtr should be initialized using the MeshManager.Singleton.CreatePlane method. Check the documentation which pop up in visual studio to try to understand how to use the method.
The header for the method is the following:
MeshPtr MeshManager.Singleton.CreatePlane(string name, string groupName, Plane plane, float width, float height, int xsegments, int ysegments, bool normals, ushort numTexCoordSets, float uTile, float vTile, Vector3 upVector)
use the up and down keys to navigate the documentation until you find it. The name should be “ground”, the groupName you should use is
ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME
and the last parameter, upVector, should be Vector3.UNIT_Z.
Import the Environment class and the Ground class in your game project and adapt them accordingly with the UML diagram for the game.
Create also the geometry for the boundaries for your level, and put it in position. It is up to you where and how to create the boundaries geometry, the best way is to create them use the cube class you created in the previous labs. Think, in which class should they be?
Part 2: Lights
For the Coursework: Implement some lights in your game such that the scene is not flatly lighted, use your judgement in placing the lights and in modifying the attenuation and colours attributes as you need.
Part 3: Shadows
For the Coursework: Activate the shadows system for your scene and generate the Edge lists when required, choose the shadows system you think is best for your game.
Coursework Notes: Putting everything together
print full screen
In order to have your game running you need to create an instance of player in the Tutorial class and call the player update method in the UpdateScene function.
When you implement the enemies and all the collectables elements (gems, power-ups, guns, etc…) you need to manage them using the List collection (see also here). Remember to delete the objects you are not using any more from the list as well as from the scene-graph.
You should have the minimum number of lists necessry to make your game running, when creating the list be smart on the type you use to declare the list.
The list management algorithms for the game are up to you to design and implement.
Lab 7 – Collision detection and Physics
print full screen
This lab is divided in two parts:
· In the first part we will see how to set up the physics engine provided and how to complete its implementation;
· In the second part we will talk about collision detection;
Those interested in physics based modelling for games please refer to:
Baraff D., Witkin A., Physics based modelling , ACM SIGGRAPH 2001 Course
For explanation about forces read the Particle Dynamics document.
More advanced reading on the functioning of a Physics Engine is
· Heberly D. E. – Game Physics, Second Edition, Morgan Kaufmann, 2010 (Electronically available in the Library)
While a complete explanation on collision detection can be found in:
· Ericson C. – Real Time Collision Detection, Morgan Kaufmann, 2005
Part 1
Watch now the following video, the code for it can be found here.The archive contains a set of classes which implement a basic physics engine. The engine is incomplete and it is up to you to code the missing bits. The project will not work until you implement the missing bits as described in the following.
For the final assignment:
· Implement the velVerletSolver method and the impulse method in the Physics.cs file as explained in the lecture, definition of the methods are already in place after the C# attributes in the file;
· Implement the compute method for the weight force in the WeightForce.cs file as explained in the lecture, definition for it is already in place at the end of the file;
As we have seen in the lecture the impulse is formulated as follows:
In the physics engine the PhysObj class contains the inverse of the mass (1/m) of the object, the restitution coefficient e and the velocity vector v of the object, use those attributes to compute J. Store the result in the impulse variable in the impulse method, see the comment in the code.
The velocity Verlet algorithm is expressed as the following:
where, x is the position of the object, v is the velocity and F is the sum of all forces applied to the object. The i+1 subscript represent the quantity at the next frame, i.e. is the newPos variable in the code, while the i subscript represent the quantity at the current frame, i.e. is the .Position property in the PhysObj object, Dt is the time step passed as parameter in the velVerletSolver method. Use the quantities in the PhysObj class to implement the algorithm, most of the quantities are already set for you in the framework. To obtain F use the ResForces method to get the sum of all forces applied to the object.
The Physics engine provided has limitations, it only simulate linear dynamics, so no rotations can be simulated. It is also partially unstable, so do not pile up objects and do not concatenate elastic forces as the simulation become unstable in those cases.
Part 2: Collision Detection
Watch the following video, the source code can be found here, please be aware that to make this demo work you need to import the Physics Engine you completed in the first part of this lab.
Part 3: Physics
For the final assignment (Masters Mandatory, UG EXTRA):Implement friction and the elastic forces as described in the lecture, apply friction to the projectile.
(EXTRA MARKS) Apply all three physics forces (wight, friction, elasticity) in your game to different elements in the game.
PhysObj class Documentation
print full screen
PhysObj class Documentation
The PhysObj class is what you will be using to transfer the physics simulation and collision detection from the physics engine to the classes in your game.
A physObj possesses a SceneNode property that you can use to pass the node of the model mesh you want to use for the simulation.
Once the PhysObj node is inserted in the SceneGraph you can add forces to it.
To add a force you have to use addForcesToList(Force force) method. The parameter of that method is an object instantiated form a class child of the Force class.
You can set the initial position of the physics object as well as its initial velocity using the Position and Velocity attributes and you can detect if a collision using the property CollisionList, which contains a lists of physics object that are in contact with the object you are checking.
Follows the list of Attributes and Methods that you should use in your game. Other attributes and methods are implemented in the class but you should avoid to use them.
Constructor:
· PhysObj(SceneMgr mSceneMgr, float radius, string id, [float invMass = 1.0f], [float restitution = 0.99f], [float frictionCoeff = 0.1f])
Constructor.
Mandatory fields are: the scene manager, the radius of the bounding sphere of the object you want to attach to the physics, a string representing a unique ID for the object
Optional fields are: the inverse of the mass of the object (1/mass), the restitution of the object, the friction coefficient for the object
Public Attributes:
· CollisionList
List of Contacts objects, it contains the list of objects which are colliding with the current one. Each contact object stores both the colliding object and the collider object.
· Position
Get/Set the initial position of the PhysObj
· Velocity
Get/Set the initial velocity of the PhysObj
· Radius
Get/Set the radius of the bounding sphere which approximate the object in the physics engine
· InvMass
Get/Set the inverse of the mass of the object
· Restitution
Get/Set the restitution coefficient of the object
· ResForces
Get/Set the sum of all forces applied to the object
· SceneNode
Get the SceneNode for the PhysObj
Public Methods
· addForceToList(Force force)
Add a force to the list of forces applied to the object