Simple radar for HL2MP

Started by
4 comments, last by Crazyfool 15 years, 9 months ago
I'm having trouble getting the equations for a radar to work in a HL2MP mod. I have a few questions in which I would find helpful if they were answered. How can I calculate where to put the marker on the radar (It's a simple square texture with a circle to represent the radar. I was thinking of making the client player the origin relative to the other players, then converting to polar coordinates and back to Cartesian when I put it on the radar which has a center at the point (60, 60). Is there a function to draw circles instead of squares. I couldn't find any in the class declaration. Here is what I have so far

#include "hud.h"
#include "cbase.h"
#include "radar_hud.h"
#include "iclientmode.h"
#include "hud_macros.h"
#include "vgui_controls/controls.h"
#include "vgui/ISurface.h"

#include "tier0/memdbgon.h"

using namespace vgui;



DECLARE_HUDELEMENT( CRadarHud );

static ConVar show_radar("show_radar", "1", 0, "toggles radar on and off");


CRadarHud::CRadarHud( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, "HudImport" )
{
	
	
	
	Panel *pParent = g_pClientMode->GetViewport();
	SetParent( pParent );   
   
	SetVisible( true );

	// create radar texture
	m_nImport = surface()->CreateNewTextureID();
	surface()->DrawSetTextureFile( m_nImport, "HUD/hud_radar" , true, true);
	
	// hides radar if player is dead
	SetHiddenBits( HIDEHUD_PLAYERDEAD);

	// Draw the radar
	SetPaintBorderEnabled(false);
	surface()->DrawSetTexture( m_nImport );
	surface()->DrawTexturedRect( 2, 2, 128, 128 );
	
}


void CRadarHud::Paint()
{
	// draws the radar	
	SetPaintBorderEnabled(false);
	surface()->DrawSetTexture( m_nImport );
	surface()->DrawTexturedRect( 2, 2, 128, 128 );
	
	//	TODO:  We need to update the dots on the screen according to where the players are

	// create player pointer
	C_BasePlayer *pOtherPlayer = NULL;
	surface()->DrawSetColor( 250, 250, 250, 10 );
	surface()->DrawFilledRect(10, 60, 15, 65);

	for(int i = 1; i <= gpGlobals->maxClients; i++ )
	{
		pOtherPlayer = UTIL_PlayerByIndex( i );

		if(!pOtherPlayer)
			continue;
		if(!pOtherPlayer->IsAlive( ))
			continue;
		if(!pOtherPlayer->IsClient( ))
			continue;
		// draw everyone
		/*if(pOtherPlayer->GetTeamNumber( ) != pPlayer->GetTeamNumber( ))
			continue; // Don't draw enemies TODO radar amplifier */
if(pOtherPlayer == C_BasePlayer::GetLocalPlayer( )) continue; // Don't draw self C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer(); Vector offset = pOtherPlayer->GetAbsOrigin() - pLocalPlayer->GetAbsOrigin(); offset /= scale; // devide by scale int drawX = offset.x + panelWidth/2; // add sixty because origin is int drawY = offset.z + panelHeight/2; // actually located at (60, 60) if ( drawX > 0 && drawY > 0 && drawX < panelWidth && drawY < panelHeight ) { // this clips to a square, which is less pretty but easier surface()->DrawFilledRect( drawX-1, drawY-1, drawX+1, drawY+1 ); Msg( "x1:%f y1:%f x2:%f y2:%f \n", drawX-1, drawY-1, drawX+1, drawY+1 ); }// end if } // end for loop } void CRadarHud::togglePrint() { if (!show_radar.GetBool()) this->SetVisible(false); else this->SetVisible(true); } void CRadarHud::OnThink() { togglePrint(); BaseClass::OnThink(); } Thank you for your time and effort, Joe [Edited by - cs_student on July 17, 2008 10:27:04 PM]
Advertisement
I can't answer specifically because I haven't done vgui programming, but mathematically, you need to know the distance that your radar will sweep, first of all.

To find the position of each player on the radar, you would do something like this (pseudo code):

const float RADAR_SWEEP_DISTANCE = 1000.0f;float fRadarImageRadius = radarSurface->width(); // or height, assuming it's square. Also could adjust for borders.foreach player in players	// Ignore self and non-playing players	if player == localplayer || !player.isclient || ! player.alive continue	// Get vector pointing from local player to player being examined	vector3d vecDistanceToPlayer = player.position - localplayer.position;	// If out of radar range, don't put on the radar	if(!vecDistanceToPlayer.distanceSquaredBelowThreshold(RADAR_SWEEP_DISTANCE)) continue;	// If within range, divide by range to get normalized distance from radar center	vecDistanceToPlayer /= RADAR_SWEEP_DISTANCE;	// Then multiply by pixel distance from radar image's center to the radar image's edge	vecDistanceToPlayer *= fRadarImageRadius;	// Now, draw a circle, or another texture, centered on vecDistanceToPlayer + vecRadarImageCenterPoint


I apologize if I am mistaken, as I haven't tested this code.
What I want to have is the relative position and proximity of the other player. Not just how far they are away from the client. ie If client is facing down the positive x direction (or pointed that way) and the other player is behind him, I want the dot to show up x units downward (indicating the player is behind the client) depending on how far the other player is from the client.

Does that make sense?

Here's a picture to further clarify



Joe
/bump
/bump (I won't bump again, as I don't want to spam)
It's late but..

int dX = centerX - otherPlayerX;int dY = centerY - otherPlayerY;int rX = radius * cos(dX);int rY = radius * sin(dY);


I have no clue how accurate it is, but I figure it might help you get in the right direction. You'll probably have to play around with the signs to get a full circle rather than only certain quadrants.

centerX/Y are the in game coordinates of the player,
otherPlayerX/Y are the in game coordinates of the player/enemy you want to draw on radar

rX/Y will be the OFFSET of the center of the radar.

Edit: and the radius might be swapped with linear distance between the 2, again not sure - its late

This topic is closed to new replies.

Advertisement