Chinaunix首页 | 论坛 | 博客
  • 博客访问: 8346485
  • 博文数量: 1413
  • 博客积分: 11128
  • 博客等级: 上将
  • 技术积分: 14685
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-13 10:03
个人简介

follow my heart...

文章分类

全部博文(1413)

文章存档

2013年(1)

2012年(5)

2011年(45)

2010年(176)

2009年(148)

2008年(190)

2007年(293)

2006年(555)

分类:

2006-11-26 19:58:04

' ________________________________________________________________________
' TrueVision3D (web: http://www.truevision3d.com)
' ????????????????????????????????????
' Tutorial 14 : Give a destination to a mesh
' ??????
' Description : In this 14th tutorial, we will load a landscape, put five
' ?????? tanks on it and use the last "mouse picking" tutorials
' to be able to select a tank and give it a destination.

' Force explicit declarations
Option Explicit

' We declare TVEngine.
Private TV3D As TVEngine

' No so new : we declare the tank as an mesh8 object
Private Tank(1 To 5) As TVMesh

' We declare the landscape
Private Land As TVLandscape

' We declare the texture factory
Private TextureFactory As TVTextureFactory

' We the declare the scene
Private Scene As TVScene

' New : we have to declare the screen obect to be able to render 3d lines
' from 2 vectors in the world
Private ScreenTV As TVScreen2DImmediate

' We declare the input engine.
Private InputEngine As TVInputEngine

' We declare the collision object
Private CollisionResult As TVCollisionResult

' The loop.
Private DoLoop As Boolean

' We need a position for the tanks
Private TankPosition(1 To 5) As D3DVECTOR

' New : we need a destination for the tanks
Private TankDestination(1 To 5) As D3DVECTOR

' New : we need a direction for the tank to make them point in the
' right direction.
Private TankDirection(1 To 5) As D3DVECTOR

' We need angles for the tanks
Private TankAngleY(1 To 5) As Single

' We need a variable that will hold the index of the tank selected
'保存当前所选择的坦克
Private intTankSelected As Integer

' We declare the WinApi function (MouseCursor)
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long

Private Sub cmdQuit_Click()

    ' We have clicked on the "Quit" button, so we change the DoLoop.
    DoLoop = False

End Sub

Private Sub Form_Load()

    ' We have to create the TV3D object before anything else.
    Set TV3D = New TVEngine

    ' Set search directory of Textures, Objects, ...
    TV3D.SetSearchDirectory App.Path
    
    ' We initialize TV3D in the picture box of the form.
    TV3D.Init3DWindowedMode Picture1.hWnd

    ' We want to see the FPS.
    TV3D.DisplayFPS = True
    
    'We set the anglesystem to degree
    TV3D.SetAngleSystem TV_ANGLE_DEGREE

    ' We create the input object.
    Set InputEngine = New TVInputEngine

    ' We create the screen object. Note that we can't use "Screen" as
    ' the name of our object because it's allready an object name
    ' reserved for VisualBasic and also the Windows API.
    Set ScreenTV = New TVScreen2DImmediate

    ' We create the scene (the world).
    Set Scene = New TVScene

    ' We set a mouse pointer
    Scene.LoadCursor "..\..\..\Media\pointer.bmp", TV_COLORKEY_BLACK, 16, 16

    ' We set background color.
    Scene.SetSceneBackGround 0, 0.3, 0.9

    ' We need to create a new texture factory
    Set TextureFactory = New TVTextureFactory

    ' The land generation
    Set Land = New TVLandscape
        
    ' Generate the height of the land from the grayscale of the image.
    Land.GenerateHugeTerrain "..\..\..\Media\Heightmaps\Track.jpg", TV_PRECISION_LOW, 8, 8, -700, -1024, True
    
    ' Then, we load the land texture.
    TextureFactory.LoadTexture "..\..\..\Media\sand.jpg", "LandTexture"
    
    ' Load the tank texture
    TextureFactory.LoadTexture "..\..\..\Media\tank.bmp", "TankTexture", , , TV_COLORKEY_NO
    
    ' We assign a texture to that land.
    Land.SetTexture GetTex("LandTexture")
    
    Dim i As Integer
    For i = 1 To 5
    
        ' We ceate the tank
        Set Tank(i) = Scene.CreateMeshBuilder
        
        ' Now, load our model.
        Tank(i).Load3DSMesh "..\..\..\Media\tank.3ds", False
    
        ' We assign the texture
        Tank(i).SetTexture GetTex("TankTexture")
        
        
        ' Set the tank's vertex color to red
        ' Warning, don't call this too often, it creates a new material :)
        Tank(i).SetColor RGBA(1, 0, 0, 1)
    
        ' Let set the initial position of the tank
        TankPosition(i).x = (100 * i) - 300
        TankPosition(i).z = 200
        TankPosition(i).y = Land.GetHeight(TankPosition(i).x, TankPosition(i).z) + 10
        Tank(i).SetPosition TankPosition(i).x, TankPosition(i).y, TankPosition(i).z
    
    Next i
    
    ' Lets select the tank(1) by default
    intTankSelected = 1
    
    ' Set the tank's vertex color to green
    Tank(intTankSelected).SetColor RGBA(0, 1, 0, 1)
    
    ' We pop the form over everything else.
    Form1.Show
        
    ' We start the main loop.
    DoLoop = True
    Main_Loop

