PDA

Ver la versión completa : Crear una rutina de disparo



Eskema
13/02/2005, 19:16
Saludos de nuevo, hay un tema que me inquieta, ¿como hago una rutina de disparo efectiva?.
Os cuento, despues de ver muchos tutos por la red, he visto que muchos usan un array para mantener la informacion de los disparos, algo como esto:

define MAXBALAS 10;

struct disparo{
int x,y;
}bala[MAXBALAS];

void creardisparo(){
int sitiolibre=0;

for(int i=0; i<=MAXBALAS; i++){
if(bala[i].x==0)
sitiolibre=i;
}

if(sitiolibre>=0){
bala[sitiolibre].x=nave.getx(); //ponemos la bala en la posicion de la nave
bala[sitiolibre].y=nave.gety();
}
}


void muevebalas(){
int i;
for(i=0; i<=MAXBALAS; i++){
if(bala[i].x !=0){
bala[i].y=bala[i].y-5; //movemos la bala 5 para arriba

if(bala[i].y<0){ //si la bala llega a la posicion y=0 desparece de la pantalla y vuelve al array
bala[i].x=0;
}
}
}
}


Este es el sistema mas visto pero sin embargo a la hora de implementarlo cuando pulsas disparo, lanza las 10 balas con una sola pulsacion, en vez de ir disparando de una en una hasta agotar las balas, que en cuanto desaparecen de la pantalla vuelven a llenar el array.
¿Alguien tiene otra forma de crear un disparo mas controlable?
gracias, Eskema

kmkzk
13/02/2005, 19:31
Hola,
Lo que tienes que hacer es poner un contador de tiempo, para que no se cree ninguna bala nueva hasta que pase un tiempo despues de haber lanzado una. Esto lo podrias hacer, por ejemplo, con una variable que se decremente en el procedimiento de movimiento de balas (siempre que esta variable sea mayor que 0), y que solo te haga el disparo si este contador es 0. Cada vez que crearas un disparo tendrias que establecer el valor de la variable al tiempo que quieras que sea el retardo.
Esto es solo un ejemplo, se podria hacer de mil maneras diferentes.
Espero que se me haya entendido :)
Un saludo

Eskema
13/02/2005, 19:39
Hmmm como estoy usando la SDL, un contador de tiempo seria usando los get_ticks(), capto tu idea. Yo habia pensado algo igual pero no se hasta q punto puede ser bueno, quiero decir, ¿la gp no se cargara demasiado controlando tiempo?

kmkzk
13/02/2005, 20:46
Hola,
supongo que se puede hacer con get_ticks(), y de hecho seria mas exacto.
De todas formas, yo lo hago asi pelo, jeje, con un contador-- en cada paso, y de esta manera no se carga la Gp. Con get_ticks() no se que pasaria (si son diez balas no creo que se sobrecarge).
Que metodos usa la gente para esto?
Un saludo!

Eskema
13/02/2005, 21:15
Eso mismo pienso yo tb que usando un contador a pelo no gastaria muchos recursos, enga gente ¿sugerencias? ¿como lo haceis vosotros?

Puck2099
13/02/2005, 22:06
Eso pasa por lo que en electrónica se llama "rebotes". Tú dejas pulsado el botón unas décimas de segundo, pero la consola es tan rápida que en ese tiempo dispara 10 veces.

La mejor solución en mi opinión (y la que uso yo en mi Lady Killer) es lo que te han comentado del contador. Vas contando el número de frames y cuando sea mayor de x pues le dejas entrar a la rutina del disparo mediante un if.

Espero haberme explicado bien :)

Saludos

oankali
14/02/2005, 10:02
La mejor solución en mi opinión (y la que uso yo en mi Lady Killer) es lo que te han comentado del contador. Vas contando el número de frames y cuando sea mayor de x pues le dejas entrar a la rutina del disparo mediante un if.


Esa solución funcionará solo si los FPS son constantes, pero si varía, o cambias la velocidad del procesador, tendrás que volver a ajustarlo todo.
La mejor solución en mi opinion es hacerlo gon get_ticks() que no gasta nada de recursos. Yo no uso SDL pero supongo que es lo mismo que GpTickCountGet().

He aquí un ejemplo de lo que yo haría utilizando mi librería list.h (http://www.nekanium.com/gp32/cLibraries.htm#List) con la que puedes gestionar una lista dinámica de disparos.
Con pocos elementos, las tablas son más rápidas que las listas encadenadas, con las listas solo tratas elementos existentes, no tienes que ir buscando en la tabla donde estan los disparos válidos. Además no tienes por que preocuparte por la cantidad de disparos.
Las listas encadenadas pueden llegar a ser muy útiles.
Puede parecer un poco complicado en un principio por los punteros, pero en los punteros radica la potencia del C :)
Ah, y otro comentario, en realidad tickInicial podría ser una variable global pero incluyéndola en cada disparo puedo controlar la vida de cada disparo en el tiempo y no solo en el recorrido, vease granadas.



typedef struct tagBALA {
int x, y;
int tickInicial;
} BALA;

// Declaramos la lista dinàmica de balas
LIST *gpBalas;

void CrearDisparo(void)
{
LISTITEM *pItem;
BALA *pBala;

// controlamos si NO es el momento de disparar
if (gpBalas->count)
{
// recuperamos la última bala disparada
pBala = gpBalas->pLast->pObject;

// si no ha pasado el tiempo suficiente, salimos
if (get_ticks() - pBala->tickInicial < TIEMPOENTREDISPAROS)
return;
}

// creamos la bala
if ((pItem = ListAddItem(gpBalas, NULL, sizeof(BALA))) == NULL)
// falta memoria, no creamos la bala
return;

// Inicializamos la bala
pBala = pItem->pObject;
pBala->x = nave.getx();
pBala->y = nave.gety();
pBala->tickInicial = get_ticks();
}


void MueveBalas(void)
{
LISTITEM *pItem, *pCurrentItem;
BALA *pBala;

pItem = gpBalas->pFirst;
while (pItem)
{
// preparamos nuestro puntero sobre la bala siguiente
// mejor hacerlo antes, por si hay que destruir la bala
pCurrentItem = pItem;
pItem = pItem->pNext;

// movemos la bala hacia arriba
pBala = pCurrentItem->pObject;
pBala->y -= 5;

// si la bala llega a la posicion y=0 desaparece de la pantalla
if (pBala->y < 0)
ListRemoveItem(pCurrentItem);
}
}


void juego()
{
// creamos la lista de balas
if ((gpBalas = ListCreate()) == NULL)
// falta memoria
return;

//...
// bucle del juego
//...

// suprimimos la lista de balas
ListDestroy(gpBalas);
}

Puck2099
14/02/2005, 11:40
Esa solución funcionará solo si los FPS son constantes, pero si varía, o cambias la velocidad del procesador, tendrás que volver a ajustarlo todo.
La mejor solución en mi opinion es hacerlo gon get_ticks() que no gasta nada de recursos. Yo no uso SDL pero supongo que es lo mismo que GpTickCountGet().


Je, je, llevas razón Oankali, es que en mi juego los FPS son siempre 60 constantes :D

Saludos

Weif Raider
04/04/2005, 01:16
Uhmmm... oankali dice que si se hace por FPS, al variar éstos, ya no sirve pq dependiendo de éstos variará el intervalo de tiempo entre las balas.

y si lo hacemos con los ticks, no pasa lo mismo?

Corregirme si me equivoco, pero si varias la velocidad del procesador, los ticks se ejecutarán en menos o más tiempo. Por lo que también variará el momento en que pueda lanzar una bala, no?

Yo lo haría calculando el número de ticks que se ejecutan por segundo. Y con la cantidad de ticks que sucedan de un disparo a otro, calcular el tiempo mínimo en el que pueden dispararse dos balas. De esta forma, si cambias la velocidad del procesador, da lo mismo, pq las balas salen en el tiempo que has marcado.

A.r.R.c.H.E.r
04/04/2005, 13:45
Se trata de que cuando pulsemos el boton despare las 10 balas una detras de otra? o que para disparar las 10 balas tengamos que pulsar 10 veces el boton?

LTK666
04/04/2005, 14:10
Si alguien conoce alguna o algunas buenas páginas con ejemplos de creación de disparos, preferiblemente en C, le importaría postearla/las?

Los que :chupete: andamos aprendiendo lo agradeceremos bastante.

