/// <summary>
        /// Selecciona todos los colliders que estan dentro de la esfera que representa el movimiento.
        /// Carga la lista objetosCandidatos
        /// </summary>
        private void selectPotentialColliders(TgcElipsoid characterElipsoid, Vector3 movementVector, List<Collider> colliders)
        {
            //Dejar solo los obstáculos que están dentro del radio de movimiento del elipsoide (lo consideramos una esfera, con su mayor radio)
            Vector3 halfMovementVec = Vector3.Multiply(movementVector, 0.5f);
            movementSphere.setValues(
                characterElipsoid.Center + halfMovementVec,
                halfMovementVec.Length() + characterElipsoid.getMaxRadius()
                );
            

            //Elegir todos los colliders que pasan un test Sphere-Sphere
            objetosCandidatos.Clear();
            foreach (Collider collider in colliders)
            {
                if (collider.Enable && TgcCollisionUtils.testSphereSphere(movementSphere, collider.BoundingSphere))
                {
                    objetosCandidatos.Add(collider);
                }
            }
        }
Пример #2
0
        public override void init()
        {
            Microsoft.DirectX.Direct3D.Device d3dDevice = GuiController.Instance.D3dDevice;

            //Cargar escenario específico para este ejemplo. Este escenario tiene dos layers: objetos normales y objetos con colisión a nivel de triángulo.
            //La colisión a nivel de triángulos es costosa. Solo debe utilizarse para objetos puntuales (como el piso). Y es recomendable dividirlo en varios
            //meshes (y no hacer un único piso que ocupe todo el escenario)
            TgcSceneLoader loader = new TgcSceneLoader();
            escenario = loader.loadSceneFromFile(GuiController.Instance.ExamplesMediaDir + "\\MeshCreator\\Scenes\\Mountains\\Mountains-TgcScene.xml");

            //Cargar personaje con animaciones
            TgcSkeletalLoader skeletalLoader = new TgcSkeletalLoader();
            personaje = skeletalLoader.loadMeshAndAnimationsFromFile(
                GuiController.Instance.ExamplesMediaDir + "SkeletalAnimations\\BasicHuman\\" + "BasicHuman-TgcSkeletalMesh.xml",
                new string[] {
                    GuiController.Instance.ExamplesMediaDir + "SkeletalAnimations\\BasicHuman\\Animations\\" + "Walk-TgcSkeletalAnim.xml",
                    GuiController.Instance.ExamplesMediaDir + "SkeletalAnimations\\BasicHuman\\Animations\\" + "StandBy-TgcSkeletalAnim.xml",
                    GuiController.Instance.ExamplesMediaDir + "SkeletalAnimations\\BasicHuman\\Animations\\" + "Jump-TgcSkeletalAnim.xml"
                });

            //Configurar animacion inicial
            personaje.playAnimation("StandBy", true);
            //Escalarlo porque es muy grande
            personaje.Position = new Vector3(0,1000,-150);
            //Rotarlo 180° porque esta mirando para el otro lado
            personaje.rotateY(Geometry.DegreeToRadian(180f));

            //BoundingSphere que va a usar el personaje
            personaje.AutoUpdateBoundingBox = false;
            characterElipsoid = new TgcElipsoid(personaje.BoundingBox.calculateBoxCenter() + new Vector3(0, 0, 0), new Vector3(12, 28, 12));
            jumping = false;

            //Almacenar volumenes de colision del escenario
            objetosColisionables.Clear();
            foreach (TgcMesh mesh in escenario.Meshes)
            {
                //Los objetos del layer "TriangleCollision" son colisiones a nivel de triangulo
                if (mesh.Layer == "TriangleCollision")
                {
                    objetosColisionables.Add(TriangleMeshCollider.fromMesh(mesh));
                }
                //El resto de los objetos son colisiones de BoundingBox. Las colisiones a nivel de triangulo son muy costosas asi que deben utilizarse solo
                //donde es extremadamente necesario (por ejemplo en el piso). El resto se simplifica con un BoundingBox
                else
                {
                    objetosColisionables.Add(BoundingBoxCollider.fromBoundingBox(mesh.BoundingBox));
                }
            }

            //Crear manejador de colisiones
            collisionManager = new ElipsoidCollisionManager();
            collisionManager.GravityEnabled = true;

            //Crear linea para mostrar la direccion del movimiento del personaje
            directionArrow = new TgcArrow();
            directionArrow.BodyColor = Color.Red;
            directionArrow.HeadColor = Color.Green;
            directionArrow.Thickness = 0.4f;
            directionArrow.HeadSize = new Vector2(5, 10);

            //Linea para normal de colision
            collisionNormalArrow = new TgcArrow();
            collisionNormalArrow.BodyColor = Color.Blue;
            collisionNormalArrow.HeadColor = Color.Yellow;
            collisionNormalArrow.Thickness = 0.4f;
            collisionNormalArrow.HeadSize = new Vector2(2, 5);

            //Caja para marcar punto de colision
            collisionPoint = TgcBox.fromSize(new Vector3(4, 4, 4), Color.Red);

            //Configurar camara en Tercer Persona
            GuiController.Instance.ThirdPersonCamera.Enable = true;
            GuiController.Instance.ThirdPersonCamera.setCamera(personaje.Position, 20, -120);
            GuiController.Instance.ThirdPersonCamera.TargetDisplacement = new Vector3(0, 45, 0);

            //Crear SkyBox
            skyBox = new TgcSkyBox();
            skyBox.Center = new Vector3(0, 0, 0);
            skyBox.Size = new Vector3(10000, 10000, 10000);
            string texturesPath = GuiController.Instance.ExamplesMediaDir + "Texturas\\Quake\\SkyBox3\\";
            skyBox.setFaceTexture(TgcSkyBox.SkyFaces.Up, texturesPath + "Up.jpg");
            skyBox.setFaceTexture(TgcSkyBox.SkyFaces.Down, texturesPath + "Down.jpg");
            skyBox.setFaceTexture(TgcSkyBox.SkyFaces.Left, texturesPath + "Left.jpg");
            skyBox.setFaceTexture(TgcSkyBox.SkyFaces.Right, texturesPath + "Right.jpg");
            skyBox.setFaceTexture(TgcSkyBox.SkyFaces.Front, texturesPath + "Back.jpg");
            skyBox.setFaceTexture(TgcSkyBox.SkyFaces.Back, texturesPath + "Front.jpg");
            skyBox.updateValues();

            //Modifier para ver BoundingBox
            GuiController.Instance.Modifiers.addBoolean("Collisions", "Collisions", true);
            GuiController.Instance.Modifiers.addBoolean("showBoundingBox", "Bouding Box", true);

            //Modifiers para desplazamiento del personaje
            GuiController.Instance.Modifiers.addFloat("VelocidadCaminar", 0, 20, 2);
            GuiController.Instance.Modifiers.addFloat("VelocidadRotacion", 1f, 360f, 150f);
            GuiController.Instance.Modifiers.addBoolean("HabilitarGravedad", "Habilitar Gravedad", true);
            GuiController.Instance.Modifiers.addVertex3f("Gravedad", new Vector3(-50, -50, -50), new Vector3(50, 50, 50), new Vector3(0, -4, 0));
            GuiController.Instance.Modifiers.addFloat("SlideFactor", 0f, 2f, 1f);
            GuiController.Instance.Modifiers.addFloat("Pendiente", 0f, 1f, 0.72f);
            GuiController.Instance.Modifiers.addFloat("VelocidadSalto", 0f, 50f, 10f);
            GuiController.Instance.Modifiers.addFloat("TiempoSalto", 0f, 2f, 0.5f);

            GuiController.Instance.UserVars.addVar("Movement");
        }
        /// <summary>
        /// Mover Elipsoide con detección de colisiones, sliding y gravedad.
        /// Se actualiza la posición del centro del Elipsoide
        /// </summary>
        /// <param name="characterElipsoid">Elipsoide del cuerpo a mover</param>
        /// <param name="movementVector">Movimiento a realizar</param>
        /// <param name="colliders">Obstáculos contra los cuales se puede colisionar</param>
        /// <returns>Desplazamiento relativo final efecutado al Elipsoide</returns> 
        public Vector3 moveCharacter(TgcElipsoid characterElipsoid, Vector3 movementVector, List<Collider> colliders)
        {
            //Guardar posicion original del Elipsoide
            Vector3 originalElipsoidCenter = characterElipsoid.Center;

            //Pasar elipsoid space
            Vector3 eCenter = TgcVectorUtils.div(characterElipsoid.Center, characterElipsoid.Radius);
            Vector3 eMovementVector = TgcVectorUtils.div(movementVector, characterElipsoid.Radius);
            eSphere.setValues(eCenter, 1);
            Vector3 eOrigCenter = eSphere.Center;


            //Ver si la distancia a recorrer es para tener en cuenta
            float distanceToTravelSq = movementVector.LengthSq();
            if (distanceToTravelSq >= EPSILON)
            {
                //Mover la distancia pedida
                selectPotentialColliders(characterElipsoid, movementVector, colliders);
                this.result = doCollideWithWorld(eSphere, eMovementVector, characterElipsoid.Radius, objetosCandidatos, 0, movementSphere, 1);
            }

            //Aplicar gravedad
            if (gravityEnabled)
            {
                //Mover con gravedad
                Vector3 eGravity = TgcVectorUtils.div(gravityForce, characterElipsoid.Radius);
                selectPotentialColliders(characterElipsoid, eGravity, colliders);
                this.result = doCollideWithWorld(eSphere, eGravity, characterElipsoid.Radius, objetosCandidatos, 0, movementSphere, onGroundMinDotValue);
            }

            //Mover Elipsoid pasando valores de colision a R3
            Vector3 movement = TgcVectorUtils.mul(eSphere.Center - eOrigCenter, characterElipsoid.Radius);
            characterElipsoid.moveCenter(movement);

            //Ajustar resultados
            result.realMovmentVector = TgcVectorUtils.mul(result.realMovmentVector, characterElipsoid.Radius);
            result.collisionPoint = TgcVectorUtils.mul(result.collisionPoint, characterElipsoid.Radius);


            return movement;
        }