End Sub

Private Sub Form_Unload(Cancel As Integer)

    ' The user asked to quit but clicked on the 'X' button at up right.
    DoLoop = False
    
    ' And ask to quit.
    Main_Quit

End Sub

Private Sub Main_Loop()

    ' The main loop
    Do
        ' Let us the capacity to use buttons of the form.
        DoEvents
        
        ' We check the input
        Check_Input
        
        ' We check and update the movement
        Check_Movement

        ' We update the camera to point on the tank selected
        '将场景视角转向选择的坦克
        Scene.SetCamera 0, 200, 0, TankPosition(intTankSelected).x, TankPosition(intTankSelected).y, TankPosition(intTankSelected).z

        ' Clear the the last frame.
        TV3D.Clear
        
        ' We render the landscape.
        Land.Render True
        
        ' Render the mesh
        Scene.RenderAllMeshes
                
        ' For each tank, we draw a line from the tank's position
        ' to the tank's destination. Note that you have to
        ' "begin" the 2d part calling the begin action of the screen class
        ' Yes, Line3D is in the 2D screen immediate :) it's easier to optimize
        ' for the engine this way.
        ScreenTV.ACTION_Begin2D
        Dim i As Integer
        For i = 1 To 5
          '在屏幕上绘制3d线段
            ScreenTV.DRAW_Line3D TankPosition(i).x, TankPosition(i).y, TankPosition(i).z, TankDestination(i).x, TankDestination(i).y, TankDestination(i).z, RGBA(0, 1, 0, 1), RGBA(0, 1, 0, 1)
        Next i
        ScreenTV.ACTION_End2D
        
        ' We display everything that we have rendered
        TV3D.RenderToScreen
    
    'We loop all of this until the DoLoop isn't True.
    Loop Until DoLoop = False
    
    ' We ask to quit.
    Main_Quit

End Sub

