se1:Creating a radar

From SeriousEngine.com

(Redirected from Creating a radar)
Jump to: navigation, search

relgetdron ouacdro

Radar for Serious Sam

I recently decided I'd give another go at coding, and while wondering what I could possibly code, I thought of a radar! So my quest has brought me to create a decent looking radar (which rotates as the player does!!), which is mighty usefull in Serious Sam :). The code is short, pretty basic, and sometimes complex looking, but when you look at it good, you'll figure out what it does. Also, since I have put all of my radar code into one part, and is short, at the end I can just throw all the code at you, and explain everything with comments.

First of all, I first made my radar image, and a dot image which is already in Serious Sam, but which we'll redefine. For the radar, I made a very basic picture in Photoshop 7.0 (great program), and put mostly everything I need in it. You can do it otherwise, but in my oppinion, if it looks good, who cares how it's made ;). So I first added my new texture item to HUD.cpp under any of the other _static CTextureObjects_:

// radar textures
static CTextureObject _rDot;
static CTextureObject _rRadar;

Now I'd need to draw it somewhere, because I like to keep stuff that is for the same thing together, I put it in the _Extern void DrawHUD_ under _COLOR colBorder = _colHUD;_.

/* Radar */
_pDP->InitTexture(&_rRadar);
_pDP->AddTexture(_pDP->GetWidth()-256, _pDP->GetHeight()-256, _pDP->GetWidth(), _pDP->GetHeight(), C_WHITE|255);
_pDP->FlushRenderingQueue();

Explanation: first we need to intialize our newly created texture. that's what the first line it for. We draw in in the HUD Drawport, that explains the _pDP. _rRadar is the _CTextureObject_ we added on the top of HUD.cpp. The _AddTexture_ function is used to actually put the texture on the screen. _AddTexture_ takes 5 parameters; left-, top-, right-, and the bottom of the texture, and the colour. The other line I am not sure about, but it's often used so I always figure, what the hey :).

You might wonder, shouldn't we tell it what our texture is? All in due time my friend. That's what we'll do now. First, locate this line:

_toArmorLarge.SetData_t( CTFILENAME("TexturesMP\\Interface\\ArStrong.tex"));

Add under it:

// initialize radar textures
_rDot.SetData_t( CTFILENAME("TexturesMP\\Computer\\Map\\PathDot.tex"));
_rRadar.SetData_t( CTFILENAME("Textures\\Interface\\radar.tex"));

And last but not least, we must make it a constant so it wont use the last mipmap of the texture (very ugly blurryness). You can add this line under the _((CTextureData*)_toArmorLarge.GetData())->Force(TEX_CONSTANT);_ line:


((CTextureData*)_rDot .GetData())->Force(TEX_CONSTANT); ((CTextureData*)_rRadar .GetData())->Force(TEX_CONSTANT);

Ok so that concluded out very basic texture for our radar graphics, but now we need to make the actual radar! So let's work on it.

First of all, let me explain how we're going to do this. We are going to check for all entities in a current level. If an entity is an _Enemy Base_ entity, we will continue with our code, if it's not, we don't do a thing. When we continue, we will initialize a new texture. This would be the dot texture we added earlier. This dot should be relative to it's actual position, but then in the radar. Also, for nice detail, if an enemies health is a certain number, it'll change colour, just like the crosshair does. First of all, let me show you the entire chunk of code, then I'll explain.

{FOREACHINDYNAMICCONTAINER(((CEntity&)*_penPlayer).GetWorld()->wo_cenEntities, CEntity, iten) { // For every entity in the level
CEntity *pen = iten;
if (IsDerivedFromClass(pen, "Enemy Base")) { // if entity is an Enemy Base
CEnemyBase *penEnemy = (CEnemyBase *)pen; // basicly we make a new enemy thing, Hey I may not know how to explain it, but atleast I know what it does.. hehe
if (penEnemy->m_penEnemy==NULL) {
continue;
}

CPlacement3D plEnemy; // we make a new placement thing
plEnemy.pl_PositionVector=penEnemy->GetPlacement().pl_PositionVector; // get the position of this enemy (
plEnemy.pl_OrientationAngle=FLOAT3D(0,0,0); // set it to 0,0,0 for now.
plEnemy.AbsoluteToRelativeSmooth(((CEntity&)*_penPlayer).GetPlacement()); // get it's position relative to the position of the player. It's a bunch of maths...

FLOAT EnemyOnHudX=plEnemy.pl_PositionVector(1); // X position of the enemy (dot) relative to the player
FLOAT EnemyOnHudY=plEnemy.pl_PositionVector(3);// Y position of the enemy (dot) relative to the player
FLOAT posX = EnemyOnHudX*2.5+_pDP->GetWidth()-128; // in my radar, the center of my radar is 128 pixels from the side
FLOAT posY = EnemyOnHudY*2.5+_pDP->GetHeight()-128;// and 128 pixels from the bottom. Also, you can set the 2.5 to different amounts. A higher number means a wider range the radar will show. I'm not good at explaining maths, so you'll have to take it for granted.. sorry :).
FLOAT fRadarRadius = 24.0f; // the radius of the radar in meters (SEd units)..
COLOR colRdot = C_WHITE|255;
FLOAT m_fEnemyHealth = 0.0f;

m_fEnemyHealth = ((CEnemyBase*)pen)->GetHealth() / ((CEnemyBase*)pen)->m_fMaxHealth; // Get the health of this enemy

if( (penEnemy->GetPlacement().pl_PositionVector - ((CEntity&)*_penPlayer).GetPlacement().pl_PositionVector ).Length() < fRadarRadius ) // if the enemy is less than 24 meters away from the player
{
colRdot = C_GREEN|255; // give the dot a green colour
if( m_fEnemyHealth<0.25f) { colRdot = C_RED|255; } // whoops, he's allmost dead. this is to check if it's health is lower than 25.
else if( m_fEnemyHealth<0.60f) { colRdot = C_YELLOW|255; } // if it's a little lower, make it yellow
else if( m_fEnemyHealth<0.01f) { colRdot = C_RED|0; } // I added this for my own test, but it appears not to always work. I want the dot to dissapear when an enemy is basicly dead.. for some reason it's health never becomes this low when he's dead?
else { colRdot = C_GREEN|255; } // or else, his health is pretty high, so he may stay green.
} else
{
colRdot = C_WHITE|0; // if his position relative to the player is more than 24 meters, make it invisible.
}

_pDP->InitTexture(&_rDot); // Here we intialize the dot texture
_pDP->AddTexture(posX-8/2,posY-8/2,posX+8/2,posY+8/2, colRdot); // we place it at the correct position. We must tell it to substract half the image size for the left, half at the top, and add half to the bottom and right, or else you wouldn't see a dot (texture) at all.
_pDP->FlushRenderingQueue(); 

}
}
}

Whoo, that wasn't too hard now was it.. hehe. Well I hope you could understand everything.. Anyways, you can just place this entire chunk under this code we added before:

/* Radar */
_pDP->InitTexture(&_rRadar);
_pDP->AddTexture(_pDP->GetWidth()-256, _pDP->GetHeight()-256, _pDP->GetWidth(), _pDP->GetHeight(), C_WHITE|255);
_pDP->FlushRenderingQueue();

And that is it! All you need for your (basic) radard code. For additional niceness, you could add some compass arrow, and in my case I modded some other stuff like weapon things... Check this image out for example:
Image:Radarexample.jpg

- Sean Stellingwerff

Oh and not to forget, thanks to asko for helping with orientation stuff :)

Personal tools