Sistema de Disparos en Desarrollo 2

Previous topic - Next topic

Jonás Perusquía

Hola amigos, he vuelto con una preguntita sobre el tema anterior:

Quote from: jonaspm on 2012-Jun-11
Hola mis queridos amigos de GLBasic que con mucho gusto ayudan a los que necesitan una mano con este fabuloso SDK...

Les cuento, venía haciendo un sistema de disparos para mi juego DitraFall (www.ditrabox.es.tl/ditrafall.htm) y pues estoy algo atorado...


Resulta que lo que hasta ahora he logrado me deja disparar 1 vez, pero al querer disparar de nuevo se reinicia el misil lanzado... me explico..

1er click= disparo
2do click devuelve el primer disparo a la posición inicial

Code (glbasic) Select
// --------------------------------- //
// Project: SHOOT
// Start: Sunday, June 10, 2012
// IDE Version: 10.283

SETCURRENTDIR("Media") // go to media files
LOADSPRITE "rocket.png", 1
LOADSPRITE "shot.png", 2

GLOBAL mx,my,b1,b2,wx,wy,mx1,my1,b3,b4

GOSUB game

SUB game:
WHILE TRUE

MOUSESTATE mx,my,b1,b2

PRINT b1, 100, 100

DRAWSPRITE 2, wx, wy
DRAWSPRITE 1,mx,my


IF b1=1
wx=mx
wy=my+15
ENDIF
wx=wx-2
SHOWSCREEN
WEND
ENDSUB


Yo quisiera poder lanzar varios misiles seguidos, pero no logro hacerlo :S


¿Me podrían ayudar a encontrar la solución? Se los agradecería mucho!


Con la ayuda de Hark0,veketor y mentalthink pude "entender" cómo implementar la función deseada:

Quote from: mentalthink on 2012-Jun-11
Hola jonas aunque no he mirado mucho el hilo, te explico porque en estó soy un "experto" más que nada porque creo que la mitad de mi vida con GLbasic me he dedicado ha hacer el disparo para los marcianos...

Te explico tienes 2 posibilidades, una es un array Dinámico, creo que por tú tierra los arrays les llamáis arreglos, y luego es hacerlo con un array estático... Te dejo esté ejemplo que te he hecho con array dinámico, el de estático a ver si lo hago mañana, que casi se me acaba la "tinta"  :D

Code (glbasic) Select
// --------------------------------- //
// Project: shot
// Start: Monday, June 11, 2012
// IDE Version: 10.283


// SETCURRENTDIR("Media") // go to media files

//Esto es para que el array, un único array esté como divido en dos, comparte el Indice, pero tiene x e y, pero en realidad es el mismo array
TYPE SHOT
x;
y;
ENDTYPE

GLOBAL shot[] AS SHOT // Aqui lo que haces es que el Array pueda tener use de las x e y , o sea shot[indice].x o shot[indice.y]
DIM    shot[0]

GLOBAL n_Shot AS SHOT // Esta variables es la que utilizamos como contador más adelante, fijate que le sucede igual que al array
// o sea puedes escribir n_Shot.x o n_Shot.y, es necesario ponerlo asi, porque sino no puedes añadir indices
// al array, porque tambien pertenece al TYPE !!!OJO EN EL CÓDIGO MÁS ABAJO PORQUE TE PUEDE CONFUNDIR ALGO!!!

GLOBAL mx,my,b1,b2    //variables para el raton
GLOBAL sx,sy    //para la pantalla asi ya tenemos el valor para el límite derecho, ya que es un shoter horizontal
GETSCREENSIZE sx,sy    // Cojemos las medidas de la pantalla, por defecto pone la resolucion a 640,480---  me parece

WHILE TRUE
MOUSESTATE mx,my,b1,b2 //function para hacer que el raton funcione
get_Positions()     //funcion para cojer las coordenadas de raton y meterselas al array
draw_Shot() //Dibujo el disparo, en este caso solo es un asterisco

SHOWSCREEN
WEND

FUNCTION get_Positions:


IF b1 // Si pulso el boton izquierdo
INC n_Shot.x // incrementa aquella variable que teniamos más arriba en 1, o sea cada vez que le doy suma 1, pero fijate que
// tiene esa .x detras de n_Shot

DIMPUSH shot[], n_Shot //Esto lo que hace es que el array se agranda, como estámos pulsando el boton, pues esté array que tenia
//indice 0, pasa a tener indice 1, indice 2, indice 10, 30 .... ETC


