2013-Jun-09 by Heiko in Falling Diamants
Da blog ich mal was zu meinem aktuellen Projekt. Falling Diamants ( was Besseres ist mir im Moment nicht eingefallen ) ist ein simpler Bejeweled Clone. Derzeit funktioniert alles, soll heißen es müssen Diamanten welche nebeneinander liegen getauscht werden, insofern sich dadorch Kombination von mindestens 3 nebeneinander liegenden Diamanten ergeben. Diese werden dann gelöscht und das Spielfeld füllt sich wieder auf. Anhängig von der Farbe der Diamanten wird es verschiedene Punkte geben.(dieses wird in Zukunft noch implementiert) ToDo: Glitzeranimationen um und auf dem Spielfeld. Spezialsteine mit besonderen Features (die ich mir noch ausdenken muss) verschiedene Leveldesigns Das komplette Menü, dies aber zum Schluss, da dies recht schnell geht... und zu guter Letzt noch bisschen passender Sound .... ach und nen schöneren Mauszeiger...lach
|
[See topic]
|
2013-Apr-25 by CW in Hex Board Engine
Tonight I went back and reviewed my mathematical implementation of the transform and discovered a place where I veered off into the weeds. What is the old saying, a thing should be made as simple as possible and no simpler? Well, I over simplified the math, so you definitely should not take any of my blog code as a sound place to work from. The mathematical model I came up with works well with hexes of set dimensions, but it totally fails for hexes which must be free to scale up or down to fit the screen size. (It also fails for the reasons I have outlined in previous posts, but this over-simplification is a new source of error.) To scale properly, the equations must be left in a generalize form and then the computer must calculate the specific values appropriate for the screen. To show you how messed up my code is, had it been working properly, the output laid over the green hexes should have been a very small, solid red rectangle in the upper left corner, where each colored pixel represents a single memory location for storing hex data. I'm not entirely clear why the hexes transformed so nicely rather than returning (messed up) sequential integer values, but I suspect it has something to do with the fact that I turned variables into constants, so the transform matrix worked but the calculation to find an integer failed and merely offset the transformed values. Whatever the true cause, it isn't worth wrestling the code to find out for sure. Sometimes the best thing to do is wipe the slate clean, start over, and build on what you learned from your earlier mistakes. That is where I am now with the mathematical transform. I am findings this project really challenging. There are so many layers to the math, and the example I am working from isn't fully explained. Ah well, it is what it is, and it is sure a whole lot better than nothing at all. I'm actually feeling quite good about it today. I may be beat, but I am not beaten. I will pick this project up again, as I have several times before. I console myself with the thought that each time I tackle this project, I get a little closer to my goal than I did the time before. And when I eventually do pick this project up again and have progress to show, you can read about it in this blog. Cheers for now! -CW
|
[See topic]
|
2013-Apr-23 by CW in Hex Board Engine
The more I think about it, the more confident I am of the correct approach. What screwed me up is that GLbasic's point of origin is in the upper left corner, while the hex example on the website has a point of origin in the lower left corner. In implementing the transform to the GLbasic screen, this change in origin caused me to rotate the hex transforms in the wrong direction, so they wound up not mapping at all to a Cartesian grid. Also, the example code scales down hexes to map to an incremental memory grid, but a far better approach which is independent of the drawn hexes would be to begin with the Cartesian unit grid and scale that up into hexes, rotating them into their proper position on the screen. I'm fairly confident that this approach would work. I will have to give it another try at some point, but for now I am going to give this project a rest and work on other things. It is my hope that this blog will be useful to others, should you wish to give this challenge a try.  -CW
|
[See topic]
|
2013-Apr-21 by CW in Hex Board Engine
04/20/2013 Bad news. Plotting the modified hexes along with the unmodified hexes shows me that I have a long way to go in implementing this hex-to-Cartesian approach. The hexes are rotated and transformed all right, but the transformation looks nothing like the example from the website. I think the origins are messing with me. I need to rework the math and try to apply the general approach to the way Glbasic orients things, if I can. (The math assumes an origin in the lower left corner, GLbasic has its screen origin in the upper left. Also, the rotation doesn't seem quite right. I wonder if I rotated it in the wrong direction? Hmm.. maybe.) And as if that were not bad enough, in trying to go from hexes on the computer screen to a simple Cartesian x,y grid map for computer memory, I've backed myself up a tree. I need to start over, this time beginning with a simple unit single-increment grid map and then translating that into hexes displayed on the screen. Instead of trying to scale the hexes down to single integers, I now makes more sense to start with integers and scale up. After all, the screen is just for display. All of the important stuff happens in memory. Yeesh. Why do I feel tired all of a sudden? 
/////////////////////////////////////////////////// // Hex v_2.2 // ---------------------------------------------- // Written by Craig Waterman // 04/2013 // ---------------------------------------------- // FloodFill function adapted from the exellent // fastfloodfill code posted by Fuzzy. = ) /////////////////////////////////////////////////
GLOBAL sw# = 1366,sh# = 768 SETSCREEN sw,sh,FALSE
LOCAL fontkey# = GENFONT() LOADFONT "smalfont.png",fontkey SETFONT fontkey
Create_Hex_Board(20,15) FOR countx = 0 TO HexBoard.ColumnCount-1 FOR county = 0 TO HexBoard.RowCount-1 DrwCenterHex(Hex[countx+county*HexBoard.ColumnCount].Screen_X,Hex[countx+county*HexBoard.ColumnCount].Screen_Y,RGB(0,255,0)) NEXT NEXT
//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 //PRINT "HexBoard.RowCount-1 = "+(HexBoard.ColumnCount-1),50,50;SHOWSCREEN;KEYWAIT 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
// Convert u TO HexBoard.UnitLength AND check FOR correct transform. (s = HexBoard.UnitLength, AND r = HexBoard.UnitLength*SQR(3)/2
//LOCAL Hex_x# = SQR(3.0),Hex_y# = 2 // //PRINT "("+Hex_x+", "+Hex_y+") transforms TO ("+Hex2Grid_X(Hex_x,Hex_y)+" , "+Hex2Grid_Y(Hex_x,Hex_y)+")",50,350 //PRINT "i = "+Floor((Hex2Grid_X(Hex_x,Hex_y)+Hex2Grid_Y(Hex_x,Hex_y)+2)/3),50,370 //LOCAL Hex_x# = 0,Hex_y# = -2 //PRINT "("+Hex_x+", "+Hex_y+") transforms TO ("+Hex2Grid_X(Hex_x,Hex_y)+" , "+Hex2Grid_Y(Hex_x,Hex_y)+")",50,390 //PRINT "j = "+Floor((Hex2Grid_X(Hex_x,Hex_y)+Hex2Grid_Y(Hex_x,Hex_y)+2)/3),50,410
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
DRAWLINE Hex2Grid_X(X-hul*sqr3/2.0,Y-hul/2.0),Hex2Grid_Y(X-hul*sqr3/2.0,Y-hul/2.0),Hex2Grid_X(X,Y-hul),Hex2Grid_Y(X,Y-hul),RGB(255,0,0) DRAWLINE Hex2Grid_X(X,Y-hul),Hex2Grid_Y(X,Y-hul),Hex2Grid_X(X+hul*sqr3/2.0,Y-hul/2.0),Hex2Grid_Y(X+hul*sqr3/2.0,Y-hul/2.0),RGB(255,0,0) DRAWLINE Hex2Grid_X(X+hul*sqr3/2.0,Y-hul/2.0),Hex2Grid_Y(X+hul*sqr3/2.0,Y-hul/2.0) ,Hex2Grid_X(X+hul*sqr3/2.0,Y+hul/2.0),Hex2Grid_Y(X+hul*sqr3/2.0,Y+hul/2.0),RGB(255,0,0) DRAWLINE Hex2Grid_X(X+hul*sqr3/2.0,Y+hul/2.0),Hex2Grid_Y(X+hul*sqr3/2.0,Y+hul/2.0) ,Hex2Grid_X(X,Y+hul),Hex2Grid_Y(X,Y+hul),RGB(255,0,0) DRAWLINE Hex2Grid_X(X,Y+hul),Hex2Grid_Y(X,Y+hul) ,Hex2Grid_X(X-hul*sqr3/2.0,Y+hul/2.0),Hex2Grid_Y(X-hul*sqr3/2.0,Y+hul/2.0),RGB(255,0,0) DRAWLINE Hex2Grid_X(X-hul*sqr3/2.0,Y+hul/2.0),Hex2Grid_Y(X-hul*sqr3/2.0,Y+hul/2.0) ,Hex2Grid_X(X-hul*sqr3/2.0,Y-hul/2.0),Hex2Grid_Y(X-hul*sqr3/2.0,Y-hul/2.0),RGB(255,0,0) SETPIXEL Hex2Grid_X(X,Y),Hex2Grid_Y(X,Y),RGB(255,0,0) ENDFUNCTION // DRWCENTERHEX
// ------------------------------------------------------------- // // --- DASHEDLINE --- // ------------------------------------------------------------- // FUNCTION DashedLine: Start_X#, Start_Y#, End_X#, End_Y#, RGB_Color% LOCAL Total_Dist# =INTEGER( SQR(POW((End_X-Start_X),2)+POW((End_Y-Start_Y),2))) LOCAL X_Dist# = INTEGER(ABS(End_X-Start_X));//PRINT "X_Dist = "+X_Dist,30,30;SHOWSCREEN;KEYWAIT LOCAL Y_Dist# = INTEGER(ABS(End_Y-Start_Y)) LOCAL Delta_X# = (X_Dist/Total_Dist) LOCAL Delta_Y# = Y_Dist/Total_Dist LOCAL Segments# = INTEGER(Total_Dist/10.0)
FOR Count = 0 TO Segments DRAWLINE Start_X+Count*10.0*Delta_X,Start_Y+Count*10.0*Delta_Y,Start_X+Count*10.0*Delta_X+(Delta_X*5.0),Start_Y+Count*10.0*Delta_Y+(Delta_Y*5.0),RGB_Color NEXT
ENDFUNCTION // DASHEDLINE
// ------------------------------------------------------------- // // --- HEX2GRID_X --- // ------------------------------------------------------------- // FUNCTION Hex2Grid_X: x#, y# LOCAL a#,b#,u#,r# u = 1.0 r = u*SQR(3.0)/2 a = 1.0/(2.0*r) b = -0.5
RETURN Floor(a*x+b*y) //(INTEGER(((a*x+b*y)*1000000.0)+.000005)/1000000.0)
ENDFUNCTION // HEX2GRID_X
// ------------------------------------------------------------- // // --- HEX2GRID_Y --- // ------------------------------------------------------------- // FUNCTION Hex2Grid_Y: x#, y#
LOCAL c#,d#,u#,r# u = 1.0 r = u*SQR(3.0)/2 c = 1.0/r d = 0
RETURN Floor(c*x+d*y) //(INTEGER(((c*x+d*y)*1000000.0)+.000005)/1000000.0)
ENDFUNCTION // HEX2GRID_Y // ------------------------------------------------------------- // // --- FLOOR --- // ------------------------------------------------------------- // FUNCTION Floor: Num# IF Num>= 0;RETURN INTEGER(Num);ELSE;RETURN INTEGER(Num-1+POW(10,-10));ENDIF ENDFUNCTION // FLOOR
// ------------------------------------------------------------- // // --- 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) // FloodFill(Item.Screen_X,Item.Screen_Y,Item.HexColor) String$="";Temp$="" // String$ = Item.Column_Num;IF LEN(String$)<2 THEN String$ = "0"+String$// String$ = Hex2Grid_X(Item.Column_Num,Item.Row_Num);IF LEN(String$)<2 THEN String$ = "0"+String$
// Temp$ = Item.Row_Num ;IF LEN(Temp$)<2 THEN Temp$ = "0"+Temp$ Temp$ = Hex2Grid_Y(Item.Column_Num,Item.Row_Num);IF LEN(Temp$)<2 THEN Temp$ = "0"+Temp$// String$ = String$+Temp$ CenterPrint(String$,Item.Screen_X,Item.Screen_Y+5) USEASBMP;SHOWSCREEN NEXT
ENDFUNCTION // DRAW_HEX_BOARD
// ------------------------------------------------------------- // // --- CENTERPRINT --- // Prints any text centered on x in row y // ------------------------------------------------------------- // FUNCTION CenterPrint: InString$,Center_On_X,Y% LOCAL sw%,sh%,fw%,fh% GETSCREENSIZE sw,sh GETFONTSIZE fw,fh // Returns the starting x value to center a string on the screen with the print command. LOCAL Start% Start=(Center_On_X-INTEGER(LEN(InString$)*fw/2));IF Start < 0 THEN Start = 0 PRINT InString$,Start,Y ENDFUNCTION // CENTERSTRING$
|
[See topic]
|
2013-Apr-21 by CW in Hex Board Engine
04/16/13 I have hammered out a version of the transform mathematics to convert hexagon coordinates to Cartesian, and coded it. It looks good on paper, but the computer results are baffling. Each hex should have a unique address and be orderly, but this is not the case. (The negative numbers are not a problem. That just needs a simple offset to begin at 0000.) I don't know if there is something I have done wrong, or if there are aspects of the system which I do not properly understand. Maybe if I try drawing the modified hexes on top of the unmodified hexes, that will tell me something. I would post a screenshot or a zipped folder with the entire package, including fonts and specialized flood-fill routine, but I don't see a way to upload photos or post attachments to the blog. (I don't have a website to link to.) Ah well. It doesn't matter. -CW
|
[See topic]
|
|