Private Sub Check_Input()
        
    ' We position the TrueVision3D mouse under the Windows mouse cursor.
    ' You must do that if you want TV to uses the Windows cursor
    ' instead of the internal DirectInput cursor, that is not always
    ' synchronized with the windows one.
    Dim tmpWindowsMousePosition As POINTAPI
    GetCursorPos tmpWindowsMousePosition
    InputEngine.SetMousePosition tmpWindowsMousePosition.x - ((Form1.Left / 15) + 12), tmpWindowsMousePosition.y - ((Form1.Top / 15) + 30)

    ' Now, for the mouse input...
    Dim tmpMouseX As Long, tmpMouseY As Long
    Dim tmpMouseB1 As Integer, tmpMouseB2 As Integer

    ' Get the movement of the mouse.
    InputEngine.GetAbsMouseState tmpMouseX, tmpMouseY, tmpMouseB1, tmpMouseB2

    ' If we clicked on the mouse button1, we wanted to select a tank...
    ' 鼠标左键选择坦克
    If tmpMouseB1 <> 0 Then
    
        '...check if the mouse pointer has collided with a Tank.
        Set CollisionResult = Scene.MousePicking(tmpMouseX, tmpMouseY, TV_COLLIDE_MESH, TV_TESTTYPE_BOUNDINGBOX)
        
        ' Check if we did have a collision with a tank
        If CollisionResult.IsCollision Then
        
            ' Yes, we did have a collision with a tank, but which one
            ' is it? We can know this by comparing the positions.
            Dim FoundTheTank As Boolean
            Dim i As Integer
                
            While Not FoundTheTank
                i = i + 1
                If Tank(i).GetPosition.x = CollisionResult.GetCollisionMesh.GetPosition.x _
                And Tank(i).GetPosition.z = CollisionResult.GetCollisionMesh.GetPosition.z Then
                    intTankSelected = i
                        
                    ' Change the color of the tank selected
                    Dim j As Integer
                    For j = 1 To 5
                        Tank(j).SetColor RGBA(1, 0, 0, 1)
                    Next j
                    Tank(i).SetColor RGBA(0, 1, 0, 1)
                    FoundTheTank = True
                End If
            Wend
        
        End If

    End If

    ' If we clicked on the mouse button2, we wanted to give a destination
    ' to the selected tank.
    '按下鼠标右键,给定坦克的目标位置
    If tmpMouseB2 <> 0 Then
    
        '...check if the mouse pointer has collided with a Tank.
        Set CollisionResult = Scene.MousePicking(tmpMouseX, tmpMouseY, TV_COLLIDE_LANDSCAPE, TV_TESTTYPE_ACCURATETESTING)
        
        ' Check if we did have a collision with the landscape
        If CollisionResult.IsCollision Then
        
            TankDestination(intTankSelected) = CollisionResult.GetImpactPoint
            
            ' Direction of the tank is the unit vector
            ' of the difference between end point and start point of the tank
            ' We use VNormalize to get a vector of length 1 (unit vector)
            '方向
            TankDirection(intTankSelected) = VNormalize(VSubtract(TankDestination(intTankSelected), TankPosition(intTankSelected)))
            
            ' Update the tank's angle, according ot the direction
            ' it uses a useful 2D function that gets the angle from a direction. (on x and z)
            '角度
            TankAngleY(intTankSelected) = Direction2Ang(TankDirection(intTankSelected).x, TankDirection(intTankSelected).z)

         
            ' Set the tank's mesh rotation
            '旋转
            Tank(intTankSelected).SetRotation 0, TankAngleY(intTankSelected), 0
        
        End If

    End If

End Sub

Private Sub Check_Movement()

    Dim i As Integer
    For i = 1 To 5
    
        ' Check if tank has reached destination, if not, update the tank
        ' position by adding a scale of the vector destination.
        '检测坦克是否抵达目的地,如果没有,通过添加矢量值的方式来更新坦克的位置
        If GetDistance3D(TankPosition(i).x, 0, TankPosition(i).z, TankDestination(i).x, 0, TankDestination(i).z) > 2 Then
        
            ' Update all the tank's position
            TankPosition(i) = VAdd(TankPosition(i), VScale(TankDirection(i), TV3D.TimeElapsed * 0.1))
            TankPosition(i).y = Land.GetHeight(TankPosition(i).x, TankPosition(i).z) + 10
        
            ' Update the tank's mesh position
            Tank(i).SetPosition TankPosition(i).x, TankPosition(i).y, TankPosition(i).z
    
        End If
    
    Next i
        
End Sub

Private Sub Main_Quit()
        
    ' We want to quit the project, so we start by desroyng
    ' the texture factory.
    Set TextureFactory = Nothing
    
    ' We destroy the screen object
    Set ScreenTV = Nothing
    
    ' We destroy the tank object
    Set Tank(1) = Nothing
    Set Tank(2) = Nothing
    
    ' We destroy the land object.
    Set Land = Nothing
    
    ' Don't forget to destroy the inputengine object...
    Set InputEngine = Nothing
    
    ' Then, we destroy the scene object.
    Set Scene = Nothing
    
    ' We finish the frenetic destroy with the TV3D object.
    Set TV3D = Nothing
    
    ' We end the application.
    End

End Sub

阅读(2506) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~