shot[n_Shot.x-1].x = mx //Esto es importante, lo que te hace es que cada vez que pulso, mete en el array la coordenada del raton
// en este caso las X del mouse, pero fijate muy importante,
//n_Shot.x-1 , el indice tiene un menos 1, estó porque, porque si no pusieramos un -1 estariamos en el final
//justo del array y el programa simplemente "peta" o sea en cuanto pulses se te cerraria

shot[n_Shot.x-1].y = my // esto es lo mismo, pero para las eje Y del mouse, recuerda -1, esto es realmente importante

ENDIF

ENDFUNCTION

FUNCTION draw_Shot:
//Bien y aqui que pasa

STATIC speed_Shot //pues que declaro está funcion, le he puesto que sea estátic , pero podría ser Local, incluso sería más
//correcto, está variable va a ser a la velocidad que se mueve "la Bala"
   speed_Shot = 2 // La variable es un incremento de valor 2



FOREACH item IN shot[] // Este tipo de For´s es algo más inusual pero para mi es la mejor manera de hacer esto te explico:

//Este for dice, Oye para cada item (esto es una variable que podría ser Perico_de_Los_palotes) , o sea, cada cosa que hay dentro
//de array shot[] (nuestro disparo), haz lo siguiente...

// Eso puede ser un poco confuso,

INC item.x , speed_Shot    //Este incremento es el que nos hace que la bala se mueva hacia la derecha, fijate que curiosamente
  //La variable item, ahora es item.x, esto es debido a que como el array tiene las "propiedades x e y"
  // la variable del for las hereda "Esto es suposición mia"

PRINT "*" ,  _ // Simplemnte dibujamos la bala que es un <asterisco> *
    item.x  ,  _ //Fijate que las lineas no está en una sola linea, esto se hace simplemente añadiendo al final , _
    item.y
 
//Free mem
// Y aqui finalmente liberamos de la memoria del ordenador o el mobil, ese array que se iba agrandado
// OJO, es muy pero que muy importante, en el PC, puede tardarte incluso 10 min en ver como el juego se ralentiza
// Pero en el mobil, depende como puedes estar 30 segundos, y notar como empiezan a bajar los FPS, esto es
// porque el array de disparo se va agrandado y va quitando espacio de memoria

IF item.x > sx // Como lo hace es muy sencillo, fijate lo que le decimos, si item.x, o sea la bala, pasa de la posicion mayor
// de la pantalla por la derecha, elimina el "objeto"


DEC n_Shot.x //OJO está linea ES MUY IMPORTANTE, recuerdas arriba que para crear el disparo con el botón derecho
//está variable iba creciendo... pues cuando llega al fina debemos obligar a que baje su valor, o sea
//Si teniamos un valor de 300 pulsaciones del raton, cuando esa vala numero 300 llegue a la derecha valdrá
//por un momento 299, si no haces esta lines el programa petará


DELETE item //Esta linea simplemente te libera de memoria el indice del array, y lo que hará si sueltas el boton, es que
//Cuando desaparezcan todas la balas tu array volverá a valer 0
ENDIF

NEXT
//Y bueno ya está , un "tochaco", pero funciona


ENDFUNCTION


Quote from: veketor on 2012-Jun-12
Hola Jonaspm:

  El código que he puesto, es muy similar a lo propuesto tanto por Hark0 como por MentalThink, el código de Mentalthink está ampliamente comentado, y es más completo que el mio, te recomiendo lo mires detenidamente. Te resumo como funciona el mio:
  - Se crea un tipo disparo con algunas funciones para manejarlo:
      *make: "crea" el disparo en pantalla, para ello, le pasamos los valores del ratón, que es desde donde nace el disparo.
      *update: actualiza-mueve el disparo en cada llamada.
      *draw: pinta en pantalla el sprite de disparo en la posición correspondiente.
  - Los disparos se almacena en un array dinámico (no hemos determinado su tamaño, ya que desconocemos cuantos disparo tendremos en pantalla). El array disparos[] está inicialmente vacío, y representa lo que tendremos en pantalla, es por ello que existe una variable llamada disp que, por poner un simil, sería como el disparo que está pendiente de salir de la nave, en el momento que pulsamos el disparo, este, sale de la nave para representarse en pantalla, añadiendose al array disparos[].
  - Los disparos se ha de eliminar de algún modo al salir de la pantalla o al impactar, como no tenemos nada con lo que impactar, lo que hacemos es borrar todo disparo que salga por el margen izquierdo con la siguiente condición:
Code (glbasic) Select
IF (disparos[contadorDisparos].posX<0)
DIMDEL  disparos[],contadorDisparos
ENDIF

  - Finalmente, creamos un temporizador para no llenar la pantalla de disparos, de tal modo que solo se puede disparar cada x segundos:
