2013-Apr-21 by CW in Hex Board Engine
04/10/13 I have discovered Fuzzy's excellent flood fill code, and modified it to use with my application. Now we can draw colored hexes on a black background. Very cool.  Eventually I will want to have a way to skin the hexes, which will allow for trees and grass and mountains and buildings and such. I can see how the flood-fill code can be improved and made to stand alone. I think this would be very useful to all of our programers, so I'll work on that. -CW  04/17/13 PS: I have finished my revision of Fuzzy's wonderful flood fill code and posted it on line here: http://www.glbasic.com/forum/index.php?topic=8663.0
|
[See topic]
|
2013-Apr-21 by CW in Hex Board Engine
I have written some code which allows a user to specify the rows and columns of a hexagon game board with the command CreateHexBoard(x,y,RGB() ). The program uses those dimensions to scale the game board to fit the current screen size, and than it draws the hexagon board onto the screen. I notice that it works great on my desktop, but on my laptop, the top row of hexes is sometimes cropped, for some reason. It must have something to do with the graphics card. I will eventually have to include a boarder offset. Note: Create a font called "smalfont.png", which is large enough to read. Or just enter the number of hexes you want in each row at the first prompt, and the number of hexes you want in each column at the second prompt. /////////////////////////////////////////////////// // Hex v_1.3 // ---------------------------------------------- // Written by Craig Waterman // 04/2013 // ---------------------------------------------- /////////////////////////////////////////////////
GLOBAL sw# = 1366,sh# = 768 SETSCREEN sw,sh,FALSE
LOCAL fontkey# = GENFONT() LOADFONT "smalfont.png",fontkey SETFONT fontkey
LOCAL X_Hexes%,Y_Hexes% CLEARSCREEN LOCAL Str$ = "How many hexes in each row of the game board?" PRINT Str$,50,50
INPUT X_Hexes,(LEN(Str$,1)+60),50
CLEARSCREEN LOCAL Str$ = "How many hexes in each Column of the game board?" PRINT Str$,50,50
INPUT Y_Hexes,(LEN(Str$,1)+60),50
/////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////// // Change these numbres to change the size of your hex board. // --------------------------------------------------- Create_Hex_Board(X_Hexes,Y_Hexes) /////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
Draw_Hex_Board(Hex[],RGB(0,255,0),RGB(0,0,0) )
LOCAL Rows = HexBoard.ColumnCount //DrwCenterHex(Hex[2+2*Rows].Screen_X,Hex[2+2*Rows].Screen_Y,RGB(0,0,255)) //DrwCenterHex(Hex[10+6*Rows].Screen_X,Hex[10+6*Rows].Screen_Y,RGB(0,0,255)) //DashedLine (Hex[2+2*Rows].Screen_X,Hex[2+2*Rows].Screen_Y,Hex[10+6*Rows].Screen_X,Hex[10+6*Rows].Screen_Y,RGB(255,0,0))
SHOWSCREEN;KEYWAIT END
// ------------------------------------------------------------- // // --- DRAWHEX --- // ------------------------------------------------------------- // FUNCTION Create_Hex_Board: Col, Row
LOCAL sw#,sh# GETSCREENSIZE sw,sh CONSTANT Hex_Default_Color# = RGB(60,150,100)
TYPE HEXes
Screen_X# // The pixel-x location where the hex is placed on the screen. Used for drawing the screen only. Screen_Y# // The pixel-y location where the hex is placed on the screen. Used for drawing the screen only. HexColor# = Hex_Default_Color // The hex fill color. Not to be confused with the hex outline color, which is handled by the DrwCenterHex function. HexSkin$ = "" // Not yet implimented. Eventually the hexes can contain illustrations of trees, and water, and houses and such. Row_Num# // Row and Column used during setup and from which Hex_I, Hex_J are calculated. Column_Num# // Row and Column used during setup and from which Hex_I, Hex_J are calculated. Hex_I# // (I,J) is the actual address of the hex in the computer memory. Hex_J# // I & J are used to find distances, adjacent hexes, firing radiuses, path-finding, and more. All the actual work happens using I & J.
ENDTYPE
TYPE HEXBOARD RowCount# ColumnCount# HexWidth# HexHeight#
ScreenOffset_X# ScreenOffset_Y# UnitLength#
ENDTYPE
GLOBAL HexBoard AS HEXBOARD HexBoard.RowCount = Row HexBoard.ColumnCount = Col
GLOBAL Hex[] AS HEXes DIM Hex[HexBoard.ColumnCount * HexBoard.RowCount] LOCAL countx%,county% FOR y = 0 TO HexBoard.RowCount-1 FOR x = 0 TO HexBoard.ColumnCount-1 Hex[y*HexBoard.ColumnCount+x].Row_Num = HexBoard.RowCount-1-y Hex[y*HexBoard.ColumnCount+x].Column_Num = x NEXT NEXT
///////////////////////////////////////////////////////////////////////
// First we calculate the actual size in pixels for the requseted hexes. // Note that vertical hexes are taller than the width of horizontal hexes // and the calculated size must reflect this. // So, for the purpose of setting a symetric hex size which will fit on the screen, // both hexwidth and hexheight are calculated at the scale of hex height. // Remember, we are calculating the size of a single hex here, measured in pixels, not // the number of hexes which can fit on any row or column of the screen.
CONSTANT RED% = RGB(255,0,0), GREEN% = RGB(0,255,0) CONSTANT ScaleFactor# = 1+1/SQR(3.0) // Size Scale Factor for height. (apx 158# taller than wide.)
/////////////////////////////////////////////////////////////////////////////////////////////////// /// Program attempt to calculate the scale of the hex lengths so as to fit the requested dimentsions onto the screen. /// Note that this section sets up the hexboard, it does not draw the hexboard to the screen. /// --------------------------------------------------------------------------------- /// (If we wanted a 9x5 hex field, we would set HexBoard.ColumnCount = 9 and HexBoard.RowCount = 5) /// ------------------------------------------------------------------------------------- HexBoard.ColumnCount = Col // Count from zero, rather than from one. HexBoard.RowCount = Row // (So the boad, counting from one, will have one extra row and column.) ////////////////////////////////////////////////////////////////////////////////////////////////////
//LOCAL HexBoard.RowCount = HexBoard.RowCount, ColumnCount = HexBoard.ColumnCount // This just makes the program easier to read. Now when I want to count hexes pre row I can do so, and when I want to count rows, I can do that too. LOCAL sx,sy,hw // S is another name for the unit value. Indeed, the unit value is what we must calculate. Until we arrive at the final unit lengeth we use the // temperary variables, sx & sy. Because the hexes in x & y must be scaled to fit the screen, we must calculate S two different ways. // These two ways are held in the sx & sy variables. Once calculated, we go with the smaller of the two S values for our Length. // (If we went with the larger of the two, the hexes in that dimension would be too large to fit on the screen.) // ------------------------------------------------------------------------------------------------------------------ //LOCAL UnitLength# // UnitLength is a fundamental value of a hex. It is the lengh of each side, and it is also half the height of the hex. // (The width of the hex is equal to the square root of 3 times the one-half of the unit length.) // The hex dimensions in Y break down like this: // ___ // /\ 1/2 Unit Length // / \ ___ // | | 1 unit length // | | ___ // \ / 1/2 UnitLenth // \/ ____ // Total Width = 1/2 * UnitLength * sqr(3) // // Each of these measurements actually calculated in relation to the very CENTER of the hex. // (In other words, when drawing the hex to the screen or when working with the hexes, many of these measurements // are actuly half the size indicated, because everything is calculated relative to the very center of the hex.) // Additionally, the unit length is calculated based on the specified x,y dimensions of the board. // (The unit length is calculated so that the entire board is scaled to fit on the current screen size.) // ----------------------------------------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------------------------------------- // In this section we determine the unit size so that all of the hexes fit on the screen. // We alse calculate the x & y offset values so that the hexes are centered on the screen. // Note that the calculations are based on the assumption that the hexes are symetrical. // A different calculation is needed to handle a forshortened or elevated hex board. // sy = INTEGER(sh/(1.5*HexBoard.RowCount+0.5)) //HexBoard.RowCount+0.5)) // UnitLenth based on the y-direction. (This will be compaired with the calculated unit length based on the x-direction.) IF HexBoard.RowCount =1 hw = INTEGER(sw/(HexBoard.ColumnCount)) //HexBoard.ColumnCount)) //This is the hex width if no shifted rows exist. (One row of hexes only.) ELSE hw = INTEGER(sw/(HexBoard.ColumnCount+0.5)) //HexBoard.ColumnCount+0.5)) //This is the hex width if shifter rows exist. (More than one row of hexes.) ENDIF
sx = INTEGER(hw/SQR(3)) //This is the unit length based on the total width of the hex rows (if shifted or not.) HexBoard.UnitLength = sy;IF sx < sy THEN HexBoard.UnitLength = sx // Compare the two unit lengths and go with the smaller unit length for all hexes.
LOCAL y_total_height = INTEGER(HexBoard.UnitLength*(1.5*HexBoard.RowCount+0.5)) HexBoard.ScreenOffset_Y = INTEGER((sh-y_total_height)/2) // This is the very top of the virtual frame. Note that hexes are located in // relation TO their centers, NOT TO their edges, so tihs naked offset is NOT a sufficient // reference to draw the hexes in theri proper locations. LOCAL x_total_width = HexBoard.UnitLength*SQR(3)*HexBoard.ColumnCount;IF HexBoard.RowCount > 1 THEN x_total_width = x_total_width+HexBoard.UnitLength*SQR(3)/2 HexBoard.ScreenOffset_X = INTEGER((sw-x_total_width)/2) //This is the far right edges of the virtual frame. Note that hexes are located in // relation to their centers, not to their edges, so this naked offset is not a sufficient // reference to draw the hexes in their proper locations.
HexBoard.HexWidth = HexBoard.UnitLength*SQR(3);HexBoard.HexHeight=2*HexBoard.UnitLength
FOR y# = 0.0 TO (HexBoard.RowCount-1)/2.0 STEP 0.5 FOR x# = 0 TO (HexBoard.ColumnCount-1) Hex[(y*2)*HexBoard.ColumnCount+x].Screen_X=HexBoard.ScreenOffset_X+(x*HexBoard.UnitLength*SQR(3))+(HexBoard.UnitLength*SQR(3)*(y-INTEGER(y)))+HexBoard.UnitLength*SQR(3)/2 Hex[(y*2)*HexBoard.ColumnCount+x].Screen_Y=HexBoard.ScreenOffset_Y+(HexBoard.UnitLength*2+HexBoard.UnitLength)*y+HexBoard.UnitLength NEXT NEXT
ENDFUNCTION // DRAWHEX
// ------------------------------------------------------------- // // --- DRWCENTERHEX --- // ------------------------------------------------------------- // // (0,0) for the x,y offset is the upperlefthand corner, off the hex. // I may need to change the offset so it is at the exact center of each hex. // (You call the center position and the function draws the scaled hex around it.) FUNCTION DrwCenterHex:X#, Y#, RGB_Color%
LOCAL hul# = HexBoard.UnitLength CONSTANT sqr3# = SQR(3.0) LOCAL uly#=INTEGER(hul/2.0*sqr3),ulx# = INTEGER(hul/2.0)
DRAWLINE X-hul*sqr3/2.0,Y-hul/2.0,X,Y-hul,RGB_Color DRAWLINE X,Y-hul,X+hul*sqr3/2.0,Y-hul/2.0,RGB_Color DRAWLINE X+hul*sqr3/2.0,Y-hul/2.0,X+hul*sqr3/2.0,Y+hul/2.0,RGB_Color DRAWLINE X+hul*sqr3/2.0,Y+hul/2.0,X,Y+hul,RGB_Color DRAWLINE X,Y+hul,X-hul*sqr3/2.0,Y+hul/2.0,RGB_Color DRAWLINE X-hul*sqr3/2.0,Y+hul/2.0,X-hul*sqr3/2.0,Y-hul/2.0,RGB_Color SETPIXEL X,Y,RGB_Color
ENDFUNCTION // DRWCENTERHEX
// ------------------------------------------------------------- // // --- DRAW_HEX_BOARD --- // ------------------------------------------------------------- // FUNCTION Draw_Hex_Board: HexBrd[] AS HEXes,FrameColor%,BckGrndColor% = 0 // Hex color is internal to Hex[], BckGrndColor refers to the background screen color on which the hexboard is drawn, not the hex colors themselves. CLEARSCREEN BckGrndColor LOCAL Temp$,String$ FOREACH Item IN HexBrd[] DrwCenterHex(Item.Screen_X,Item.Screen_Y,FrameColor)
USEASBMP;SHOWSCREEN NEXT
ENDFUNCTION // DRAW_HEX_BOARD
The program creates a global game board array which is accessible to the programer. This is very unsatisfying, as only a single hexagon board can be defined by the user. I would rather the programer be able to call as many instances of hexagon arrays as is desired and allowed by memory capacity, but I am at a loss on how to accomplish this. Ah well. I will focus on the mechanics of a single hexagon board for now, and tackle allowing the user to define multiple, local instances of type HexBoard in a future revision. -CW
|
[See topic]
|
2013-Apr-21 by CW in Hex Board Engine
03/28/13 Project begun. Fuzzy has given me a link which seems helpful. http://playtechs.blogspot.com/2007/04/hex-grids.htmlThis website explains how to distort hexagons into a shape with better maps to the x,y nature of computer memory. Unfortunately, the explanation leaves a lot to be desired, and I have attempted to reverse-engineer the math so as to understand what it all means. It is slow-go and very challenging. At times I feel as though I am wrestling to decipher the Rosetta Stone. On top of that, the framework used is completely different from how graphics are displayed in GL basic. So not only must I puzzle it all out, I must translate it into a form which can be used in GLbasic. Yikes!
|
[See topic]
|
2013-Apr-21 by CW in Hex Board Engine
3/28/13 Part of the problem with trying to work with hexagons on a computer is that hexes have six degrees of freedom (six neighbors), while grids only have four. Six directions in which game pieces can move are much more natural than four, so hex boards are superior to checkerboards for making games on. Unfortunately, computer memory is laid out on a grid, so we need a way to map hexagons to a grid, and we need a way to know which hexes fall within a given radius, a given firing range, and a distance between any tow hexes. My game engine would allow for all of that, as well as a method for drawing, filling, skinning, and placing icons on any grid. And a method to highlight any hex, and for drawing dashed lines between any hexes on the board. The following illustration shows the problem of trying to map hexes to computer memory. Notice how moving one hex up or down changes the footprint on the grid. Depending on which row a piece is on, the footprint changes; an in no way do the hexes map neatly onto a gridwork. That is the heart of the problem. -CW
|
[See topic]
|
2013-Apr-21 by CW in Hex Board Engine
The purpose of this project is to create a engine which can run in the background and handle all bookwork involved in maintaining a hexagon game board. This will free programers to focus the game mechanics. I have attempted this project several times in the past, and each time I have failed. But each time I get a little closer to my goal. Can I succeed this time? Perhaps. But as I code in my free time, and as I like to dabble a little here and dabble a little there, this will be a long-term project. What sorts of games can be created with such an engine? Two types, which I can see. The first are games which resemble those played on paper maps. Here is an outstanding open-sourced hexagon-based game called Battle for Wesnoth. https://wesnoth.orgMy engine will be far to slow and too limited to match what Wesnoth has, but it gives you an idea of the sort of paper-map type of game which should be within your reach. If you have ever seen a paper game called "Ogre", by Steve Jackson games, that is certainly within your reach.  The second type of game is much simpler, and certainly within the scope of my hex board engine. That type of game would be something like Reversi, played on hexes. -CW
|
[See topic]
|
|