Imports Microsoft.DirectX
Imports Microsoft.DirectX.Direct3D
Imports Microsoft.DirectX.DirectInput
Imports Microsoft.DirectX.DirectSound
Imports System.Threading
Public Class GameEngine
Dim DispGrafico As Direct3D.Device
Dim SchermoIntero As Boolean
Dim Tastiera As DirectInput.Device
Dim Suoni As DirectSound.Device
Dim th As Thread
Dim Livello As Integer
Dim CarroNemico As oggX
Dim Nemici As New List(Of Nemico)
Dim Proiettili As New List(Of Proiettile)
Dim Giocatore As oggX
Dim Terreno As oggX
Dim AngoloGiocatore As Integer = 0
Dim Tempo As Integer
Dim Sparo As SecondaryBuffer
Dim FineLivello As SecondaryBuffer
Dim TempoScaduto As SecondaryBuffer
Sub New()
InitializeComponent()
SchermoIntero = (MsgBox("Schermo intero?", MsgBoxStyle.YesNo) = MsgBoxResult.Yes)
End Sub
Sub New(ByVal s As Boolean)
InitializeComponent()
SchermoIntero = s
End Sub
Private Sub GameEngine_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim ParametriGrafici As New PresentParameters()
If SchermoIntero = True Then
ParametriGrafici.BackBufferCount = 2
ParametriGrafici.AutoDepthStencilFormat = DepthFormat.D16
ParametriGrafici.EnableAutoDepthStencil = True
ParametriGrafici.DeviceWindowHandle = Me.Handle
ParametriGrafici.SwapEffect = SwapEffect.Flip
ParametriGrafici.Windowed = False
ParametriGrafici.BackBufferWidth = My.Computer.Screen.Bounds.Width
ParametriGrafici.BackBufferHeight = My.Computer.Screen.Bounds.Height
ParametriGrafici.BackBufferFormat = Format.X8R8G8B8
Else
ParametriGrafici.BackBufferCount = 2
ParametriGrafici.AutoDepthStencilFormat = DepthFormat.D16
ParametriGrafici.EnableAutoDepthStencil = True
ParametriGrafici.DeviceWindowHandle = Me.Handle
ParametriGrafici.SwapEffect = SwapEffect.Flip
ParametriGrafici.Windowed = True
End If
DispGrafico = New Direct3D.Device(0, Direct3D.DeviceType.Hardware, Me.Handle, CreateFlags.HardwareVertexProcessing, ParametriGrafici)
Tastiera = New DirectInput.Device(SystemGuid.Keyboard)
Tastiera.SetDataFormat(DeviceDataFormat.Keyboard)
Tastiera.SetCooperativeLevel(Me, CooperativeLevelFlags.Background Or CooperativeLevelFlags.NonExclusive)
Tastiera.Acquire()
Suoni = New DirectSound.Device
Suoni.SetCooperativeLevel(Me, CooperativeLevel.Priority)
Sparo = Me.CaricaSuono(Application.StartupPath & "\Audio\Sparo.wav")
FineLivello = Me.CaricaSuono(Application.StartupPath & "\Audio\FineLivello.wav")
TempoScaduto = Me.CaricaSuono(Application.StartupPath & "\Audio\TempoScaduto.wav")
Me.GeneraLivello()
Me.Show()
Me.Focus()
th = New Thread(AddressOf MainLoop)
th.Start()
End Sub
Sub MainLoop()
Do
Dim a As Double = Rad(AngoloGiocatore)
Tastiera.Poll()
Dim t As KeyboardState = Tastiera.GetCurrentKeyboardState()
DispGrafico.Clear(ClearFlags.Target Or ClearFlags.ZBuffer, Color.Blue, 1, 0)
DispGrafico.BeginScene()
DispGrafico.SamplerState(0).MinFilter = TextureFilter.Linear
If t.Item(Key.F1) = True Then
Process.Start(Application.StartupPath & "\Comandi.txt")
If SchermoIntero = True Then
Application.Exit()
End If
End If
If t.Item(Key.F2) = True Then
DispGrafico.Transform.View = Matrix.LookAtLH(New Vector3(0, 3000, 5), New Vector3(0, 0, 0), New Vector3(0, 1, 0))
Else
DispGrafico.Transform.View = Matrix.LookAtLH(Giocatore.pos + New Vector3(Math.Sin(a) * 200, 0, Math.Cos(a) * 200), Giocatore.pos, New Vector3(0, 1, 0))
End If
DispGrafico.Transform.Projection = Matrix.PerspectiveFovLH(CSng(Math.PI / 16), 4 / 3, 1, 4000)
DispGrafico.RenderState.Lighting = True
DispGrafico.RenderState.Ambient = Color.White
Me.AggiungiMesh(Terreno)
Dim Casuale As New Random()
For i As Integer = 0 To Nemici.Count - 1
Dim CorrNemico As Nemico = Nemici.Item(i)
Dim PrecPosNemico As Vector3 = CorrNemico.mesh.pos
Dim PrecRotNemico As Vector3 = CorrNemico.mesh.rot
With CorrNemico
If .IANemico_Azione = 0 Then
.IANemico_Azione = Casuale.Next(1, 13)
Select Case .IANemico_Azione
Case 1, 2, 3, 4
.IANemico_Obiettivo = Casuale.NextDouble()
Case 5, 6, 7, 8, 9
.IANemico_Obiettivo = Casuale.Next(1, 50)
.IANemico_PrecPos = .mesh.pos
Case 10, 11, 12
.IANemico_Obiettivo = Casuale.Next(5, 50)
End Select
Else
Select Case .IANemico_Azione
Case 1, 2
If .mesh.rot.Y > .IANemico_Obiettivo Then
.IANemico_Azione = 0
Else
.mesh.rot.Y += 0.1
End If
Case 3, 4
If .mesh.rot.Y > .IANemico_Obiettivo Then
.IANemico_Azione = 0
Else
.mesh.rot.Y -= 0.1
End If
Case 5, 6
If Me.DistanzaPunti(.IANemico_PrecPos, .mesh.pos) > .IANemico_Obiettivo Then
.IANemico_Azione = 0
Else
.mesh.pos.X += 5 * Math.Sin(.mesh.rot.Y)
.mesh.pos.Z += 5 * Math.Cos(.mesh.rot.Y)
End If
Case 7, 8, 9
If Me.DistanzaPunti(.IANemico_PrecPos, .mesh.pos) > .IANemico_Obiettivo Then
.IANemico_Azione = 0
Else
.mesh.pos.X -= 5 * Math.Sin(.mesh.rot.Y)
.mesh.pos.Z -= 5 * Math.Cos(.mesh.rot.Y)
End If
Case 10, 11, 12
If .IANemico_Passaggio = .IANemico_Obiettivo Then
.IANemico_Azione = 0
Else
.IANemico_Passaggio += 1
End If
End Select
End If
End With
If CollisioneNemico(i) = True Then
CorrNemico.mesh.pos = PrecPosNemico
CorrNemico.mesh.rot = PrecRotNemico
End If
Nemici.Item(i) = CorrNemico
Me.AggiungiMesh(CorrNemico.mesh)
If t.Item(Key.Space) = True Then
Dim MinGioc As New Vector3()
Dim MaxGioc As New Vector3()
Me.BoundingBox(Giocatore, MinGioc, MaxGioc)
Dim MinNemico As New Vector3()
Dim MaxNemico As New Vector3()
Me.BoundingBox(CorrNemico.mesh, MinNemico, MaxNemico)
Proiettili.Add(New Proiettile(Me, Giocatore.pos, New Vector3(0, Me.Rad(AngoloGiocatore), 0)))
End If
Dim e As Boolean = False
For p As Integer = 0 To Proiettili.Count - 1
If Me.CollisioneOggetto(Proiettili(p).mesh, CorrNemico.mesh) Then
Sparo.Play(0, BufferPlayFlags.Default)
Nemici.RemoveAt(i)
e = True
Exit For
End If
Next
If Nemici.Count = 0 Then
My.Computer.FileSystem.WriteAllText(Application.StartupPath & "\Livello.txt", Livello + 1, False)
FineLivello.Play(0, BufferPlayFlags.Default)
TimerTempo.Stop()
Me.GeneraLivello()
End If
If e = True Then
Exit For
End If
Next
Dim PrecPosGiocatore As Vector3 = Giocatore.pos
Dim PrecRotGiocatore As Vector3 = Giocatore.rot
If t.Item(Key.Right) = True Then
If AngoloGiocatore <> 360 Then
AngoloGiocatore += 2.5
Else
AngoloGiocatore = 0
End If
ElseIf t.Item(Key.Left) = True Then
If AngoloGiocatore <> 0 Then
AngoloGiocatore -= 2.5
Else
AngoloGiocatore = 360
End If
End If
If t.Item(Key.Up) = True Then
Giocatore.pos.X -= 5 * Math.Sin(a)
Giocatore.pos.Z -= 5 * Math.Cos(a)
ElseIf t.Item(Key.Down) = True Then
Giocatore.pos.X += 5 * Math.Sin(a)
Giocatore.pos.Z += 5 * Math.Cos(a)
End If
Giocatore.rot.Y = (AngoloGiocatore * 2 * Math.PI) / 360
If CollisioneGiocatore() = True Then
Giocatore.pos = PrecPosGiocatore
Giocatore.rot = PrecRotGiocatore
End If
Me.AggiungiMesh(Giocatore)
For p As Integer = 0 To Proiettili.Count - 1
Try
Proiettili(p).mesh.pos.X -= 5 * Math.Sin(Proiettili(p).mesh.rot.Y)
Proiettili(p).mesh.pos.Z -= 5 * Math.Cos(Proiettili(p).mesh.rot.Y)
Me.AggiungiMesh(Proiettili(p).mesh)
Proiettili(p).s += 1
If Proiettili(p).s = 100 Then
Proiettili.RemoveAt(p)
End If
Catch ex As Exception
End Try
Next
If t.Item(Key.Escape) Then
Application.Exit()
End If
DispGrafico.EndScene()
DispGrafico.Present()
Application.DoEvents()
If SchermoIntero = False Then
Dim s As String = "i"
If Tempo = 1 Then
s = "o"
End If
Me.Text = "GN TankBattle - tempo rimanente:" & Tempo.ToString & " second" & s & " - Nemici rimanenti:" & Nemici.Count
End If
If Tempo = 0 Then
TimerTempo.Stop()
TempoScaduto.Play(0, BufferPlayFlags.Default)
Me.GeneraLivello()
End If
Loop
End Sub
Function Rad(ByVal grad As Double) As Double
Return (grad * 2 * Math.PI) / 360
End Function
Function NuovaMesh(ByVal fileSrc As String, ByVal materialiOn As Boolean, ByVal textureOn As Boolean, ByVal TexPath As String, ByVal pos As Vector3, ByVal rot As Vector3) As oggX
With NuovaMesh
Dim materiali() As ExtendedMaterial = Nothing
.mesh = Mesh.FromFile(fileSrc, MeshFlags.Dynamic, DispGrafico, materiali)
.numX = UBound(materiali)
ReDim .tex(.numX)
ReDim .mat(.numX)
Dim i As Integer
For i = 0 To .numX
If textureOn Then
If materiali(i).TextureFilename <> "" Then
.tex(i) = TextureLoader.FromFile(DispGrafico, TexPath & "\" & materiali(i).TextureFilename)
End If
End If
If materialiOn Then
.mat(i) = materiali(i).Material3D
.mat(i).Ambient = .mat(i).Diffuse
End If
Next
.pos = pos
.rot = rot
End With
End Function
Sub AggiungiMesh(ByVal Modello As oggX)
DispGrafico.Transform.World = Me.generaMatWorld(Modello)
For i As Integer = 0 To Modello.numX
DispGrafico.Material = Modello.mat(i)
DispGrafico.SetTexture(0, Modello.tex(i))
Modello.mesh.DrawSubset(i)
Next
End Sub
Function generaMatWorld(ByVal m As oggX) As Matrix
Dim pos As Matrix = Matrix.Translation(m.pos)
Dim rot As Matrix = Matrix.RotationYawPitchRoll(m.rot.Y, m.rot.X, m.rot.Z)
Return Matrix.Multiply(rot, pos)
End Function
Function CaricaSuono(ByVal src As String) As SecondaryBuffer
Dim d As New BufferDescription()
d.Flags = BufferDescriptionFlags.ControlPan Or BufferDescriptionFlags.ControlFrequency Or BufferDescriptionFlags.ControlVolume
Return New SecondaryBuffer(src, d, Suoni)
End Function
Private Sub GameEngine_FormClosing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
End
End Sub
Private Function DistanzaPunti(ByVal pt1 As Vector3, ByVal pt2 As Vector3) As Double
Dim dx As Double = pt2.X - pt1.X
Dim dy As Double = pt2.Z - pt1.Z
Dim d As Double = Math.Sqrt((dx ^ 2) + (dy ^ 2))
Return d
End Function
Sub GeneraLivello()
Try
Livello = CInt(My.Computer.FileSystem.ReadAllText(Application.StartupPath & "\Livello.txt"))
Catch ex As Exception
If MsgBox("Impossibile leggere dal file livello.txt. Iniziare dal livello 1?", MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
Livello = 1
My.Computer.FileSystem.WriteAllText(Application.StartupPath & "\Livello.txt", 1, False)
Else
Application.Exit()
End If
End Try
If SchermoIntero = False Then
Control.CheckForIllegalCrossThreadCalls = False
End If
Tempo = 60
Nemici.Clear()
Proiettili.Clear()
CarroNemico = Me.NuovaMesh(Application.StartupPath & "\Grafica\Carro_Armato_Nemico\Mesh.x", True, True, Application.StartupPath & "\Grafica\Carro_Armato_Nemico\", New Vector3(0, 0, 0), New Vector3(0, 0, 0))
Dim Casuale As New Random()
For i As Integer = 1 To Livello
Dim pos As New Vector3()
Do
pos = New Vector3(Casuale.Next(-100, 100), 0, Casuale.Next(-100, 100))
CarroNemico.pos = pos
If Nemici.Count <> 0 Then
If Me.Collisione(CarroNemico, listaMesh(Nemici)) = False Then
Nemici.Add(New Nemico(CarroNemico))
Exit Do
End If
Else
Nemici.Add(New Nemico(CarroNemico))
Exit Do
End If
Loop
Next
Giocatore = Me.NuovaMesh(Application.StartupPath & "\Grafica\Carro_Armato_Giocatore\Mesh.x", True, True, Application.StartupPath & "\Grafica\Carro_Armato_Giocatore\", New Vector3(Casuale.Next(-100, 100), 0, Casuale.Next(-100, 100)), New Vector3(0, 0, 0))
Terreno = Me.NuovaMesh(Application.StartupPath & "\Grafica\Terreno\Mesh.x", True, True, Application.StartupPath & "\Grafica\Terreno\", New Vector3(0, -9.5, 0), New Vector3(0, 0, 0))
TimerTempo.Start()
End Sub
Function CollisioneGiocatore() As Boolean
Return Me.Collisione(Giocatore, listaMesh(Nemici))
End Function
Function CollisioneNemico(ByVal i As Integer) As Boolean
Dim m1 As oggX = Nemici.Item(i).mesh
Dim m2 As New List(Of oggX)(listaMesh(Nemici))
m2.RemoveAt(i)
m2.Add(Giocatore)
Return Collisione(m1, m2)
End Function
Function Collisione(ByVal mesh1 As oggX, ByVal mesh2 As List(Of oggX)) As Boolean
For Each i As oggX In mesh2
If CollisioneOggetto(mesh1, i) Then
Return True
Exit Function
End If
Next
Return False
End Function
Sub BoundingBox(ByVal corrMesh As oggX, ByRef min As Vector3, ByRef max As Vector3)
Dim descr As VertexBufferDescription = corrMesh.mesh.VertexBuffer.Description
Dim vertexData As GraphicsStream = corrMesh.mesh.VertexBuffer.Lock(0, 0, LockFlags.ReadOnly)
Geometry.ComputeBoundingBox(vertexData, corrMesh.mesh.NumberVertices, descr.VertexFormat, min, max)
corrMesh.mesh.VertexBuffer.Unlock()
Dim t As Matrix = Me.generaMatWorld(corrMesh)
Return
End Sub
Function CollisioneOggetto(ByVal m1 As oggX, ByVal m2 As oggX) As Boolean
Dim min1 As New Vector3()
Dim max1 As New Vector3()
Me.BoundingBox(m1, min1, max1)
Dim min2 As New Vector3()
Dim max2 As New Vector3()
Me.BoundingBox(m2, min2, max2)
Dim w As Double = max2.X - min2.X
Dim h As Double = max2.Z - min2.Z
Return m1.pos.X >= m2.pos.X AndAlso m1.pos.X <= m2.pos.X + w AndAlso m1.pos.Z >= m2.pos.Z AndAlso m1.pos.Z <= m2.pos.Z + h
End Function
Private Sub TimerTempo_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TimerTempo.Tick
Tempo -= 1
Me.Text = "GN TankBattle - tempo rimanente:" & Tempo.ToString & " secondi - Nemici rimanenti:" & Nemici.Count
End Sub
Function listaMesh(ByVal n As List(Of Nemico)) As List(Of oggX)
Dim m As New List(Of oggX)
For Each i As Nemico In n
m.Add(i.mesh)
Next
Return m
End Function
End Class