At our last post we went on to the creation of a basic AI system, and sequenced it to attack if another unit is on sight. For this post we'll implement the battle initiation to our player, add some more visuals, fix some bugs and start working on other windows like statistics.
➤ Additions on UI
Since we add something in almost every post of this series, let's do some more visual additions here too. I noticed we don't have a city size indicator on our map, I added one on the UI where we'll display over it the size and name. Add a bit of transparency on it so it looks a bit faded.
Changed the code inside the city drawing loop to the following
For Y = 0 To MaxFactions
For X = 0 To MaxCitiesPF
If Faction(Y).City(X).Enabled = 1 Then
sRect = New Rectangle(625, 281, 96, 16)
dRect = New Rectangle(GridWorld(Faction(Y).City(X).TileX, Faction(Y).City(X).TileY).SX + OffSetX - 44 * ZoomVar, GridWorld(Faction(Y).City(X).TileX, Faction(Y).City(X).TileY).SY + OffSetY - 30 * ZoomVar, 140 * ZoomVar, 20 * ZoomVar)
DrawTexturedQuad(sRect, dRect, 1120, 720, 3, 1.0F, 1, 1, 1, 0.7)
Dim CityPopulation As Integer = (51 + (Faction(Y).City(X).Population \ 200)) TexY = CityPopulation \ 17
TexX = CityPopulation - TexY * 17
DrawText((CityPopulation - TexY * 17) + 1, GridWorld(Faction(Y).City(X).TileX, Faction(Y).City(X).TileY).SX + OffSetX - 38 * ZoomVar, GridWorld(Faction(Y).City(X).TileX, Faction(Y).City(X).TileY).SY + OffSetY - 24 * ZoomVar, 1.2 * ZoomVar, 1, FactionColors(Y).R, FactionColors(Y).G, FactionColors(Y).B, 1)
DrawText(Faction(Y).City(X).Name, GridWorld(Faction(Y).City(X).TileX, Faction(Y).City(X).TileY).SX + OffSetX - 12 * ZoomVar, GridWorld(Faction(Y).City(X).TileX, Faction(Y).City(X).TileY).SY + OffSetY - 24 * ZoomVar, 1.2 * ZoomVar, 1, FactionColors(Y).R, FactionColors(Y).G, FactionColors(Y).B, 1)
If TexX <= 6 Then
sRect = New Rectangle(TexX * 64, TexY * 40, 64, 40)
Else
sRect = New Rectangle(6 * 64, TexY * 40, 64, 40)
End If
dRect = New Rectangle(GridWorld(Faction(Y).City(X).TileX, Faction(Y).City(X).TileY).SX + OffSetX, GridWorld(Faction(Y).City(X).TileX, Faction(Y).City(X).TileY).SY + OffSetY - 8 * ZoomVar, 64 * ZoomVar, 40 * ZoomVar)
DrawTexturedQuad(sRect, dRect, 1088, 160, 0, 1.0F, 1, 1, 1, 1)
End If
Next
Next
You'll also notice that I changed the population division for size to 100 instead of 20000 which was way too much.
Now that there is a placeholder for our city size and name, let's also display our turn number and date on our main UI side bar.
Just add the following (inside our UI drawing code), which checks which turn we are on, and translates it to a date.
Dim GameTimeToDate As String
If GameTime < 200 Then
GameTimeToDate = (200 - GameTime) * 10 & " BC"
Else
GameTimeToDate = (GameTime) * 10 & " AD"
End If
DrawText(GameTimeToDate, 844 * (ScreenWidth / UISizeW), 150 * (ScreenHeight / UISizeH), 1.0, 1, 0.8, 0.8, 0.8, 1)
DrawText(GameTime, 912 * (ScreenWidth / UISizeW), 150 * (ScreenHeight / UISizeH), 1.0, 1, 0.8, 0.8, 0.8, 1)
You should see now on the top of our side bar right under the minimap these values.
Now in order to make our factions more recognizable on the map, I created separate outlined background sheets for units with different colors based on our faction colors and changed the unit outline code to draw based on their indexes. Code and result below. (Also changed the factioncolors sprite index to 10)
Changed this (Inside drawing units code)
DrawTexturedQuad(sRect, dRect, 1472, 448, 5, 1, 1 - FactionColors(Y).R, 1 - FactionColors(Y).G, 1 - FactionColors(Y).B, 0.7)
To this
DrawTexturedQuad(sRect, dRect, 1472, 448, 5 + Y, 1, 1, 1, 1, 0.75)
Now we have units and cities easily recognizable by color.
➤Fixing unit selection
Now, to fix some things first of which was that after enemy faction finished turn, you had to press space button to select your unit. (Add the following and the end of END_TURN_STEPS code.
If UnitSelected < MaxUnitsPF Then
If Faction(0).Unit(UnitSelected + 1).ID <> 0 Then
UnitSelected += 1
Else
UnitSelected = 0
End If
Else
UnitSelected = 0
End If
On pressing space button there was a bug that caused to choose over maximum units, so the above code should be the one that is in button click event too.
➤ Player battle initiation
Added a declaration to hold a state where when mouse hovers over an available moving tile, that tile has an enemy unit on it.
Public UnitSelectedEnemyHover As Integer 'Direction Mouse Hovers over has an enemy unit
Change the code inside "MOUSE_HOVER_UNIT" to the following
Dim HoveringOver As Int16 = 0
Dim EnemyHover As Int16 = 10
For Q = 0 To 7
If GridPX = Faction(FactionID).Unit(ID).TileToM(Q).X And GridPY = Faction(FactionID).Unit(ID).TileToM(Q).Y And Faction(FactionID).Unit(ID).TileToMA(Q) = True Then
UnitSelectedMouseHover = Q
HoveringOver = 1
For Y = 1 To MaxFactions
For X = 0 To MaxUnitsPF
If Faction(Y).Unit(X).TileX = GridPX And Faction(Y).Unit(X).TileY = GridPY And Faction(Y).Unit(X).ID <> 0 Then
EnemyHover = Q
TargetF = Y
TargetU = X
End If
Next
Next
Exit For
End If
EnemyHover = 10
Next
UnitSelectedEnemyHover = EnemyHover
If HoveringOver = 0 Then
UnitSelectedMouseHover = 10
End If
Where the addition is that when we check available tiles to move we also check if there is a unit there and hold the available tile index.
Inside the Z loop we have on our drawing units code add the following
If UnitSelectedEnemyHover = Z Then
sRect = New Rectangle(1216, 392, 64, 56) 'Y * 56
DrawTexturedQuad(sRect, dRect, 1472, 448, 5 + Y, 1.1, 1, 1, 1, 1) 'GridWorld(Faction(Y).Unit(X).TileX, Faction(Y).Unit(X).TIleY).Z
DrawTexturedQuad(sRect, dRect, 1472, 448, 1, 1.1, 1, 1, 1, 1) 'GridWorld(Faction(Y).Unit(X).TileX, Faction(Y).Unit(X).TIleY).Z
End If
To draw the battle initiation icon.
Now to initiate a battle, we'll go to mouse click.
ElseIf Func = "MOUSE_MOVE_UNIT" Then
If UnitSelectedMouseHover <> 10 And Faction(FactionID).Unit(UnitSelected).OnTheMove = 0 And Faction(FactionID).Unit(UnitSelected).TurnPoints > 0 And Faction(FactionID).Unit(UnitSelected).ID <> 0 And UnitSelectedEnemyHover = 10 Then
Faction(FactionID).Unit(UnitSelected).TargetX = GridWorld(Faction(FactionID).Unit(UnitSelected).TileToM(UnitSelectedMouseHover).X, Faction(FactionID).Unit(UnitSelected).TileToM(UnitSelectedMouseHover).Y).SX
Faction(FactionID).Unit(UnitSelected).TargetY = GridWorld(Faction(FactionID).Unit(UnitSelected).TileToM(UnitSelectedMouseHover).X, Faction(FactionID).Unit(UnitSelected).TileToM(UnitSelectedMouseHover).Y).SY
Faction(FactionID).Unit(UnitSelected).OnTheMove = 1
Faction(FactionID).Unit(UnitSelected).TileToMC = UnitSelectedMouseHover
Faction(FactionID).Unit(UnitSelected).TurnPoints -= 1
ElseIf UnitSelectedMouseHover <> 10 And Faction(FactionID).Unit(UnitSelected).OnTheMove = 0 And Faction(FactionID).Unit(UnitSelected).TurnPoints > 0 And Faction(FactionID).Unit(UnitSelected).ID <> 0 And UnitSelectedEnemyHover <> 10 Then
If Faction(FactionID).Unit(UnitSelected).TurnPoints > 0 Then
ApplyDamage(FactionID, UnitSelected, TargetF, TargetU)
Faction(FactionID).Unit(UnitSelected).TurnPoints -= 1
End If
End If
Now that we can initiate a battle by clicking on that enemy unit tile, let's go back to our rendering code where we draw the damage visuals, and we remove the attack damage from the health and add the following to remove the unit if it takes too much damage.
If Faction(Y).Unit(X).Health <= 0 Then
Faction(Y).Unit(X).ID = 0
End If
While doing so I found a bug in which the enemy units where going after dead units so I modified the enemy code a bit inside Get_Unit_Fov sub
If Faction(I).Unit(Q).TileX = X And Faction(I).Unit(Q).TileY = Y And I <> FactionID Then
Changed to
If Faction(I).Unit(Q).TileX = X And Faction(I).Unit(Q).TileY = Y And I <> FactionID And Faction(I).Unit(Q).ID <> 0 Then
In order for enemy units to not chase units that had their ID revert back to 0
Inside enemyfactions sub this was also changed since it made enemy units to do multiple damage
ApplyDamage(I, Q, TargetF, TargetU)
CounterT = 1
to
ApplyDamage(I, Q, TargetF, TargetU)
CounterT = 1
Faction(I).Unit(Q).TurnPoints -= 1
➤ Adding some more abilities to units
We are going to add some abilities to our worker units in particular and to all our units an ability to fortify so their defense capability goes up.
We'll need to add a couple of buttons on our sidebar.
Inside GameButtons("CREATE") add the following buttons
SButton(91).Text = "Next Unit"
SButton(91).Enabled = 1
SButton(91).X = 825 : SButton(91).Y = 467
SButton(91).Width = 15 : SButton(91).Height = 15
SButton(92).Text = "Fortify"
SButton(92).Enabled = 1
SButton(92).X = 841 : SButton(92).Y = 467
SButton(92).Width = 15 : SButton(92).Height = 15
Inside GameButtons("CLICK")
ElseIf SButtonHover = 91 Then 'Add under this, the code we have when we press space (the one we used on fixing unit selection above on this post)
Now for fortifying. Add this declaration inside our unitstruct which will hold a fortified state
Dim Fortified As Int16
Inside our Unit_F("MOUSE_MOVE_UNIT") add the following to both cases of our clause
Faction(FactionID).Unit(UnitSelected).Fortified = 0 'If the unit moves or attacks, it loses it's fortified ability
Now moving to our button click add the following code
ElseIf SButtonHover = 92 Then 'Fortifying unit
If Faction(0).Unit(UnitSelected).TurnPoints > 0 Then 'If selected unit has at least 1 turn point left
Faction(0).Unit(UnitSelected).TurnPoints -= 1
Faction(0).Unit(UnitSelected).Fortified = 2
'Then select next unit
If UnitSelected < MaxUnitsPF Then
If Faction(0).Unit(UnitSelected + 1).ID <> 0 Then
UnitSelected += 1
Else
UnitSelected = 0
End If
Else
UnitSelected = 0
End If
End If
So if a unit has turn points it will fortify lose one turn point and the selection will move to the next available unit.
Now let's go to our rendering code where we have the damage applying and modify it as seen below
Faction(Y).Unit(X).Health -= Faction(Y).Unit(X).DamageApl
to the following
Faction(Y).Unit(X).Health -= Faction(Y).Unit(X).DamageApl / Faction(Y).Unit(X).Fortified
Now if a unit is fortified, it will get half the damage applied. Let's add some visual addition so the player knows if the unit is fortified. I just added the following code after the unit health and turn point bar and a small cube in the sprite sheet.
'Fortify
If Faction(Y).Unit(X).Fortified = 0 Then
sRect = New Rectangle(858, 297, 7, 6)
Else
sRect = New Rectangle(858, 303, 7, 6)
End If
dRect = New Rectangle(Faction(Y).Unit(X).X + OffSetX + 51 * ZoomVar, Faction(Y).Unit(X).Y + OffSetY - 34 * ZoomVar, 8 * ZoomVar, 8 * ZoomVar)
DrawTexturedQuad(sRect, dRect, 1120, 720, 3, 1.0F, 1, 1, 1, 1)
Now let's do an addition to our normal ability button, the one we click to create a city
Went over to ParseMap sub which we used to create a map and generate resources on it based on tiles and added the following clause
ElseIf func = "NEWIDOVER" Then
For X = 0 To MaxGridX
For Y = 0 To MaxGridY
If GridWorld(X, Y).IDOver = 30 Or GridWorld(X, Y).IDOver = 49 Or GridWorld(X, Y).IDOver = 50 Then
GridWorld(X, Y).IDResource = 4
End If
Next
Next
Now when we click Sbutton 1 (the one we use to create a city if the unit is a settler)
ElseIf faction(0).unit(UnitSelected).id = 2 Then 'If that unit is a worker
If GridWorld(Faction(0).Unit(UnitSelected).TileX, Faction(0).Unit(UnitSelected).TileY).ID = 4 Or GridWorld(Faction(0).Unit(UnitSelected).TileX, Faction(0).Unit(UnitSelected).TileY).ID = 5 Then
GridWorld(Faction(0).Unit(UnitSelected).TileX, Faction(0).Unit(UnitSelected).TileY).IDOver = 50
ParseMap("NEWIDOVER")
Faction(0).Unit(UnitSelected).ID = 0
ElseIf GridWorld(Faction(0).Unit(UnitSelected).TileX, Faction(0).Unit(UnitSelected).TileY).ID = 7 Or GridWorld(Faction(0).Unit(UnitSelected).TileX, Faction(0).Unit(UnitSelected).TileY).ID = 8 Then
GridWorld(Faction(0).Unit(UnitSelected).TileX, Faction(0).Unit(UnitSelected).TileY).IDOver = 30
ParseMap("NEWIDOVER")
Faction(0).Unit(UnitSelected).ID = 0
ElseIf GridWorld(Faction(0).Unit(UnitSelected).TileX, Faction(0).Unit(UnitSelected).TileY).ID = 15 Then
GridWorld(Faction(0).Unit(UnitSelected).TileX, Faction(0).Unit(UnitSelected).TileY).IDOver = 49
ParseMap("NEWIDOVER")
Faction(0).Unit(UnitSelected).ID = 0
Else
End If
Now you can change the resources around your cities. Let's add this to our enemy worker units too now.
Inside our EnemyFactions sub added a clause just for unit id = 2
ElseIf faction(i).unit(q).id = 2 Then
RndN = Int(Rnd() * 10)
UnitSelected = Q
CounterT = 100
Do Until CounterT = 0
If RndN <= 7 Then
Unit_F("MOVE_CALCULATE", Q, I) 'Calculate available tiles
RndTile = Int(Rnd() * 8)
Do Until Faction(I).Unit(Q).TileToMA(RndTile) = True
RndTile = Int(Rnd() * 8)
Loop
UnitSelectedMouseHover = RndTile
Unit_F("MOUSE_MOVE_UNIT", Q, I) 'Move unit
Else
If GridWorld(Faction(I).Unit(Q).TileX, Faction(I).Unit(Q).TileY).ID = 4 Or GridWorld(Faction(I).Unit(Q).TileX, Faction(I).Unit(Q).TileY).ID = 5 Then
GridWorld(Faction(I).Unit(Q).TileX, Faction(I).Unit(Q).TileY).IDOver = 50
ParseMap("NEWIDOVER")
Faction(I).Unit(Q).ID = 0
ElseIf GridWorld(Faction(I).Unit(Q).TileX, Faction(I).Unit(Q).TileY).ID = 7 Or GridWorld(Faction(i).Unit(Q).TileX, Faction(i).Unit(Q).TileY).ID = 8 Then
GridWorld(Faction(I).Unit(Q).TileX, Faction(I).Unit(Q).TileY).IDOver = 30
ParseMap("NEWIDOVER")
Faction(I).Unit(Q).ID = 0
ElseIf GridWorld(Faction(I).Unit(Q).TileX, Faction(I).Unit(Q).TileY).ID = 15 Then
GridWorld(Faction(I).Unit(Q).TileX, Faction(I).Unit(Q).TileY).IDOver = 49
ParseMap("NEWIDOVER")
Faction(I).Unit(Q).ID = 0
Else
End If
Exit Do
End If
CounterT -= 1
Loop
Another addition we'll do in the AI code is to make enemy settlers search for unclaimed territory before building a city
So under this clause inside our AI code If Faction(I).Unit(Q).ID < 2 Then 'Settler and inside our loop inside this Else 'Create a city
If GridWorld(Faction(I).Unit(UnitSelected).TileX, Faction(I).Unit(UnitSelected).TileY).LAND <> I Then 'If the unit is not over it's own territory
➤ Adding a statistics screen
In this post we'll add a simple statistics screen, in which we will be able to see which faction is more powerful on the current turn.
I added a small statistics window to the sprite sheet with 4 placeholder for values (Units, Territory, Research, Population).
So let's start programming our statistics window!
On GameButtons("CREATE"), we create our button
SButton(93).Text = "Statistics"
SButton(93).Enabled = 1
SButton(93).X = 846 : SButton(93).Y = 487
SButton(93).Width = 15 : SButton(93).Height = 15
SButton(94).Text = "Statistics"
SButton(94).Enabled = 1
SButton(94).X = 720 : SButton(94).Y = 508
SButton(94).Width = 93 : SButton(94).Height = 18
SButton(94).UIState = 3
On GameButtons("CLICK"), we create the link to our click button event
ElseIf SButtonHover = 93 Then 'If the mouse is statistics button
SUIWindow = 3
ElseIf SButtonHover = 94 Then 'If the mouse is over close statistics button
If SUIWindow = 3 Then
SUIWindow = 0
End If
Inside drawcalls where we draw our UI
ElseIf SUIWindow = 3 Then 'STATISTICS WINDOW
'Statistics window
sRect = New Rectangle(857, 325, 249, 136)
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, 1120, 720, 3, 1.0F, 1, 1, 1, 1)
Dim BarWidth(MaxFactions, 3) As Point
Dim TotalBarWidth(3) As Integer
Dim TotalCount As Integer
Dim ScrBarWidth(MaxFactions, 3) As Integer
For Y = 0 To MaxFactions
'Count Units
TotalCount = 0
For X = 0 To MaxUnitsPF
If Faction(Y).Unit(X).ID <> 0 Then
TotalCount += 1
End If
Next
BarWidth(Y, 0).Y = TotalCount
'Count Territory
BarWidth(Y, 1).Y = Faction(Y).LandOwned(0) + Faction(Y).LandOwned(1) + Faction(Y).LandOwned(2) + Faction(Y).LandOwned(3)
'Count Research
For X = 0 To 28
If Lib_Research_S(Y, X).Researched = 0 Then
BarWidth(Y, 2).Y += 1
End If
Next
'Count Population
BarWidth(Y, 3).Y = Faction(Y).STLibrary.BasicA(3)
TotalBarWidth(0) += BarWidth(Y, 0).Y
TotalBarWidth(1) += BarWidth(Y, 1).Y
TotalBarWidth(2) += BarWidth(Y, 2).Y
TotalBarWidth(3) += BarWidth(Y, 3).Y
Next
For X = 0 To 3
For Y = 0 To MaxFactions
If TotalBarWidth(X) <> 0 Then
dRect = New Rectangle(651 * (ScreenWidth / UISizeW), (426 + X * 20 + Y * (14 / MaxFactions)) * (ScreenHeight / UISizeH), ((BarWidth(Y, X).Y * 161) / TotalBarWidth(X)) * (ScreenWidth / UISizeW), (14 / MaxFactions) * (ScreenHeight / UISizeH))
DrawQuad(dRect.X, dRect.Y, dRect.Width, dRect.Height, 1.0F, 0.45F, FactionColors(Y).R, FactionColors(Y).G, FactionColors(Y).B)
End If
Next
Next
And the result can be seen on the following image.
What we did is to simply get the values for these 4 properties, and translate them to a width appropriate to our statistics window.
Comments
Post a Comment