Archived

This topic is now archived and is closed to further replies.

fortress

plotting hex tiles

Recommended Posts

I am thinking of making a hex-based game myself. You can look at the code I came up with and modify it to suit your purposes if you like. I'm quite a C++ newbie so beware. Anyways here is my "Hexagon" class. Please tell me what you think. Being a newbie, any constructive criticism would be helpful.

    
#include <cmath> // Required for math functions to work


HDC g_pHDC; // Global pointer to the device context handle

HWND hWnd; // Global window handle


// Point class and definition definition

// This is used by the Hex class


class Point {
public:
void SetX(int X) {itsX = X;}
void SetY(int Y) {itsY = Y;}
int GetX() const {return itsX;}
int GetY() const {return itsY;}
private:
int itsX;
int itsY;
};

// Hexagon class definition

class Hexagon {
public:
Hexagon();
Hexagon(Point center,int radius);
void SetRadius(int radius);
int GetRadius();
int GetAltitude();
void SetCenterPoint(Point center);
bool IsInsideHex(int X, int Y);
void drawHex(bool drawInfo);
private:
~Hexagon();
int itsAltitude;
int itsRadius;
Point itsPoints[6];
Point itsCenter;
void calcPoints(void);
};

// Hexagon Class

Hexagon::Hexagon() {
}

Hexagon::Hexagon(Point center,int radius) {
SetCenterPoint(center);
SetRadius(radius);
calcPoints();
}

void Hexagon::SetCenterPoint(Point center) {
itsCenter = center;
calcPoints();
}

int Hexagon::GetAltitude(){
return itsAltitude;
}

int Hexagon::GetRadius(){
return itsRadius;
}

void Hexagon::SetRadius(int radius) {
itsRadius = radius;
itsAltitude = int(float(sqrt(3)/2)*itsRadius);
calcPoints();
}

void Hexagon::calcPoints(void){
itsPoints[0].SetX(itsCenter.GetX());
itsPoints[0].SetY(itsCenter.GetY() - itsRadius);

itsPoints[1].SetX(itsCenter.GetX() + itsAltitude);
itsPoints[1].SetY(itsCenter.GetY() - int(itsAltitude/2));

itsPoints[2].SetX(itsCenter.GetX() + itsAltitude);
itsPoints[2].SetY(itsCenter.GetY() + int(itsAltitude/2));

itsPoints[3].SetX(itsCenter.GetX());
itsPoints[3].SetY(itsCenter.GetY() + itsRadius);

itsPoints[4].SetX(itsCenter.GetX() - itsAltitude);
itsPoints[4].SetY(itsCenter.GetY() + int(itsAltitude/2));

itsPoints[5].SetX(itsCenter.GetX() - itsAltitude);
itsPoints[5].SetY(itsCenter.GetY() - int(itsAltitude/2));
}

void Hexagon::drawHex(bool drawInfo) {
TCHAR szBuffer[50];

TEXTMETRIC tm;
GetTextMetrics (g_pHDC, &tm) ;
static int cyChar = tm.tmHeight + tm.tmExternalLeading;
static int cxChar = tm.tmAveCharWidth;
if(drawInfo){
TextOut( g_pHDC, 5, cyChar * 0, szBuffer, wsprintf(szBuffer, TEXT("Center Point: %d,%d"), itsCenter.GetX(),itsCenter.GetY() ));
TextOut( g_pHDC, 5, cyChar * 1, szBuffer, wsprintf(szBuffer, TEXT("Outer Circle Radius: %d"), itsRadius));
TextOut( g_pHDC, 5, cyChar * 2, szBuffer, wsprintf(szBuffer, TEXT("Inner Circle Radius: %d"), itsAltitude));
TextOut( g_pHDC, 5, cyChar * 3, szBuffer, wsprintf(szBuffer, TEXT("Point %d: %d,%d"), 0, itsPoints[0].GetX() , itsPoints[0].GetY()));
}
MoveToEx(g_pHDC,itsPoints[0].GetX(),itsPoints[0].GetY(), 0x00);
for(int i = 1;i<=5;i++) {
LineTo(g_pHDC,itsPoints[i].GetX(),itsPoints[i].GetY());
if(drawInfo){
TextOut( g_pHDC, 5, cyChar * (i + 3), szBuffer, wsprintf(szBuffer, TEXT("Point %d: %d,%d"), i, itsPoints[i].GetX() , itsPoints[i].GetY()));
}
}
LineTo(g_pHDC,itsPoints[0].GetX(),itsPoints[0].GetY());
}

bool Hexagon::IsInsideHex(int X, int Y){
int myBase = abs(X - itsCenter.GetX());
int myHeight = abs(Y - itsCenter.GetY());
int myHypotenuse = sqrt((myBase*myBase)+(myHeight*myHeight));
return (myHypotenuse <= itsAltitude);
}

Hexagon::~Hexagon() {
}


I did this using GDI so you will probably want to port the actual drawing mechanism over to DirectDraw or something. All the drawing code is handled in the DrawHex fuction. I also wanted a way to determine if the user clicked within the hexagon so I added the IsInHex function. It takes X and Y corrdinates and determines if the user clicked in the hex or not. I just created an array of hexagon objects and on mouseclick event loop through them and check the IsInHex function. Pretty simple. I'm kinda cheating because I wanted it to be fast, so if the user clicks really near the apex of the top or bottom of the hexagon it might not register a mouse click. Basicaly I'm just calculating if that click is in the "in-circle" of the hexagon. Math is not yet my strong suit (but I'm trying) and http://mathworld.wolfram.com has been invaluable to me on this project.

As a final note, passing a drawInfo parameter of true to the DrawHex function causes debugging information to be drawn on the screen. I used this when calling DrawHex from a mouse click event to view some debugging information. You will probably want want to strip this out. This code doesnt take into account for putting textures on the hexagon, but the point calculation seems solid, so you can replace the drawing code with whatever polygon drawing function your target API provides.

Ok, enough rambling.
~ chaosbob

Edited by - chaosbob on February 17, 2002 11:48:08 AM

Share this post


Link to post
Share on other sites
well i have to say that this is alot more complete then what i have come up with so far
and looks alot more usefull
thank you for the reply.

Share this post


Link to post
Share on other sites