Posts tagged with: Scripts

Unity 3D – Script para rotacionar objeto no próprio eixo

rodar

Quer ver o script funcionando?  CLIQUE AQUI.

Quer o arquivo fonte do Unity?  DOWNLOAD.

Abaixo coloco o código fonte dos dois arquivos:

RotateObject.cs


using UnityEngine;
using System.Collections;
/// Esse é um script que rotaciona um objeto no seu eixo.
/// Funcionalidades
/// Rotaciona o objeto no próprio eixo com possibilidade de smooth
///
/// Autor: Daniel Almeida - daniel@immersive.com.br / daniel@compilamasnaoroda.com.br
/// Data: 03/05/2014
/// Versão 1

public class RotateObject : MonoBehaviour
{
 //valores iniciais de rotação
 public float rotationX = 0.0f;
 public float rotationY = 0.0f;
 //velocidade que terá a rotação
 public float rotationSpeedX = 250.0f;
 public float rotationSpeedY = 120.0f;
 //Se movimento é com suavização
 public bool smooth = true;
 //limita a rotação no eixo X
 public float rotationMinX = -360.0f;
 public float rotationMaxX = 360.0f;
 //limita a rotação no eixo Y
 public float rotationMinY = -20f;
 public float rotationMaxY = 80f;
 //tempo para dar o smooth
 public float smoothTime = 0.3f;
 //variaveis referencia para velocidade
 private float xVelocity = 0.0f;
 private float yVelocity = 0.0f;
 //guarda o valor de x e y enquanto está interpolando
 private float xSmooth = 0.0f;
 private float ySmooth = 0.0f; 

 void Start()
 {
 //inicia já na posição setada
 xSmooth = rotationX;
 ySmooth = rotationY;
 //inicializa nas posicões passadas
 updateRotation();
 }

 void LateUpdate()
 {
 if (Input.GetMouseButton(0)) {
 rotationX -= Input.GetAxis("Mouse X") * rotationSpeedX * Time.deltaTime;
 rotationY -= Input.GetAxis("Mouse Y") * rotationSpeedY * Time.deltaTime;
 } 

 if (smooth)
 {
 //trava a rotação smooth nos limites
 if (rotationMinX != -360 && rotationMaxX != 360)
 {
 rotationX = Mathf.Clamp(rotationX, rotationMinX, rotationMaxX);
 }
 if (rotationMinY != -360 && rotationMaxY != 360)
 {
 rotationY = Mathf.Clamp(rotationY, rotationMinY, rotationMaxY);
 }

 xSmooth = Mathf.SmoothDamp(xSmooth, rotationX, ref xVelocity, smoothTime);
 ySmooth = Mathf.SmoothDamp(ySmooth, rotationY, ref yVelocity, smoothTime);
 }
 updateRotation();
 }

 void updateRotation()
 {
 Quaternion rotation;

 if (smooth)
 {
 rotation = Quaternion.Euler(ySmooth, xSmooth, 0);
 }
 else
 {
 //acerta os angulos para nao passarem de -360 ou 360
 rotationX = ClampAngle(rotationX, rotationMinX, rotationMaxX);
 rotationY = ClampAngle(rotationY, rotationMinY, rotationMaxY);
 rotation = Quaternion.Euler(rotationY, rotationX, 0);
 }
 transform.rotation = rotation;
 }

 float ClampAngle(float angle, float min, float max)
 {
 //acerta os angulos para nao passarem de -360 ou 360
 if (angle < -360)
 angle += 360;
 if (angle > 360)
 angle -= 360;
 //garante que o angulo esta no intervalor setado
 return Mathf.Clamp(angle, min, max);
 }
}

CameraZoom.cs


using UnityEngine;
using System.Collections;
/// Esse é um script que controla o zoom da câmera
/// Funcionalidades
/// Script conta com smooth de movimento, trava do zoom e possibilidade de setar um novo zoom, dentro do zoom minimo e zoom máximo
///
/// Autor: Daniel Almeida - daniel@immersive.com.br / daniel@compilamasnaoroda.com.br
/// Data: 03/05/2014
/// Versão 1

public class CameraZoom : MonoBehaviour
{

//Objeto alvo, ele que será o foco do zoom
public Transform target;
public bool zoomActive = true;
//zoom inicial, minimo , maximo , velocidade e desacelaração do zoom
public float zoom = 10.0f;
public float zoomMin = 5.0f;
public float zoomMax = 20.0f;
public float zoomSpeed = 10.0f;
public float zoomDampening = 5.0f;
//----------------------------------------------------------Variáveis PRIVADAS------------------------------------------
private float currentzoom;
private float desiredzoom;
private float zoomDistance;
void Start()
{
desiredzoom = zoom;
currentzoom = zoom;
updatePosition();
}
void LateUpdate()
{
if (zoomActive)
{
desiredzoom -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * zoomSpeed * Mathf.Abs(desiredzoom);
desiredzoom = Mathf.Clamp(desiredzoom, zoomMin, zoomMax);
currentzoom = Mathf.Lerp(currentzoom, desiredzoom, Time.deltaTime * zoomDampening);
zoom = currentzoom;
}
updatePosition();
}

void updatePosition()
{
transform.position = transform.rotation * new Vector3(0.0f, 0.0f, -zoom) + target.transform.position;
}

float ClampAngle(float angle, float min, float max)
{
//acerta os angulos para nao passarem de -360 ou 360
if (angle < -360)
angle += 360;
if (angle > 360)
angle -= 360;
//garante que o angulo esta no intervalor setado
return Mathf.Clamp(angle, min, max);
}
public void setZoom(float _zoom)
{
desiredzoom = Mathf.Clamp(_zoom, zoomMin, zoomMax);
}

//----------------------------------------------------------METODO doLockZoom------------------------------------------
public void doLockZoom(bool zoomLock)
{
zoomActive = !zoomLock;
}
}
Share

Script de Câmera Orbital – Unity3D

Precisei fazer um app que usa intensamente uma câmera orbital e teria que rodar tanto em tablets quanto em desktop.
Pesquisei um monte, mas os scripts que achei sempre faltava algo, então juntei um coisa aqui uma ali e fiz um script até que bem completo.
Falta ainda fazer a câmera seguir um ponto em movimento e colidir com paredes etc, mas como não iria utilizar isso não fiz agora.
Uma breve descrição do que o script faz, tudo isso controlado por variáveis expostas e funções públicas:

  • Funciona tanto para mobile quanto desktop
  • Troca o ponto algo com ou sem smooth
  • Possibilidade de usar o botão direito ou esquerdo do mouse para rotacionar
  • Possibilidade de usar as setas do teclado para rotacionar
  • Zoom com scroll do mouse ou control + seta , 2 dedos no mobile , com velocidade controlavel
  • Seleção de quais eixos serão usados
  • Rotação com ou sem smooth , com velocidade controlável
  • Trava de ângulo nos eixos , para limitar a rotação
  • Trava de zoom mínimo e zoom máximo

Ainda tem alguns scripts de exemplo para trocar a rotação ou o ponto central, com várias opções para controle.

Contact Point é para centralizar o ponto da câmera aonde clicar no objeto e Seconds to Action funciona no mobile apenas, dedo por x segundos sobre o objeto/botão para ativar a ação.

O código fonte está bem comentado para facilitar.

Abaixo um link com um exemplo rodando e também um projeto com o código fonte.

