Casino Online
Casino online








Mercato forex
Mercato forex






B8. Muoversi nello spazio 3D


Mouse camera
Guardare dall'alto il nostro terreno che rotea ci fa sentire un po' degli dei, ma sarebbe bello andare a dargli un'occhiata più da vicino. Per questo, implementeremo una telecamera mobile che possa essere ruotata in ogni direzione con il mouse. Questo tipo di telecamera di chiama mouse-camera e ha la particolarità di intrappolare il puntatore all'interno della finestra, poiché esso definisce il punto verso cui si sta guardando (che, quindi, deve sempre essere al centro dello schermo).
Cominciamo a scrivere il codice che legga l'input del mouse e ruoti la telecamera:
Public Class Game
    
    '...
    
    'TELECAMERA -------------------------------------
    'Ricorda la precedente posizione del mouse
    Private PrevMouseState As MouseState
    'Queste variabili sono usate per memorizzare
    'la rotazione su Y (LeftRight) e su X (UpDown)
    'Essendo angoli, sono misurati in radianti
    Private LeftRightRotation As Single
    Private UpDownRotation As Single
    'Posizione della telecamera
    Private CameraPosition As Vector3
    'Inoltre, consideriamo un'altra variabile:
    'la velocità di rotazione:
    Private RotationSpeed As Single = 0.3
    
    '...
    
#Region "Gestione telecamera"

    'Questa procedura calcola l'angolo di spostamento
    'sulla base dello spostamento x-y del mouse
    'sullo schermo. ElapsedTime è un parametro
    'Single che rappresenta quanti secondi sono
    'passati dal frame precedente. Infatti più
    'tempo sarà passato e più la telecamera
    'verrà ruotata (non su tutti i computer il
    'programma gira a 60 frame per secondo!)
    Private Sub ProcessMouseInput(ByVal ElapsedTime As Single)
        'Ottiene lo stato del mouse
        Dim CurrentMouseState As MouseState = Mouse.GetState

        'Se il mouse è fermo, ossia la sua
        'posizione è uguale a quella precedente,
        'non fa niente. Altrimenti procede
        If CurrentMouseState <> PrevMouseState Then
            'Calcola gli spostamenti su X e su Y
            Dim DX As Single = _
                CurrentMouseState.X - PrevMouseState.X
            Dim DY As Single = _
                CurrentMouseState.Y - PrevMouseState.Y
            'Modifica la rotazione sulla base di questi tre
            'fattori
            LeftRightRotation -= DX * RotationSpeed * ElapsedTime
            UpDownRotation -= DY * RotationSpeed * ElapsedTime
            'Come abbiamo già detto, il mouse deve sempre
            'stare al centro della finestra, perciò lo
            'rimettiamo in posizione
            Mouse.SetPosition(Me.GraphicsDevice.Viewport.Width / 2, _
                Me.GraphicsDevice.Viewport.Height / 2)
            UpdateView()
        End If
    End Sub

    'Questo metodo ricalcola la matrice di vista sulla base della
    'rotazione della telecamera
    Private Sub UpdateView()
        'Prima di tutto, creiamo una matrice di rotazione che
        'rappresenti l'attuale stato della telecamera
        Dim Rotation As Matrix = _
            Matrix.CreateRotationX(UpDownRotation) * _
            Matrix.CreateRotationY(LeftRightRotation)

        'Ora, ammettiamo di essere nella posizione iniziale e,
        'quindi di guardare dritto davanti a noi. In questo
        'caso il punto che guarderemmo sarebbe dato dalla 
        'somma della nostra posizione e del vettore "avanti"
        '(ossia un vector3 con x=0, y=0 e z=-1). Allo
        'stesso modo, il vettore "su" sarebbe il classico
        'vettore con x=0, y=1 e z=0. Definiamo questi
        'vettori:
        Dim Forward As New Vector3(0, 0, -1)
        Dim Up As New Vector3(0, 1, 0)

        'Tuttavia, dato che ora noi stiamo ruotati, anche questi
        'vettori ci seguiranno nella rotazione. Quindi per
        'ottenere i veri target e up vector bisogna ruotare
        'quelli iniziali:
        Dim RotForward As Vector3 = _
            Vector3.Transform(Forward, Rotation)
        Dim RotUp As Vector3 = Vector3.Transform(Up, Rotation)

        'Allora, il vettore "su" ruotato va bene così, ma
        'il nostro punto-bersaglio non è ancora pronto:
        Dim Target As Vector3 = CameraPosition + RotForward

        'Quindi reimposta la matrice
        ViewMatrix = Matrix.CreateLookAt(CameraPosition, Target, RotUp)
    End Sub

