Strategy game data, working with the UI (Post #18 / Strategy game #9)

 Now that our city is built, we can delve a bit on the management aspect of the game, create some extra visuals and build units based on chosen production.


 Changes to our code

Before we go calculating strategy data, we need to change a bit our code so we have some basic insight what land our factions hold and the resources on it. I removed the fog of war from our FOV_FOW_Grid() sub and moved it unto our Faction_F(...) sub as follows

        ElseIf func = "REFRESH_FACTIONS" Then

        For Q = 0 To MaxGridX
                For I = 0 To MaxGridY
                    GridWorld(Q, I).LAND = 10 'No faction index
                Next
            Next

            For Q = 0 To MaxCitiesPF
                For I = 0 To MaxFactions
                    If Faction(I).City(Q).Enabled = 1 Then
                        For Y = (Faction(I).City(Q).TileY - 3) To (Faction(I).City(Q).TileY + 3)
                            For X = (Faction(I).Unit(Q).TileX - 3) To (Faction(I).Unit(Q).TileX + 3)
                                If X >= 0 And X <= MaxGridX And Y >= 0 And Y <= MaxGridY Then
                                    If GridWorld(X, Y).FOV = 0 Then GridWorld(X, Y).FOV = 1
                                    GridWorld(X, Y).FOW = 1
                                   GridWorld(X, Y).LAND = I
                                    GridWorld(X, Y).CITY = Q 'Don't forget to declare City and Land on our Grid structure
                                End If
                            Next
                        Next
                    End If
                Next
            Next

 Now I also created this button (shown in the following picture) to show our player a different color on our tiles for which faction owns them.

The next code goes to 

GameButtons("CREATE")      

      SButton(2).Text = "Faction Colors"
            SButton(2).Enabled = 1
            SButton(2).X = 924 : SButton(1).Y = 467
            SButton(2).Width = 15 : SButton(1).Height = 15

 GameButtons("CLICK")

 ElseIf SButtonHover = 2 Then 'If the mouse is over faction colors button
                If GameColors = 0 Then
                    GameColors = 1
                Else
                    GameColors = 0
                End If
            End If

Public variables

    Public GameColors As Int16 

Draw_Calls("GRID_TEXTURED") 'Right after drawing map resources

 If GameColors = 1 Then
                                If GridWorld(X, Y).LAND < 10 Then '10 is our no faction owned index
                                    sRect = New Rectangle(GridWorld(X, Y).LAND * 64, 0, 64, 40)
                                    dRect = New Rectangle(GridWorld(X, Y).SX + OffSetX, GridWorld(X, Y).SY + OffSetY - 8 * ZoomVar, 64 * ZoomVar, 40 * ZoomVar)
                                    DrawTexturedQuad(sRect, dRect, 384, 40, 6, 1.0F, 1, 1, 1, 0.4)
                                End If
                            End If

And a new sprite sheet for faction colors.

        TextureLoadingBmp = My.Resources.FactionColors
        LoadTexture(ImgTex(6), TextureLoadingBmp)

And these code parts were updated since it crashed when unit available tiles were outside our grid. (Drawing units) - I planned to do a debugging post but I couldn't wait, since this crashed a lot. The second part is just another if inside our "MOUSE_MOVE_UNIT" on_click that kept moving a settler even after it created a city.

For Z = 0 To 7
                                If Faction(Y).Unit(X).TileToM(Z).X >= 0 And Faction(Y).Unit(X).TileToM(Z).X <= MaxGridX And Faction(Y).Unit(X).TileToM(Z).Y >= 0 And Faction(Y).Unit(X).TileToM(Z).Y <= MaxGridY Then
                                    sRect = New Rectangle((11 + Z) * 64, 392, 64, 56) 'Y * 56
                                    dRect = New Rectangle(GridWorld(Faction(Y).Unit(X).TileToM(Z).X, Faction(Y).Unit(X).TileToM(Z).Y).SX + OffSetX, GridWorld(Faction(Y).Unit(X).TileToM(Z).X, Faction(Y).Unit(X).TileToM(Z).Y).SY + OffSetY - 24 * ZoomVar, 64 * ZoomVar, 56 * ZoomVar)
                                    If Z = UnitSelectedMouseHover Then
                                        DrawTexturedQuad(sRect, dRect, 1472, 448, 1, 1, 1, 0, 0, 0.6)
                                    Else
                                        DrawTexturedQuad(sRect, dRect, 1472, 448, 1, 1, 1, 1, 1, 0.6)
                                    End If
                                End If
                            Next

 "MOUSE_MOVE_UNIT"

This part : If UnitSelectedMouseHover <> 10 And Faction(0).Unit(UnitSelected).OnTheMove = 0 And Faction(0).Unit(UnitSelected).TurnPoints > 0 And Faction(0).Unit(UnitSelected).ID <> 0 Then

Added this : (And Faction(0).Unit(UnitSelected).ID <> 0 )

 

Now combining all the above, when you press that new button you should have a result like the one shown below (faction coloring works on cities not units)

Now when we have more factions creating cities we'll see the other colors of our new sprite sheet coloring our tiles. They show borders, and since we have borders we can calculate our in border available resources.

            'Nulling our resources
            For I = 0 To MaxFactions
                For Q = 1 To 10
                    Faction(I).STLibrary.Resource(Q) = 0
                Next
                For Q = 0 To 3
                    Faction(I).LandOwned(Q) = 0
                    Faction(I).CityPoints(Q) = 0
                Next
                For Q = 0 To MaxCitiesPF
                    Faction(I).City(Q).Prosperity = 0
                Next
            Next
                'Calculate resources based on borders
                For Q = 0 To MaxGridX
                For I = 0 To MaxGridY
                    If GridWorld(Q, I).LAND <> 10 Then 'There is a faction claim on the tile
                        If GridWorld(Q, I).IDResource > 0 Then 'There is a resource on that tile
                            Faction(GridWorld(Q, I).LAND).STLibrary.Resource(GridWorld(Q, I).IDResource) += 1

                            Faction(GridWorld(Q, I).LAND).City(GridWorld(Q, I).CITY).Prosperity += 1
                        End If

                        If GridWorld(Q, I).ID <= 3 Then 'Water tiles
                            Faction(GridWorld(Q, I).LAND).LandOwned(0) += 1
                        ElseIf GridWorld(Q, I).ID <= 6 Then 'Snow tiles
                            Faction(GridWorld(Q, I).LAND).LandOwned(1) += 1
                        ElseIf GridWorld(Q, I).ID <= 13 Then 'Forest tiles
                            Faction(GridWorld(Q, I).LAND).LandOwned(2) += 1
                        ElseIf GridWorld(Q, I).ID <= 16 Then 'Desert and Sand tiles
                            Faction(GridWorld(Q, I).LAND).LandOwned(3) += 1
                        End If
                    End If
                Next
            Next

We can test this if we build a city next to a resource and add the resource values to show on our UI with the code below. (Add it to our UI rendering code)

            For Y = 0 To 9
                If Y <= 4 Then
                    DrawText(Faction(0).STLibrary.Resource(Y + 1), 850 * (ScreenWidth / UISizeW), (174 + (Y * 20)) * (ScreenHeight / UISizeH), 1.1, 1, 0.8, 0.8, 0.8, 1)
                Else
                    DrawText(Faction(0).STLibrary.Resource(Y + 1), 915 * (ScreenWidth / UISizeW), (174 + ((Y - 5) * 20)) * (ScreenHeight / UISizeH), 1.1, 1, 0.8, 0.8, 0.8, 1)
                End If
            Next


Basic strategy game elements

Now in order to have some strategy depth we'll add some data to our faction structure. This can be really tricky to do when trying to create a balanced game, since all of these data will interact to create a certain process. For our tutorial purposes I'll create an imaginary faction management system which will run through the next algorithm, which is pretty much explanatory on it's own since it's pretty basic. (Have in mind that I'm creating this tutorial while programming it, so I don't know what will work and probably it will change a lot through the process - I doubt the game will be balanced).

 The variables I added to my faction structure are the following. The second one refers to the strategylibrary structure.

Dim LandOwned() As Integer

Dim CityPoints() As Integer

Dim STLibrary As StrategyLibrary

  Public Structure StrategyLibrary
        'Resources
        Dim Resource() As Integer 'And the following index references
        '(1) Copper As Integer        '(2) Iron As Integer
        '(3) Dairy As Integer        '(4) Agriculture As Integer
        '(5) FishSmall As Integer        '(6) FishLarge As Integer
        '(7) Oil As Integer        '(8) HeavyMetals As Integer
        '(9) Gems As Integer        '(10) Gold As Integer


        Dim BasicA() As Integer 'And the following index references (where 2,4,6,8 are modifiers for 1,3,5,7)
        '(1) Treasury As Integer         '(2) Income As Integer
        '(3) Population As Integer        '(4) Growth As Integer
        '(5) Technology As Integer        '(6) Advancement As Integer
        '(7) Construction As Integer        '(8) Industrialization As Integer


        Dim PolicyPoints As Integer
        Dim BasicB() As Integer
        '(1) Education As Integer        '(2) Taxation As Integer
        '(3) Luxuries As Integer        '(4) Unemployment As Integer
        '(5) Civility As Integer        '(6) Militarism As Integer
        '(7) Science As Integer

    End Structure

And in our Faction_F("CREATE_FACTIONS") 

                ReDim Faction(I).LandOwned(3)
                ReDim Faction(I).CityPoints(3)
                ReDim Faction(I).STLibrary.Resource(10)
                ReDim Faction(I).STLibrary.BasicA(8)
                ReDim Faction(I).STLibrary.BasicB(7)

'Also added resource generation for gold and gems on "GENERATE_RESOURCES"

Now we have our references which are heavily changed by resources and modifiers and modifiers that are affected by policy points. Let's update our Faction_F to hold and change these data.

  ElseIf func = "END_TURN" Then

            For I = 0 To MaxFactions
                Faction(I).STLibrary.BasicA(2) = Faction(I).CityPoints(1) + (1 + Faction(I).STLibrary.BasicB(1) + Faction(I).STLibrary.BasicB(2) + Faction(I).STLibrary.BasicB(4) - Faction(I).STLibrary.BasicB(6)) * ((Faction(I).LandOwned(0) \ 50) + (Faction(I).LandOwned(1) \ 70) + (Faction(I).LandOwned(2) \ 45) + (Faction(I).LandOwned(3) \ 150) + Faction(I).STLibrary.Resource(9) + Faction(I).STLibrary.Resource(10)) '(2) Calculating Income by total land and resources
                Faction(I).STLibrary.BasicA(4) = Faction(I).CityPoints(0) + (1 - Faction(I).STLibrary.BasicB(3) + Faction(I).STLibrary.BasicB(4) + Faction(I).STLibrary.BasicB(5) - Faction(I).STLibrary.BasicB(2)) * (Faction(I).STLibrary.Resource(3) + Faction(I).STLibrary.Resource(4) + Faction(I).STLibrary.Resource(5) + Faction(I).STLibrary.Resource(6) + Faction(I).STLibrary.Resource(7)) '(2) Calculating Population increase by policies and resources
                Faction(I).STLibrary.BasicA(6) = Faction(I).CityPoints(2) + (1 + Faction(I).STLibrary.BasicB(1) + Faction(I).STLibrary.BasicB(5) + Faction(I).STLibrary.BasicB(6) - Faction(I).STLibrary.BasicB(4) - Faction(I).STLibrary.BasicB(7)) * (Faction(I).STLibrary.Resource(1) + Faction(I).STLibrary.Resource(2) + Faction(I).STLibrary.Resource(7) + Faction(I).STLibrary.Resource(8)) '(2) Calculating Technology increase by policies and resources
                Faction(I).STLibrary.BasicA(8) = Faction(I).CityPoints(2) + (1 + Faction(I).STLibrary.BasicB(1) + Faction(I).STLibrary.BasicB(5) + Faction(I).STLibrary.BasicB(6) + Faction(I).STLibrary.BasicB(7) - Faction(I).STLibrary.BasicB(3) - Faction(I).STLibrary.BasicB(4)) * (Faction(I).STLibrary.Resource(1) + Faction(I).STLibrary.Resource(2) + Faction(I).STLibrary.Resource(7) + Faction(I).STLibrary.Resource(8) + Faction(I).STLibrary.Resource(10)) '(2) Calculating Industrialization increase by policies and resources

                Faction(I).STLibrary.BasicA(1) += Faction(I).STLibrary.BasicA(2) '(1) Calculating Treasury by adding Inc
                Faction(I).STLibrary.BasicA(3) += Faction(I).STLibrary.BasicA(4) '(3) Calculating Population by adding Growth
                Faction(I).STLibrary.BasicA(5) += Faction(I).STLibrary.BasicA(6) '(1) Calculating Technology by adding Advancement
                Faction(I).STLibrary.BasicA(7) += Faction(I).STLibrary.BasicA(8) '(3) Calculating Construction by adding Industrialization
 

                Faction(I).CityPoints(0) = 0 'Popul from cities modifier
                Faction(I).CityPoints(1) = 0 'Inc from cities modifier
                Faction(I).CityPoints(2) = 0 'Unemp from cities modifier

                For Q = 0 To MaxCitiesPF
                    If Faction(I).City(Q).Enabled = 1 Then
                        Faction(I).City(Q).Population += Faction(I).City(Q).Prosperity * Faction(I).STLibrary.BasicA(4)
                        Faction(I).City(Q).Luxuries += Faction(I).City(Q).Prosperity * Faction(I).STLibrary.BasicA(2)
                        Faction(I).City(Q).Unemployment += Faction(I).City(Q).Prosperity * Faction(I).STLibrary.BasicA(2) * Faction(I).STLibrary.BasicA(4)
                        Faction(I).City(Q).Civility = 100
                        Faction(I).City(Q).Income += (Faction(I).City(Q).Civility + Faction(I).City(Q).Unemployment + Faction(I).City(Q).Luxuries + Faction(I).City(Q).Population) / 4
                        Faction(I).CityPoints(0) += Faction(I).City(Q).Population \ 500
                        Faction(I).CityPoints(1) += Faction(I).City(Q).Luxuries \ 500
                        Faction(I).CityPoints(2) += Faction(I).City(Q).Population \ 800
                    End If
                Next          

 Next

What I did here was to just throw in resources, land and policies to mix up and give values to our faction data. This was done inside "END_TURN" so let's connect this to our END TURN button on our UI.

Gamebuttons("CREATE")

            SButton(3).Text = "End Turn"
            SButton(3).Enabled = 1
            SButton(3).X = 825 : SButton(3).Y = 509
            SButton(3).Width = 130 : SButton(3).Height = 26

Gamebuttons("CLICK")

ElseIf SButtonHover = 3 Then 'If the mouse is over end turn
                Faction_F("END_TURN")

Try creating a city and clicking end turn. When you end the turn it will calculate available resources pass the rest of the data through the above algorithm and give new data.

Now let's go a bit further and add some more things to our code.

 I created some variables and a sub (Call RandomNames() on load of the application), to hold color values (I did it on a previous post now we'll actually update it and use it) and a sub to create random city names with the simplest way there is. It adds a vowel then a consonant on a random sized word.

 Public Structure ColorArrNull
        Dim R As Single
        Dim G As Single
        Dim B As Single
    End Structure

    Public FactionColors(9) As ColorArrNull

    Public CityNames(50) As String
    Public Sub RandomNames()
        Dim X As Integer
        Dim Y As Integer
        Dim I, Q As Integer
        Dim RandomS As String
        Dim RandomSI As Integer
        Dim StrA As String = "AEIOUY"
        Dim StrB As String = "BCDFGHJKLMNPQRSTVWXZ"


        For I = 0 To 50
            Q = Int(Rnd() * 12) + 0
            For RandomSI = 0 To Q
                If RandomSI Mod 2 = 0 Then
                    X = Int(Rnd() * 6) + 1
                    RandomS = GetChar(StrA, X)
                Else
                    X = Int(Rnd() * 20) + 1
                    RandomS = GetChar(StrB, X)
                End If
                CityNames(I) &= RandomS
            Next
        Next

        FactionColors(0).R = 0 : FactionColors(0).G = 1 : FactionColors(0).B = 0
        FactionColors(1).R = 1 : FactionColors(1).G = 0 : FactionColors(1).B = 0
        FactionColors(2).R = 0 : FactionColors(2).G = 0 : FactionColors(2).B = 1
        FactionColors(3).R = 0 : FactionColors(3).G = 1 : FactionColors(3).B = 1
        FactionColors(4).R = 1 : FactionColors(4).G = 1 : FactionColors(4).B = 0
        FactionColors(5).R = 1 : FactionColors(5).G = 0.5 : FactionColors(5).B = 0
    End Sub

I also change the UI sprite sheet to the following so we can try opening our faction-city management window.

Add a variable to hold an index for which city to show on our new window. (If there is one)

Public SUICity As Integer 'Which City to show on faction management window

Update our city structure with the following

Dim GroundOn As Integer
        Dim ConstructTurns As Integer
        Dim ConstructionID As Integer
        Dim Income As Integer

Adding this on our city creation sub

If GridWorld(X, Y).ID <= 3 Then 'Water tiles
                Faction(FactionN).City(ID).GroundOn = 0
            ElseIf GridWorld(x, y).ID <= 6 Then 'Snow tiles
                Faction(FactionN).City(ID).GroundOn = 0
            ElseIf GridWorld(x, y).ID <= 13 Then 'Forest tiles
                Faction(FactionN).City(ID).GroundOn = 1
            ElseIf GridWorld(x, y).ID <= 16 Then 'Desert and Sand tiles
                Faction(FactionN).City(ID).GroundOn = 2
            End If

Adding the button

SButton(4).Text = "Faction & City Management"
            SButton(4).Enabled = 1
            SButton(4).X = 882 : SButton(4).Y = 487
            SButton(4).Width = 15 : SButton(4).Height = 15

On button Click

ElseIf SButtonHover = 4 Then 'If the mouse is over faction - city management
                SUIWindow = 1

On Render
            If SUIWindow = 1 Then
                'Faction - management window
                sRect = New Rectangle(280, 8, 535, 214)
                dRect = New Rectangle(ScreenWidth - 140 * (ScreenWidth / UISizeW) - sRect.Width * (ScreenWidth / UISizeW), (ScreenHeight - (sRect.Height + 5) * (ScreenHeight / UISizeH)), sRect.Width * (ScreenWidth / UISizeW), sRect.Height * (ScreenHeight / UISizeH))
                DrawTexturedQuad(sRect, dRect, 815, 548, 3, 1.0F, 1, 1, 1, 1)


                DrawText(Faction(0).STLibrary.BasicA(1), 415 * (ScreenWidth / UISizeW), (350) * (ScreenHeight / UISizeH), 1.2, 1, 0.8, 0.8, 0.8, 1)
                DrawText(Faction(0).STLibrary.BasicA(2), 415 * (ScreenWidth / UISizeW), (363) * (ScreenHeight / UISizeH), 1.2, 1, 0.8, 0.8, 0.8, 1)
                DrawText(Faction(0).STLibrary.BasicA(3), 415 * (ScreenWidth / UISizeW), (376) * (ScreenHeight / UISizeH), 1.2, 1, 0.8, 0.8, 0.8, 1)
                DrawText(Faction(0).STLibrary.BasicA(5), 415 * (ScreenWidth / UISizeW), (389) * (ScreenHeight / UISizeH), 1.2, 1, 0.8, 0.8, 0.8, 1)
                DrawText(Faction(0).STLibrary.BasicA(7), 415 * (ScreenWidth / UISizeW), (402) * (ScreenHeight / UISizeH), 1.2, 1, 0.8, 0.8, 0.8, 1)

                'City - management window
                If Faction(0).City(SUICity).Enabled = 1 Then
                    'City ground
                    sRect = New Rectangle(280 + 177 * Faction(0).City(SUICity).GroundOn, 222, 177, 59)
                    dRect = New Rectangle(ScreenWidth - 140 * (ScreenWidth / UISizeW) - 182 * (ScreenWidth / UISizeW), (ScreenHeight - (194) * (ScreenHeight / UISizeH)), sRect.Width * (ScreenWidth / UISizeW), sRect.Height * (ScreenHeight / UISizeH))
                    DrawTexturedQuad(sRect, dRect, 815, 548, 3, 1.0F, 1, 1, 1, 1)
                    DrawText(Faction(0).City(SUICity).Name, 686 * (ScreenWidth / UISizeW), (330) * (ScreenHeight / UISizeH), 1.2, 1, 0.8, 0.8, 0.8, 1)
                End If
            End If

 Since it's going to get complicated and a bit spaghetti code from this point forward, have in mind that when the strategy tutorial series is finished I'll post the whole code together and not in parts, in order for you to have the code and the series to refer on how to do things.

 

Comments