DOWNLOAD CÓDIGO FONTE

EXEMPLO ONLINE

Vou colocar o código aqui escondido também

using UnityEngine;
using System.Collections;
/// <Descricao>
/// componente 'TransfereTargetCamera'
/// Esse é um script que gira a camera entorno de um ponto
/// Funcionalidades
/// Seleção de eixos para rotacionar
/// Rotação com ou sem desaceleração
/// Trava de angulos para rotação
/// Troca de eixo com ou sem desaceleração
/// Zoom com ou sem desaceleração
/// Metodo para ver se está sendo rotacionada a camera
/// Metodos para alterar os paramentros da camera
/// Versão para web/standalone e mobile
/// 
/// Autor: Daniel Almeida - daniel@immersive.com.br / daniel@compilamasnaoroda.com.br
/// Data: 02/12/2011
/// Versão 1
/// </Descricao>
public class CameraOrbitalMouse : MonoBehaviour
{
    //----------------------------------------------------------Variáveis PÚBLICAS------------------------------------------
    public bool mobile = false;
    //Objeto alvo, em torno dele que a camera girará
    public Transform target;
    //se deve seguir o objeto alvo
    //private bool followsTarget = false;
    //se precisa clicar para rotacionar
    public bool mouseClicked = true;
    //se setas do teclado giram a camera
    public bool arrowMode = false;
    public float arrowVelocityX = 1;
    public float arrowVelocityY = 1;
    public float arrowZoomVelocity = 1;

    //seleciona se rotacionará no angulo x,y, ou em ambos
    public enum MouseButtons : int { LEFT, RIGHT };
    public MouseButtons mouseButton;
    //seleciona se rotacionará no angulo x,y, ou em ambos
    public enum Axis : int { X, Y, XY };
    public Axis eixo;
    //Se movimento é com suavização
    public bool smooth = false;
    //tempo para dar o smooth
    public float smoothTime = 0.3f;
    //valores iniciais de rotação
    public float rotationX = 0.0f;
    public float rotationY = 0.0f;
    //limita a rotação no eixo X
    public float rotationMinX = -360.0f;
    public float rotationMaxX = 360.0f;
    //limita a rotação no eixo Y
    public float rotationMinY = -20f;
    public float rotationMaxY = 80f;
    //velocidade que terá a rotação
    public float rotationSpeedX = 250.0f;
    public float rotationSpeedY = 120.0f;
    //se terá zoom
    public bool zoomActive = true;
    //zoom inicial, minimo , maximo , velocidade e desacelaração do zoom
    public float zoom = 10.0f;
    public float zoomMin = 5.0f;
    public float zoomMax = 20.0f;
    public float zoomSpeed = 10.0f;
    public float zoomDampening = 5.0f;
    //----------------------------------------------------------Variáveis PRIVADAS------------------------------------------
    // private bool travaZoom = true;
    private float currentzoom;
    private float desiredzoom;
    //guarda o valor da posicao final do target
    private Vector3 targetPosition = Vector3.zero;
    //guarda o valor de x e y enquanto está interpolando
    private float xSmooth = 0.0f;
    private float ySmooth = 0.0f;
    //variaveis referencia para velocidade
    private float xVelocity = 0.0f;
    private float yVelocity = 0.0f;
    //smooth do reposicionamento
    private bool targetSmooth = false;
    private Vector3 posSmooth = Vector3.zero;
    private Vector3 posVelocity = Vector3.zero;
    //guarda se a câmera está sendo rotacionada pelo usuário
    private bool movingSmooth = false;
    private bool movingMouse = false;
    private Vector3 positionOld;
    private float lastMouseX;
    private float lastMouseY;
    private bool rotationLock = false;
    private bool travaZoom = true;

    //----------------------deletar tudo 
    public float zoomNearLimit = 5;
    public float zoomFarLimit = 12;
    public float zoomScreenToWorldRatio = 3.0f;
    public float orbitScreenToWorldRatio = 1.0f;
    public float twistScreenToWorldRatio = 5.0f;

    // don't change these
    Vector3 orbitSpeed = Vector3.zero;
    //float twistSpeed = 0;
    float distWeight = 0;
    float zoomDistance;
    // float zoomSpeedMobile = 0;
    float lastf0f1Dist;