Weif Raider
04/04/2005, 14:22
Archer, por lo que entendí, es que salga una bala cada vez que apretas el botón. El problema que tenía era que saían las 10 de golpe y quería dejar un espacio en el tiempo entre bala y bala.

El problema es dejar un espacio constante en el tiempo si se varía la velocidad del procesador o los FPS.

A.r.R.c.H.E.r
04/04/2005, 18:26
Pero para que salga una bala cada vez que apretas una vez el boton no hace falta nada de los FPS, yo lo soluciono de la siguiente manera:

Declaro un contador por ejemplo unsigned char est_A, cuando el boton A esta pulsado se va incrementando en 1 unidad siempre que no sobrepase el valor 2... eso seria asi.

if (BOTON_A_APRETADO && est_A<2) est_A++;

Con esto lo que logramos es poder seleccionar si lo que queremos es detectar una sola pulsacion o que se mantenga pulsado el boton esto seria asi:

if (est_A==1) Dispara();

esto solo dispara 1 bala cada vez que pulsemos el boton.


Solo nos falta que cuando dejemos de pulsar el boton ponga est_A a 0.

pos creo que con esto ya esta, si est_A valiese 2 querria decir que se mantiene pulsado el boton pero no disparaia ninguna bala porque solo lo hace cuando est_A vale 1. ;)

Weif Raider
04/04/2005, 20:24
Creo que no estamos hablando de lo mismo.

Imagina que apretas el boton de disparo muy rapido. Por ejemplo, 5 pulsaciones por segundo (apretar + soltar). Y tú quieres que como máximo se puedan disparar 3 balas por segundo. Tienes q poner un contador que limite el número de balas que disparas.

oankali
05/04/2005, 08:34
Uhmmm... oankali dice que si se hace por FPS, al variar éstos, ya no sirve pq dependiendo de éstos variará el intervalo de tiempo entre las balas.

y si lo hacemos con los ticks, no pasa lo mismo?

Corregirme si me equivoco, pero si varias la velocidad del procesador, los ticks se ejecutarán en menos o más tiempo. Por lo que también variará el momento en que pueda lanzar una bala, no?

Yo lo haría calculando el número de ticks que se ejecutan por segundo. Y con la cantidad de ticks que sucedan de un disparo a otro, calcular el tiempo mínimo en el que pueden dispararse dos balas. De esta forma, si cambias la velocidad del procesador, da lo mismo, pq las balas salen en el tiempo que has marcado.


Je je, ha tardado pero al fin alguien se ha dado cuenta del problema de GpTickCountGet(). Pero si te fijas bien Weif Raider, en mi ejemplo no utilizo directamente esa función sino una derivada get_ticks() que vendría a ser lo que tu dices, una función independiente de la velocidad del procesador.
De echo, en mi librería clock.h (http://www.nekanium.com/gp32/cLibraries.htm#Clock) hay una variable global que indica los ticks por segundo para cada velocidad de procesador y dos macros, TicksToMs(ticks) y MsToTicks(ms), que passan de ticks a milisegundos y al revés que son las que utilizo en mis programas.

Oankali.

Weif Raider
05/04/2005, 10:20
Oks Oankali, ahora sí que me cuadra! :brindis:

Buenas librerías, ahora voy a empezar a hacer cosas para la Gp32, stoy instalando entornos, SDK y esas cosas... pero leí las librerías que tienes sobre fuentes, clock, etc... y me gustaría probarlas... ya te contaré! ;)

Por cierto, si tienes un ratillo mándame un msg para poder poner sprites de 16 bits con el SDK, ok? No me corre nada de prisa, iré viendo el SDK para familiarizarme con él y eso...

oankali
05/04/2005, 13:19
[...]

Por cierto, si tienes un ratillo mándame un msg para poder poner sprites de 16 bits con el SDK, ok? No me corre nada de prisa, iré viendo el SDK para familiarizarme con él y eso...

Ya he colgado en mi web (http://www.nekanium.com/gp32/news.htm) un pequeño tutorial para instalar el devkitARM con las librerias 16 bits. También hay un pequeño programa de test.
Asi es como lo tengo yo.
Cuando tenga tiempo (y ganas :rolleyes: ) continuaré con los otros tutoriales previstos.

Oankali.

Weif Raider
06/04/2005, 00:27
Okss oankali, muchas gracias... lo probaré en cuanto pueda ;)