Jump to content

Bousing

Fosiles
  • Content Count

    31
  • Joined

  • Last visited

Everything posted by Bousing

  1. Saludos amigos Escribo porque tengo una duda. Necesito hacer un juego con una cámara isometrica como la de warcraft 3, age of empire, etc. Como el juego es para móviles necesito hacerla con touch. Mi estrategia es la siguiente, crear un GameObject y hacer que la cámara principal sea hijo de este objeto y programar una clase para que el GameOject que contiene a la camara se mueva con el dedo. Yo hice este código: //UN SOLO TOQUE PARA MOVER LA CÁMARA if (Input.touchCount == 1) { if (Input.GetTouch ().phase == TouchPhase.Began) { worldStartPoint = getToque (Input.GetTouch ().position); } //CUANDO EL TOUCH ESTÁ EN MOVIMIENTO if(Input.GetTouch().phase == TouchPhase.Moved){ //SE OBTIENEN LAS COORDENADAS DE LA NUEVA POSICIÓN Vector2 endPosition = getToque (Input.GetTouch ().position) - worldStartPoint; this.transform.Translate (endPosition.x,,endPosition.y); } } } //MÉTODO PARA CAPTURAR LA POSICIÓN EN LA PANTALLA DE UN TOQUE TÁCTIL private Vector2 getToque(Vector2 toque){ RaycastHit hit; Physics.Raycast (Camera.main.ScreenPointToRay (toque), out hit); return hit.point; } pero cuando hago la prueba con Unity Remote, solamente puedo mover el objeto en el eje X y no en el eje Z. A mi también me gustaría se pudiera mover fluido y corrido como en clash of clans que no es necesario despegar el dedo de la pantalla para seguir moviendolo. Alguén podría ayudarme ?. Muchísimas gracias por leer.
  2. Saludos amigos! En esta ocasión escribo porque necesito asesoría sobre backend para un videojuego. Quiero hacer un juego al estilo multiplayer como clash of clans. Pero tengo muchas dudas porque no estoy seguro que es lo que me conviene, ni que bases de datos usar. Por el momento planeo usar NoSQL orientado a documentos como el bd a tiempo real de firebase o mongoDB porque estos motores tienden a ser más veloces, facilidad para queries, y me parece más cómodo que SQL. Quiero aprovechar tambien para preguntar si esto me va bien https://unity3d.com/es/unity/features/multiplayer ? no estoy claro pero creo que es un backend as service que ofrece Unity si no me equivoco, eso me sustituiría la posibilidad de programar un backend ? De lo contrario pretendo hacer un API con NodeJS y express. Otra opción que evaluo es usar el sistema de Networking que ofrece unity y hacer que cada cliente tenga su propio host y lo que haga es asociar con otros clientes como el esquema que muestra la documentación https://docs.unity3d.com/es/current/Manual/UNetConcepts.html Cualquier sugerencia la agradecería muchísimo porque no tengo ni idea de como hacer un juego online. Estas estrategias que les he mencionado las ideé en base a lo que he investigado, pero igual tengo muchas lagunas que me impiden diseñar un plan de acción sólido. Gracias por leer.
  3. Muchas gracias. Realmente ignoraba que la clase transform tenía esa propiedad. Obviamente lo primero que hice fue escribir "parent" en google pero como no sabía bien lo que era lo deje así. Tengo que estudiarme todo el API. Saludos y gracias
  4. Saludos compañeros En este ocasión, les escribo porque tengo una duda muy puntual. Ando haciendo un juego de plataformas en 2D y quiero hacer plataformas moviles que se muevan tanto izquierda, derecha, arriba o hacia abajo. Lo hice, y funciona bien. Lo que sucede es que cuando monto allí a mi personaje este no se mueve junto a la plataforma, sino que la plataforma se mueve independientemente y el personaje se cae. Intente lo siguiente void OnCollisionEnter2D(Collision2D objeto){ if(objeto.GameObject.tag == "NombreDeLaPlataforma"){ this.transform.position = objeto.transform.postion; } } Eso me da la posición de la plataforma cuando el objeto la toca pero solo sucede una vez y la plataforma se mueve sin el personaje y posteriormente este se cae :D ... como hago para que ese código que les acabo de dar sea continuo hasta que salte o mueva el personaje ? Pense en un while con un booleano de condición de salida, pero eso más bien va a destrozar el programa. Si saben como hacerlo de esa manera, o saben como solucionarlo de otra manera, estaría muy agradecido si comparten la respuesta. Un abrazo!!
  5. Toma este enlace http://aev.org.es/unity-controlador-tactil-para-dispositivos-moviles-nuevo-sistema-ui/ eso me enseño a hacer controles táctiles con los botones del canvas. Es super sencillo. Como bien te dice ese tutorial, los metodos de tu script que quieres que activen los botones deben ser públicos. y allí activas la animación del animator. Saludos
  6. Amigos, ya resolví el problema. Como bien dije, no pude usar Unity porque el WebGl que usa no es muy funcional para smartphones (de hecho no me funciono). Así que lo hice de otra manera con PhaserWorld (JavaScript)y HTML5. No es tan cómodo como Unity ya que eso se construye con puro código, se los comparto para que lo vean https://jlbousing.github.io/experimentoPhaser/ eso es un experimento. Voy a hacer un proyecto basado en eso. Saludos y gracias.
  7. Se ve buenísimo, pero no creo que me sirva porque el detalle de usar herramientas o framework que te lo hagan todo es que personalizar tu proyecto es difícil. Sobretodo si quieres hacerlo con una base de datos etc. Pero es cuestión de probarlo gracias. Parece que no puedo usar Unity :( porque los proyectos en HTML5 con creados con WebGL y no es compatible con Smartphones (por lo menos no el de Unity). Hice una pequeña prueba https://jlbousing.github.io/pruebaJuegoImg/ y no corre en smartphones. Entonces tengo que usar mi plan B: Un framework muy chevere de HTML5 Y JS que se llama phaserworld. Pero si conocen una manera de hacer juegos en HTML5 sin WebGL les agradecería cualquier información. Saludos
  8. Saludos a todos Primero que nada no se si este post debería estar en esta sección. Si no es así me disculpo. Escribo porque necesito hacer un proyecto para que sea en web. De tal manera que los usuarios puedan jugarlo en navegadores de manera responsive. Es decir que se pueda jugar tanto en PC como smarthphones y otros dispositivos. El juego es en 2D y consiste en mover la camara con el mouse sobre una imagen y al hacerle click a una parte de la imagen se abra un input en esa misma posición donde se dió click para que el usuario escriba algo que si es correcto se sume el score y abra como un modal para redireccionar a otra pagina o mostrar alguna información. Aunque estoy investigando muchos frameworks para hacer videojuegos en HTML5 Y Js, quiero usar Unity porque además que tengo experiencia con este motor gráfico es muy comodo para mi mover la camara con el mouse, incluso hice una pruebita y funciono bien. Lo que me preocupa es el tema de la concurrencia porque el proyecto será usado por muchas personas y necesito conectarlo bien con la base de datos. Además de eso me preocupa el caso de uso que les comente en el tercer párrafo de este post, porque no he visto que en Unity se haga eso y si la respuesta es afirmativa, ¿Cómo lo podría hacer ? Saludos
  9. Lo probé y esta muy bueno. Lo que si me pareció raro fue la iluminación, pero tampoco es un problema, supongo que ustedes quisieron que se vea así. Saludos
  10. Hice lo siguiente: Aumente la gravedad de manera exagerada y resuelve el problema. Pero no me gusta esa solución. Lo dejaré así mientras descubro como resolver el problema.
  11. Saludos a todos En esta oportunidad, comento otro problema que tengo con mi proyecto. Tengo problemas con las animaciones (las descargue de Asset Store), y lo que sucede es que esas animaciones le afectan a la física del jugador. Es decir el personaje cae muy lentamente independientemente de la cantidad de la masa en el rigidbody. Estoy seguro que es eso, porque probé con un cubo, o con el modelo del personaje sin animaciones y caen al suelo como debe ser. Entonces yo creo que es la animación que afecta al personaje. Ademas que cuando activo la animación de correr, el personaje del jugador corre por el aire (lo muevo con el transform en el script) pero nunca cae, sigue corriendo. Alguien tiene idea de lo que esta sucediendo ? Gracias!!
  12. Gracias por la respuesta. Pero una pregunta, como logro cambiarle el pivote ? Intente subir el collider como sugirieron pero el pivote sigue estando en los pies. Y otra cosa, noto también que el Collider baja posiciones en el eje Y cuando le doy Run
  13. Gracias pioj, pero ya lo intenté... a lo mejor se debe a un defecto de esos muñecos hechos en MakeHuman, aunque sospecho más que es algo de Unity 5 porque he usado personajes de MH en Unity 4 y no he tenido ese problema. Ni idea de como solucionarlo.
  14. Saludos amigos, espero que estén bien. Escribo porque tengo una problema que me tiene estresado. He creado un personaje con MakeHuman, pero el problema es que cuando le agrego un character collider o capsule collider al personaje tengo problemas. Utilizo Unity 5, en el 4 no tenía tantos problemas en 3D, por eso detesto el 5, pero quiero aprenderlo a usar. Mi problema es que el personaje flota, o cae muy lentamente, aún cuando le aumento la masa en el RigidBody. Y otro problema es que el collider, tanto capsule como chracter controller se bajan unas unidades en el eje Y y hace que llegue al suelo primero el collider que el personaje haciendo que este flote en el aire, tal como muestra la foto que adjunté. Una solución que se me ocurrió fue ponerle box collider a los zapatos del personaje pero fue terrible porque aunque funcionó el personaje tiembla siempre. En resumen, necesito ayuda
  15. Muchísimas gracias, entendí lo que hay que hacer. Me iré por la primera opción porque pienso que así es como debe ser. Pero para eso puedo usar esa misma textura que descargue ? Si es así supongo que tengo que hacer mapeado y esas cosas no ?
  16. Saludos a todos Escribo porque necesito hacer un personaje con una textura como la de Sackboy de Little Big Planet, en mi caso no es un muñeco de trapo, sino un peluche pero no tengo idea de hacer que quede la piel como peluche. Pues veran, busque una textura de peluche en internet y la agregue al material pero no se como lograrlo. Después de muchos intentos me quedo como en la imagen que adjunté. Me imagino que no es difícil pero es mi primer proyecto en 3D desde 0 y tengo ese pequeño problema. Si me pueden ayudar estará totalmente agradecido. Un saludo!!!
  17. Lo probé y está buenísimo. Yo siendo tú mejoraría lo siguiente: Cuando estas comprando armas los zombies te atacan. Aunque así demasiado real porque es lo que pasaría en la vida real, yo pondria a los zombies en pausa por comodidad del jugador. Pero esta excelente.
  18. Saludos a todos Escribo porque estoy desarrollando un videojuego y tengo varios problemas. El juego en realidad es para android, pero como tenía problemas con el GUITexture ya que no se por que no lo reconoce cuando lo instalo tuve que buscar otra alternativa y fue con el boton del canvas, que me pareció muy sencillo y por ahora es multiplataforma, funciona en android y PC (razón por la cual posteo mis problemas en la sección de pc y web). Como bien dije, ya tengo mis controles de movimientos, por ahora solo he hecho dos, para la izquierda y derecha. Pero mi problema es que el personaje se mueve con su respectiva animación pero llega un punto que se detiene y se devuelve como si estuviese haciendo el paso de la luna de Michael Jackson, cosa que no debería pasar. Comparto el código para ver si tuve algún error (que no creo), o a lo mejor el error es de la animación, el personaje lo hice con sprites separados, es decir las piernas,brazos,etc. Todo esta separado y lo anime con el animation y la lógica los estados con el animator. public float speed; private bool izquierda; private bool derecha; public GameObject player; private Animator animator; private float posicion = -167; // Use this for initialization void Start () { animator = player.GetComponent<Animator> (); //SE INICIALIZA EL Animator DEL PERSONAJE } // Update is called once per frame void Update () { if (izquierda) { player.transform.Rotate(0,posicion,0); animator.SetBool("Right",false); //SE DESACTIVAN LAS ANIMACIONES DE CORRER HACIA LA DERECHA animator.SetBool("Left",true); //SE ACTIVAN LAS ANIMACIONES DE CORRER HACIA LA IZQUIERDA animator.SetFloat("Speed",speed); //float atras = speed * -1; player.transform.Translate(Vector3.left * Time.deltaTime * speed); //EL JUGADOR SE MUEVE HACIA LA IZQUIERDA } if (derecha) { player.transform.Rotate(0,0,0); //EL PERSONAJE ROTA HACIA LA DERECHA animator.SetBool("Left",false); //SE DESACTIVAN LAS ANIMACIONES DE CORRER HACIA LA IZQUIERDA animator.SetBool("Right",true); //SE ACTIVAN LAS ANIMACIONES DE CORRER HACIA LA DERECHA animator.SetFloat("Speed",speed); //player.transform.Translate(speed * Time.deltaTime * Vector3.right,0,0); //EL JUGADOR SE MUEVE HACIA LA DERECHA this.transform.Translate(Vector3.right * Time.deltaTime * speed); } } //FUNCIONES PUBLICAS public void MoverDerecha(){ derecha = true; } public void MoverIzquierda(){ izquierda = true; } public void Stop(){ derecha = false; izquierda = false; animator.SetFloat("Speed", 0); } Mi otro problema es con la cámara. Tengo un script para que la cámara principal siga al personaje pero cuando lo ejecuto el personaje se ve incompleto, como en la imagen que adjunto. El código que use fue este public Transform Personaje; void Update () { //transform.position = new Vector3 (Personaje.position.x, Personaje.position.y, Personaje.position.z); transform.position = new Vector2 (Personaje.position.x, Personaje.position.y); } Como la primera linea de la función hacía lo mismo, intente con la segunda (despreciando el eje z) pero también hace lo mismo, el personaje se ve incompleto. Si alguien sabe que esta pasando con al menos uno de mis dos problemas, se lo agradecería saludos
  19. Saludos a todos. Escribo porque necesito ayuda con los controles de movimiento de un juego en 2D que ando haciendo. Acoto primero que nada que he visto muchísimos scrips en este foro que ayudan pero simplemente no entiendo. Se que utilizan como controles (derecha,izquierda,salto) un Game Object y le añaden un componente que se llama GUITexture. Pero no entiendo el funcionamiento, vi videos en youtube, de verdad lo intente y no me funcionó. Yo lo que hice fue crear un Game object y quiero que ejecute este script cuando el usuario lo toque con el dedo: public GameObject player; public float speed = 0; private float posicion = 0; private Animator animator; //private bool Boton_Derecho; void Start () { animator = player.GetComponent<Animator> ();//SE INICIALIZA EL Animator DEL PERSONAJE } // Update is called once per frame void Update () { animator.SetBool ("Right", true); //SE ACTIVAN LAS ANIMACIONES DE CAMINAR HACIA LA DERECHA animator.SetBool ("Left", false);//SE DESACTIVAN LAS ANIMACIONES DE CAMINAR HACIA LA IZQUIERDA animator.SetFloat ("Speed", speed); player.transform.Rotate (0, 0, 0); //EL PERSONAJE ROTA HACIA LA DERECHA player.transform.Translate (speed * Time.deltaTime, 0, 0); //EL PERSONAJE SE MUEVE HACIA LA DERECHA } } al principio, lo probé con el API de touch así void Update () { int FingerCounter = 0; //CONTADOR QUE CUENTA LAS TOCADAS DEL BOTON foreach(Touch touch in Input.touches){ if (touch.phase != TouchPhase.Ended && touch.phase != TouchPhase.Canceled && Boton.guiTexture.HitTest(touch.position)) { FingerCounter++; Boton_Izquierdo = true; } } if (FingerCounter > 0 && Boton_Izquierdo) { Vector3 temp = player.transform.position; //SE GUARDA LA POSICION DEL PERSONAJE EN EL EJE XY animator.SetBool("Left",true); //EL PERSONAJE VOLTEA HACIA LA IZQUIERDA animator.SetBool("Right",false); //SE DESACTIVAN LAS ANIMACIONES DEL PERSONAJE PARA CUANDO MIRA HACIA LA DERECHA animator.SetFloat("Speed",speed); //EL PERSONAJE CAMBIA DE ESTADO A CORRER player.transform.Rotate(0,posicion,0); //EL PERSONAJE VOLTEA HACIA LA IZQUIERDA float atras = speed * -1; player.transform.Translate(atras * Time.deltaTime,0,0); } if (FingerCounter == 0) { animator.SetFloat("Speed",0); //SE CAMBIA A IDLE } Boton_Izquierdo = false; //SE VUELVE A PONER FALSO PARA OTROS MOVIMIENTOS } pero tampoco funciona. Si me pueden ayudar... agradecido porque tengo muchos días atascado. Saludos
  20. Adngel, muchísimas gracias hermano. utilice el SimpleMove y funciono muy bien... Ya tengo solucionado la movilidad del jugador, también gracias por toda la explicación, ya que no conozco bien el API de Unity y no sabía como hacerlo correctamente. Muchas gracias también a todos los que respondieron. Saludos
  21. Recomiendo Java, sobretodo si quieres hacer videojuegos para Android o multiplataforma, aunque si lo haras en Unity usaras C# o JavaScript que en sintaxis son prácticamente igual a Java, sobretodo C#. En verdad el lenguaje considero que no es tan importante, lo importante es que domines bien la programación orientada a objetos. Pues veras también puedes hacer juegos con Python ya que tiene una librería para juegos http://www.pygame.org. Pero usamos motores gráficos como Unity para no complicarnos la vida. Hacer un videojuego desde 0 sin motor grafico...wow me da flojera con tan solo pensarlo y eso que amo la programación (Creo que minecraft fue hecho en java desde 0). Saludos
  22. Ya solucione el problema, aunque no tiene sentido era que el CharacterController debía estar por debajo del personaje y no dentro de él como lo mostré antes, esto lo descubrí porque quize meterle el script controlador de tercera persona que Unity trae y por defecto eso lo configura así y ya no se hunde en el suelo. Atraviesa las montañas y los objetos pero es culpa del script que programe (deje el código al principio). No se como hacer para que el personaje si no detecta el suelo se caiga y bloquee la animación, ya que con mi Script puedo correr en el aíre, cosa que no debe suceder. Yo tengo un Script muy bueno y funciona al pelo, pero como dije antes todo el código del proyecto lo quiero hacer yo por mi cuenta, así que no lo quiero usar en mi juego. Intente estudiar el código de ese script pero esta programado de una manera muy diferente al mio y como no estoy familiarizado con el API de Unity no lo entiendo lo compartiré a continuación para que me ayuden a descubrir como ese programador hizo para hacer que el muñeco no atraviese los objetos y cuando este caminando en el aire se caiga y no siga caminando. Acoto algo antes, ya he probado con el booleano IsGrounded, lo pongo como condición dentro de todos mis IF pero no me funciona using UnityEngine; using System.Collections; // Require these components when using this script [RequireComponent(typeof (Animator))] [RequireComponent(typeof (CapsuleCollider))] [RequireComponent(typeof (Rigidbody))] public class BotControlScript : MonoBehaviour { public Transform enemy; [System.NonSerialized] public float lookWeight; // the amount to transition when using head look //[System.NonSerialized] //public Transform enemy; // a transform to Lerp the camera to during head look public float animSpeed = 1.5f; // a public setting for overall animator animation speed public float lookSmoother = 3f; // a smoothing setting for camera motion public bool useCurves; // a setting for teaching purposes to show use of curves private Animator anim; // a reference to the animator on the character private AnimatorStateInfo currentBaseState; // a reference to the current state of the animator, used for base layer private AnimatorStateInfo layer2CurrentState; // a reference to the current state of the animator, used for layer 2 private CapsuleCollider col; // a reference to the capsule collider of the character static int idleState = Animator.StringToHash("Base Layer.Idle"); static int locoState = Animator.StringToHash("Base Layer.Locomotion"); // these integers are references to our animator's states static int jumpState = Animator.StringToHash("Base Layer.Jump"); // and are used to check state for various actions to occur static int jumpDownState = Animator.StringToHash("Base Layer.JumpDown"); // within our FixedUpdate() function below static int fallState = Animator.StringToHash("Base Layer.Fall"); static int rollState = Animator.StringToHash("Base Layer.Roll"); static int waveState = Animator.StringToHash("Layer2.Wave"); void Start () { // initialising reference variables anim = GetComponent<Animator>(); col = GetComponent<CapsuleCollider>(); // enemy = GameObject.Find("Enemy").transform; if(anim.layerCount ==2) anim.SetLayerWeight(1, 1); } void FixedUpdate () { float h = Input.GetAxis("Horizontal"); // setup h variable as our horizontal input axis float v = Input.GetAxis("Vertical"); // setup v variables as our vertical input axis anim.SetFloat("Speed", v); // set our animator's float parameter 'Speed' equal to the vertical input axis anim.SetFloat("Direction", h); // set our animator's float parameter 'Direction' equal to the horizontal input axis anim.speed = animSpeed; // set the speed of our animator to the public variable 'animSpeed' anim.SetLookAtWeight(lookWeight); // set the Look At Weight - amount to use look at IK vs using the head's animation currentBaseState = anim.GetCurrentAnimatorStateInfo(0); // set our currentState variable to the current state of the Base Layer (0) of animation if(anim.layerCount ==2) layer2CurrentState = anim.GetCurrentAnimatorStateInfo(1); // set our layer2CurrentState variable to the current state of the second Layer (1) of animation // LOOK AT ENEMY // if we hold Alt.. if(Input.GetButton("Fire2")) { // ...set a position to look at with the head, and use Lerp to smooth the look weight from animation to IK (see line 54) anim.SetLookAtPosition(enemy.position); lookWeight = Mathf.Lerp(lookWeight,1f,Time.deltaTime*lookSmoother); } // else, return to using animation for the head by lerping back to 0 for look at weight else { lookWeight = Mathf.Lerp(lookWeight,0f,Time.deltaTime*lookSmoother); } // STANDARD JUMPING // if we are currently in a state called Locomotion (see line 25), then allow Jump input (Space) to set the Jump bool parameter in the Animator to true if (currentBaseState.nameHash == locoState) { if(Input.GetButtonDown("Jump")) { anim.SetBool("Jump", true); } } // if we are in the jumping state... else if(currentBaseState.nameHash == jumpState) { // ..and not still in transition.. if(!anim.IsInTransition(0)) { if(useCurves) // ..set the collider height to a float curve in the clip called ColliderHeight col.height = anim.GetFloat("ColliderHeight"); // reset the Jump bool so we can jump again, and so that the state does not loop anim.SetBool("Jump", false); } // Raycast down from the center of the character.. Ray ray = new Ray(transform.position + Vector3.up, -Vector3.up); RaycastHit hitInfo = new RaycastHit(); if (Physics.Raycast(ray, out hitInfo)) { // ..if distance to the ground is more than 1.75, use Match Target if (hitInfo.distance > 1.75f) { // MatchTarget allows us to take over animation and smoothly transition our character towards a location - the hit point from the ray. // Here we're telling the Root of the character to only be influenced on the Y axis (MatchTargetWeightMask) and only occur between 0.35 and 0.5 // of the timeline of our animation clip anim.MatchTarget(hitInfo.point, Quaternion.identity, AvatarTarget.Root, new MatchTargetWeightMask(new Vector3(0, 1, 0), 0), 0.35f, 0.5f); } } } // JUMP DOWN AND ROLL // if we are jumping down, set our Collider's Y position to the float curve from the animation clip - // this is a slight lowering so that the collider hits the floor as the character extends his legs else if (currentBaseState.nameHash == jumpDownState) { col.center = new Vector3(0, anim.GetFloat("ColliderY"), 0); } // if we are falling, set our Grounded boolean to true when our character's root // position is less that 0.6, this allows us to transition from fall into roll and run // we then set the Collider's Height equal to the float curve from the animation clip else if (currentBaseState.nameHash == fallState) { col.height = anim.GetFloat("ColliderHeight"); } // if we are in the roll state and not in transition, set Collider Height to the float curve from the animation clip // this ensures we are in a short spherical capsule height during the roll, so we can smash through the lower // boxes, and then extends the collider as we come out of the roll // we also moderate the Y position of the collider using another of these curves on line 128 else if (currentBaseState.nameHash == rollState) { if(!anim.IsInTransition(0)) { if(useCurves) col.height = anim.GetFloat("ColliderHeight"); col.center = new Vector3(0, anim.GetFloat("ColliderY"), 0); } } // IDLE // check if we are at idle, if so, let us Wave! else if (currentBaseState.nameHash == idleState) { if(Input.GetButtonUp("Jump")) { anim.SetBool("Wave", true); } } // if we enter the waving state, reset the bool to let us wave again in future if(layer2CurrentState.nameHash == waveState) { anim.SetBool("Wave", false); } } } Espero que puedan ayudarme y muchísimas gracias a los que han respondido en este post, saludos.
UnitySpain © Todos los derechos reservados 2020
×
×
  • Create New...