Automatic layering system
From VbGORE Visual Basic Online RPG Engine
This was originally part of an upgrade (Version 1.1.0 to be specific), but was omitted due to the complications it would bring to the typical user, and the amount that vbGORE would have to be altered to make it work (such as the help, GUIs, etc).
Contents |
Pros and Cons
Pros:
- Automatic layering - The layers are decided based on the Y axis along with the height of the Grh. This prevents having to break up certain graphics (like trees) into "behind" and "front" parts.
- Faster mapping - Because you don't have to worry about the layers as much, you will be able to map a lot faster.
- Less Grhs - There will be less Grhs because you won't have to break them into multiple parts.
Cons:
- Automatic layering - This is also a con, since you have to hope the automatic layering gives you what you want. If it does not, you have to do some cheap hacks to get it to work.
- Remake maps - Since the maps work completely different, you will have to remake them all.
How it works
Here is a copy-and-paste from the original entry in the upgrade guide:
"Added a new rendering system. How this system works is instead of what is drawn being decided on what layer the Grh is on, there are three tile types. These types are always below (layer 1 and 2), mixed (layer 3 to 5) and always above (layer 6). The always below is used for the ground tiles. Mixed is used for anything that has depth - trees, buildings, chairs, etc. Layer 6 is used for special cases, like birds or clouds, though it is not a very common type to have to use, which is why there is only one layer for it. The mixed layer works by sorting on a pseudo-Z axis calculated by the Y + Height of a Grh. This algorithm is also applied to particle effects (ie bless), Grh effects (ie Spike Field), characters (NPCs and PCs both), blood splatters (from when you hit a NPC / get hit) and projectiles (ie Ninja Star). Because of this new system, previously made maps will not function correctly. Though, you no longer have to split up your trees and have part of it on layer 2/3 and the other part on layer 4/5 just so you can walk in front of it and stand behind it, as the engine will do this for you. This also fixes a lot of issues with putting the shadows on these Grhs, since they are now just one Grh, so they cast just one shadow. For those who are worried about performance, there was no FPS drop when tested against ~500 Grhs on layer 3-5, so performance is not a concern."
Adding guide
Follow this guide just like you would any other upgrade guide, since this is how it was written (which is why it is in 3 parts). Start with the last on the end of the page, and move up to the first.
Fix - Animations
Open GameClient.vbp.
In module TileEngine, add:
<vb> Public Function Engine_GetFrameFromGrh(Grh As Grh) As Long '************************************************************ 'Get a Grh and return the frame (useful for animations) '************************************************************ Dim i As Long
'Check for a valid GrhIndex If Grh.GrhIndex < 1 Then Exit Function If Grh.GrhIndex > NumGrhs Then Exit Function 'Round down on the frame counter i = Int(Grh.FrameCounter) 'Check for a frame count overflow If i > GrhData(Grh.GrhIndex).NumFrames Then Exit Function 'Return the Grh index Engine_GetFrameFromGrh = GrhData(Grh.GrhIndex).Frames(Int(Grh.FrameCounter))
End Function</vb>
Find:
<vb>
Engine_AddToRenderList_Grh RenderList(), RenderListSize, RenderListIndex, BloodList(j).Grh.GrhIndex, X, Y, _
Y + GrhData(BloodList(j).Grh.GrhIndex).pixelHeight, -1, -1, -1, -1, 0, 1, 0</vb>
Replace with:
<vb>
Engine_AddToRenderList_Grh RenderList(), RenderListSize, RenderListIndex, Engine_GetFrameFromGrh(BloodList(j).Grh), X, Y, _
Y + GrhData(BloodList(j).Grh.GrhIndex).pixelHeight, -1, -1, -1, -1, 0, 1, 0
</vb>
Find:
<vb>
Engine_AddToRenderList_Grh RenderList(), RenderListSize, RenderListIndex, OBJList(j).Grh.GrhIndex, X, Y, _
Y + GrhData(OBJList(j).Grh.GrhIndex).pixelHeight, .Light(1), .Light(2), .Light(3), .Light(4), 0, 1, 1</vb>
Replace with:
<vb>
Engine_AddToRenderList_Grh RenderList(), RenderListSize, RenderListIndex, Engine_GetFrameFromGrh(OBJList(j).Grh), X, Y, _
Y + GrhData(OBJList(j).Grh.GrhIndex).pixelHeight, .Light(1), .Light(2), .Light(3), .Light(4), 0, 1, 1
</vb>
Find:
<vb>
Engine_AddToRenderList_Grh RenderList(), RenderListSize, RenderListIndex, MapData(.TileX, .TileY).Graphic(Layer).GrhIndex, _
.PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, .PixelPosY + PixelOffsetY + _
GrhData(MapData(.TileX, .TileY).Graphic(Layer).GrhIndex).pixelHeight, MapData(.TileX, .TileY).Light(1), _
MapData(.TileX, .TileY).Light(2), MapData(.TileX, .TileY).Light(3), MapData(.TileX, .TileY).Light(4), _
0, 0, MapData(.TileX, .TileY).Shadow(Layer)
</vb>
Replace with:
<vb>
Engine_AddToRenderList_Grh RenderList(), RenderListSize, RenderListIndex, Engine_GetFrameFromGrh(MapData(.TileX, .TileY).Graphic(Layer)), _
.PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, .PixelPosY + PixelOffsetY + _
GrhData(MapData(.TileX, .TileY).Graphic(Layer).GrhIndex).pixelHeight, MapData(.TileX, .TileY).Light(1), _
MapData(.TileX, .TileY).Light(2), MapData(.TileX, .TileY).Light(3), MapData(.TileX, .TileY).Light(4), _
0, 0, MapData(.TileX, .TileY).Shadow(Layer)
</vb>
Find:
<vb>
Engine_AddToRenderList_Grh RenderList(), RenderListSize, RenderListIndex, GrhData(EffectList(j).Grh.GrhIndex).Frames(Int(EffectList(j).Grh.FrameCounter)), X, Y, _
Y + GrhData(EffectList(j).Grh.GrhIndex).pixelHeight, -1, -1, -1, -1, EffectList(j).Angle, 0, 1
</vb>
Replace with:
<vb>
Engine_AddToRenderList_Grh RenderList(), RenderListSize, RenderListIndex, Engine_GetFrameFromGrh(EffectList(j).Grh), X, Y, _
Y + GrhData(EffectList(j).Grh.GrhIndex).pixelHeight, -1, -1, -1, -1, EffectList(j).Angle, 0, 1
</vb>
Find:
<vb>
Engine_AddToRenderList_Grh RenderList(), RenderListSize, RenderListIndex, ProjectileList(j).Grh.GrhIndex, _
X, Y, Y + GrhData(ProjectileList(j).Grh.GrhIndex).pixelHeight, -1, -1, -1, -1, ProjectileList(j).Rotate, 0, 1
</vb>
Replace with:
<vb>
Engine_AddToRenderList_Grh RenderList(), RenderListSize, RenderListIndex, Engine_GetFrameFromGrh(ProjectileList(j).Grh), _
X, Y, Y + GrhData(ProjectileList(j).Grh.GrhIndex).pixelHeight, -1, -1, -1, -1, ProjectileList(j).Rotate, 0, 1
</vb>
Open EditorMap.vbp.
In module TileEngine, add:
<vb> Public Function Engine_GetFrameFromGrh(Grh As Grh) As Long '************************************************************ 'Get a Grh and return the frame (useful for animations) '************************************************************ Dim i As Long
'Check for a valid GrhIndex If Grh.GrhIndex < 1 Then Exit Function If Grh.GrhIndex > NumGrhs Then Exit Function 'Round down on the frame counter i = Int(Grh.FrameCounter) 'Check for a frame count overflow If i > GrhData(Grh.GrhIndex).NumFrames Then Exit Function 'Return the Grh index Engine_GetFrameFromGrh = GrhData(Grh.GrhIndex).Frames(Int(Grh.FrameCounter))
End Function</vb>
Find:
<vb>
'************** Layer 3 to 5 **************
For Layer = 3 To 5
LightOffset = ((Layer - 1) * 4) + 1
For j = 1 To TileLayer(Layer).NumTiles
With TileLayer(Layer).Tile(j)
Engine_UpdateGrh MapData(.TileX, .TileY).Graphic(Layer), True
Engine_AddToRenderList_Grh RenderList(), RenderListSize, RenderListIndex, MapData(.TileX, .TileY).Graphic(Layer).GrhIndex, _
.PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, .PixelPosY + PixelOffsetY + _
GrhData(MapData(.TileX, .TileY).Graphic(Layer).GrhIndex).pixelHeight, MapData(.TileX, .TileY).Light(1), _
MapData(.TileX, .TileY).Light(2), MapData(.TileX, .TileY).Light(3), MapData(.TileX, .TileY).Light(4), _
0, 0, MapData(.TileX, .TileY).Shadow(Layer)
End With
Next j
Next Layer
</vb>
Replace with:
<vb>
'************** Layer 2 to 5 **************
For Layer = 2 To 5
LightOffset = ((Layer - 1) * 4) + 1
For j = 1 To TileLayer(Layer).NumTiles
With TileLayer(Layer).Tile(j)
Engine_UpdateGrh MapData(.TileX, .TileY).Graphic(Layer), True
Engine_AddToRenderList_Grh RenderList(), RenderListSize, RenderListIndex, Engine_GetFrameFromGrh(MapData(.TileX, .TileY).Graphic(Layer)), _
.PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, .PixelPosY + PixelOffsetY + _
GrhData(MapData(.TileX, .TileY).Graphic(Layer).GrhIndex).pixelHeight, MapData(.TileX, .TileY).Light(LightOffset), _
MapData(.TileX, .TileY).Light(LightOffset + 1), MapData(.TileX, .TileY).Light(LightOffset + 2), MapData(.TileX, .TileY).Light(LightOffset + 3), _
0, 0, MapData(.TileX, .TileY).Shadow(Layer)
End With
Next j
Next Layer
</vb>
Fix - Effect rendering
Open GameClient.vbp.
Find:
<vb>
'************** Grh-Based (Non-Particle) Effects **************
</vb>
Replace the block of code (from For j = ... to Next j) with:
<vb>
'************** Grh-Based (Non-Particle) Effects **************
For j = 1 To LastEffect
If EffectList(j).Grh.GrhIndex Then
X = Engine_PixelPosX(EffectList(j).Pos.X - minX) + PixelOffsetX + TileBufferOffset
Y = Engine_PixelPosY(EffectList(j).Pos.Y - minY) + PixelOffsetY + TileBufferOffset
'Time ran out
If EffectList(j).Time <> 0 And EffectList(j).Time < timeGetTime Then
Engine_Effect_Erase j
'Draw the effect
ElseIf Y >= -32 And Y <= (ScreenHeight + 32) And X >= -32 And X <= (ScreenWidth + 32) Then
Engine_UpdateGrh EffectList(j).Grh, False
If EffectList(j).Animated = 1 Then
If EffectList(j).Grh.Started = 0 Then
Engine_Effect_Erase j
GoTo NextEffect
End If
End If
If EffectList(j).Grh.FrameCounter >= 1 Then
If Int(EffectList(j).Grh.FrameCounter) <= GrhData(EffectList(j).Grh.GrhIndex).NumFrames Then
Engine_AddToRenderList_Grh RenderList(), RenderListSize, RenderListIndex, GrhData(EffectList(j).Grh.GrhIndex).Frames(Int(EffectList(j).Grh.FrameCounter)), X, Y, _
Y + GrhData(EffectList(j).Grh.GrhIndex).pixelHeight, -1, -1, -1, -1, EffectList(j).Angle, 0, 1
End If
End If
'Update but not draw
Else
Engine_UpdateGrh EffectList(j).Grh, False
If EffectList(j).Animated = 1 Then
If EffectList(j).Grh.Started = 0 Then Engine_Effect_Erase j
End If
End If
End If
NextEffect:
Next j
</vb>
Add - New rendering system
Open \Data\Head.dat.
At the end of the file, add:
<ini> 'The height is used in the calculation of the overall height of the character for finding the drawing order. 'This is simply just the height of the graphic - the Grh's height is not used because it is often not the 'exact height of the graphic. The height of the head and body are added together. If you have any other 'height contributors (such as large head-wear) I recommend you add height to that layer, too. Height=27 </ini>
Open \Data\Body.dat.
Find:
<ini> [2] </ini>
Before, add:
<ini> 'The height is used in the calculation of the overall height of the character for finding the drawing order. 'This is simply just the height of the graphic - the Grh's height is not used because it is often not the 'exact height of the graphic. The height of the head and body are added together. If you have any other 'height contributors (such as large head-wear) I recommend you add height to that layer, too. Height=34 </ini>
At the end of the file, add:
<ini> Height=34 </ini>
Open GameClient.vbp.
Find:
<vb> Private ChatVA() As TLVERTEX </vb>
After, add:
<vb> 'Render list - used to sort the list of graphics before rendering them Private Type RenderList
X As Long Y As Long Z As Integer 'The value used to sort by (Y + Height) Grh As Long Light(0 To 3) As Long Center As Byte Shadow As Byte Angle As Single CharIndex As Long 'If it is a character, this is its index ParticleEffectIndex As Byte 'If it is a particle effect, this is its index
End Type </vb>
Find:
<vb> 'Bodies list Public Type BodyData
Walk(1 To 8) As Grh Attack(1 To 8) As Grh HeadOffset As Position
End Type </vb>
Replace with:
<vb> 'Bodies list Public Type BodyData
Walk(1 To 8) As Grh Attack(1 To 8) As Grh HeadOffset As Position Height As Long
End Type </vb>
Find:
<vb> Public Type HeadData
Head(1 To 8) As Grh Blink(1 To 8) As Grh AgrHead(1 To 8) As Grh AgrBlink(1 To 8) As Grh
End Type </vb>
Replace with:
<vb> 'Heads list Public Type HeadData
Head(1 To 8) As Grh Blink(1 To 8) As Grh AgrHead(1 To 8) As Grh AgrBlink(1 To 8) As Grh Height As Long
End Type </vb>
Find:
<vb>
BodyData(LoopC).HeadOffset.Y = CLng(Var_Get(DataPath & "Body.dat", LoopC, "HeadOffsetY"))
</vb>
After, add:
<vb>
BodyData(LoopC).Height = CLng(Var_Get(DataPath & "Body.dat", LoopC, "Height"))
</vb>
Find:
<vb>
'Fill List
For LoopC = 1 To NumHeads
For i = 1 To 8
Engine_Init_Grh HeadData(LoopC).Head(i), CLng(Var_Get(DataPath & "Head.dat", LoopC, i)), 0
Engine_Init_Grh HeadData(LoopC).Blink(i), CLng(Var_Get(DataPath & "Head.dat", LoopC, "b" & i)), 0
Engine_Init_Grh HeadData(LoopC).AgrHead(i), CLng(Var_Get(DataPath & "Head.dat", LoopC, "a" & i)), 0
Engine_Init_Grh HeadData(LoopC).AgrBlink(i), CLng(Var_Get(DataPath & "Head.dat", LoopC, "ab" & i)), 0
Next i
Next LoopC
</vb>
Replace with:
<vb>
'Fill List
For LoopC = 1 To NumHeads
For i = 1 To 8
Engine_Init_Grh HeadData(LoopC).Head(i), CLng(Var_Get(DataPath & "Head.dat", LoopC, i)), 0
Engine_Init_Grh HeadData(LoopC).Blink(i), CLng(Var_Get(DataPath & "Head.dat", LoopC, "b" & i)), 0
Engine_Init_Grh HeadData(LoopC).AgrHead(i), CLng(Var_Get(DataPath & "Head.dat", LoopC, "a" & i)), 0
Engine_Init_Grh HeadData(LoopC).AgrBlink(i), CLng(Var_Get(DataPath & "Head.dat", LoopC, "ab" & i)), 0
Next i
HeadData(LoopC).Height = CLng(Var_Get(DataPath & "Head.dat", LoopC, "Height"))
Next LoopC
</vb>
Find:
<vb>
Engine_Init_Grh HeadData(LoopC).AgrBlink(i), CLng(Var_Get(DataPath & "Head.dat", LoopC, "ab" & i)), 0
</vb>
After, add:
<vb>
HeadData(LoopC).Height = CLng(Var_Get(DataPath & "Head.dat", LoopC, "Height"))
</vb>
Find:
<vb>
'Grh has a delay, so just update the frame and then leave
Engine_UpdateGrh Grh, LoopAnim
</vb>
Replace with:
<vb>
'Grh has a delay, so just update the frame and then leave
If Animate Then Engine_UpdateGrh Grh, LoopAnim
</vb>
At the end of the TileEngine module, add:
<vb> Private Sub Engine_AddToRenderList_Char(ByRef RenderList() As RenderList, ByRef RenderListSize As Long, ByRef Index As Long, _
ByVal CharIndex As Long, ByVal X As Long, ByVal Y As Long, ByVal Z As Integer)
'***************************************************************** 'Adds a character to the RenderList() 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_AddToRenderList_Char '*****************************************************************
'Increase the index
Index = Index + 1
'Increase array size if needed
If Index > RenderListSize Then
RenderListSize = RenderListSize + 50
ReDim Preserve RenderList(1 To RenderListSize)
End If
'Add the components
With RenderList(Index)
.CharIndex = CharIndex
.X = X
.Y = Y
.Z = Z
End With
End Sub
Private Sub Engine_AddToRenderList_PE(ByRef RenderList() As RenderList, ByRef RenderListSize As Long, ByRef Index As Long, _
ByVal ParticleEffectIndex As Long, ByVal Z As Integer)
'***************************************************************** 'Adds a Particle Effect to the RenderList() 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_AddToRenderList_PE '*****************************************************************
'Increase the index
Index = Index + 1
'Increase array size if needed
If Index > RenderListSize Then
RenderListSize = RenderListSize + 50
ReDim Preserve RenderList(1 To RenderListSize)
End If
'Add the components
With RenderList(Index)
.ParticleEffectIndex = ParticleEffectIndex
.Z = Z
End With
End Sub
Private Sub Engine_AddToRenderList_Grh(ByRef RenderList() As RenderList, ByRef RenderListSize As Long, ByRef Index As Long, _
ByVal Grh As Long, ByVal X As Long, ByVal Y As Long, ByVal Z As Integer, ByVal Light0 As Long, ByVal Light1 As Long, ByVal Light2 As Long, _ ByVal Light3 As Long, ByVal Angle As Single, ByVal Center As Byte, ByVal Shadow As Byte)
'***************************************************************** 'Adds a Grh (such as a tile, Grh-based effect, projectile, etc) to the RenderList() 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_AddToRenderList_Grh '*****************************************************************
'Increase the index
Index = Index + 1
'Increase array size if needed
If Index > RenderListSize Then
RenderListSize = RenderListSize + 50
ReDim Preserve RenderList(1 To RenderListSize)
End If
'Add the components
With RenderList(Index)
.Angle = Angle
.Center = Center
.Grh = Grh
.Light(0) = Light0
.Light(1) = Light1
.Light(2) = Light2
.Light(3) = Light3
.Shadow = Shadow
.X = X
.Y = Y
.Z = Z
End With
End Sub </vb>
Find:
<vb>Sub Engine_Render_Screen(ByVal TileX As Integer, ByVal TileY As Integer, ByVal PixelOffsetX As Integer, ByVal PixelOffsetY As Integer) </vb>
Replace sub with:
<vb> Sub Engine_Render_Screen(ByVal TileX As Integer, ByVal TileY As Integer, ByVal PixelOffsetX As Integer, ByVal PixelOffsetY As Integer) '************************************************************ 'Draw current visible to scratch area based on TileX and TileY 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_Render_Screen '************************************************************ Dim RenderList() As RenderList Dim RenderListSize As Long Dim RenderListIndex As Long Dim FrameUseMotionBlur As Boolean 'Lets us know if this frame is using motion blur so we don't have to leave support for it on Dim LightOffset As Long Dim Y As Long 'Keeps track of where on map we are Dim X As Long Dim j As Long Dim Angle As Single Dim Layer As Byte Dim pList() As Integer Dim ValueList() As Integer Dim TempGrh As Grh
'Check for valid positions
If UserPos.X = 0 Then Exit Sub
If UserPos.Y = 0 Then Exit Sub
If UserCharIndex = 0 Then Exit Sub
'Check if we need to update the graphics
If TileX <> LastTileX Or TileY <> LastTileY Then
'Figure out Ends and Starts of screen
ScreenMinY = TileY - (WindowTileHeight \ 2)
ScreenMaxY = TileY + (WindowTileHeight \ 2)
ScreenMinX = TileX - (WindowTileWidth \ 2)
ScreenMaxX = TileX + (WindowTileWidth \ 2)
minY = ScreenMinY - TileBufferSize
maxY = ScreenMaxY + TileBufferSize
minX = ScreenMinX - TileBufferSize
maxX = ScreenMaxX + TileBufferSize
'Update the last position
LastTileX = TileX
LastTileY = TileY
'Re-create the tile layers
Engine_CreateTileLayers
End If
'Calculate the particle offset values
'Do NOT move this any farther down in the module or you will get "jumps" as the left/top borders on particles
ParticleOffsetX = (Engine_PixelPosX(ScreenMinX) - PixelOffsetX)
ParticleOffsetY = (Engine_PixelPosY(ScreenMinY) - PixelOffsetY)
'Check if we have the device
If D3DDevice.TestCooperativeLevel <> D3D_OK Then
'The worst we can do at this point is avoid an error we can't fix!
On Error Resume Next
'Do a loop while device is lost
If D3DDevice.TestCooperativeLevel = D3DERR_DEVICELOST Then Exit Sub
'Clear all the textures
LastTexture = -999
For j = 1 To NumGrhFiles
Set SurfaceDB(j) = Nothing
SurfaceTimer(j) = 0
SurfaceSize(j).X = 0
SurfaceSize(j).Y = 0
Next j
'Clear the D3DXSprite
If AlternateRenderDefault = 1 Or AlternateRenderMap = 1 Or AlternateRenderText = 1 Then
SpriteBegun = 0
Set Sprite = Nothing
Set Sprite = D3DX.CreateSprite(D3DDevice)
End If
Set DeviceBuffer = Nothing
Set DeviceStencil = Nothing
Set BlurStencil = Nothing
Set BlurTexture = Nothing
Set BlurSurf = Nothing
'Make sure the scene is ended
D3DDevice.EndScene
'Reset the device
D3DDevice.Reset D3DWindow
Set DeviceBuffer = D3DDevice.GetRenderTarget
Set DeviceStencil = D3DDevice.GetDepthStencilSurface
Set BlurStencil = D3DDevice.CreateDepthStencilSurface(BufferWidth, BufferHeight, D3DFMT_D16, D3DMULTISAMPLE_NONE)
Set BlurTexture = D3DX.CreateTexture(D3DDevice, BufferWidth, BufferHeight, 0, D3DUSAGE_RENDERTARGET, DispMode.Format, D3DPOOL_DEFAULT)
Set BlurSurf = BlurTexture.GetSurfaceLevel(0)
'Reset the render states
Engine_Init_RenderStates
'Load the particle textures
Engine_Init_ParticleEngine True
On Error GoTo 0
Else
'We have to bypass the present the first time through here or else we get an error
If NotFirstRender Then
'Close off the last sprite
If SpriteBegun Then
Sprite.End
SpriteBegun = 0
LastTexture = -101
End If
With D3DDevice
'End the rendering (scene)
.EndScene
'Flip the backbuffer to the screen
.Present ByVal 0, ByVal 0, 0, ByVal 0
End With
Else
'Set NotFirstRender to True so we can start displaying
NotFirstRender = True
End If
End If
'Check if running (turn on motion blur)
If UseMotionBlur Then
If UserCharIndex > 0 Then
If CharList(UserCharIndex).Moving = 1 And CharList(UserCharIndex).Running Then
BlurIntensity = 45
Else
If BlurIntensity < 255 Then
BlurIntensity = BlurIntensity + (ElapsedTime * 0.8)
If BlurIntensity > 255 Then BlurIntensity = 255
End If
End If
End If
End If
'Set the motion blur if needed
If UseMotionBlur Then
If BlurIntensity < 255 Or ZoomLevel > 0 Then
FrameUseMotionBlur = True
D3DDevice.SetRenderTarget BlurSurf, BlurStencil, 0
End If
End If
'Begin the scene D3DDevice.BeginScene 'Clear the screen with a solid color (to prevent artifacts) D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET, 0, 1#, 0 '******************************************************** '************ Update and draw layer 1 and 2 ************* '********************************************************
'Set the alternate rendering for the map on / off
AlternateRender = AlternateRenderMap
'Loop through the lower 2 layers
For Layer = 1 To 2
LightOffset = ((Layer - 1) * 4) + 1
'Loop through all the tiles we know we will draw for this layer
For j = 1 To TileLayer(Layer).NumTiles
With TileLayer(Layer).Tile(j)
Engine_UpdateGrh MapData(.TileX, .TileY).Graphic(Layer)
'Check if we have to draw with a shadow or not (slighty changes because we have to animate on the shadow, not the main render)
If MapData(.TileX, .TileY).Shadow(Layer) = 1 Then
Engine_Render_Grh MapData(.TileX, .TileY).Graphic(Layer), .PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, 0, 1, True, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1
Engine_Render_Grh MapData(.TileX, .TileY).Graphic(Layer), .PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, 0, 0, True, MapData(.TileX, .TileY).Light(LightOffset), MapData(.TileX, .TileY).Light(LightOffset + 1), MapData(.TileX, .TileY).Light(LightOffset + 2), MapData(.TileX, .TileY).Light(LightOffset + 3)
Else
Engine_Render_Grh MapData(.TileX, .TileY).Graphic(Layer), .PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, 0, 1, True, MapData(.TileX, .TileY).Light(LightOffset), MapData(.TileX, .TileY).Light(LightOffset + 1), MapData(.TileX, .TileY).Light(LightOffset + 2), MapData(.TileX, .TileY).Light(LightOffset + 3)
End If
End With
Next j
Next Layer
'Set the alternate rendering back to what it was before
AlternateRender = AlternateRenderDefault
'********************************************************
'********** Update and draw the ground objects **********
'********************************************************
For j = 1 To LastObj
If OBJList(j).Grh.GrhIndex Then
X = Engine_PixelPosX(OBJList(j).Pos.X - minX) + PixelOffsetX + OBJList(j).Offset.X + TileBufferOffset
Y = Engine_PixelPosY(OBJList(j).Pos.Y - minY) + PixelOffsetY + OBJList(j).Offset.Y + TileBufferOffset
If Y >= -32 Then
If Y <= (ScreenHeight + 32) Then
If X >= -32 Then
If X <= (ScreenWidth + 32) Then
Engine_UpdateGrh OBJList(j).Grh, True
With MapData(OBJList(j).Pos.X, OBJList(j).Pos.Y)
Engine_AddToRenderList_Grh RenderList(), RenderListSize, RenderListIndex, OBJList(j).Grh.GrhIndex, X, Y, _
Y + GrhData(OBJList(j).Grh.GrhIndex).pixelHeight, .Light(1), .Light(2), .Light(3), .Light(4), 0, 1, 1
End With
End If
End If
End If
End If
End If
Next j
'********************************************************
'****** Start storing graphics in the RenderList() ******
'****** so it can be sorted by their Y co-ordinate ******
'********************************************************
'************** Characters **************
For j = 1 To LastChar
If CharList(j).Active Then
X = Engine_PixelPosX(CharList(j).Pos.X - minX) + PixelOffsetX + TileBufferOffset
Y = Engine_PixelPosY(CharList(j).Pos.Y - minY) + PixelOffsetY + TileBufferOffset
If Y >= -32 And Y <= (ScreenHeight + 32) And X >= -32 And X <= (ScreenWidth + 32) Then
'Update the NPC chat and draw the character
Engine_NPCChat_Update j
Engine_AddToRenderList_Char RenderList(), RenderListSize, RenderListIndex, j, X, Y, _
Y + CharList(j).Body.Height + CharList(j).Head.Height
Else
'Update just the real position
CharList(j).RealPos.X = X + CharList(j).MoveOffset.X
CharList(j).RealPos.Y = Y + CharList(j).MoveOffset.Y
End If
End If
Next j
'************** Layer 3 to 5 **************
AlternateRender = AlternateRenderMap
For Layer = 3 To 5
LightOffset = ((Layer - 1) * 4) + 1
For j = 1 To TileLayer(Layer).NumTiles
With TileLayer(Layer).Tile(j)
Engine_UpdateGrh MapData(.TileX, .TileY).Graphic(Layer), True
Engine_AddToRenderList_Grh RenderList(), RenderListSize, RenderListIndex, MapData(.TileX, .TileY).Graphic(Layer).GrhIndex, _
.PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, .PixelPosY + PixelOffsetY + _
GrhData(MapData(.TileX, .TileY).Graphic(Layer).GrhIndex).pixelHeight, MapData(.TileX, .TileY).Light(1), _
MapData(.TileX, .TileY).Light(2), MapData(.TileX, .TileY).Light(3), MapData(.TileX, .TileY).Light(4), _
0, 0, MapData(.TileX, .TileY).Shadow(Layer)
End With
Next j
Next Layer
AlternateRender = AlternateRenderDefault
'************** Grh-Based (Non-Particle) Effects **************
For j = 1 To LastEffect
If EffectList(j).Grh.GrhIndex Then
X = Engine_PixelPosX(EffectList(j).Pos.X - minX) + PixelOffsetX + TileBufferOffset
Y = Engine_PixelPosY(EffectList(j).Pos.Y - minY) + PixelOffsetY + TileBufferOffset
'Time ran out
If EffectList(j).Time <> 0 And EffectList(j).Time < timeGetTime Then
Engine_Effect_Erase j
'Draw the effect
ElseIf Y >= -32 And Y <= (ScreenHeight + 32) And X >= -32 And X <= (ScreenWidth + 32) Then
Engine_UpdateGrh EffectList(j).Grh, False
If EffectList(j).Animated = 1 Then
If EffectList(j).Grh.Started = 0 Then Engine_Effect_Erase j
End If
Engine_AddToRenderList_Grh RenderList(), RenderListSize, RenderListIndex, EffectList(j).Grh.GrhIndex, X, Y, _
Y + GrhData(EffectList(j).Grh.GrhIndex).pixelHeight, -1, -1, -1, -1, EffectList(j).Angle, 0, 1
'Update but not draw
Else
Engine_UpdateGrh EffectList(j).Grh, False
If EffectList(j).Animated = 1 Then
If EffectList(j).Grh.Started = 0 Then Engine_Effect_Erase j
End If
End If
End If
Next j
'************** Projectiles **************
'Check if it is close enough to the target to remove
For j = 1 To LastProjectile
If ProjectileList(j).Grh.GrhIndex Then
If Abs(ProjectileList(j).X - ProjectileList(j).tX) < 20 Then
If Abs(ProjectileList(j).Y - ProjectileList(j).tY) < 20 Then
Engine_Projectile_Erase j
End If
End If
End If
Next j
For j = 1 To LastProjectile
If ProjectileList(j).Grh.GrhIndex Then
'Update the position
Angle = DegreeToRadian * Engine_GetAngle(ProjectileList(j).X, ProjectileList(j).Y, ProjectileList(j).tX, ProjectileList(j).tY)
ProjectileList(j).X = ProjectileList(j).X + (Sin(Angle) * ElapsedTime * 0.63)
ProjectileList(j).Y = ProjectileList(j).Y - (Cos(Angle) * ElapsedTime * 0.63)
'Update the rotation
If ProjectileList(j).RotateSpeed > 0 Then
ProjectileList(j).Rotate = ProjectileList(j).Rotate + (ProjectileList(j).RotateSpeed * ElapsedTime * 0.01)
Do While ProjectileList(j).Rotate > 360
ProjectileList(j).Rotate = ProjectileList(j).Rotate - 360
Loop
End If
'Draw if within range
X = ((-minX - 1) * 32) + ProjectileList(j).X + PixelOffsetX + TileBufferOffset
Y = ((-minY - 1) * 32) + ProjectileList(j).Y + PixelOffsetY + TileBufferOffset
If Y >= -32 Then
If Y <= (ScreenHeight + 32) Then
If X >= -32 Then
If X <= (ScreenWidth + 32) Then
Engine_UpdateGrh ProjectileList(j).Grh, True
Engine_AddToRenderList_Grh RenderList(), RenderListSize, RenderListIndex, ProjectileList(j).Grh.GrhIndex, _
X, Y, Y + GrhData(ProjectileList(j).Grh.GrhIndex).pixelHeight, -1, -1, -1, -1, ProjectileList(j).Rotate, 0, 1
End If
End If
End If
End If
End If
Next j
'************** Blood Splatters **************
'Seperate loop to remove the unused - I dont like removing while drawing
For j = 1 To LastBlood
If BloodList(j).Grh.GrhIndex Then
If BloodList(j).Grh.Started = 0 Then Engine_Blood_Erase j
End If
Next j
'Loop to do drawing
For j = 1 To LastBlood
If BloodList(j).Grh.GrhIndex Then
X = Engine_PixelPosX(BloodList(j).Pos.X - minX) + PixelOffsetX + TileBufferOffset
Y = Engine_PixelPosY(BloodList(j).Pos.Y - minY) + PixelOffsetY + TileBufferOffset
If Y >= -32 Then
If Y <= (ScreenHeight + 32) Then
If X >= -32 Then
If X <= (ScreenWidth + 32) Then
Engine_UpdateGrh BloodList(j).Grh, True
Engine_AddToRenderList_Grh RenderList(), RenderListSize, RenderListIndex, BloodList(j).Grh.GrhIndex, X, Y, _
Y + GrhData(BloodList(j).Grh.GrhIndex).pixelHeight, -1, -1, -1, -1, 0, 1, 0
End If
End If
End If
End If
End If
Next j
'********************************************************
'************ Sort the RenderList() by the Z ************
'*********** value then draw then all in order **********
'********************************************************
If RenderListIndex > 0 Then
'Size the array down
ReDim Preserve RenderList(1 To RenderListIndex)
RenderListSize = RenderListIndex
'Sort the array
ReDim ValueList(1 To RenderListIndex)
ReDim pList(1 To RenderListIndex)
For j = 1 To RenderListIndex
ValueList(j) = RenderList(j).Z
pList(j) = j
Next j
Engine_SortIntArray ValueList(), pList(), 1, RenderListIndex
Erase ValueList() 'Erase the ValueList() - we don't need it anymore
'Create a temporary Grh (one without any animations since we don't need to animate)
TempGrh.FrameCounter = 1
TempGrh.LastCount = 0
TempGrh.Started = 1
'Loop through all the graphics in the RenderList()
For j = 1 To RenderListIndex
If RenderList(pList(j)).CharIndex > 0 Then
'Draw a character
With RenderList(pList(j))
Engine_Render_Char .CharIndex, .X, .Y
End With
ElseIf RenderList(pList(j)).ParticleEffectIndex > 0 Then
'Draw a particle effect
Effect_Update RenderList(pList(j)).ParticleEffectIndex
Else
'Draw a grh
With RenderList(pList(j))
TempGrh.GrhIndex = .Grh
If .Shadow Then Engine_Render_Grh TempGrh, .X, .Y, .Center, 0, False, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1, .Angle
Engine_Render_Grh TempGrh, .X, .Y, .Center, 0, False, .Light(0), .Light(1), .Light(2), .Light(3), 0, .Angle
End With
End If
Next j
'Done with the RenderList()
Erase RenderList
End If
'********************************************************
'********** Perform the rest of the rendering ***********
'********************************************************
'************** Layer 6 **************
Layer = 6
LightOffset = ((Layer - 1) * 4) + 1
For j = 1 To TileLayer(Layer).NumTiles
With TileLayer(Layer).Tile(j)
Engine_UpdateGrh MapData(.TileX, .TileY).Graphic(Layer)
If MapData(.TileX, .TileY).Shadow(Layer) = 1 Then
Engine_Render_Grh MapData(.TileX, .TileY).Graphic(Layer), .PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, 0, 1, True, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1
Engine_Render_Grh MapData(.TileX, .TileY).Graphic(Layer), .PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, 0, 0, True, MapData(.TileX, .TileY).Light(LightOffset), MapData(.TileX, .TileY).Light(LightOffset + 1), MapData(.TileX, .TileY).Light(LightOffset + 2), MapData(.TileX, .TileY).Light(LightOffset + 3)
Else
Engine_Render_Grh MapData(.TileX, .TileY).Graphic(Layer), .PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, 0, 1, True, MapData(.TileX, .TileY).Light(LightOffset), MapData(.TileX, .TileY).Light(LightOffset + 1), MapData(.TileX, .TileY).Light(LightOffset + 2), MapData(.TileX, .TileY).Light(LightOffset + 3)
End If
End With
Next j
'************** Update weather ************** 'Do the general weather updating Engine_Weather_Update
'************** Chat bubbles **************
'Loop through the chars
For j = 1 To LastChar
If CharList(j).Active Then
If LenB(CharList(j).BubbleStr) <> 0 Then
If CharList(j).RealPos.X > -25 Then
If CharList(j).RealPos.X < ScreenWidth + 25 Then
If CharList(j).RealPos.Y > -25 Then
If CharList(j).RealPos.Y < ScreenHeight + 25 Then
Engine_Render_ChatBubble CharList(j).BubbleStr, CharList(j).RealPos.X, CharList(j).RealPos.Y
CharList(j).BubbleTime = CharList(j).BubbleTime - ElapsedTime
If CharList(j).BubbleTime <= 0 Then
CharList(j).BubbleTime = 0
CharList(j).BubbleStr = vbNullString
End If
End If
End If
End If
End If
End If
End If
Next j
'************** Damage text **************
'Loop to do drawing
For j = 1 To LastDamage
If DamageList(j).Counter > 0 Then
DamageList(j).Counter = DamageList(j).Counter - ElapsedTime
X = (((DamageList(j).Pos.X - minX) - 1) * TilePixelWidth) + PixelOffsetX + TileBufferOffset
Y = (((DamageList(j).Pos.Y - minY) - 1) * TilePixelHeight) + PixelOffsetY + TileBufferOffset
If Y >= -32 Then
If Y <= (ScreenHeight + 32) Then
If X >= -32 Then
If X <= (ScreenWidth + 32) Then
Engine_Render_Text Font_Default, DamageList(j).Value, X, Y, D3DColorARGB(255, 255, 0, 0)
End If
End If
End If
End If
DamageList(j).Pos.Y = DamageList(j).Pos.Y - (ElapsedTime * 0.001)
End If
Next j
'Seperate loop to remove the unused - I dont like removing while drawing
For j = 1 To LastDamage
If DamageList(j).Width Then
If DamageList(j).Counter <= 0 Then Engine_Damage_Erase j
End If
Next j
'************** Misc Rendering **************
'Update and render particle effects Effect_UpdateAll
'Clear the shift-related variables LastOffsetX = ParticleOffsetX LastOffsetY = ParticleOffsetY
'Render the GUI
Engine_Render_GUI
'************** Mini-map **************
Const tS As Single = 3 'Size of the mini-map dots
'Check if the mini-map is being shownquit
If ShowMiniMap Then
'Make sure the mini-map vertex buffer is valid
If MiniMapVBSize > 0 Then
'Clear the texture
LastTexture = 0
D3DDevice.SetTexture 0, Nothing
'Draw the map outline
D3DDevice.SetStreamSource 0, MiniMapVB, FVF_Size
D3DDevice.DrawPrimitive D3DPT_TRIANGLELIST, 0, MiniMapVBSize \ 3
'Draw the characters
For X = 1 To LastChar
If CharList(X).Active Then
'The user's character
If X = UserCharIndex Then
j = D3DColorARGB(200, 0, 255, 0) 'User's character
Engine_Render_Rectangle CharList(X).Pos.X * tS, CharList(X).Pos.Y * tS, tS, tS, 1, 1, 1, 1, 1, 1, 0, 0, j, j, j, j, , False
GoTo NextChar
End If
'Part of the user's group or one of the user's slaves
If CharList(X).CharType = ClientCharType_Grouped Or (CharList(X).CharType = ClientCharType_Slave And UserCharIndex = CharList(X).OwnerChar) Then
If X <> UserCharIndex Then
j = D3DColorARGB(200, 100, 220, 100) 'PC (grouped) or the user's slave
Engine_Render_Rectangle CharList(X).Pos.X * tS, CharList(X).Pos.Y * tS, tS, tS, 1, 1, 1, 1, 1, 1, 0, 0, j, j, j, j, , False
GoTo NextChar
End If
End If
'Check if the character is in screen, since the only characters drawn outside of the screen are grouped characters
If CharList(X).Pos.X > ScreenMinX Then
If CharList(X).Pos.X < ScreenMaxX Then
If CharList(X).Pos.Y > ScreenMinY Then
If CharList(X).Pos.Y < ScreenMaxY Then
'Character is a PC
If CharList(X).CharType = ClientCharType_PC Then
j = D3DColorARGB(200, 0, 255, 255) 'PC (not grouped)
'Character is a NPC
Else
j = D3DColorARGB(200, 0, 150, 150) 'NPC
End If
'Any character but one part of the user's group
Engine_Render_Rectangle CharList(X).Pos.X * tS, CharList(X).Pos.Y * tS, tS, tS, 1, 1, 1, 1, 1, 1, 0, 0, j, j, j, j, , False
End If
End If
End If
End If
End If
NextChar:
Next X
End If
End If
'Show FPS Engine_Render_Text Font_Default, "FPS: " & FPS, ScreenWidth - 80, 2, -1
'Check if using motion blur / zooming
If UseMotionBlur Then
If FrameUseMotionBlur Then
With D3DDevice
'Perform the zooming calculations
' * 1.333... maintains the aspect ratio
' ... / 1024 is to factor in the buffer size
BlurTA(0).tU = ZoomLevel * 1.333333333
BlurTA(0).tV = ZoomLevel
BlurTA(1).tU = ((ScreenWidth + 1) / 1024) - (ZoomLevel * 1.333333333)
BlurTA(1).tV = ZoomLevel
BlurTA(2).tU = ZoomLevel * 1.333333333
BlurTA(2).tV = ((ScreenHeight + 1) / 1024) - ZoomLevel
BlurTA(3).tU = BlurTA(1).tU
BlurTA(3).tV = BlurTA(2).tV
'Draw what we have drawn thus far since the last .Clear
LastTexture = -100
.SetRenderTarget DeviceBuffer, DeviceStencil, 0
.SetTexture 0, BlurTexture
.SetRenderState D3DRS_TEXTUREFACTOR, D3DColorARGB(BlurIntensity, 255, 255, 255)
.SetTextureStageState 0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR
.DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, BlurTA(0), FVF_Size
.SetTextureStageState 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE
End With
End If
End If
End Sub </vb>
Find:
<vb> Sub Effect_UpdateAll() </vb>
Replace sub with:
<vb> Sub Effect_UpdateAll() '***************************************************************** 'Updates all of the effects and renders them - a wrapper for Effect_Update to update all effects 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_UpdateAll '***************************************************************** Dim LoopC As Long
'Make sure we have effects If NumEffects = 0 Then Exit Sub
'Update every effect in use
For LoopC = 1 To NumEffects
If LoopC <> WeatherEffectIndex Then Effect_Update LoopC
Next
End Sub
Sub Effect_Update(ByVal EffectIndex As Byte) '***************************************************************** 'Updates an effect and renders it 'More info: http://www.vbgore.com/CommonCode.Particles.Effect_Update '*****************************************************************
'Make sure the effect is in use
If Effect(EffectIndex).Used Then
'Set the render state for the particle effects
D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_ONE
'Update the effect position if the screen has moved
Effect_UpdateOffset EffectIndex
'Update the effect position if it is binded
Effect_UpdateBinding EffectIndex
'Find out which effect is selected, then update it
If Effect(EffectIndex).EffectNum = EffectNum_Fire Then Effect_Fire_Update EffectIndex
If Effect(EffectIndex).EffectNum = EffectNum_Snow Then Effect_Snow_Update EffectIndex
If Effect(EffectIndex).EffectNum = EffectNum_Heal Then Effect_Heal_Update EffectIndex
If Effect(EffectIndex).EffectNum = EffectNum_Bless Then Effect_Bless_Update EffectIndex
If Effect(EffectIndex).EffectNum = EffectNum_Protection Then Effect_Protection_Update EffectIndex
If Effect(EffectIndex).EffectNum = EffectNum_Strengthen Then Effect_Strengthen_Update EffectIndex
If Effect(EffectIndex).EffectNum = EffectNum_Rain Then Effect_Rain_Update EffectIndex
If Effect(EffectIndex).EffectNum = EffectNum_EquationTemplate Then Effect_EquationTemplate_Update EffectIndex
If Effect(EffectIndex).EffectNum = EffectNum_Waterfall Then Effect_Waterfall_Update EffectIndex
If Effect(EffectIndex).EffectNum = EffectNum_Summon Then Effect_Summon_Update EffectIndex
'Render the effect
Effect_Render EffectIndex, False
'Set the render state back for normal rendering
D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA
End If
End Sub </vb>
Open EditorMap.vbp.
Find:
<vb> Public InfoLayer As InfoLayer </vb>
After, add:
<vb> 'Render list - used to sort the list of graphics before rendering them Private Type RenderList
X As Long Y As Long Z As Integer 'The value used to sort by (Y + Height) Grh As Long Light(0 To 3) As Long Center As Byte Shadow As Byte Angle As Single CharIndex As Long 'If it is a character, this is its index ParticleEffectIndex As Byte 'If it is a particle effect, this is its index
End Type </vb>
At the end of the TileEngine module, add:
<vb> Private Sub Engine_AddToRenderList_Char(ByRef RenderList() As RenderList, ByRef RenderListSize As Long, ByRef Index As Long, _
ByVal CharIndex As Long, ByVal X As Long, ByVal Y As Long, ByVal Z As Integer)
'***************************************************************** 'Adds a character to the RenderList() 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_AddToRenderList_Char '*****************************************************************
'Increase the index
Index = Index + 1
'Increase array size if needed
If Index > RenderListSize Then
RenderListSize = RenderListSize + 50
ReDim Preserve RenderList(1 To RenderListSize)
End If
'Add the components
With RenderList(Index)
.CharIndex = CharIndex
.X = X
.Y = Y
.Z = Z
End With
End Sub
Private Sub Engine_AddToRenderList_PE(ByRef RenderList() As RenderList, ByRef RenderListSize As Long, ByRef Index As Long, _
ByVal ParticleEffectIndex As Long, ByVal Z As Integer)
'***************************************************************** 'Adds a Particle Effect to the RenderList() 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_AddToRenderList_PE '*****************************************************************
'Increase the index
Index = Index + 1
'Increase array size if needed
If Index > RenderListSize Then
RenderListSize = RenderListSize + 50
ReDim Preserve RenderList(1 To RenderListSize)
End If
'Add the components
With RenderList(Index)
.ParticleEffectIndex = ParticleEffectIndex
.Z = Z
End With
End Sub
Private Sub Engine_AddToRenderList_Grh(ByRef RenderList() As RenderList, ByRef RenderListSize As Long, ByRef Index As Long, _
ByVal Grh As Long, ByVal X As Long, ByVal Y As Long, ByVal Z As Integer, ByVal Light0 As Long, ByVal Light1 As Long, ByVal Light2 As Long, _ ByVal Light3 As Long, ByVal Angle As Single, ByVal Center As Byte, ByVal Shadow As Byte)
'***************************************************************** 'Adds a Grh (such as a tile, Grh-based effect, projectile, etc) to the RenderList() 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_AddToRenderList_Grh '*****************************************************************
'Increase the index
Index = Index + 1
'Increase array size if needed
If Index > RenderListSize Then
RenderListSize = RenderListSize + 50
ReDim Preserve RenderList(1 To RenderListSize)
End If
'Add the components
With RenderList(Index)
.Angle = Angle
.Center = Center
.Grh = Grh
.Light(0) = Light0
.Light(1) = Light1
.Light(2) = Light2
.Light(3) = Light3
.Shadow = Shadow
.X = X
.Y = Y
.Z = Z
End With
End Sub </vb>
Find:
<vb>
If TileBufferSize < 2 Then TileBufferSize = 2
</vb>
After, add:
<vb>
'Cache the TileBufferOffset value to prevent always having to calculate it on the fly TileBufferOffset = ((10 - TileBufferSize) * 32)
</vb>
Find:
<vb> Public TileBufferSize As Integer </vb>
After, add:
<vb> Public TileBufferOffset As Long 'Used to calculate offset value in certain cases </vb>
Find:
<vb>
BodyData(LoopC).HeadOffset.Y = CLng(Var_Get(DataPath & "Body.dat", Str$(LoopC), "HeadOffsetY"))
</vb>
After, add:
<vb>
BodyData(LoopC).Height = CLng(Var_Get(DataPath & "Body.dat", LoopC, "Height"))
</vb>
Find:
<vb>
'Fill List
For LoopC = 1 To NumHeads
For i = 1 To 8
Engine_Init_Grh HeadData(LoopC).Head(i), CLng(Var_Get(DataPath & "Head.dat", Str$(LoopC), Str(i))), 0
Engine_Init_Grh HeadData(LoopC).Blink(i), CLng(Var_Get(DataPath & "Head.dat", Str$(LoopC), "b" & i)), 0
Engine_Init_Grh HeadData(LoopC).AgrHead(i), CLng(Var_Get(DataPath & "Head.dat", Str$(LoopC), "a" & i)), 0
Engine_Init_Grh HeadData(LoopC).AgrBlink(i), CLng(Var_Get(DataPath & "Head.dat", Str$(LoopC), "ab" & i)), 0
Next i
Next LoopC
</vb>
Replace with:
<vb>
'Fill List
For LoopC = 1 To NumHeads
For i = 1 To 8
Engine_Init_Grh HeadData(LoopC).Head(i), CLng(Var_Get(DataPath & "Head.dat", Str$(LoopC), Str(i))), 0
Engine_Init_Grh HeadData(LoopC).Blink(i), CLng(Var_Get(DataPath & "Head.dat", Str$(LoopC), "b" & i)), 0
Engine_Init_Grh HeadData(LoopC).AgrHead(i), CLng(Var_Get(DataPath & "Head.dat", Str$(LoopC), "a" & i)), 0
Engine_Init_Grh HeadData(LoopC).AgrBlink(i), CLng(Var_Get(DataPath & "Head.dat", Str$(LoopC), "ab" & i)), 0
Next i
HeadData(LoopC).Height = CLng(Var_Get(DataPath & "Head.dat", LoopC, "Height"))
Next LoopC
</vb>
Find:
<vb> 'Bodies list Public Type BodyData
Walk(1 To 8) As Grh Attack(1 To 8) As Grh HeadOffset As Position
End Type </vb>
Replace with:
<vb> 'Bodies list Public Type BodyData
Walk(1 To 8) As Grh Attack(1 To 8) As Grh HeadOffset As Position Height As Long
End Type </vb>
Find:
<vb> 'Heads list Public Type HeadData
Head(1 To 8) As Grh Blink(1 To 8) As Grh AgrHead(1 To 8) As Grh AgrBlink(1 To 8) As Grh
End Type </vb>
Replace with:
<vb> 'Heads list Public Type HeadData
Head(1 To 8) As Grh Blink(1 To 8) As Grh AgrHead(1 To 8) As Grh AgrBlink(1 To 8) As Grh Height As Long
End Type </vb>
Find:
<vb> Public Sub Engine_SortIntArray(TheArray() As Integer, TheIndex() As Integer, ByVal LowerBound As Integer, ByVal UpperBound As Integer) </vb>
Replace sub with:
<vb> Public Sub Engine_SortIntArray(TheArray() As Integer, TheIndex() As Integer, ByVal LowerBound As Integer, ByVal UpperBound As Integer) '***************************************************************** 'Sort an array of integers 'More info: http://www.vbgore.com/GameClient.TileEngine.Engine_SortIntArray '***************************************************************** Dim indxt As Long 'Stored index Dim swp As Integer 'Swap variable Dim i As Integer 'Subarray Low Scan Index Dim j As Integer 'Subarray High Scan Index
For j = LowerBound + 1 To UpperBound
indxt = TheIndex(j)
swp = TheArray(indxt)
For i = j - 1 To LowerBound Step -1
If TheArray(TheIndex(i)) <= swp Then Exit For
TheIndex(i + 1) = TheIndex(i)
Next i
TheIndex(i + 1) = indxt
Next j
End Sub </vb>
Find:
<vb> Sub Engine_Render_Screen(ByVal TileX As Integer, ByVal TileY As Integer, ByVal PixelOffsetX As Integer, ByVal PixelOffsetY As Integer) </vb>
Replace sub with:
<vb> Sub Engine_Render_Screen(ByVal TileX As Integer, ByVal TileY As Integer, ByVal PixelOffsetX As Integer, ByVal PixelOffsetY As Integer)
'*********************************************** 'Draw current visible to scratch area based on TileX and TileY '*********************************************** Dim LightOffset As Long Dim RenderList() As RenderList Dim RenderListSize As Long Dim RenderListIndex As Long Dim ScreenX As Integer 'Keeps track of where to place tile on screen Dim ScreenY As Integer Dim Grh As Grh Dim x2 As Long Dim y2 As Long Dim Y As Long 'Keeps track of where on map we are Dim X As Long Dim j As Long Dim Layer As Byte Dim pList() As Integer Dim ValueList() As Integer Dim TempGrh As Grh
minXOffset = 0 minYOffset = 0
'Check if we need to update the graphics
If TileX <> LastTileX Or TileY <> LastTileY Then
'Figure out Ends and Starts of screen
ScreenMinY = TileY - (WindowTileHeight \ 2)
ScreenMaxY = TileY + (WindowTileHeight \ 2)
ScreenMinX = TileX - (WindowTileWidth \ 2)
ScreenMaxX = TileX + (WindowTileWidth \ 2)
minY = ScreenMinY - TileBufferSize
maxY = ScreenMaxY + TileBufferSize
minX = ScreenMinX - TileBufferSize
maxX = ScreenMaxX + TileBufferSize
'Update the last position
LastTileX = TileX
LastTileY = TileY
'Re-create the tile layers
Engine_CreateTileLayers
End If
'Calculate the particle offset values 'Do NOT move this any farther down in the module or you will get "jumps" as the left/top borders on particles ParticleOffsetX = (Engine_PixelPosX(ScreenMinX) - PixelOffsetX) * 1 ParticleOffsetY = (Engine_PixelPosY(ScreenMinY) - PixelOffsetY) * 1 'Check if we have the device If Not Engine_ValidateDevice Then Exit Sub Engine_EndScreenRender D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET, 0, 1#, 0 D3DDevice.BeginScene DrawingGameScreen = True '******************************************************** '************ Update and draw layer 1 and 2 ************* '********************************************************
'Loop through the lower 2 layers
For Layer = 1 To 2
LightOffset = ((Layer - 1) * 4) + 1
'Loop through all the tiles we know we will draw for this layer
For j = 1 To TileLayer(Layer).NumTiles
With TileLayer(Layer).Tile(j)
Engine_UpdateGrh MapData(.TileX, .TileY).Graphic(Layer)
'Check if we have to draw with a shadow or not (slighty changes because we have to animate on the shadow, not the main render)
If MapData(.TileX, .TileY).Shadow(Layer) = 1 Then
Engine_Render_Grh MapData(.TileX, .TileY).Graphic(Layer), .PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, 0, 1, True, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1
Engine_Render_Grh MapData(.TileX, .TileY).Graphic(Layer), .PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, 0, 0, True, MapData(.TileX, .TileY).Light(LightOffset), MapData(.TileX, .TileY).Light(LightOffset + 1), MapData(.TileX, .TileY).Light(LightOffset + 2), MapData(.TileX, .TileY).Light(LightOffset + 3)
Else
Engine_Render_Grh MapData(.TileX, .TileY).Graphic(Layer), .PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, 0, 1, True, MapData(.TileX, .TileY).Light(LightOffset), MapData(.TileX, .TileY).Light(LightOffset + 1), MapData(.TileX, .TileY).Light(LightOffset + 2), MapData(.TileX, .TileY).Light(LightOffset + 3)
End If
End With
Next j
'Tile preview
If frmSetTile.Visible Then
If DrawLayer = Layer Then
Grh.FrameCounter = 1
Grh.GrhIndex = Val(frmSetTile.GrhTxt.Text)
j = D3DColorARGB(200, 255, 255, 255)
If frmSetTile.ShadowChk.Value = 1 Then
If Val(frmSetTile.ShadowTxt.Text) = 1 Then Engine_Render_Grh Grh, Engine_PixelPosX(minXOffset + (HovertX - minX)) + TileBufferOffset + PixelOffsetX, Engine_PixelPosY(minYOffset + (HovertY - minY)) + TileBufferOffset + PixelOffsetY, 0, 0, False, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1
End If
Engine_Render_Grh Grh, Engine_PixelPosX(minXOffset + (HovertX - minX)) + TileBufferOffset + PixelOffsetX, Engine_PixelPosY(minYOffset + (HovertY - minY)) + TileBufferOffset + PixelOffsetY, 0, 0, False, j, j, j, j, 0
End If
End If
Next Layer
'********************************************************
'****** Start storing graphics in the RenderList() ******
'****** so it can be sorted by their Y co-ordinate ******
'********************************************************
'************** Characters **************
For j = 1 To LastChar
If CharList(j).Active Then
X = Engine_PixelPosX(CharList(j).Pos.X - minX) + PixelOffsetX + TileBufferOffset
Y = Engine_PixelPosY(CharList(j).Pos.Y - minY) + PixelOffsetY + TileBufferOffset
If Y >= -32 And Y <= (ScreenHeight + 32) And X >= -32 And X <= (ScreenWidth + 32) Then
'Update the NPC chat and draw the character
'Engine_NPCChat_Update j
Engine_AddToRenderList_Char RenderList(), RenderListSize, RenderListIndex, j, X, Y, _
Y + CharList(j).Body.Height + CharList(j).Head.Height
Else
'Update just the real position
CharList(j).RealPos.X = X + CharList(j).MoveOffset.X
CharList(j).RealPos.Y = Y + CharList(j).MoveOffset.Y
End If
End If
Next j
'************** Layer 3 to 5 **************
For Layer = 3 To 5
LightOffset = ((Layer - 1) * 4) + 1
For j = 1 To TileLayer(Layer).NumTiles
With TileLayer(Layer).Tile(j)
Engine_UpdateGrh MapData(.TileX, .TileY).Graphic(Layer), True
Engine_AddToRenderList_Grh RenderList(), RenderListSize, RenderListIndex, MapData(.TileX, .TileY).Graphic(Layer).GrhIndex, _
.PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, .PixelPosY + PixelOffsetY + _
GrhData(MapData(.TileX, .TileY).Graphic(Layer).GrhIndex).pixelHeight, MapData(.TileX, .TileY).Light(1), _
MapData(.TileX, .TileY).Light(2), MapData(.TileX, .TileY).Light(3), MapData(.TileX, .TileY).Light(4), _
0, 0, MapData(.TileX, .TileY).Shadow(Layer)
End With
Next j
Next Layer
'************** Tile preview **************
If frmSetTile.Visible Then
j = D3DColorARGB(200, 255, 255, 255)
If Val(frmSetTile.GrhTxt.Text) > 0 Then
If Val(frmSetTile.GrhTxt.Text) < NumGrhs Then
Engine_AddToRenderList_Grh RenderList, RenderListSize, RenderListIndex, Val(frmSetTile.GrhTxt.Text), _
Engine_PixelPosX(minXOffset + (HovertX - minX)) + TileBufferOffset + PixelOffsetX, Engine_PixelPosY(minYOffset + (HovertY - minY)) + TileBufferOffset + PixelOffsetY, _
Engine_PixelPosY(minYOffset + (HovertY - minY)) + TileBufferOffset + PixelOffsetY + GrhData(Val(frmSetTile.GrhTxt.Text)).pixelHeight, _
j, j, j, j, 0, 0, 0
End If
End If
End If
'********************************************************
'************ Sort the RenderList() by the Z ************
'*********** value then draw then all in order **********
'********************************************************
If RenderListIndex > 0 Then
'Size the array down
ReDim Preserve RenderList(1 To RenderListIndex)
RenderListSize = RenderListIndex
'Sort the array
ReDim ValueList(1 To RenderListIndex)
ReDim pList(1 To RenderListIndex)
For j = 1 To RenderListIndex
ValueList(j) = RenderList(j).Z
pList(j) = j
Next j
Engine_SortIntArray ValueList(), pList(), 1, RenderListIndex
Erase ValueList() 'Erase the ValueList() - we don't need it anymore
'Create a temporary Grh (one without any animations since we don't need to animate)
TempGrh.FrameCounter = 1
TempGrh.LastCount = 0
TempGrh.Started = 1
'Loop through all the graphics in the RenderList()
For j = 1 To RenderListIndex
If RenderList(pList(j)).CharIndex > 0 Then
'Draw a character
With RenderList(pList(j))
Engine_Render_Char .CharIndex, .X, .Y
End With
ElseIf RenderList(pList(j)).ParticleEffectIndex > 0 Then
'Draw a particle effect
Effect_Update RenderList(pList(j)).ParticleEffectIndex
Else
'Draw a grh
With RenderList(pList(j))
TempGrh.GrhIndex = .Grh
If .Shadow Then Engine_Render_Grh TempGrh, .X, .Y, .Center, 0, False, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1, .Angle
Engine_Render_Grh TempGrh, .X, .Y, .Center, 0, False, .Light(0), .Light(1), .Light(2), .Light(3), 0, .Angle
End With
End If
Next j
'Done with the RenderList()
Erase RenderList
End If
'********************************************************
'********** Perform the rest of the rendering ***********
'********************************************************
'************** Layer 6 **************
Layer = 6
LightOffset = ((Layer - 1) * 4) + 1
For j = 1 To TileLayer(Layer).NumTiles
With TileLayer(Layer).Tile(j)
Engine_UpdateGrh MapData(.TileX, .TileY).Graphic(Layer)
If MapData(.TileX, .TileY).Shadow(Layer) = 1 Then
Engine_Render_Grh MapData(.TileX, .TileY).Graphic(Layer), .PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, 0, 1, True, ShadowColor, ShadowColor, ShadowColor, ShadowColor, 1
Engine_Render_Grh MapData(.TileX, .TileY).Graphic(Layer), .PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, 0, 0, True, MapData(.TileX, .TileY).Light(LightOffset), MapData(.TileX, .TileY).Light(LightOffset + 1), MapData(.TileX, .TileY).Light(LightOffset + 2), MapData(.TileX, .TileY).Light(LightOffset + 3)
Else
Engine_Render_Grh MapData(.TileX, .TileY).Graphic(Layer), .PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, 0, 1, True, MapData(.TileX, .TileY).Light(LightOffset), MapData(.TileX, .TileY).Light(LightOffset + 1), MapData(.TileX, .TileY).Light(LightOffset + 2), MapData(.TileX, .TileY).Light(LightOffset + 3)
End If
End With
Next j
'************** Info **************
If InfoChkValue = 1 Then
For X = 1 To InfoLayer.NumTiles
For Y = 1 To InfoLayer.Tile(X).NumGrhs
With InfoLayer.Tile(X).Grh(Y)
Engine_Render_Grh .Grh, .PixelPosX + PixelOffsetX, .PixelPosY + PixelOffsetY, 0, 0, False
End With
Next Y
Next X
End If
'************** Grid **************
If GridChkValue = 1 Then
j = D3DColorARGB(25, 255, 255, 255)
Grh.GrhIndex = 2
Grh.FrameCounter = 1
Grh.Started = 0
ScreenY = minYOffset
For Y = minY To maxY
ScreenX = minXOffset
For X = minX To maxX
Engine_Render_Grh Grh, Engine_PixelPosX(ScreenX) + PixelOffsetX + TileBufferOffset, Engine_PixelPosY(ScreenY) + PixelOffsetY + TileBufferOffset, 0, 0, , j, j, j, j
ScreenX = ScreenX + 1
Next X
ScreenY = ScreenY + 1
Next Y
End If
'************** Update weather **************
If WeatherChkValue = 1 Then
'Make sure the right weather is going on
Engine_Weather_Update
Else
If WeatherEffectIndex > 0 Then
If Effect(WeatherEffectIndex).Used Then Effect_Kill WeatherEffectIndex
End If
'Change the light of all the tiles back
If FlashTimer > 0 Then
For X = 1 To MapInfo.Width
For Y = 1 To MapInfo.Height
For x2 = 1 To 4
MapData(X, Y).Light(x2) = SaveLightBuffer(X, Y).Light(x2)
Next x2
Next Y
Next X
FlashTimer = 0
End If
End If
'************** Misc Rendering **************
'Update and render particle effects Effect_UpdateAll
'Clear the shift-related variables
LastOffsetX = ParticleOffsetX
LastOffsetY = ParticleOffsetY
'************** Mini-map **************
Const tS As Single = 2 'Size of the mini-map dots
If ShowMiniMap Then
'Draw the map outline
For X = 1 To NumMiniMapTiles
Engine_Render_Rectangle MiniMapTile(X).X * tS, MiniMapTile(X).Y * tS, tS, tS, 1, 1, 1, 1, 1, 1, 0, 0, MiniMapTile(X).Color, MiniMapTile(X).Color, MiniMapTile(X).Color, MiniMapTile(X).Color
Next X
'Draw the characters
j = D3DColorARGB(200, 0, 255, 255)
For X = 1 To LastChar
Engine_Render_Rectangle CharList(X).Pos.X * tS, CharList(X).Pos.Y * tS, tS, tS, 1, 1, 1, 1, 1, 1, 0, 0, j, j, j, j
Next X
'Draw the position indicator
j = D3DColorARGB(200, 0, 255, 0)
Engine_Render_Rectangle UserPos.X * tS, UserPos.Y * tS, tS, tS, 1, 1, 1, 1, 1, 1, 0, 0, j, j, j, j
End If
End Sub </vb>