#End Region
       
       '...
       
    Protected Overrides Sub LoadContent()
        Shader = GetEffect(AppPath & "\SimpleShader.fx")
        LoadHeightMap(GetTexture(AppPath & "\HeightMap.bmp"))
        SetVertices()
        SetIndices()
        SetNormals()
        CopyToBuffer()

        ProjectionMatrix = Matrix.CreatePerspectiveFieldOfView( _
            MathHelper.PiOver4, _
            Me.GraphicsDevice.Viewport.AspectRatio, _
            1, 500)

        'Imposta la posizione della telecamera 
        CameraPosition = New Vector3(0, 40, TerrainLength / 2)
        'Sposta il mouse al centro della finestra
        Mouse.SetPosition(Me.GraphicsDevice.Viewport.Width / 2, _
                Me.GraphicsDevice.Viewport.Height / 2)
        'Imposta la posizione originale del mouse
        PrevMouseState = Mouse.GetState
        'Ricalcola la matrice di vista
        UpdateView()

        MyBase.LoadContent()
    End Sub
    
    '...
    
    Protected Overrides Sub Update(ByVal GameTime As GameTime)
        'Calcola la nuova direzione della telecamera
        ProcessMouseInput(GameTime.ElapsedGameTime.TotalSeconds)
        MyBase.Update(GameTime)
    End Sub

    '...
End Class 
(Per uscire dal programma premete Alt+F4)
Ora siamo in grado di ruotare la telecamera per guardarci attorno. Che ne dite di muoverla?
#Region "Gestione telecamera"
    
    '...
    
    'Questa procedura legge i tasti premuti e sposta la
    'telecamera di conseguenza
    Private Sub ProcessKeyboardInput()
        'Questo vettore rappresenta lo spostamento
        Dim Motion As New Vector3(0, 0, 0)
        Dim KeyState As KeyboardState = Keyboard.GetState

        'Con W si va avanti
        If KeyState.IsKeyDown(Keys.W) Then
            Motion += New Vector3(0, 0, -1)
        End If
        'Con S si retrocede
        If KeyState.IsKeyDown(Keys.S) Then
            Motion += New Vector3(0, 0, 1)
        End If
        'Con D ci si sposta a destra
        If KeyState.IsKeyDown(Keys.D) Then
            Motion += New Vector3(1, 0, 0)
        End If
        'Con A ci si sposta a sinistra
        If KeyState.IsKeyDown(Keys.A) Then
            Motion += New Vector3(-1, 0, 0)
        End If
        'Con Su ci si muove in alto
        If KeyState.IsKeyDown(Keys.Up) Then
            Motion += New Vector3(0, 1, 0)
        End If
        'Con Giù ci si muove in basso
        If KeyState.IsKeyDown(Keys.Down) Then
            Motion += New Vector3(0, -1, 0)
        End If

        UpdatePosition(Motion)
    End Sub
    
    '...
    
    'Ricalcola la nuova posizione
    Private Sub UpdatePosition(ByVal Motion As Vector3)
        'Ricordate che la telecamera è comunque ruotata
        'perciò anche il vettore di movimento
        'sarà ruotato di conseguenza
        Dim Rotation As Matrix = _
            Matrix.CreateRotationX(UpDownRotation) * _
            Matrix.CreateRotationY(LeftRightRotation)
        Dim RotMotion As Vector3 = Vector3.Transform(Motion, Rotation)

        CameraPosition += RotMotion
        UpdateView()
    End Sub
#End Region

    '...
    
    Protected Overrides Sub Update(ByVal GameTime As GameTime)
        'Calcola la nuova direzione della telecamera
        ProcessMouseInput(GameTime.ElapsedGameTime.TotalSeconds)
        ProcessKeyboardInput()

        MyBase.Update(GameTime)
    End Sub
    
    '... 
Ecco un video del risultato finale.








 

The Totem's Lair - Copyright (C) 2009
È vietata la riproduzione sia totale che parziale del sito.