    //----------------------------------------------------------EXECUTADO AO INICIAR----------------------------------------
    void Start()
    {
        //verifica se o target foi setado
        if (target == null)
        {
            Debug.LogWarning("O Target da câmera não foi setado, mantendo posição (0,0,0) para o target", gameObject);
        }
        else
        {
            targetPosition = target.position;
        }
        //faz toda válidação dos inputs do zoom
        if (zoomMin < 0)
        {
            Debug.LogWarning("Zoom mínimo menor que zero, alterando para o valor padrão = 0", gameObject);
            zoomMin = 0;
        }
        if (zoomMax < 0 || zoomMax < zoomMin)
        {
            Debug.LogWarning("Zoom máximo não pode ser menor que zero ou menor que o zoom mínimo, alterando para o valor zoomMin + 10", gameObject);
            zoomMax = zoomMin + 10;
        }
        if (zoom < zoomMin || zoom > zoomMax)
        {
            Debug.LogWarning("Zoom fora no range mínimo e máximo, alterando para o valor máximo", gameObject);
            zoom = zoomMax;
        }

        if (zoomDampening < 0)
        {
            Debug.LogWarning("zoomDampening < 0 causa o mesmo efeito do que = 0 , setando o valor para 0", gameObject);
            zoomDampening = 0;
        }

        if (zoomSpeed < 0)
        {
            Debug.LogWarning("zoomSpeed < 0 causa o mesmo efeito do que = 0 , setando o valor para 0", gameObject);
            zoomSpeed = 0;
        }

        //seta o zoom desejado e o zoom corrente        
        desiredzoom = zoom;
        currentzoom = zoom;

        // faz o rigidbody não afetar rotação
        if (rigidbody)
        {
            rigidbody.freezeRotation = true;
        }
        //inicia já na posição setada
        xSmooth = rotationX;
        ySmooth = rotationY;
        //inicializa posicoes
        posSmooth = target.position;
        //inicializa nas posicões passadas
        updatePosition();
        //pega a posicao inicial da camera
        positionOld = transform.position;
        //pega a posicao inicial do mouse
        lastMouseX = Input.GetAxis("Mouse X");
        lastMouseY = Input.GetAxis("Mouse Y");

    }
    //----------------------------------------------------------EXECUTADO UMA VEZ POR FRAME------------------------------------------
    // chamado uma x por frame
    void Update()
    {
       /* if (followsTarget) {
            if (target == null)
            {
                Debug.LogWarning("O Target da câmera não foi setado, mantendo posição (0,0,0) para o target", gameObject);
            }
            else
            {
                targetPosition = target.position;
            }
        }*/
    }
    void LateUpdate()
    {
        //Debug.Log("orbit x " + orbitSpeed.x + "    orbit y " + orbitSpeed.y);
        if (!mobile)
        {
            //verifica qual axe foi escolhido
            if (!mouseClicked || (Input.GetMouseButton(0) && (mouseButton == MouseButtons.LEFT)) || (Input.GetMouseButton(1) && (mouseButton == MouseButtons.RIGHT)) || (arrowMode && !Input.GetKey("left ctrl") && !Input.GetKey("right ctrl") && (Input.GetKey("up") || Input.GetKey("down") || Input.GetKey("left") || Input.GetKey("right"))))
            {

                if (((eixo == Axis.X) || (eixo == Axis.XY)) && !rotationLock)
                {
                    if (Input.GetKey("up") || Input.GetKey("down") || Input.GetKey("left") || Input.GetKey("right"))
                    {
                        
                            rotationX += (Input.GetKey("right") ? 1 : (Input.GetKey("left") ? -1 : 0)) * arrowVelocityX * rotationSpeedX * Time.deltaTime;
                       
                    }

                    else
                    {
                        //faz as contas no eixo x
                        rotationX += Input.GetAxis("Mouse X") * rotationSpeedX * Time.deltaTime;
                    }
                }
                if (((eixo == Axis.Y) || (eixo == Axis.XY)) && !rotationLock)
                {
                    if (Input.GetKey("up") || Input.GetKey("down") || Input.GetKey("left") || Input.GetKey("right"))
                    {                       
                            rotationY += (Input.GetKey("down") ? 1 : (Input.GetKey("up") ? -1 : 0)) * arrowVelocityY * rotationSpeedY * Time.deltaTime;
                      
                    }
                    
                    else
                    {
                        //faz as contas no eixo y
                        rotationY -= Input.GetAxis("Mouse Y") * rotationSpeedY * Time.deltaTime;
                    }
                }

                //verifica se o mouse está sendo movido
                movingMouse = (lastMouseX != Input.GetAxis("Mouse X") || lastMouseY != Input.GetAxis("Mouse Y"));
            }
            else
            {
                movingMouse = false;
            }
           
        }
        else
        {
            if (!rotationLock)
            {
                Touch f0;
                if (Input.touchCount == 1)
                {

                    // finger data
                    f0 = Input.GetTouch(0);

                    // finger delta
                    Vector3 f0Delta = new Vector3(f0.deltaPosition.x, -f0.deltaPosition.y, 0);

                    // if finger moving
                    if (f0.phase == TouchPhase.Moved)
                    {


                        // compute orbit speed
                        orbitSpeed += (f0Delta + f0Delta * distWeight) * Time.deltaTime;

                        rotationX = orbitSpeed.x * rotationSpeedX * 0.2f;
                        rotationY = orbitSpeed.y * rotationSpeedY * 0.3f;
                        movingMouse = true;
                    }
                }
                else if (Input.touchCount == 2)
                {
                    f0 = Input.GetTouch(0);
                    if (f0.phase == TouchPhase.Moved)
                    {
                        Touch touch2 = Input.touches[1];
                        desiredzoom = Vector2.Distance(f0.position, touch2.position);
                        if (travaZoom)
                        {
                            travaZoom = false;
                        }
                        else
                        {
                            zoom += (currentzoom - desiredzoom) * Time.deltaTime;
                        }
                        zoom = Mathf.Clamp(zoom, zoomMin, zoomMax);

                        currentzoom = desiredzoom;
                    }
                }
                else
                {
                    movingMouse = false;
                }
            }
            if (Input.touchCount != 2)
            {
                travaZoom = true;
            }
        }
        if (smooth)
        {
            //trava a rotação smooth nos limites
            if (rotationMinX != -360 && rotationMaxX != 360)
            {
                rotationX = Mathf.Clamp(rotationX, rotationMinX, rotationMaxX);
            }
            if (rotationMinY != -360 && rotationMaxY != 360)
            {
                rotationY = Mathf.Clamp(rotationY, rotationMinY, rotationMaxY);
            }

            xSmooth = Mathf.SmoothDamp(xSmooth, rotationX, ref xVelocity, smoothTime);
            ySmooth = Mathf.SmoothDamp(ySmooth, rotationY, ref yVelocity, smoothTime);
        }
        //se smooth do zoom ativo...
        if (zoomActive && !mobile)
        {

            if (arrowMode && (Input.GetKey("left ctrl") || Input.GetKey("right ctrl")) && (Input.GetKey("up") || Input.GetKey("down")))
            {
              
                    desiredzoom -= (Input.GetKey("down") ? -1 : (Input.GetKey("up") ? 1 : 0)) * Time.deltaTime * arrowZoomVelocity * zoomSpeed * Mathf.Abs(desiredzoom);
               
            }        
            else
            {
                desiredzoom -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * zoomSpeed * Mathf.Abs(desiredzoom);
            }

            //clamp the zoom min/max
            desiredzoom = Mathf.Clamp(desiredzoom, zoomMin, zoomMax);
            // For smoothing of the zoom, lerp zoom
            currentzoom = Mathf.Lerp(currentzoom, desiredzoom, Time.deltaTime * zoomDampening);
            zoom = currentzoom;
        }

        if (targetSmooth)
        {

            posSmooth = Vector3.SmoothDamp(posSmooth, targetPosition, ref posVelocity, smoothTime);
        }

        //pega a ultima posicao do mouse
        lastMouseX = Input.GetAxis("Mouse X");
        lastMouseY = Input.GetAxis("Mouse Y");

        updatePosition();

    }

    void updatePosition()
    {

        Quaternion rotation;
        Vector3 position;

        if (smooth)
        {
            //acerta os angulos para nao passarem de -360 ou 360
            //xSmooth = ClampAngle(xSmooth, rotationMinX, rotationMaxX);
            //ySmooth = ClampAngle(ySmooth, rotationMinY, rotationMaxY);
            //garante que o angulo esta no intervalor setado
            //pega a rotacao
            rotation = Quaternion.Euler(ySmooth, xSmooth, 0);
        }
        else
        {
            //acerta os angulos para nao passarem de -360 ou 360
            rotationX = ClampAngle(rotationX, rotationMinX, rotationMaxX);
            rotationY = ClampAngle(rotationY, rotationMinY, rotationMaxY);
            //garante que o angulo esta no intervalor setado
            //pega a rotacao
            rotation = Quaternion.Euler(rotationY, rotationX, 0);
        }
        //faz a conta da posicao
        if (targetSmooth)
        {
            position = rotation * new Vector3(0.0f, 0.0f, -zoom) + posSmooth;
        }
        else
        {
            position = rotation * new Vector3(0.0f, 0.0f, -zoom) + targetPosition;
        }

        //seta nos valores
        transform.rotation = rotation;
        transform.position = position;

        //se está sendo movida a camera
        movingSmooth = positionOld != transform.position;       

        positionOld = transform.position;
    }