Code (glbasic) Select
((ultimaPulsacion+frecuencia_disparos)<(GETTIMERALL()))
Donde ultimaPulsacion guarda el instante del último disparo válido y frecuencia_disparos, se encarga de poner un retardo entre disparos, todo ello se compara con gettimerall() que devuelve un contador que contiene el tiempo que lleva el programa en funcionamiento.

Sobre multitouch: si lo soporta, mira en los foros.

Saludos
     


Ahora mi pregunta es... ¿Sería posible añadir la misma función pero para Asteroides generados al azar?

Tal y como trabaja el juego:
http://www.youtube.com/watch?v=AnaiPgwrYo8

Gracias!
<HTML><BASIC><EC>
Be free and do good things

Hark0

Buenas, no acabo de entender la pregunta

Que quieres añadir a los asteroides? Que disparen auto?
http://litiopixel.blogspot.com
litiopixel.blogspot.com - Desarrollo videojuegos Indie · Pixel-Art · Retroinformática · Electrónica Development Indie Videogames · Pixel-Art · Retrocomputing · Electronic

Jonás Perusquía

Mas bien, preguntaba si es posible utilizar el mismo metodo de los disparos pero para la aparicion y movimiento de los asteroides
<HTML><BASIC><EC>
Be free and do good things

mentalthink

#3
Hola Jonas por supuesto, pero te doy un consejo para el tema de enemigos, lo mejor es utilizar o hacer una clase o varias...

EJ:

Lo primero es crear un array de enemigos en el fuente dónde declaras los arrays, por ejemplo el primer documento algo asi:

global enemy[] as TENEMY
dim    enemy[10]

Ahora en un source a parte, para tenerlo más organzado te haces una "Clase" es muy sencillo y muy pero que muy útil

TYPE
x;
y;
speed;


function initialize_Clase:
foreach item in enemy[]
  self.x         = rnd(480)
  self.y         = rnd(320)
  self.speed  = rnd(5)
next
endfunction

function move_Clase:
foreach item in enemy[]
inc self.x, self.speed
next
ednfunction

function collision_Clase:
foreach item in enemy[]
   if boxcoll(self.x,self.y   _
                 20    ,    20   _
                  mx  ,     my _              //Esto es la posicion del Player
                  20  ,      20)               // Esto es el tamaño en caja del player
        delete item
   endif
endfunction

endtype

function all_process_Enemy:
      foreach item in Enemy[]
         item.move_Clase    ()
         item.initialize_Clase()
         item.collision_Clase ()
     next
endfunction

//////////////////////////////////////
Bien está ultima función es la que tienes que llamar en tú código main... Lo bueno de usar un código así es que puedes añadir lo que te da la gana en cualquier momento y te va a funcionar sin problemas...

*** Jonas si tienes problemas con el código me lo dices... que no lo he revisado y quizás haga algo raro, está manera de poner enemigos es la que estoy usando en mi juego, y te aseguro que va la mar de bien, a parte  que como comento , modificar el código es realmente sencillo.




Jonás Perusquía

gracias mentalthink eso de usar Arrays y Functions es muy nuevo para mi jaja, saludos!
<HTML><BASIC><EC>
Be free and do good things

mentalthink

Es muy sencillo ya verás cuando le pilles el truco es muy facil, es com hacer un type con x e y, pero vas a poder hacer lo que quieras dentro de ese array, y luego modificarlo es super sencillo, de hecho mi juego el nucleo es ese... a parte puedes hacer máquinas de estado , que el nombre suena muy complejo, pero luego es la mar de sencillo, es como decirle a cada cosa lo que tiene que hacer por su cuenta...

Miratelo que es muy pero que muy potente... creo que sería el equivalente a las clases en C++

Jonás Perusquía

#6
Le di un par de vueltas al codigo y me surgieron unas pequeñas dudas...


Quoteglobal enemy[] as TENEMY       //¿Aqui declaramos enemy como si fuera variable?
dim    enemy[10]          //¿Aqui son cuantos asteroides aparecen no?

TYPE // ¿Se divide el TYPE en 3 variables no?
x;
y;
speed;

function move_Clase:
foreach item in enemy[]
inc self.x, self.speed            //Aqui no entiendo muy bien... ¿Se le suma self.speed a self.x cada FPS?
next
ednfunction

function collision_Clase:
foreach item in enemy[]
   if boxcoll(self.x,self.y   _            // ¿No se puede usar sprcoll?
                 20    ,    20   _
                  mx  ,     my _         
                  20  ,      20)             
        delete item
   endif
