History: Rectangle2D as Player GUI Feedback for Game
Source of version: 2
Copy to clipboard
So this explains how to use GUI for player feedback in your game, such as showing blood onscreen when the player gets hit.
This specific example uses alpha to fade the image onto and off the screen.
Here's an animated GIF to show the idea:
{IMG(src="http://www.knightforged.com/bloodscreen.gif")}{IMG}
Here is my simple material script:
{CODE(caption="Simple material for blood")}
material Blood {
technique {
pass {
lighting on
ambient 1 1 1
diffuse 1 1 1
emissive 0 0 0 1
alpha_rejection greater 128
texture_unit {
texture blood.png
scale 1 1
}
}
}
}{CODE}
Some variables to set this up, I put these in my class Player.
{CODE(caption="Some class member variables", colors="c++")}// Node for onscreen blood
Ogre::SceneNode *BloodNode;
// Rectangle containing blood material
Ogre::Rectangle2D *BloodScreen;
// Boolean used to enable showing of blood
bool showBlood;
// Length blood will be shown onscreen
Ogre::Real bloodTime;
// Used to change alpha of bloodscren
int bloodAlpha;
// Boolean on whether alpha should increase/decrease
bool bloodUp;
// Functions to start and display blood onscreen
void startBlood()
void displayBlood();{CODE}
Now initialize everything
{CODE(caption="Player::init()", colors="c++")}int ScreenX = APP->Viewport->getActualHeight();
int ScreenY = APP->Viewport->getActualWidth();
double XRatio = ScreenX/1600.0;
double YRatio = ScreenY/900.0;
BloodScreen = new Ogre::Rectangle2D(true);
BloodScreen->setCorners(-2.08*XRatio,YRatio/1.5,2.08*XRatio,-1*YRatio/1.5);
BloodScreen->setMaterial("Blood");
BloodScreen->setRenderQueueGroup(Ogre::RENDER_QUEUE_BACKGROUND);
Ogre::AxisAlignedBox box;
box.setInfinite();
BloodScreen->setBoundingBox(box);
BloodNode = SceneMgr->getRootSceneNode()->createChildSceneNode("BloodScreen");
BloodNode->attachObject(BloodScreen);
BloodNode->setVisible(false);
bloodCount = 255;
bloodUp = false;
showBlood = false;{CODE}
Next we need to start showing the onscreen feedback during a certain action.
Do this in frameRenderingQueued
{CODE(caption="frameRenderingQueued", colors="c++")}void Player::frameRenderingQueued(const Ogre::FrameEvent &evt) {
if (PlayerAction & PLAYER_HIT) {
disableAction(PLAYER_HIT);
startBlood();
}
if (showBlood)
displayBlood();
}{CODE}
Next is the startBlood() function, this starts the process of course.
{CODE(caption="Start showing the blood", colors="c++")}void Player::startBlood() {
// Display blood node
BloodNode->setVisible(true);
showBlood = true;
// Get how much time has passed since program started and add how much time to show blood
bloodTime = APP->getCurrentFrame() + 5000;
bloodCount = 255;
}{CODE}
And now the meat of it, fading the blood onto the screen and back off.
{CODE(caption="Alternate alpha value of blood",wrap="1", colors="c++")}void Player::displayBlood(const Ogre::FrameEvent &evt) {
// Check if enough time has passed
// i.e. the current time is greater than how much time we needed
if (bloodTime < APP->getCurrentFrame()) {
showBlood = false;
BloodNode->setVisible(false);
return;
}
// If current alpha is at 0, increase alpha otherwise decrease it
if (bloodCount <= 0)
bloodUp = true;
else if (bloodCount >= 255)
bloodUp = false;
if (bloodUp)
bloodCount++;
else
bloodCount--;
// Get material in order to apply alpha
Ogre::MaterialPtr mat = BloodScreen->getMaterial();
// Apply alpha value
mat->getTechnique(0)->getPass(0)->setAlphaRejectValue((unsigned char)bloodCount);
}{CODE}
And there you have it! You may want to pass in either (const Ogre::FrameEvent &evt) or (evt.timeSinceLastFrame) to displayBlood()
and calculate the alpha change according to evt.timeSinceLastFrame to account for jumps in FPS.
And you will need to adjust the time (I put 4000) to how much time you need; and of course if you don't want the fade in/out and just
want it to go on screen then omit the alpha change and simply set the node's visibility to off when the time is up.
Hope you enjoy it.