    float ClampAngle(float angle, float min, float max)
    {
        //acerta os angulos para nao passarem de -360 ou 360
        if (angle < -360)
            angle += 360;
        if (angle > 360)
            angle -= 360;
        //garante que o angulo esta no intervalor setado
        return Mathf.Clamp(angle, min, max);
    }
    //----------------------------------------------------------METODO setTarget------------------------------------------
    //Esse método serve para se passar um novo target para a câmera
    //deve ser informado se terá transição de uma posição para outra ou se o corte será seco
    //Parametros : novaPosicao(Vector3, transform ou gameObject)
    //             smoothly (bool)
    public void setTarget(Vector3 novaPosicao, bool smoothly = false)
    {
        targetPosition = novaPosicao;
        targetSmooth = smoothly;
        //se não for para ter suavidade sincroniza o ponto inicial e final, isso previne que se clicar em um objeto que tem o smooth
        //ele partirá do ponto corrente.
        if (!targetSmooth)
        {
            posSmooth = targetPosition;
        }
    }
    //sobrecarga para o metodo setTarget
    public void setTarget(Transform novaPosicao, bool smoothly = false)
    {
        setTarget(novaPosicao.position, smoothly);
    }
    //sobrecarga para o metodo setTarget
    public void setTarget(GameObject novaPosicao, bool smoothly = false)
    {
        setTarget(novaPosicao.transform.position, smoothly);
    }
    //----------------------------------------------------------METODO isMoving------------------------------------------
    //metodo usado para saber se a camera está girando
    //parametro affectedSmooth = true pega se a camera está em movimento (usuário ou smooth movendo)
    //parametro affectedSmooth = false pega se a camera está em movimento (apenas o usuário a movendo)
    public bool isMoving(bool affectedSmooth = false)
    {
        if (affectedSmooth)
        {
            return movingSmooth;
        }
        else
        {
            return movingMouse;
        }

    }
    //----------------------------------------------------------METODO setRotation------------------------------------------
    public void setRotation(float newRotationX, float newRotationY, bool smoothly)
    {
        //pega o valor no range de -360 a 360
        float rotationXNormalizado = rotationX % 360;
        float rotationYNormalizado = rotationY % 360;
        //apara as arestas
        rotationX = ClampAngle(newRotationX, rotationMinX, rotationMaxX);
        rotationY = ClampAngle(newRotationY, rotationMinY, rotationMaxY);
        //pega o valor no range de -360 a 360
        xSmooth = xSmooth % 360;
        ySmooth = ySmooth % 360;

        //clipa a rotação para pegar o caminho mais perto do ponto de destino
        if (rotationX - rotationXNormalizado > 180)
        {
            rotationX -= 360;
        }
        else if (rotationX - rotationXNormalizado < -180)
        {
            rotationX += 360;
        }
        //clipa a rotação para pegar o caminho mais perto do ponto de destino
        if (rotationY - rotationYNormalizado > 180)
        {
            rotationY -= 360;
        }
        else if (rotationY - rotationYNormalizado < -180)
        {
            rotationY += 360;
        }
        //se mudança a seco, iguala a variavel de smooth
        if (!smoothly)
        {
            xSmooth = rotationX;
            ySmooth = rotationY;
        }
    }

    public void setZoom(float _zoom)
    {
        desiredzoom = Mathf.Clamp(_zoom, zoomMin, zoomMax);
    }

    //----------------------------------------------------------METODO setRotationAndLock------------------------------------------
    //faz o mesmo que setrotation mas manda travar a rotação 
    public void setRotationAndLock(float newRotationX, float newRotationY, bool smoothly, bool rotationLock)
    {
        setRotation(newRotationX, newRotationY, smoothly);
        doLockRotation(rotationLock);
    }
    //----------------------------------------------------------METODO doLockRotation------------------------------------------
    //faz o mouse não rotacionar mais a camera
    public void doLockRotation(bool rotationLock)
    {
        this.rotationLock = rotationLock;
    }

    //----------------------------------------------------------METODO doLockZoom------------------------------------------
    //faz o mouse não dar mais zoom na camera
    public void doLockZoom(bool zoomLock)
    {
        zoomActive = !zoomLock;
    }
}

using UnityEngine;
using System.Collections;

/// <Descricao>
/// componente 'TransfereTargetCamera'
/// Este script deve ser usado em conjunto com o script CameraOrbitalMouse.cs,
/// Ele envia uma nova posição para o target e diz se deve ser com transição ou se já troca
/// de lugar na hora.
/// </Descricao>
[AddComponentMenu("Scripts/TransfereTargetCamera")]
public class TransfereTargetCamera : MonoBehaviour
{
    //camera que será afetada
    public Camera cameraTarget;
    public bool smooth = false;
    public enum MouseButtons : int { LEFT, RIGHT };
    public MouseButtons mouseButton;
    public Transform useObjectPosition;
    public Vector3 targetPosition = Vector3.zero;
    public bool contactPoint;
    public float secondsToAction = 2;
    private float contadorTempo = 0;
    private bool contando = false;

    void Start()
    {

    }

    void update()
    {

    }

    void OnMouseOver()
    {
        if ((Input.GetMouseButton(0) && (mouseButton == MouseButtons.LEFT)) || (Input.GetMouseButton(1) && (mouseButton == MouseButtons.RIGHT)))
        {
            if (cameraTarget && !contactPoint && !cameraTarget.GetComponent<CameraOrbitalMouse>().mobile)
            {
                // Debug.DrawLine(collider.con)
                cameraTarget.GetComponent<CameraOrbitalMouse>().setTarget(useObjectPosition != null ? useObjectPosition.position : targetPosition, smooth);
            }
        }
    }

    void Update()
    {
        if (cameraTarget.GetComponent<CameraOrbitalMouse>().mobile)//acoes para mobile
        {
            Touch f0;

            if (Input.touchCount >= 1)
            {

                // finger data
                f0 = Input.GetTouch(0);


                // if finger moving
                if (f0.phase == TouchPhase.Began)
                {
                    contadorTempo = 0;
                    contando = true;
                }
                else if (f0.phase == TouchPhase.Ended || f0.phase == TouchPhase.Canceled || f0.phase == TouchPhase.Moved)
                {
                    contando = false;
                }
            }


            if (contando)
            {
                contadorTempo += Time.deltaTime;

                if (contadorTempo >= secondsToAction)
                {
                    Ray ray = Camera.main.ScreenPointToRay(new Vector3(f0.position.x, f0.position.y, 0)); // Construct a ray from the current mouse coordinates

                    RaycastHit hit;

                    if (Physics.Raycast(ray, out hit))
                    {
                        cameraTarget.GetComponent<CameraOrbitalMouse>().setTarget(hit.point, smooth);
                        Debug.Log("atiraaa", gameObject);
                    }

                    cameraTarget.GetComponent<CameraOrbitalMouse>().setTarget(hit.point, smooth);
                    contando = false;
                    contadorTempo = 0;
                }
            }
        }
        else//acoes para standalone / web
        {

            if (((Input.GetMouseButton(0) && (mouseButton == MouseButtons.LEFT)) || (Input.GetMouseButton(1) && (mouseButton == MouseButtons.RIGHT))) && contactPoint)
            {

                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); // Construct a ray from the current mouse coordinates

                RaycastHit hit;

                if (Physics.Raycast(ray, out hit))
                {
                    if (hit.collider.gameObject == gameObject)
                    {
                        cameraTarget.GetComponent<CameraOrbitalMouse>().setTarget(hit.point, smooth);
                    }
                }
            }
        }
    }
}

using UnityEngine;
using System.Collections;

/// <Descricao>
/// componente 'SetaNovaRotacao'
/// </Descricao>
[AddComponentMenu("Scripts/SetaNovaRotacao")]
public class SetaNovaRotacao : MonoBehaviour
{

    //camera que será afetada
    public Camera cameraTarget;
    public float rotationX = 0;
    public float rotationY = 0;
    public bool smooth = false;
    
    void Start()
    {

    }

    void OnMouseDown()
    {
        if (cameraTarget)
        {
            cameraTarget.GetComponent<CameraOrbitalMouse>().setRotation(rotationX, rotationY, smooth );
            
        }
    }   
}

using UnityEngine;
using System.Collections;

