Abril 19, 2013, 05:07:09 PM Ultima modificación: Abril 23, 2013, 10:48:04 AM por hhAnt
Hola a todos,

Necesito vuestra ayuda en lo siguiente: Tengo el sprite de una torreta, como por ej. el siguiente,


El caso es que quiero que el sprite se gire sobre si mismo (la base gris y el cañon azul, todo a la vez, como una pieza) a cada golpe de tecla unos 45º y que lo haga de modo suave, es decir, que no lo haga a "saltos".

A priori parece un problema sencillo, pero por más que he buscado mucho por internet y visto tutoriales no he visto ningún fragmento de  GML que haga lo que busco, así que recurro a vosotros de nuevo a ver si podéis echarme un cable.

edit: lo que hago es:
        -en eventos "press <left> y press<right" escribo el codigo direction +=45 y direction -=45
        -en el evento step el codigo image_angle = direction
        Esto hace que la torreta gire 45º a la izq. o derecha, pero lo hace de un "salto", lo que quiero es que se mueva suavemente de una posición a otra, ¿Alguien sabe como puedo hacerlo?


Espero que algún alma caritativa se apiade de mí  :-[

No es muy facil. Lo que haría es poner un cuenta regresiva de giro cuando necesito girar, algo asi como:
cant_giro = 45 //Positivo para girar a derecha y negativo hacia izquierda

Tambien vas a tener que agregar en create la declaracion de la variable, para prevenir errores:
cant_giro = 0

Y en el step giramos:
if cant_giro > 0{ //Si debemos girar a la derecha
     image_angle +=5 //Girar 5 grados
     cant_giro -= 5 //Restar 5 grados a cant_giro
}
if cant_giro < 0{ //Si debemos girar a la derecha
     image_angle -=5 //Girar 5 grados
     cant_giro += 5 //Sumar 5 grados a cant_giro
}


Es algo simple, se puede hacer mejor pero eso es lo que se me ocurre. Tené en cuenta que los grados que quieras girar (en este caso 45) tiene que ser múltiplo de cuanto girs por step (en este caso 5)
No lo probe pero creo que sí andaría, cualquier cosa avisa
El Manual

- Ley de la gravitación selectiva: toda herramienta se caerá donde produzca el mayor daño.
- Si todo parece estar bien, es obvio que uno no encontró el problema
- Todo aquello que se corte a medida resultara ser demasiado corto.
- Todo archivo borrado era necesario, todo archivo conservado es inutil
- Cuando a usted se le ocurra la solución ideal, alguien habrá resuelto ya el problema.

                                                               Murphy


#2 Abril 19, 2013, 07:51:52 PM Ultima modificación: Abril 19, 2013, 07:57:57 PM por Klind
hhAnt puedes hacerlo así también (ya lo hice aquí y me funcionó perfectamente):

Abre tu objeto Torre y pones:

En el evento Create
[GML]nuevaDir = 0
contador = 0
rotando = false[/GML]

En el evento Step
[GML]if rotando = true
{
    for (i = 0 ; i <45 ; i += 1)
    {
        image_angle += nuevaDir
        break;
    }
    contador -= 1
    if contador = 0 {rotando = false}
}[/GML]

En el evento press <left>
[GML]if rotando = false
{
    nuevaDir = +1
    contador = 45
    rotando = true
} [/GML]

En el evento press <right>
[GML]if rotando = false
{
    nuevaDir = -1
    contador = 45
    rotando = true
} [/GML]

Listo  ;D

¡Saludos!

EDIT:

Acabo de leer la respuesta de Mgbu y está más práctica, lo único que debes agregarle es el rotando = true/false.
Solo intento crear ideas, en forma de obras de arte interactivas.


Mil gracias,

Mgbu, primero decirte que lo que has comentado de "no es muy fácil" me ha animado porque creía que lo que yo quería era algo obvio y no lo veía, por lo que has hecho que no me sienta tan burro. Tú código funciona perfectamente con la salvedad de que si una vez empezada la animación de la rotación le doy a una de las teclas antes de que esta termine (es decir, que la torreta pase de estar en posición de 0º a 45º), la posición final no es de 45º sino un angulo distinto, ¿Sabes por que puede ser esto? y por otro lado tampoco termino de comprender porque el angulo que quiero "avanzar" tiene que ser multiplo de lo que giro en cada step.

Klind, ¿que decir?, tu código funciona de maravilla, es justo lo que buscaba.

De nuevo, muchas gracias a los dos y a ver cuando llega el momento de que mi cerebro me permita hacer estas cosas por mi mismo  XD

Cita de: hhAnt en Abril 20, 2013, 11:33:26 AM
Tú código funciona perfectamente con la salvedad de que si una vez empezada la animación de la rotación le doy a una de las teclas antes de que esta termine (es decir, que la torreta pase de estar en posición de 0º a 45º), la posición final no es de 45º sino un angulo distinto, ¿Sabes por que puede ser esto? y por otro lado tampoco termino de comprender porque el angulo que quiero "avanzar" tiene que ser multiplo de lo que giro en cada step
Ah si, por ejemplo imaginate que la torreta se esta moviendo de 0 a 45, pero cuando anda en 20 yo presiono y hago mover la torreta 45 grados más, o sea 20 + 45 = 65 grados. Eso se puede solucionar con una condición que permita girar la torreta sólo cuando haya terminado, así:
if cant_giro = 0 cant_giro = 45 //Solo girar si ha dejado de girar. Positivo para girar a derecha y negativo hacia izquierda

Me equivoque en lo de multiplo, en realidad eso se llama divisor :-[
El angulo que quieres avanzar tiene que ser divisor de lo que giras en cada step porque uno necesita que cant_giro llegue a 0. El problema es que puede ocurrir que nunca llegue a 0, o que tarde más de de lo que es necesario. Pongo este ejemplo: uno quiere girar la torreta 12 grados, y 5 por step.
CitarEn el primer step cant_giro va a ser 12
En el segundo cant_giro va a ser 12 - 5 = 7
En el tercer step cant_giro va a ser 7 - 5 = 2
En el cuarto step cant_giro va a ser 2 - 5 = -3
En el quinto step cant_giro es negativo, entonces va a ser -3 + 5 = 2
En el sexto step cant_giro va a ser 2 - 5 = -3
... Y asi hasta el infinito y mas allá
Entonces es como que se "pasa de largo". Una forma es que si cant_giro es menor que la cantidad de grados por step simplemente girar lo que dice cant_step. en mi ejemplo sería:
CitarEn el primer step cant_giro va a ser 12
En el segundo cant_giro va a ser 12 - 5 = 7
En el tercer step cant_giro va a ser 7 - 5 = 2
En el cuarto step cant_giro va a ser menor que 5, entonces le restamos lo que dice cant_step 2 - 2 = 0
Fin
O la otra forma mas facil es hacer que sean divisores y listo, asi no se complica el código:
CitarEn el primer step cant_giro va a ser 12
En el segundo cant_giro va a ser 12 - 6 = 6
En el tercer step cant_giro va a ser 6 - 6 = 0
Fin
Mira que ahora resto de 6 en 6, pero como 6 no es divisor de 45 tu deberías usar 1, 3, 5, 9, 15 o 45
El Manual

- Ley de la gravitación selectiva: toda herramienta se caerá donde produzca el mayor daño.
- Si todo parece estar bien, es obvio que uno no encontró el problema
- Todo aquello que se corte a medida resultara ser demasiado corto.
- Todo archivo borrado era necesario, todo archivo conservado es inutil
- Cuando a usted se le ocurra la solución ideal, alguien habrá resuelto ya el problema.

                                                               Murphy



Hola de nuevo, Mgbu.

Efectivamente añadiendo "cant_giro = 0" se solventa el problemilla de las teclas, respecto a la explicación de como funciona la rotación ahora me queda mucho más claro, yo empecé a aprender a programar con C# (y ahí me quedé) luego me pasé a GM porque era más sencillo pero me está costando pillarle el punto a la forma en que se organiza, pero bueno, poco a poco.

Te agradezco enormemente las molestias que te has tomado.
Saludos.

Hola de nuevo, como os comenté los códigos que me distéis funcionan perfectamente, pero os quiero preguntar unas cosas para conocer mejor el funcionamiento interno de GM.

Es sobre el siguiente código que puso Klind

En el evento Step
[GML]if rotando = true
{
    for (i = 0 ; i <45 ; i += 1)
    {
        image_angle += nuevaDir
        break;
    }
    contador -= 1
    if contador = 0 {rotando = false}
}[/GML]

En el evento press <left>
[GML]if rotando = false
{
    nuevaDir = +1
    contador = 45
    rotando = true
} [/GML]

Yo este código lo interpreto del siguiente modo:

Si apreto la tecla izquierda, la vble. nuevaDir aumenta en 1 unidad, la vble. contador 45 unidades y rotando pasa de ser falsa a verdadera lo que hace que se active el código del evento step

Ahora, en el evento step, el bucle for se pone en funcionamiento y según entiendo cuando termina, es decir, cuando "i" llega a 44 e image_angle ha ido aumentando hasta un valor de 45 entonces salta al próximo código que sería restar la vble. contador, que pasaría de ser 45 a 44 porque se le resta 1.
Esto es lo que no entiendo, en el momento que termina el "for", image_angle ya ha rotado 45º, y después de esto se le resta 1 por primera vez a la vble. contador, se supone que rotando sigue siendo cierta, por lo que el bucle "for" se tendría que poner otra vez en funcionamiento y girar otros 45º, pero en la práctica no lo hace, ¿Alguién me podría arrojar algo de luz sobre este tema? porque por más vueltas que le doy no termino de entenderlo.

gracias.



Lo mismo pensaba yo, pero como funcionaba pensé que estaba medio dormido, pero sí, era verdad, ahora que me fijo te explico por que funciona:

La sentencia break termina el ciclo for, entonces el ciclo for solo se ejecuta una vez, entonces ese código en Step es lo mismo que esto:
[gml]if rotando = true
{
    image_angle += nuevaDir
    contador -= 1
    if contador = 0 {rotando = false}
}[/gml]

PD: Pensándolo bien no era el único dormido :P
El Manual

- Ley de la gravitación selectiva: toda herramienta se caerá donde produzca el mayor daño.
- Si todo parece estar bien, es obvio que uno no encontró el problema
- Todo aquello que se corte a medida resultara ser demasiado corto.
- Todo archivo borrado era necesario, todo archivo conservado es inutil
- Cuando a usted se le ocurra la solución ideal, alguien habrá resuelto ya el problema.

                                                               Murphy


Ups! Es cierto, joer, pues me daba cuenta, estoy empanao  :-[

Muchas gracias de nuevo, Mgbu

Jajajajaja cierto.

Puse dos variables que hacían lo mismo, se puede quitar el For o el Contador y seguiría funcionando igual.

Pero sí, es eso hhAnt, el break lo que hace es parar el ciclo For y pasar a las siguientes líneas de código.

Cualquier otra cosa que necesites, preguntas y te ayudamos  ;D
Solo intento crear ideas, en forma de obras de arte interactivas.


Muy amable Klind, gracias por tu ofrecimiento.