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.
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
Post a Comment