/// <Descricao>
/// componente 'SetaNovaRotacao'
/// </Descricao>
[AddComponentMenu("Scripts/SetaNovaRotacao")]
public class SetaNovaRotacaoTrava : MonoBehaviour
{

    //camera que será afetada
    public Camera cameraTarget;
    public float rotationX = 0;
    public float rotationY = 0;
    public bool smooth = false;
    public bool rotationLock = false;
    void Start()
    {

    }

    void OnMouseDown()
    {
        if (cameraTarget)
        {
            cameraTarget.GetComponent<CameraOrbitalMouse>().setRotationAndLock(rotationX, rotationY, smooth , rotationLock);
            
        }
    }
}

Share

Unity3D – A janela Console e a classe Debug

Já que falei sobre mensagens para debug no lejos, agora falarei sobre isso no Unity3D.

Exibir mensagens para acompanhar resultados dentro de sua lógica é uma prática indispensável e no Unity isso ganha algumas funcionalidades a mais.

Para exibir uma mensagem é utilizada a classe Debug, que contém os métodos Log, LogError, LogWarning, Break, DrawLine e DrawRay, vou explicar todas.

Debug.Log();

Se a mensagem for simples podemos utilizar o método Log:

Debug.Log(“Teste de mensagem”);

Será exibida uma mensagem com o ícone branco padrão (Linha 1 da imagem).

Podemos sinalizar um objeto para ser realçado quando clicamos na mensagem na tela console

Debug.Log(“Teste de mensagem” , gameObject);

Ao clicar na linha 2 o objeto indicado ganha um destaque.

Debug.LogError();

É uma variação do Log, funciona igual, mas mostra um ícone vermelho de erro, igual da linha 3 da imagem.

Se o botão Error Pause estiver clicado na janela console e uma mensagem desse tipo for enviada, a aplicação será pausada automaticamente.

Ele aceita a indicação de um gameObject também.

Debug.LogError(“Mensagem com icone de erro”);

Debug.LogWarning();

É uma variação do Log, funciona igual, mas mostra um ícone amarelo de alerta, igual da linha 4 da imagem.

Ele aceita a indicação de um gameObject também.

Debug.LogWarning(“Mensagem com icone de alerta”);

Debug.Break();

É utilizado para pausar o aplicativo, esse método não tem parâmetros.


Vou dar uma parada agora de explicar os métodos e explicar os botões da tela console, pois os dois últimos métodos não a usam.

Clear

Limpa a tela do console.

Collapse

Agrupa as mensagem iguais, por exemplo, ao invés de mostrar 5 números 0 mostra apenas 1:

Clear on play

Limpa o console quando é clicado em play.

Error pause

Pausa a aplicação quando alguma mensagem de erro for enviada.

Open editor log

Abre o editor de texto padrão do sistema com todos os logs no Unity3D.


Voltando aos métodos.

Debug.DrawLine();

Desenha uma linha entre um ponto inicial e um ponto final, com cor e tempo de duração, se o tempo não for passado ou for 0 essa linha ficará visível durante 1 frame.

Debug.DrawLine(pontoInicial : Vector3, pontoFinal : Vector3, cor : Color , tempoSegundos : float);

Exemplo:

Debug.DrawLine(Vector3.zero, new Vector3(1, 0, 0), Color.red , 2);

Desenhará uma linha vermelha que ficará visível por 2 segundos.

Essa linha ficará visível na scene view e só ficará na game view se o botão gizmos estiver ativo.

Debug.DrawRay();

Desenha uma linha entre um ponto inicial e uma direção, com cor e tempo de duração, se o tempo não for passado ou for 0 essa linha ficará visível durante 1 frame.

Debug.DrawRay(pontoInicial : Vector3, pontoFinal : Vector3, cor : Color , tempoSegundos : float);

Exemplo:

