VERSION 5.00 Object = "{6BF52A50-394A-11D3-B153-00C04F79FAA6}#1.0#0"; "wmp.dll" Begin VB.Form Form1 Caption = "Form1" ClientHeight = 8055 ClientLeft = 60 ClientTop = 345 ClientWidth = 8880 LinkTopic = "Form1" ScaleHeight = 8055 ScaleWidth = 8880 StartUpPosition = 3 'Windows Default Begin VB.Timer Timer1 Interval = 39 Left = 3720 Top = 2760 End Begin WMPLibCtl.WindowsMediaPlayer WindowsMediaPlayer1 CausesValidation= 0 'False Height = 15 Left = 840 TabIndex = 0 TabStop = 0 'False Top = 600 Visible = 0 'False Width = 15 URL = "moscow-disko.wav" rate = 1 balance = 0 currentPosition = 0 defaultFrame = "" playCount = 1 autoStart = -1 'True currentMarker = 0 invokeURLs = -1 'True baseURL = "" volume = 50 mute = 0 'False uiMode = "invisible" stretchToFit = 0 'False windowlessVideo = 0 'False enabled = -1 'True enableContextMenu= 0 'False fullScreen = 0 'False SAMIStyle = "" SAMILang = "" SAMIFilename = "" captioningID = "" enableErrorDialogs= 0 'False _cx = 26 _cy = 26 End End Attribute VB_Name = "Form1" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = True Attribute VB_Exposed = False Dim bRunning As Boolean ' Variabile per definire l'usica dal ciclo di rendering ' Tutte le definizioni sono state spostate nel nuovo tipo "SceneObject" Dim D3DX As D3DX8 '//A helper library Dim D3DDevice As Direct3DDevice8 ' // E' stato portato via perche' ora serve ' // Anche nella procedura di caricamento Dim rot As Single ' Variabile dove contenere l'animazione Dim Anim(16) As Animation Dim CurrAnim As Integer ' Variabile per tenere la macchina a stati Dim FSM(16, 5) As Integer Dim NextAction As Integer ' Massimo numero di modelli diversi sulla scena Const MAX_OBJECT = 32 Dim SceneObjs(MAX_OBJECT) As SceneObject Dim LastSceneObj As Integer ' Massimo numero di transform node distinti sulla scena Const MAX_TRANSFORM_NODE = 1024 Dim TrnNds(MAX_TRANSFORM_NODE) As TransformNode Dim LastTrnNd As Integer ' Tipo di vertici utilizzati Private Type CUSTOMVERTEX X As Single 'x Y As Single 'y Z As Single 'z. Nx As Single ' coordinate delle normali Ny As Single Nz As Single tU As Single ' coordinate di mappatura tV As Single End Type ' Tipo di dati che contiene tutte le informazioni di un oggetto sulla scena Private Type SceneObject V() As CUSTOMVERTEX I() As Integer Name As String TotV As Long TotI As Long VBuffer As Direct3DVertexBuffer8 '//Stores our Geometry.... IBuffer As Direct3DIndexBuffer8 '//Stores our indices Material As D3DMATERIAL8 te As Direct3DTexture8 End Type Private Type TransformNode Name As String tX As Single ' Translazioni tY As Single tZ As Single rX As Single ' Rotazioni rY As Single rZ As Single sX As Single ' Cambiamenti di scala sY As Single sZ As Single pX As Single ' Pivot pY As Single pZ As Single ScObj As Integer ChildName As String ' Primo figlio ChildID As Integer ' Indice nell'array del primo figlio BrotherName As String ' Prossimo fratello BrotherID As Integer ' Indice nell'array del prossimo fratello End Type ' Tipi per le animazioni Private Type KeyAnim AttrName As String ' Nome dell'attributo che si sta animando Frames As Integer ' Quanti fotogrammi formano l'animazione della chiave Value() As Single ' Valori ai vari fotogrammi End Type Private Type NodeAnim NodeName As String ' Nome del nodo da animare NodeId As Integer ' ID del nodo da animare tX As KeyAnim ' Traslazioni tY As KeyAnim tZ As KeyAnim rX As KeyAnim ' Rotazioni rY As KeyAnim rZ As KeyAnim sX As KeyAnim ' Variazioni di scala sY As KeyAnim sZ As KeyAnim End Type Private Type Animation TotNodes As Integer ' Nodi da animare Nodes() As NodeAnim ' Array delle animazioni dei nodi LastFrame As Integer ' Ultimo fotogramma CurFrame As Integer ' Fotogramma corrente End Type ' Crea un vettore Private Function MakeVector(ByVal X As Single, ByVal Y As Single, ByVal Z As Single) As D3DVECTOR MakeVector.X = X MakeVector.Y = Y MakeVector.Z = Z End Function ' Crea un vertice Private Function MakeVertex(ByVal X As Single, ByVal Y As Single, ByVal Z As Single, _ ByVal Nx As Single, ByVal Ny As Single, ByVal Nz As Single, _ ByVal U As Single, ByVal V As Single) As CUSTOMVERTEX MakeVertex.X = X MakeVertex.Y = Y MakeVertex.Z = Z MakeVertex.Nx = Nx MakeVertex.Ny = Ny MakeVertex.Nz = Nz MakeVertex.tU = U MakeVertex.tV = 1 - V End Function ' Attivata quando l'utente clicca sulla finestra, per chiudere l'applicazione Private Sub Form_Click() bRunning = False End Sub Private Function CreateTransformNode(ScObj As Integer, Name As String) _ As Integer TrnNds(LastTrnNd).sX = 1 TrnNds(LastTrnNd).sY = 1 TrnNds(LastTrnNd).sZ = 1 TrnNds(LastTrnNd).ScObj = ScObj TrnNds(LastTrnNd).Name = Name CreateTransformNode = LastTrnNd LastTrnNd = LastTrnNd + 1 End Function Private Function AddObject(FileName As String, TextureName As String) As Integer SceneObjs(LastSceneObj) = LoadObject(FileName, TextureName) AddObject = LastSceneObj LastSceneObj = LastSceneObj + 1 End Function Private Function LoadObject(FileName As String, TextureName As String) _ As SceneObject Dim X, Y, Z, Nx, Ny, Nz, tU, tV As Single Dim I1, I2, I3 As Integer With LoadObject .TotV = 0 .TotI = 0 Open FileName For Input As #1 Input #1, .TotV, .TotI ReDim .V(.TotV), .I(.TotI) For T = 0 To .TotV - 1 Input #1, X, Y, Z, Nx, Ny, Nz, tU, tV .V(T) = MakeVertex(X, Y, Z, Nx, Ny, Nz, tU, tV) Next For T = 0 To .TotI - 1 Step 3 Input #1, I1, I2, I3 .I(T) = I1 .I(T + 1) = I2 .I(T + 2) = I3 Next Close #1 Set .IBuffer = D3DDevice.CreateIndexBuffer(Len(.I(0)) * .TotI, 0, _ D3DFMT_INDEX16, D3DPOOL_DEFAULT) D3DIndexBuffer8SetData .IBuffer, 0, Len(.I(0)) * .TotI, 0, .I(0) Set .VBuffer = D3DDevice.CreateVertexBuffer(Len(.V(0)) * .TotV, 0, _ D3DFVF_XYZ Or D3DFVF_NORMAL Or D3DFVF_TEX1, D3DPOOL_DEFAULT) D3DVertexBuffer8SetData .VBuffer, 0, Len(.V(0)) * .TotV, 0, .V(0) ' Carica la texture Set .te = D3DX.CreateTextureFromFileEx(D3DDevice, _ TextureName, D3DX_DEFAULT, D3DX_DEFAULT, _ 1, 0, D3DFMT_UNKNOWN, _ D3DPOOL_MANAGED, D3DX_FILTER_POINT, _ D3DX_FILTER_POINT, &HFF000000, _ ByVal 0, ByVal 0) ' Imposta il materiale .Material.diffuse.r = 1 .Material.diffuse.g = 1 .Material.diffuse.b = 1 End With End Function Private Function FindShape(Name As String) For I = 0 To LastSceneObj - 1 If SceneObjs(I).Name = Name Then FindShape = I Exit Function End If Next FindShape = -1 End Function Private Function FindTn(Name As String) For I = 0 To LastTrnNd - 1 If TrnNds(I).Name = Name Then FindTn = I Exit Function End If Next FindTn = -1 End Function Private Sub LoadScene(FileName As String) Dim X, Y, Z, Nx, Ny, Nz, tU, tV As Single Dim I1, I2, I3 As Integer Dim ShapeInScene As Integer Dim TNInScene As Integer Dim CurTN As Integer Dim TextureName As String Dim ShName As String Dim TNName As String Dim ShNum As Integer Open FileName For Input As #1 Input #1, ShapeInScene ' Carica le Shapes For U = 0 To ShapeInScene - 1 With SceneObjs(LastSceneObj) .TotV = 0 .TotI = 0 ' Carica la texture Input #1, .Name Input #1, TextureName 'MsgBox ("[" & .Name & "]<" & TextureName & ">") If TextureName <> "" Then Set .te = D3DX.CreateTextureFromFileEx(D3DDevice, _ TextureName, D3DX_DEFAULT, D3DX_DEFAULT, _ 1, 0, D3DFMT_UNKNOWN, _ D3DPOOL_MANAGED, D3DX_FILTER_POINT, _ D3DX_FILTER_POINT, &HFF000000, _ ByVal 0, ByVal 0) End If ' Imposta il materiale Input #1, .Material.emissive.r, .Material.emissive.g, .Material.emissive.b Input #1, .Material.Ambient.r, .Material.Ambient.g, .Material.Ambient.b Input #1, .Material.diffuse.r, .Material.diffuse.g, .Material.diffuse.b Input #1, .Material.specular.r, .Material.specular.g, .Material.specular.b, .Material.power ' Carica la geometria Input #1, .TotV, .TotI ReDim .V(.TotV), .I(.TotI) For T = 0 To .TotV - 1 Input #1, X, Y, Z, Nx, Ny, Nz, tU, tV .V(T) = MakeVertex(X, Y, Z, Nx, Ny, Nz, tU, tV) Next For T = 0 To .TotI - 1 Step 3 Input #1, I1, I2, I3 .I(T) = I1 .I(T + 1) = I2 .I(T + 2) = I3 Next Set .IBuffer = D3DDevice.CreateIndexBuffer(Len(.I(0)) * .TotI, 0, _ D3DFMT_INDEX16, D3DPOOL_DEFAULT) D3DIndexBuffer8SetData .IBuffer, 0, Len(.I(0)) * .TotI, 0, .I(0) Set .VBuffer = D3DDevice.CreateVertexBuffer(Len(.V(0)) * .TotV, 0, _ D3DFVF_XYZ Or D3DFVF_NORMAL Or D3DFVF_TEX1, D3DPOOL_DEFAULT) D3DVertexBuffer8SetData .VBuffer, 0, Len(.V(0)) * .TotV, 0, .V(0) End With ' Passa alla shape successiva LastSceneObj = LastSceneObj + 1 Next U Input #1, TNInScene For U = 0 To TNInScene - 1 Input #1, TNName Input #1, ShName If ShName <> "" Then ShNum = FindShape(ShName) If ShNum = -1 Then MsgBox "Shape not found: " & ShName End End If Else ShNum = -1 End If CurTN = CreateTransformNode(ShNum, TNName) Input #1, TrnNds(CurTN).ChildName Input #1, TrnNds(CurTN).BrotherName Input #1, TrnNds(CurTN).tX, TrnNds(CurTN).tY, TrnNds(CurTN).tZ Input #1, TrnNds(CurTN).rX, TrnNds(CurTN).rY, TrnNds(CurTN).rZ Input #1, TrnNds(CurTN).sX, TrnNds(CurTN).sY, TrnNds(CurTN).sZ Input #1, TrnNds(CurTN).pX, TrnNds(CurTN).pY, TrnNds(CurTN).pZ Next U ' Trasfroma i nomi in indici For U = 0 To TNInScene - 1 If TrnNds(U).ChildName <> "" Then TrnNds(U).ChildID = FindTn(TrnNds(U).ChildName) Else TrnNds(U).ChildID = -1 End If If TrnNds(U).BrotherName <> "" Then TrnNds(U).BrotherID = FindTn(TrnNds(U).BrotherName) Else TrnNds(U).BrotherID = -1 End If Next U Close #1 End Sub Private Sub renderNode(matPar As D3DMATRIX, Id As Integer) Dim matTemp As D3DMATRIX Dim matWorld As D3DMATRIX With TrnNds(Id) If .BrotherID >= 0 Then ' se c'e almeno un fratello renderNode matPar, .BrotherID ' Lo visualizza con la stessa trasformazione End If ' Imposta le trasformazioni dell'oggetto D3DXMatrixIdentity matWorld D3DXMatrixTranslation matTemp, -.pX, -.pY, -.pZ ' Sposta il pivot D3DXMatrixMultiply matWorld, matWorld, matTemp D3DXMatrixScaling matTemp, .sX, .sY, .sZ D3DXMatrixMultiply matWorld, matWorld, matTemp If .sX * .sY * .sZ < 0 Then D3DDevice.SetRenderState D3DRS_CULLMODE, D3DCULL_CW Else D3DDevice.SetRenderState D3DRS_CULLMODE, D3DCULL_CCW End If D3DXMatrixRotationX matTemp, .rX * (3.1416 / 180) D3DXMatrixMultiply matWorld, matWorld, matTemp D3DXMatrixRotationY matTemp, .rY * (3.1416 / 180) D3DXMatrixMultiply matWorld, matWorld, matTemp D3DXMatrixRotationZ matTemp, .rZ * (3.1416 / 180) D3DXMatrixMultiply matWorld, matWorld, matTemp D3DXMatrixTranslation matTemp, .tX + .pX, .tY + .pY, .tZ + .pZ D3DXMatrixMultiply matWorld, matWorld, matTemp D3DXMatrixMultiply matWorld, matWorld, matPar ' concatena le trasforamzioni dei genitori If .ChildID >= 0 Then ' se c'e almeno un figlio renderNode matWorld, .ChildID ' Lo visualizza con la nuova trasformazione End If D3DDevice.SetTransform D3DTS_WORLD, matWorld End With If TrnNds(Id).ScObj >= 0 Then With SceneObjs(TrnNds(Id).ScObj) D3DDevice.SetMaterial .Material ' Imposta la texture D3DDevice.SetTexture 0, .te ' Disegna l'oggetto D3DDevice.SetStreamSource 0, .VBuffer, _ Len(.V(0)) D3DDevice.SetIndices .IBuffer, 0 D3DDevice.DrawIndexedPrimitive D3DPT_TRIANGLELIST, 0, _ .TotV, 0, .TotI / 3 End With End If End Sub Private Function LoadKeyAnim(LastFrame As Integer) As KeyAnim With LoadKeyAnim Input #1, .AttrName, .Frames If .Frames > LastFrame Then LastFrame = .Frames End If ReDim .Value(.Frames) For I = 0 To .Frames - 1 Input #1, .Value(I) Next End With End Function ' Carica una animazione Private Function LoadAnimation(FileName As String) As Animation Open FileName For Input As #1 Dim LastFrame As Integer With LoadAnimation Input #1, .TotNodes ReDim .Nodes(.TotNodes) For I = 0 To .TotNodes - 1 With .Nodes(I) Input #1, .NodeName .NodeId = FindTn(.NodeName) .tX = LoadKeyAnim(LastFrame) .tY = LoadKeyAnim(LastFrame) .tZ = LoadKeyAnim(LastFrame) .rX = LoadKeyAnim(LastFrame) .rY = LoadKeyAnim(LastFrame) .rZ = LoadKeyAnim(LastFrame) .sX = LoadKeyAnim(LastFrame) .sY = LoadKeyAnim(LastFrame) .sZ = LoadKeyAnim(LastFrame) End With Next .LastFrame = LastFrame End With Close #1 End Function Private Sub GetKey(Val As Single, Key As KeyAnim, T As Integer) If T < Key.Frames Then Val = Key.Value(T) End If End Sub Private Sub AnimateNode(N As NodeAnim, T As Integer) If N.NodeId > -1 Then GetKey TrnNds(N.NodeId).tX, N.tX, T GetKey TrnNds(N.NodeId).tY, N.tY, T GetKey TrnNds(N.NodeId).tZ, N.tZ, T GetKey TrnNds(N.NodeId).rX, N.rX, T GetKey TrnNds(N.NodeId).rY, N.rY, T GetKey TrnNds(N.NodeId).rZ, N.rZ, T GetKey TrnNds(N.NodeId).sX, N.sX, T GetKey TrnNds(N.NodeId).sY, N.sY, T GetKey TrnNds(N.NodeId).sZ, N.sZ, T End If End Sub Private Function Animate(A As Animation) As Boolean For I = 0 To A.TotNodes - 1 AnimateNode A.Nodes(I), A.CurFrame Next A.CurFrame = A.CurFrame + 1 If A.CurFrame = A.LastFrame Then A.CurFrame = 0 Animate = True Else Animate = False End If End Function Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) If KeyCode = 37 Then 'sinistra NextAction = 2 End If If KeyCode = 39 Then 'destra NextAction = 1 End If If KeyCode = 38 Then 'su NextAction = 3 End If If KeyCode = 40 Then ' giu NextAction = 4 End If End Sub ' Programma vero e prorpio! Private Sub Form_Load() ' Inizializzazione della libreria ''''''''''''''''''''''''''''''''' ' Dichiarazioni variabili per le DirectX Dim Dx As DirectX8 Dim D3D As Direct3D8 ' Dim D3DDevice As Direct3DDevice8 ' // E' stato portato via Dim DispMode As D3DDISPLAYMODE Dim D3DWindow As D3DPRESENT_PARAMETERS ' Dichiarazioni variabili per l'applicazione Dim Light As D3DLIGHT8 ' Matrici che devono rimanere nel ciclo di rendering Dim matView As D3DMATRIX Dim matProj As D3DMATRIX Dim matWorld As D3DMATRIX ' Si collega con le DirectX Set Dx = New DirectX8 Set D3D = Dx.Direct3DCreate() ' Imposta la modalita' video in finsetra D3D.GetAdapterDisplayMode D3DADAPTER_DEFAULT, DispMode D3DWindow.Windowed = 1 D3DWindow.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC D3DWindow.BackBufferFormat = DispMode.Format ' Imposta lo Z-Buffere D3DWindow.AutoDepthStencilFormat = D3DFMT_D16 D3DWindow.EnableAutoDepthStencil = 1 ' Crea l'applicazione Set D3DDevice = D3D.CreateDevice(D3DADAPTER_DEFAULT, _ D3DDEVTYPE_HAL, hWnd, _ D3DCREATE_SOFTWARE_VERTEXPROCESSING, _ D3DWindow) ' Definisce il tipo di vertici utilizzati D3DDevice.SetVertexShader D3DFVF_XYZ Or D3DFVF_NORMAL Or _ D3DFVF_TEX1 ' Abilita l'illuminazione D3DDevice.SetRenderState D3DRS_LIGHTING, True D3DDevice.SetRenderState D3DRS_SPECULARENABLE, True ' Abilita lo Z-Buffer D3DDevice.SetRenderState D3DRS_ZENABLE, True ' Inizializzazione dell'applicazione '''''''''''''''''''''''''''''''''''' ' Mostra la finestra Me.Show ' Imposta la luce Light.Type = D3DLIGHT_DIRECTIONAL Light.Direction = MakeVector(-1, 0.5, 0.25) Light.diffuse.r = 0.5 Light.diffuse.g = 0.5 Light.diffuse.b = 0.5 D3DDevice.SetLight 0, Light D3DDevice.LightEnable 0, 1 Light.Type = D3DLIGHT_DIRECTIONAL Light.Direction = MakeVector(1, -0.5, 0.25) Light.diffuse.r = 1 Light.diffuse.g = 1 Light.diffuse.b = 1 D3DDevice.SetLight 1, Light D3DDevice.LightEnable 1, 1 Set D3DX = New D3DX8 ' Crea la geometria LoadScene ("robot.scn") Anim(0) = LoadAnimation("robotS01.anm") Anim(1) = LoadAnimation("robotS02.anm") Anim(2) = LoadAnimation("robotS03.anm") Anim(3) = LoadAnimation("robotS04.anm") Anim(4) = LoadAnimation("robotS05.anm") Anim(5) = LoadAnimation("robotS06.anm") Anim(6) = LoadAnimation("robotS07.anm") Anim(7) = LoadAnimation("robotS08.anm") Anim(8) = LoadAnimation("robotS09.anm") Anim(9) = LoadAnimation("robotS10.anm") Anim(10) = LoadAnimation("robotS11.anm") Anim(11) = LoadAnimation("robotS12.anm") Anim(12) = LoadAnimation("robotS13.anm") Anim(13) = LoadAnimation("robotS14.anm") Anim(14) = LoadAnimation("robotS15.anm") Anim(15) = LoadAnimation("robotS16.anm") 'Anim.LastFrame = 15 'Inizializza la macchina a stati FSM(0, 0) = 0: FSM(0, 1) = 1: FSM(0, 2) = 2: FSM(0, 3) = 6: FSM(0, 4) = 9 FSM(1, 0) = 1: FSM(1, 1) = 0: FSM(1, 2) = 2: FSM(1, 3) = 6: FSM(1, 4) = 9 FSM(2, 0) = 3: FSM(2, 1) = 3: FSM(2, 2) = 3: FSM(2, 3) = 3: FSM(2, 4) = 3 FSM(3, 0) = 3: FSM(3, 1) = 5: FSM(3, 2) = 4: FSM(3, 3) = 5: FSM(3, 4) = 5 FSM(4, 0) = 3: FSM(4, 1) = 5: FSM(4, 2) = 4: FSM(4, 3) = 3: FSM(4, 4) = 3 FSM(5, 0) = 0: FSM(5, 1) = 1: FSM(5, 2) = 2: FSM(5, 3) = 6: FSM(5, 4) = 9 FSM(6, 0) = 7: FSM(6, 1) = 7: FSM(6, 2) = 7: FSM(6, 3) = 7: FSM(6, 4) = 7 FSM(7, 0) = 7: FSM(7, 1) = 8: FSM(7, 2) = 8: FSM(7, 3) = 8: FSM(7, 4) = 8 FSM(8, 0) = 0: FSM(8, 1) = 1: FSM(8, 2) = 2: FSM(8, 3) = 6: FSM(8, 4) = 9 FSM(9, 0) = 10: FSM(9, 1) = 10: FSM(9, 2) = 10: FSM(9, 3) = 10: FSM(9, 4) = 10 FSM(10, 0) = 10: FSM(10, 1) = 14: FSM(10, 2) = 14: FSM(10, 3) = 14: FSM(10, 4) = 11 FSM(11, 0) = 12: FSM(11, 1) = 12: FSM(11, 2) = 12: FSM(11, 3) = 12: FSM(11, 4) = 12 FSM(12, 0) = 12: FSM(12, 1) = 13: FSM(12, 2) = 13: FSM(12, 3) = 13: FSM(12, 4) = 13 FSM(13, 0) = 10: FSM(13, 1) = 14: FSM(13, 2) = 14: FSM(13, 3) = 14: FSM(13, 4) = 14 FSM(14, 0) = 0: FSM(14, 1) = 1: FSM(14, 2) = 2: FSM(14, 3) = 6: FSM(14, 4) = 15 FSM(15, 0) = 0: FSM(15, 1) = 1: FSM(15, 2) = 2: FSM(15, 3) = 6: FSM(15, 4) = 9 ' Inizializza la variabile di permanenza nel ciclo di rendering bRunning = True ' Ciclo di rendering '''''''''''''''''''' ' Ripete fino a quando bRunning vale falso Do While bRunning ' Cancella lo schermo D3DDevice.Clear 0, ByVal 0, _ D3DCLEAR_TARGET Or D3DCLEAR_ZBUFFER, _ &H0, 1#, 0 ' Imposta la cinepresa D3DXMatrixLookAtLH matView, MakeVector(10, 15, -50), _ MakeVector(0, 10, 0), MakeVector(0, 1, 0) D3DDevice.SetTransform D3DTS_VIEW, matView D3DXMatrixPerspectiveFovLH matProj, 3.1416 / 4, 1, 0.1, 500 D3DDevice.SetTransform D3DTS_PROJECTION, matProj ' Inizia a disegnare su video D3DDevice.BeginScene D3DXMatrixIdentity matWorld renderNode matWorld, 0 ' Finisce la fase di disegno D3DDevice.EndScene ' Trasferisce il contenuto del Doppio Buffer sullo schermo D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0 ' Restituisce il controllo a Windows per dargli la possibilita' di gestire altri eventi DoEvents Loop ' Rilascio delle risorse '''''''''''''''''''''''' Set D3DDevice = Nothing Set D3D = Nothing Set Dx = Nothing ' Chiude l'applicazione Unload Me End Sub Private Sub Timer1_Timer() If Animate(Anim(CurrAnim)) Then CurrAnim = FSM(CurrAnim, NextAction) NextAction = 0 End If rot = rot + 5 If rot = 360 Then rot = 0 Form1.Caption = CurrAnim & " " & NextAction & " -> " & FSM(CurrAnim, NextAction) End Sub