endfunction

endtype
última preguntita: ¿El nombre de la Function puede ser cualquiera?

De antemano muchas gracias por toda la ayuda
<HTML><BASIC><EC>
Be free and do good things

mentalthink

Hola ditrabox, mira te explico...

global enemy[] as TENEMY       //¿Aqui declaramos enemy como si fuera variable?
dim    enemy[10]          //¿Aqui son cuantos asteroides aparecen no?

Esto lo que hace es crearte 10 enemigos, pero ojo son 10 functions de las que le he puesto, más o menos para que te hagas una idea significa que el array o sea cada elemento tiene esas 3 funciones...

El otro Type que ves que "encapsula a las functions", es para que cada grafico tenga su propia posicion x e y y su propia velocidad

Lo que pone inc self.x en realidad es lo mismo que decir en un array normal inc my_Array[num_Indice].x,velocidad, lo que yo he hecho en el código es para que cada gráfico tenga su propia velocidad...

Lo de Sprcoll, por supuesto que lo puedes usar, lo que pasa que yo ya me he acostumbrado, a parte de que el juego te va a ir tremendamente más rápido en cuanto a consumo, puedes hacer lo mismo, obviamente no vas a tener el mismo control sobre la colision, pero por ejemplo si un dia usas un fondo 3D con collisiones 2D, y usas Sprcoll, lo más probable es que en cada colision el juego se pare por unas décimas de segundo, porque el SPRColl, mira cuando hay 3D, la textura completa del objecto que esté en pantalla en ese momento y de ahí que el juego se pare, si la textura es de 64x64 como que no pasará nada, pero lo unico que verás es la geomtria con un borron como textura... yo estoy usando texturas de entre 1024x1024 y 2056x2056***

Lo del nombre de la function, eso es a tú gusto, lo que pasa que yo suelo escribir mis códigos asi, ya hace un tiempo me hize una ISO, a modo personal para nombrar todo lo que se puede tocar con GLBasic, y a la hora de buscar cosas las encuentro con mucha facilidad...

*** Lo que digo de las texturas, si alguna vez haces algo en 3D, recuerda usar en Potencia de 2, que que es eso?¿, pues que si de ancho mide 512 pixeles, de alto igual, y si mide los que sea en X, lo mismo en Y, el tema es que si la haces más ancha que alta, o alta que ancha... como en realidad es una Matriz y las OpenGL se ve que no se entienden muy bien con cosas que no son cuadradas, el juego se ralentiza en montón, solo por esa chorrada...




Jonás Perusquía

muchas gracias mentalthink, me ha servido mucho tu explicacion, voy a trabajar en implementar el codigo escribiendolo desde 0 y luego les comento como me fue


un GRAN GRACIAS POR TODO!
<HTML><BASIC><EC>
Be free and do good things

mentalthink

De nada hombre y si no te funciona pues me preguntas a ver si lo solucionamos... que mis dotes de programación no es que sean demasiadas...

Saludos,Ditrabox.

Hark0

Bravo por la explicación... creo que no hace falta añadir nada más...  :P

;)
http://litiopixel.blogspot.com
litiopixel.blogspot.com - Desarrollo videojuegos Indie · Pixel-Art · Retroinformática · Electrónica Development Indie Videogames · Pixel-Art · Retrocomputing · Electronic

mentalthink

 :-[ :-[ :-[

Una cosilla importante que se me ha olvidado, el tema de usar .self y no usar el nombre del Array, es según leí en el libro de MrT o no sé dónde, que si usas el nombre del array puede saltar el código, aunque yo ha veces llamo algún array porque me hace falta solo un indice, porque no me es necesario recorrer todo el array...

Una cosa importante, que me parece que no he puesto es cuando se inizializa algo en las "clases" solo hay que llamarlo una vez... si se mete en loop, se quedará parado o lo que le hayamos dicho en la función de inicio...

PS: Si no se entiene muy bien, porque hizé la explicación muy rápido y os interesa os subo un .PDF más elaborado, pero no tiene ningún misterio, al principio es un poco lio, por lo del self, pero luego escribir modificar o añadir cosas es realmente muy pero que muy sencillo, a parte de ser realmente productivo...
:booze:

Jonás Perusquía

me ha servido demasiado toda su ayuda, en breve publicare en el foro el juego en el que he estado trabajando :)
<HTML><BASIC><EC>
Be free and do good things

mentalthink

Pues perfecto Jonas, a la espera estaremos.!!!! :booze: