Sistema de disparos en desarrollo

Previous topic - Next topic

Jonás Perusquía

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!
<HTML><BASIC><EC>
Be free and do good things

Hark0

Yo haría una matriz para los disparos... algo así, escribo de memoria, si hay faltas/fallos/bugs, disculpame:


type bala
activada
posx
posy
endtype

local balas=6
dim cargador[balas] as bala


for n=0 to balas-1
cargador[n].activada=0
cargador[n].posx=0
cargador[n].posy=0
next

----------------------

Con esto declaras las balas y tal.... y tienes hasta 6 para disparar.

Haces una rutina que cuando pulses una tecla o el mouse, se capture la posicion XY que te interesa y se lo pasas a la bala de turno.

En pseudocodigo:

si tecladisparo=true
   cargador[bala_actual].activada=1
   cargador[bala_actual].posx=posicionx personaje
   cargador[bala_actual].posy=posiciony personaje

    bala_actual=+1   

     si bala_actual=7 entonces hemos llegado al fin del cargador.
finsi


luego en el mainloop, comprueba qué balas están activadas y comprueba su posición, impacto, etc....

puedes hacer 2 cosas cuando se alcanza el final del cargador...

1- ponerlo a cero y entonces se dispara infinito...
2- obligar al jugador a que pulse una tecla para que recargue....



Espero te sirva de ayuda, disculpa la parquedad, no tengo mucho tiempo en este momento.

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

Hark0

Recuerda en poner a cero la variable activada cuando impacte con algo o salga fuera de pantalla, sino las balas no terminan nunca de llegar a ninguna parte.



Saludos.

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

veketor

Prueba con esto:
Code (glbasic) Select

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

TYPE _disparo
posX
posY

FUNCTION make: mouseX, mouseY
self.posX=mouseX;
self.posY=mouseY+15;
ENDFUNCTION

FUNCTION draw:
DRAWSPRITE 2, self.posX, self.posY
ENDFUNCTION

FUNCTION update:
self.posX=self.posX-2; // movemos dos pixels a la izquierda a cada llamada
ENDFUNCTION
ENDTYPE

GLOBAL disparos[] AS _disparo;
GLOBAL ultimaPulsacion=GETTIMERALL();
GLOBAL disp AS _disparo;
GLOBAL frecuencia_disparos=100;
GOSUB game




SUB game:
WHILE TRUE


MOUSESTATE mx,my,b1,b2

PRINT b1, 100, 100

//DRAWSPRITE 2, wx, wy
DRAWSPRITE 1,mx,my
DEBUG GETTIMERALL()+"\n"
IF (b1=1) AND ((ultimaPulsacion+frecuencia_disparos)<(GETTIMERALL()))
ultimaPulsacion=GETTIMERALL();
DEBUG ultimaPulsacion+" | "+GETTIMER()+2000
disp.make(mx,my);
DIMPUSH disparos[], disp;
// wx=mx
// wy=my+15

ENDIF

FOR contadorDisparos=0 TO LEN(disparos[])-1
IF (contadorDisparos>0)
disparos[contadorDisparos].update();
disparos[contadorDisparos].draw();
IF (disparos[contadorDisparos].posX<0)
DIMDEL  disparos[],contadorDisparos
ENDIF
ENDIF
NEXT

SHOWSCREEN
WEND
ENDSUB


Al trabajar con ratón para detectar la pulsación, he metido una variable llamada "ultimaPulsacion" y "frecuencia_disparos" para evitar auto-fire.
Los disparos tienen un tipo propio,  y se almacena en un array llamado disparos[], el tipo disparos tiene una función para crearlos en la posición de la pulsación del ratón y para actualizar su movimiento. Cuando un disparo se sale de la pantalla, lo eliminamos del array.

Saludos.

mentalthink

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





Jonás Perusquía

Gracias por sus respuestas, les voy a dar una vuelta y les comento que tal... GRACIAS!!!

una preguntita... ¿GLBasic soporta multi-touch?
<HTML><BASIC><EC>
Be free and do good things

Jonás Perusquía

Utilizé la forma de veketor y me anda muy bien, pero me gustaría aprender a escribirlo yo xD alguien me podría explicar como funciona?

Se los agradezco mucho
<HTML><BASIC><EC>
Be free and do good things

veketor

#7
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
     

mentalthink

Hola jonas, lo primer darte las gracias veketor por la referencia ha mi código...

Jonas como dice Veketor, mirate los 3 códigos, al principio es un "coñazo" pero hay que pasar por el aro, verás que de cada código puedes hacer cosas algo distintas, por ejemplo veketor creo que ha implementado el disparo NO- Automático, cosa que yo no he hecho, luego ya verás que aunque parece "complicao" al principio luego te saldrá casi sin discurrir...

Sobre lo que comentas de Multitouch si que lo permite, pero ojo que hay androids que no lo hacen... me refiero al telefono... estó si miras en el help (F1), un comando llamado getmousecount, verás como se hace, es muy sencillito es un for, y cuenta cuantos dedos están a la vez en la pantalla...

Un saludo,

Jonás Perusquía

#9
es posible utilizar el mismo código pero para generar asteroides de la misma manera que aparecen actualmente en mi juego?

http://www.youtube.com/watch?v=AnaiPgwrYo8
<HTML><BASIC><EC>
Be free and do good things