Пример #4
0
        public Game()
        {
            Fuentes.cargarFuentes();

            //sprites
            if (!inicializo)
            {
                mapita = new TgcSprite();
                mapita.Texture = TgcTexture.createTexture(GuiController.Instance.AlumnoEjemplosMediaDir + "\\sprites\\preview.png");
                motoSprite = new TgcSprite();
                motoSprite.Texture = TgcTexture.createTexture(GuiController.Instance.AlumnoEjemplosMediaDir + "\\sprites\\dirtbike.png");
                timer = new TgcSprite();
                timer.Texture = TgcTexture.createTexture(GuiController.Instance.AlumnoEjemplosMediaDir + "\\sprites\\gate.png");

                //Ubicarlo centrado en la pantalla
                screenSize = GuiController.Instance.Panel3d.Size;
                textureSize = mapita.Texture.Size;
                motoTextureSize = motoSprite.Texture.Size;
                mapita.Scaling = (new Vector2(0.7f, 0.7f));
                motoSprite.Scaling = (new Vector2(0.5f, 0.5f));

                mapita.Position = new Vector2(FastMath.Max(screenSize.Width / 2 - textureSize.Width * 0.7f / 2, 0), 16);

                motoSprite.Position = new Vector2(FastMath.Max(screenSize.Width / 2 - motoTextureSize.Width * 0.5f / 2 - textureSize.Width * 0.7f / 2, 0), 8);

                timer.Position = new Vector2(screenSize.Width - 250, screenSize.Height - 125);

                timer.Scaling = new Vector2(0.9f, 0.8f);
                posMotoInicial = motoSprite.Position;
                inicializo = true;
            }
            d3dDevice = GuiController.Instance.D3dDevice;

            d3dDevice.Transform.Projection =
                Matrix.PerspectiveFovLH(Geometry.DegreeToRadian(45.0f),
                TgcD3dDevice.aspectRatio, 1f, 5000000f);

            string texturesPath = GuiController.Instance.AlumnoEjemplosMediaDir + "skybox\\";
            TgcSceneLoader loader = new TgcSceneLoader();
            collisionManager = new ElipsoidCollisionManager();
            collisionManager.GravityEnabled = false;
            tiempoAcelerando = 0f;
            tiempoDescelerando = 0f;
            velIni = 0f;
            tocandoPiso = false;
            saltando = true;
            ultimoMov = new Vector3(0, 0, 0);

            //skybox
            inicializarSkybox(texturesPath);

            //checkpoints
            int posCP = -150;
            foreach (TgcBoundingBox bb in checkpoints)
            {
                bb.setExtremes(new Vector3(-200, -100, posCP), new Vector3(200, 1000, posCP - 10));
                posCP -= 1300;
            }

            //carga la ciudad
            scene = loader.loadSceneFromFile(GuiController.Instance.AlumnoEjemplosMediaDir + "pistaDesierto\\pistaDesierto2-TgcScene.xml");

            //cargo la moto
            motorcycle = loader.loadSceneFromFile(GuiController.Instance.AlumnoEjemplosMediaDir + "moto\\Moto2-TgcScene.xml").Meshes[0];
            motorcycle.move(-40, 100, -150);

            //cargo la piramide
            piramid = loader.loadSceneFromFile(GuiController.Instance.AlumnoEjemplosMediaDir + "piramide\\piramide-TgcScene.xml").Meshes[0];
            piramid.Scale = new Vector3(5, 5, 5);
            piramid.move(-265, -45, -13750);

            //cargo texto ganaste

            textGanaste = new TgcText2d();
            textGanaste2 = new TgcText2d();

            //Cargar Textos
            textGanaste.Text = "FELICIDADES, HAS GANADO";
            textGanaste2.Text = "APRETE Q PARA VOLVER AL MENU";
            textGanaste.Position = new Point(0, 50);
            textGanaste2.Position = new Point(0, 100);
            textGanaste.changeFont(new System.Drawing.Font("TimesNewRoman", 23, FontStyle.Bold | FontStyle.Bold));
            textGanaste2.changeFont(new System.Drawing.Font("TimesNewRoman", 23, FontStyle.Bold | FontStyle.Bold));

            textGanaste.Color = Color.White;
            textGanaste2.Color = Color.White;

            // Creo texto contador de tiempo
            textoContadorTiempo = new TgcText2d();
            textoContadorTiempo.Color = Color.Black;
            textoContadorTiempo.Align = TgcText2d.TextAlign.RIGHT;
            textoContadorTiempo.Position = new Point(630, 400); //(680, 400)
            textoContadorTiempo.Size = new Size(300, 100);
            textoContadorTiempo.changeFont(new System.Drawing.Font(Fuentes.fuente.Families[0], 25, FontStyle.Regular));

            // Creo texto mejor tiempo
            textoMejorTiempo = new TgcText2d();
            textoMejorTiempo.Color = Color.Black;
            textoMejorTiempo.Align = TgcText2d.TextAlign.RIGHT;
            textoMejorTiempo.Position = new Point(630, 430);  //(680, 430)
            textoMejorTiempo.Size = new Size(300, 100);
            textoMejorTiempo.changeFont(new System.Drawing.Font(Fuentes.fuente.Families[0], 25, FontStyle.Regular));

            //Texto para mostrar fps
            textFPS = new TgcText2d();
            textFPS.Position = new Point((screenSize.Width / (-2)), 0);
            textFPS.Text = "FPS: ";
            textFPS.Color = Color.Yellow;

            //camara
            GuiController.Instance.ThirdPersonCamera.Enable = true;
            GuiController.Instance.ThirdPersonCamera.setCamera(motorcycle.Position + new Vector3(0,0,-100), 10, 200);
            GuiController.Instance.ThirdPersonCamera.rotateY(-0.7f);

            //creo la bounding elipsoid

            motorcycle.Scale = new Vector3(0.5f, 0.5f, 0.5f);

            // motorcycle.AutoUpdateBoundingBox = false;
            characterElipsoid = new TgcElipsoid(motorcycle.BoundingBox.calculateBoxCenter() + new Vector3(0, 0, 0), new Vector3(23, 23, 23) * 0.5f);

            //cargo los colliders
            objetosColisionables.Clear();
            foreach (TgcMesh mesh in scene.Meshes)
            {
                //Los objetos del layer "TriangleCollision" son colisiones a nivel de triangulo
                if (mesh.Layer == "TriangleCollision")
                {
                    objetosColisionables.Add(TriangleMeshCollider.fromMesh(mesh));

                }
                //El resto de los objetos son colisiones de BoundingBox. Las colisiones a nivel de triangulo son muy costosas asi que deben utilizarse solo
                //donde es extremadamente necesario (por ejemplo en el piso). El resto se simplifica con un BoundingBox
                else
                {
                    objetosColisionables.Add(BoundingBoxCollider.fromBoundingBox(mesh.BoundingBox));
                }
            }

            //agrego Piramide Como objeto Colisionable
            objetosColisionables.Add(BoundingBoxCollider.fromBoundingBox(piramid.BoundingBox));

            //Cargo lineaInicio

            lineaInicio = new TgcBox();
            lineaInicio.Position = new Vector3(-7, 30, -50);
            lineaInicio.Size = new Vector3(200, 2000, 1);
            lineaInicio.updateValues();

            //Cargo lineaFin
            lineaFin = new TgcBox();
            lineaFin.Size = new Vector3(100, 1000, 1);
            lineaFin.Position = new Vector3(0, 15, -13250);
            lineaFin.Color = Color.White;
            lineaFin.updateValues();

            //La agrego como objeto colisionable
            objetosColisionables.Add(BoundingBoxCollider.fromBoundingBox(lineaInicio.BoundingBox));

            showBB = false;

            //iluminacion
            ojalaQueAnde = new ShadowMap(scene, motorcycle);

            //DEBUG
            //Crear linea para mostrar la direccion del movimiento del personaje
            directionArrow = new TgcArrow();
            directionArrow.BodyColor = Color.Red;
            directionArrow.HeadColor = Color.Green;
            directionArrow.Thickness = 0.4f;
            directionArrow.HeadSize = new Vector2(5, 10);

            //Linea para normal de colision
            collisionNormalArrow = new TgcArrow();
            collisionNormalArrow.BodyColor = Color.Blue;
            collisionNormalArrow.HeadColor = Color.Yellow;
            collisionNormalArrow.Thickness = 0.4f;
            collisionNormalArrow.HeadSize = new Vector2(2, 5);

            //Caja para marcar punto de colision
            collisionPoint = TgcBox.fromSize(new Vector3(4, 4, 4), Color.Red);
            //TERMINA DEBUG
        }