void OnCollisionEnter(Collision collision) {
foreach (ContactPoint contact in collision.contacts) {
Debug.DrawRay(contact.point, contact.normal, Color.green, 2);
}

Desenhará uma linha verde que ficará visível por 2 segundos identificando os pontos de contato.

Essa linha ficará visível na scene view e só ficará na game view se o botão gizmos estiver ativo.

E é isso ai , mensagem de debug sempre facilitando nossa vida.

Share

Lejos – classe RConsole – Ferramenta para Debug

Nesse vídeo demonstro a utilização da classe RConsole do Lejos, ela cria uma conexão entre o Lego e o computador, enviando mensagens para serem mostradas em um console no computador, facilitando muito a visualização de dados para debug.

Abaixo um comparativo entre algumas formas de exibir dados em texto:

1 – Utilizando a classe LCD:


 
import lejos.nxt.*;
.
.
.
LCD.drawString(String,coluna,linha);

Com ela você tem uma área de 22 colunas e 7 linhas.
Passa-se a string que quer exibir, coluna e linha inicial para o texto.
O texto fica sempre fixo nessa posição.
A classe LCD tem ainda os metodos drawInt, drawChar… para maiores detalhes acesse o LINK.
 
2 – Utilizando a classe System


import lejos.nxt.*;
.
.
.
 System.out.println("Valor de i= " + i);

Com ela você tem uma área de 22 colunas e 7 linhas.  
Passa-se a string que quer exibir e as linhas vão sendo preenchidas, acabando as 7 linhas vai sumindo as primeiras e aparecendo as novas no fim.

3 – Utilizando a classe RConsole

 

import lejos.nxt.*;
import lejos.nxt.comm.RConsole;
.
.
.
 RConsole.openBluetooth(40000);
 RConsole.println("Valor de i= " + i );
 RConsole.close();

Para utilizar a classe RConsole primeiro deve abrir a conexão entre o lego e o computador. Passando o tempo que o programa deve esperar para aceitar uma conexão (no caso 40 segundos), isso serve para dar tempo de abrir o programa de visualização no computador.
RConsole.openBluetooth(milisegundos para iniciar);
Quando o programa iniciar vá até a pasta “caminho da instalação do lejos/bin/nxjconsoleviewer.bat” , escolha o tipo de conexão e mande conectar.
Veja as demais formas de conexões no LINK.
Depois basta ir mandando as mensagens para serem mostradas e no final feche a conexão.

Share

Tocar animação de trás para frente no Unity3D

Precisei fazer uma animação que deveria ser tocada normalmente se clicasse em um botão e se clicasse novamente ela voltaria a animação no sentido contrário.

Para isso temos que controlar a velocidade da animação alterando o parâmetro speed, 1 é o valor normal, 2 toca duas vezes mais rápido e assim vai, números negativos tocam de trás para frente.

Modificando o parâmetro speed para  um número negativo funciona apenas se a animação ainda não chegou no final, pois quando chegar no fim a propriedade time fica igual a zero, como se a animação estivesse voltado ao ponto zero.

Por exemplo , se formos tocar uma animação de 5 segundos, o time começa em 0 e vai passando os segundos até 5, eu imaginava que ao chegar no quinto segundo a animação pararia e o time continuaria no 5, mas o Unity não funciona assim, chegando no final a variável time fica 0.

Se você inverter a velocidade para -1 para fazer voltar ele irá fazer assim: time = 0, -1 , -2 … segundos e na realidade queremos que fique 5 , 4 ,3 , 2… .

Então o que devemos fazer é falar para o parâmetro time que ele está no fim da animação, negativar a velocidade e dar play:

animation["nome da animação"].time = animation["nome da animação"].length;
velocidade = -1;
animation.Play("nome da animação");

Fazendo isso ele toca de trás para frente a partir do fim da animação.
Clique na imagem abaixo para ver um exemplo funcionando.

O código usado foi:

//diz que vai começar tocando para frente
int velocidade = 1;
//objeto que contem a animação
public GameObject destino;
void OnMouseDown()    {
      //seta a velocidade
     destino.animation["Take 001"].speed = velocidade;
     //se quero que a animação volte e ela está parada no fim
     if (velocidade == -1 & destino.animation["Take 001"].time == 0){
           //digo que o tempo que a animação tem é o tamanho dela, já que quando ela chega no fim o time fica 0
          destino.animation["Take 001"].time = destino.animation["Take 001"].length;
      }
     //dá play na anime
     destino.animation.Play("Take 001");
     //seta a nova direção para a animação  no próximo clique
     velocidade *= -1;
}

DOWNLOAD
CLIQUE AQUI para baixar o exemplo

Share

Volante bluetooth – lego nxt + unity3d

Ter idéias boas para desenvolver coisas com o lego nxt é muito difícil, um dia jogando Dirt 2 no Xbox com o volante wireless tive a idéia de fazer um volante desse com o lego, isso ficou na minha cabeça por um tempo, com esse feriado de páscoa, resolvi por em prática já que não tinha nada para fazer mesmo.
O negócio funciona assim, o lego manda para um servidor socket escrito em java os dados de rotação e de dois botões(acelerador e freio, os dois juntos da a marcha ré), esse servidor manda para o unity3D uma string com as informações concatenadas, o unity processa a string e separa as informações.
Utilizei um jogo de carro de corrida já pronto, disponível em : JCar Demo , Todos os créditos para o autor, apenas modifiquei um script que controla o carro para adaptar na minha lógica.

O vídeo abaixo demonstra o funcionamento.


Para essa brincadeira foi desenvolvido 3 códigos.
O primeiro é para o cérebro do Lego, que apenas pega os dados de rotação de um motor e os estados de 2 sensores do toque, concatena em uma string separando por “/” as informações, exemplo:
“-20/true/false”, que seria -20 graus , acelerador apertado e freio não apertado.

import lejos.nxt.*;
import lejos.nxt.comm.*;
import java.io.*;

public class VolanteLego {

	public static void main(String [] args)  throws Exception 
	{
		String connected = "Conectando";
        String waiting = "Aguardando...";
        String closing = "Fechando...";
        String texto;
        //Tira a força do Motor para poder girar manualmente
        Motor.A.setPower(0);
        //Pega os sensores
        TouchSensor acelerador = new TouchSensor(SensorPort.S1);
        TouchSensor freio = new TouchSensor(SensorPort.S2);
		
			LCD.drawString(waiting,0,0);
			LCD.refresh();
			//fica aguardando o pc conectar
	        BTConnection btc = Bluetooth.waitForConnection();
	        
			LCD.clear();
			LCD.drawString(connected,0,0);
			LCD.refresh();	
			//cria o canal de saida
			DataOutputStream dos = btc.openDataOutputStream();
			
			while (!Button.ENTER.isPressed()) {
				LCD.clear();
				//monta uma string com os dados, eles serão filtrados no unity
				texto = Motor.A.getTachoCount() + "/" + acelerador.isPressed() + "/" + freio.isPressed();
				//apenas para Debug
				LCD.drawString(texto, 0, 0);
				LCD.refresh();
				//envia os daos e atualiza o canal
				// \n necessario para falar que acabou a string
				dos.writeBytes(texto + "\n");
				dos.flush();				
			}	
			//fecha e limpa tudo depois que terminou
			dos.close();
			Thread.sleep(100); 
			LCD.clear();
			LCD.drawString(closing,0,0);
			LCD.refresh();
			btc.close();
			LCD.clear();		
	}
}



O segundo código é um servidor em java, ele se conecta com o lego, pega os dados e transmite via socket, para ser capturado no unity3D.

import lejos.pc.comm.*;
import java.io.*;
import java.net.*;


public class VolantePC {	
	// variaveis para UDP socket
	static DatagramSocket udpSocket;
	static int porta = 23175;
	static InetAddress localhost;	
	static DataOutputStream dos ;
	static DataInputStream dis ;
	//string que será compartilhada
	static String bufferStr="";
	
	public static void main(String[] args) {
		// Conecta o nxt
		NXTConnector conn = new NXTConnector();				
		boolean connected = conn.connectTo("btspp://");
		
		if (!connected) {
			System.err.println("Falhou a conexao com o NXT");
			System.exit(1);
		}
		
		//canais de entrada e saida
		 dos = conn.getDataOut();
		 dis = conn.getDataIn();
		
		// cria o socket para enviar
		try
		{
			localhost = InetAddress.getLocalHost();
			udpSocket = new DatagramSocket();
		}
		catch(SocketException e)
		{
			System.out.println("Não abriu o socket");
		}
		catch(UnknownHostException e)
		{
			System.out.println("Não achou o localhost!");
		}
		
		// Inicia uma nova thread para enviar os dados para o pc
		System.out.println("Transmitindo dados UDP na porta "+porta);
		(new Thread(new EnviarDados(udpSocket))).start();
		
		//loop de leitura dos dados do lego
		while(true)
		{			
			try {
				bufferStr = dis.readLine() + "\n";				
			} catch (IOException ioe) {
				System.out.println("IO Exception lendo os bytes:");
				System.out.println(ioe.getMessage());
				break;
			}
		}
		
	}
//  thread para enviar os dados
	public static class EnviarDados implements Runnable
	{
				DatagramSocket datagrama;
		
		public EnviarDados(DatagramSocket datagrama)
		{
			this.datagrama = datagrama;
		}
		
		public void run()
		{			
			// buffer para os dados de saida
			DatagramPacket pacote;
			byte[] pacoteBuffer;
						
			try
			{
				// le os dados para o buffer
				while(true)
				{				
					// converte para byte array para enviar o pacote
					pacoteBuffer = stringToByteArray(bufferStr);
					pacote = new DatagramPacket(pacoteBuffer, pacoteBuffer.length, VolantePC.localhost, VolantePC.porta);
					datagrama.send(pacote);		
					System.out.println(bufferStr);					
					Thread.sleep(33);
				}				
			}catch(IOException e){
				System.out.println("erro");
			}catch(InterruptedException e) {				
				e.printStackTrace();
			}
		}		
		//le a string e converte para um array de bytes
		byte[] stringToByteArray(String str)
		{
			int length = str.length();
			byte[] byteArray = new byte[length];
			for(int i=0; i<length; i = i + 1)
			{
				byteArray[i] = (byte)(str.charAt(i) & 0xff);
			}
			return byteArray;
		}
	}
}

O terceiro é um javascript que se conecta com o servidor socket, filtra a string com os dados e fornece funções para passar os dados para o jogo.

#pragma strict

import System.Net.Sockets;
import System.Net;
import System.Text;

// qual porta o socket usará
var porta:int = 23175;
//string recebida no socket
private var dados:String = "";
// buffer dos dados pegos
private var buffer:byte[];
// Referencia para o socket UDP
private var cliente:UdpClient;
private var source:IPEndPoint;
private var rotacao:String;
private var aceleracao:String;
private var freio:String;

//inicia o socket
function Awake()
{
	IniciarSocket();
}
//le os dados
function Update()
{
	buffer = cliente.Receive(source);
	dados = Encoding.ASCII.GetString(buffer);
	dados = dados.Replace("\n", "");//limpa o finalizador da string
	//filtra os dados
	rotacao = dados.Substring(0,dados.IndexOf("/"));
	dados = dados.Substring(dados.IndexOf("/")+1);
	aceleracao = dados.Substring(0,dados.IndexOf("/"));
	freio = dados.Substring(dados.IndexOf("/")+1);
}
public function getRotation():float{
	//transforma os dados em um range de -1 até 1, depois inverte o sinal 
	return parseFloat(Mathf.Clamp(parseInt(rotacao), -90, 90)/100.0f)*-1.0f;
}
function getAcceleration():float{
	//se só acelerar vai para frente, se aceletar e freiar da ré , ou desacelera
	return aceleracao=="true"?(freio=="true"?-1:1):0;
}
function getBrake():boolean{
	//só freiará se apenas o freio estiver apertado
return (freio=="true" && aceleracao=="false");
}

/**
* Inicia a comunicação com o servidor
*/
function IniciarSocket()
{
	try
	{
		cliente = new UdpClient(porta);		
		source = new IPEndPoint(IPAddress.Any, 0);
	}
	catch(e:System.Exception)
	{
		Debug.Log(e.ToString());
	}
}

Mais um código em C# foi modificado no JCar, para ler as informações desse último código, ele apenas pega os dados e utiliza no jogo.
Para você refazer esse negócio na sua casa, coloquei os códigos para download, apenas tenho umas observações.
O código javascript deve ficar dentro da pasta plugin, pois o unity tem uma frescura no compilador que atrapalha a referência na chamada de um código javascript por um script em c#, colocando dentro da pasta chamada plugins ele é compilado antes, não causando mais problemas.
Passos para refazer:
- Baixar o demo do JCar que está no link acima e substituir o arquivo JControlledCar.cs.
- Copiar a pasta Plugins que contem o arquivo ClienteSocket.js na pasta Assets.
- Dentro do unity3D, colocar o ClienteSocket.js no gameobject Car.
- O JCar usa o torque do motor em 560, acho muito, então diminui para 400, para ficar mais fácil de controlar.

Depois disso é só executar os programas na sequência – Lego , servidor , jogo no Unity e pronto.

PS: Se alguém tiver uma idéia boa de algum projeto bacana que seria legal desenvolver com o lego e quiser compartilhar, posta nos comentários.

DOWNLOADS:
Código fonte

Share

Unity 3d- Criação de polígono

Estava curioso sobre como o Unity3D manipulava polígonos via script e fiz um teste seguindo o estilo da ferramenta Lathe do 3Ds Max, que pega uma linha e de acordo com um eixo é criado copias dessa linha de forma circular, com os novos pontos criados é feita a triangularização para formar o polígono.

Quadro 1.

Mostra os vértices que são usados para formar a linha.

Quadro 2.

A Linha amarela mostra o eixo que será usado para fazer a rotação dos pontos ao seu redor.

Quadro 3.

Mostra o polígono já formado e triangularizado (não sei se essa palavra existe), com uma textura e reflexo aplicado.

Note as linhas cinzas mostrando quantas vezes a linha original foi copiada, no caso coloquei 30 cópias, no mínimo são 3 e quanto mais cópias mais definido e mais pesado, isso é configurável.

O teste utilizou lógicas diversas, como contas com ângulos para criação dos pontos , para triangularizar os pontos e para formar o polígono com UV , Normais, etc, claro que não são as formas mais otimizadas, pois fiz tudo da minha cabeça sem utilizar técnicas conhecidas, mas deu certo para o que eu queria.

Abaixo o arquivo do teste para download.

DOWNLOAD

Share

Unity 3D – Teste tiro de canhão

Esse foi um teste que fiz de disparo de canhão com Unity 3D, tem física, partículas, rotação das partes do canhão com as setas do teclado, animação do canhão quando dispara, explosão de fogo quando acerta uma caixa e troca da textura da caixa quando ela é atingida pela bala do canhão. Abaixo do vídeo tem o código fonte.

Código Fonte:
DOWNLOAD

Share

Tutorial Flash – Arrastando MovieClips – AS3

Hoje vou mostrar quatro modos de arrastar objetos no flash, mais conhecido como “DRAG”.
Drag é quando você clica sobre o objeto, segura o botão apertado e move o mouse, o objeto segue seu movimento, soltando o botão o objeto deixa de seguir.
O objeto pode seguir a partir do ponto que foi clicado ou do ponto (0,0) de si mesmo.

Primeiro modo de DRAG – (BOLA AMARELA)
startDrag() e stopDrag() a partir do ponto clicado;

Esse é o modo mais fácil de fazer, primeiro se adiciona um ouvinte para o evento MOUSE_DOWN que é quando você está com o mouse sobre o objeto e pressiona o botão esquerdo do mouse, depois adiciona outro ouvinte para o evento MOUSE_UP que captura quando você solta o botão esquerdo do mouse sobre o objeto.
O evento MOUSE_UP foi colocado no stage pois dependendo do tipo de drag o mouse nem sempre estará sobre o objeto quando o botão esquerdo for solto.
Esses dois eventos chamam a função controleBola que verifica o event.type, verifica se foi o MOUSE_DOWN ou MOUSE_UP que foi executado, claro que poderia ter sido feito de outra forma, como por exemplo duas funções diferentes, uma para cada tipo de evento , mas assim o código fica mais curto.
Se o evento foi MOUSE_DOWN usamos o startDrag() que manda o objeto seguir o mouse.
Se o evento foi MOUSE_UP usamos o stopDrag() que manda o objeto parar de seguir o mouse.

bolaMC.addEventListener(MouseEvent.MOUSE_DOWN , controleBola);stage.addEventListener(MouseEvent.MOUSE_UP , controleBola);
function controleBola(event:MouseEvent):void {
	switch (event.type) {
		case "mouseDown" :
			bolaMC.startDrag();
			break;
		case "mouseUp" :
			bolaMC.stopDrag();
			break;
	}
}

Segundo modo de DRAG – (ESTRELA AZUL)
startDrag() e stopDrag() a partir do seu ponto (0,0);

Para fazer isso apenas coloque true no parâmetro lockCenter do startDrag():

bolaMC.startDrag(true);

O objeto se deslocará colocando o seu ponto(0,0) na posição do mouse.

Terceiro modo de DRAG – (QUADRADO VERDE)
Coloca o ponto (0,0) do objeto no valor x e y do mouse, similar ao startDrag(true).

Como no primeiro iniciamos pegando os eventos MOUSE_DOWN e MOUSE_UP do objeto, mas agora iremos também usar o evento ENTER_FRAME para executar a função que moverá o objeto para a posição do mouse.
Primeiro declaramos a variável booleana quadradoDrag que nos dirá se o objeto deverá ou não seguir o mouse.
Na função controleQuadrado dizemos para a variável quadradoDrag que deve seguir quando o evento for MOUSE_DOWN e que não deve quando for o evento MOUSE_UP.
Na função loop que é chamada a cada frame devido ao evento ENTER_FRAME, verificamos se o quadradoDrag está sinalizando para mover e atribuímos o valor x e y do mouse para o valor x e y do objeto respectivamente.

quadradoMC.addEventListener(Event.ENTER_FRAME , loopQuadrado);
quadradoMC.addEventListener(MouseEvent.MOUSE_DOWN , controleQuadrado);
stage.addEventListener(MouseEvent.MOUSE_UP , controleQuadrado);
var quadradoDrag:Boolean = false;
function controleQuadrado(event:MouseEvent):void {
	switch (event.type) {
		case "mouseDown" :
			quadradoDrag = true;
			break;
		case "mouseUp" :
			quadradoDrag = false;
			break;
	}
}
function loopQuadrado(event:Event):void{
	if(quadradoDrag){
		quadradoMC.x = mouseX;
		quadradoMC.y = mouseY;
	}
}

Quarto modo de DRAG – (TRIÂNGULO VERMELHO)
Calculando a posição do mouse e subtraindo a posição de onde foi clicado sobre o objeto, similar ao startDrag().

Funciona da mesma forma que o terceiro tipo, mas agora ao invés de uma variável dizer que deve seguir, usaremos um objeto Pointer, que serve para armazenar dois pontos, x e y, acessível via ponto.x e ponto.y
Iniciamos com a variável offset do tipo Point setada em null, que quer dizer que não tem nada armazenado nela.
Quando a função de controle é chamada pelo evento MOUSE_OVER, pegamos a posição do mouse relativa ao ponto (0,0) do objeto, como mostra a imagem abaixo.

Quando a função de controle é chamada pelo evento MOUSE_UP, setamos null novamente, para offset para zerar o objeto.
E na função de loop verificamos se o offset não é null, se for não fazemos nada, se tiver valores dentro dele, pegamos a posição do mouse e subtraímos a posição do mouse relativa que foi setada no evento MOUSE_OVER e passamos para o objeto.

trianguloMC.addEventListener(Event.ENTER_FRAME , loopTriangulo);
trianguloMC.addEventListener(MouseEvent.MOUSE_DOWN , controleTriangulo);
stage.addEventListener(MouseEvent.MOUSE_UP , controleTriangulo);
var offset:Point = null;
function controleTriangulo(event:MouseEvent):void {
	switch (event.type) {
		case "mouseDown" :
			offset = new Point(event.localX , event.localY);
			break;
		case "mouseUp" :
			offset = null;
			break;
	}
}

function loopTriangulo(event:Event):void{
	if(offset != null){
		trianguloMC.x = mouseX - offset.x;
		trianguloMC.y = mouseY - offset.y;
	}
}

No exemplo coloquei mais um função que faz o objeto clicado ficar sobre os demais, não vou explicar isso, pois não é o foco deste post, mas está aplicado no .fla que está para download abaixo.

DOWNLOAD
startDrag.zip

Share

Eventos AddEventListener e RemoveEventListener

Nessa vídeo aula tento demonstrar de forma simples como funciona o básico do sistema de eventos do actionscript 3, abordo apenas a adição e remoção de ouvintes de eventos (AddEventListener e RemoveEventListener), em um próximo vídeo falarei do disparo de eventos. Iremos colocar ação em um botão em actionscript 3.

Sempre que faço uma vídeo aula tento escrever um roteiro, mas dessa vez transcrevi a vídeo aula e vou colocar em modo texto também, para que preferir ler do que ver o vídeo.

TRANSCRIÇÃO

Entender o que é evento no actionscript 3 é muito importante, pois a maioria das classes que usamos responde utilizando os eventos.
Por exemplo, o click do mouse em um botão, o click é um evento que o botão sofre, o botão por sua vez avisa que foi clicado, o programa ouvindo esse grito reage de acordo com o que deve ser feito.
Existem diversos tipos de eventos, como finalização de um carregamento, mouse sobre um movieclip, redimensionamento da tela, etc…
Vou tentar explicar de uma forma simples, vamos imaginar um general e um soldado no campo de batalha, o soldado está na luta com um rádio enquanto o general está no comando no quartel, o soldado ficou incumbido de reportar para o general quando uma bomba explodir no campo de batalha.
Quando um bomba explode ele grita, explodiu uma bomba, o ato da bomba explodir é um evento, o soldado percebendo esse evento chama o general, agora se o general vai escutar esse chamado é outra coisa.
E no actionscript3 é igual, sempre que acontece um evento, ele é disparado, mas só é ouvido se esse evento for cadastrado para ser ouvido.
Voltando ao exemplo do soldado, ele está lá gritando quando as bombas explodem, ai o general vê que seu rádio está desligado, ele liga o rádio e diz, soldado agora estou te ouvindo.
Pronto agora sim, todos os eventos de explosão de bombas serão ouvidos pelo general, e quando o general escuta um grito do soldado ele ordena mais contra-atraques.
No actionscript3 quando é cadastrado um ouvinte de evento é preciso informar quem será ouvido, no nosso caso é o soldado, qual evento será ouvido, que é a explosão e qual função reagirá quando esse evento for ouvido, desempenhado pelo nosso general.
Vamos partir para o código, quando clicarmos no soldado ele vai dar o avisa da bomba que explodiu , primeiramente vamos criar a função que reagirá ao chamado.

import flash.events.Event;

function explodiuBomba(event:Event):void{
 mensagem.text = "explodiu uma bomba ";
}

Agora cadastramos o soldado para ser ouvido pelo general.

soldado1.addEventListener(MouseEvent.CLICK , bombaExplodiu);

Pronto , tem gente ouvindo, tem gente gritando e tem gente reagindo ao evento.
Tem eventos para tudo, abaixo tem alguns links para maior aprofundamento no assunto.
Vamos incrementar mais um pouco isso, imagina que temos 2 soldados no campo com essa mesma função de ouvir as explosões, podemos utilizar informações passadas pelo evento para saber qual foi o soldado que avisou, vamos também cadastrar o soldado2.

import flash.events.Event;
function explodiuBomba(event:Event):void{
 mensagem.text = "explodiu uma bomba - " + event.target.name;
}

soldado1.addEventListener(MouseEvent.CLICK , explodiuBomba);
soldado2.addEventListener(MouseEvent.CLICK , explodiuBomba);

Sempre que um evento acontece é passado um objeto com informações sobre o evento, como o nome de quem sofreu o evento, o tipo de evento e diversas outras informações.
Nesse caso nós pegamos o evento e extraímos o seu alvo, quem foi que sofreu o evento usando o target, e pegamos o seu nome com o name.
Em uma próxima vídeo aula vou falar como disparar um evento customizado, passando um objeto com as informações que quiser.
Mas beleza, você deve estar pensando e seu eu não quiser mais ouvir esse soldado gritando na minha orelha?
É fácil, basta parar de ouvi-lo.
Da mesma forma que cadastramos para ouvir nós podemos descadastrar.
Vamos fazer assim, clicando no general manda o soldado 2 ficar quieto.

function calarSoldado(event:Event):void{
 mensagem.text = "cala a boca soldado 2";
 soldado2.removeEventListener(MouseEvent.CLICK , explodiuBomba);
}
general.addEventListener(MouseEvent.CLICK , calarSoldado);

Pronto, agora não escutamos mais esse mala gritando e deixamos ele morrer no campo de batalha.
Bom era isso que eu queria falar, não deixe de dar uma olhada nos links que estão ai embaixo.
Até a próxima.

Download do .fla.

DOWNLOAD

Links úteis

Documentação da adobe em português sobre eventos – LINK

Share

Pages:12