Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: SCUMM en 27 Enero 2014, 19:38 pm



Título: Problema con un getch() indisciplinado
Publicado por: SCUMM en 27 Enero 2014, 19:38 pm
Buenas, resulta que he hecho un pequeño videojuego para clase de programación
y parece que no quiere funcionar, el videojuego es muy simple, aparece una pantalla con dos vaqueros y cuando suena la campana cada jugador pulsa la tecla de la acción que quiere realizar.
En base a lo que haya hecho cada uno el resultado es diferente.
He aquí la parte conflictiva de mi código:

    do
    {
        system("cls");
        bool fin=false;
        char accionpri;
        char accionse;
        unsigned tiempo=0;
        ImprimirDuelo(vaqueroa,vaquerob);
        tiempo=rand() % 5;
        Sleep(tiempo*1000);
        Beep(440, 900);
        fflush(stdin);
        fflush(stdout);
        accionpri=getch();
        accionse=getch();
        victoria=ResolverDuelo(accionpri,accionse);
        Sleep(3000);
    }while(victoria==0);

El problema es que los getch deberían capturar las acciones del primer y segundo jugador después de que suene la campana, sin embargo se puede introducir accionpri y accionse antes.
¿Alguna idea de como solucionarlo?Muchas gracias.


Título: Re: Problema con un getch() indisciplinado
Publicado por: vangodp en 28 Enero 2014, 16:08 pm
No se si funciona por que el código esta a medias.
Pero no deberías declarar variables en un bucle creo. Estarías declarando varias variables con el mismo nombre lo que no puede ser, lo que si puedes hacer es declarar antes y cambiar el valor tantas veces como quieras dentro.
Sobre el getch no puedo decirte si funciona o no(código incompleto), pero creo que el problema puede ser el de arriba.
Código
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. int main () {
  5.    //declarar las variables fuera del bucle.
  6.    bool fin=false;
  7.    char accionpri;
  8.    char accionse;
  9.    unsigned tiempo=0;
  10.    int tiempo = 0;
  11.  
  12.    do {
  13.        system("cls");
  14.        // Aqui las vuelve a asignar los valores necesarios a las varibles si te hace falta
  15.        fin=false;
  16.        tiempo=0;
  17.        ImprimirDuelo(vaqueroa,vaquerob);
  18.        tiempo=rand() % 5;
  19.        Sleep(tiempo*1000);
  20.        Beep(440, 900);
  21.        fflush(stdin);
  22.        fflush(stdout);
  23.        accionpri=getch();
  24.        accionse=getch();
  25.        victoria=ResolverDuelo(accionpri,accionse);
  26.        Sleep(3000);
  27.    } while(victoria==0);
  28.  
  29.    cin.ignore();
  30.    return 0;
  31. }
  32.  


Título: Re: Problema con un getch() indisciplinado
Publicado por: SCUMM en 28 Enero 2014, 19:37 pm
la verdad es que moví un par de cosas para no poner todo el tocho de código en el post y no caí en que estaba metiendo la declaración de variables dentro del bucle
(a mas de uno le ha tenido que dar un ictus).

El problema es que el getch() no se activa despues de que suene el Beep sino que recibe el imput que se le haya estado metiendo antes (si hay algun tramposo que no respete el Beep) Me ha dicho un amigo que tengo que hacerlo con un evento pero la verdad es que no se como implementarlo (aparte de que la solución ideal sería la mas simple).
¡Por cierto!¡Muchas gracias por responder!


Título: Re: Problema con un getch() indisciplinado
Publicado por: vangodp en 28 Enero 2014, 22:04 pm
hice este a ver si te sirve.
Juegas con la a y la l, lo cambias si no te gusta :D
Tiene partes de cpp pero lo puedes cambiar para c sin problemas.

Código
  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <conio.h>
  4. #include <windows.h>
  5. using namespace std;
  6.  
  7. int main () {
  8.    char victory = '0';
  9.    char play = '0';
  10.    int fin = 0;
  11.    do {
  12.        system ("cls");
  13.        play    = '0';
  14.        victory = '0';     //ponemos a 0 para no haber trampas
  15.        fflush(stdin);
  16.        fflush(stdout);
  17.        // teclas para jugar a y b minusculas =D, a = jugador 1 : b = jugador 2
  18.        // aqui el beep        
  19.        victory = getch();
  20.        Sleep (50);
  21.        switch (victory) {
  22.            case 'a':
  23.                cout << "player 1 vence!" << endl; // llamar funcion para player uno vencedor
  24.                break;
  25.            case 'l':
  26.                cout << "player 2 vence!" << endl; // llamar funcion para player dos vencedor
  27.                break;
  28.            default:
  29.                cout << "tecla no correcta!";
  30.                break;
  31.        }//FIN SWITCH
  32.  
  33.        cout << "Terminar? s/n" << endl;  // Seguir jugando n = salir cualquier otra tecla continua ;)
  34.        scanf ("%c", &play );
  35.        fin = (( play == 'n' ) ? 1 : 0  );
  36.    } while( !fin );
  37.  
  38.  
  39.    cin.ignore();
  40.    return 0;
  41. }
  42.  



Título: Re: Problema con un getch() indisciplinado
Publicado por: SCUMM en 29 Enero 2014, 00:37 am
Aquí explico la mecánica del juego:
Código
  1. void Instrucciones()
  2. {    
  3.    system("cls");
  4.    cout<<"Bang es un juego de duelos de vaqueros en el viejo oeste para dos jugadores."<<endl<<endl;
  5.    cout<<"Cuando empieza la partida un jugador tomara el control de el               "<<endl;
  6.    cout<<"primer vaquero controlado con los botones a,s,d, el otro controlara con los"<<endl;
  7.    cout<<"botones b,n,m al segundo vaquero, El objetivo es matar al otro en un duelo!"<<endl<<endl;
  8.    cout<<"              |Vaquero 1|Vaquero 2|                                        "<<endl;
  9.    cout<<"    Disparar  |    a    |    b    |                                        "<<endl;
  10.    cout<<"    Recargar  |    s    |    n    |                                        "<<endl;
  11.    cout<<"    Esquivar  |    d    |    m    |                                        "<<endl<<endl;
  12.    cout<<"Cuando suena la campana cada vaquero hace su accion, disparar, recargar    "<<endl;
  13.    cout<<" (hasta un maximo de tres balas) o esquivar(esta accion te puede salvar    "<<endl;
  14.    cout<<"de la muerte) En caso de que los dos vaqueros disparen a la vez, el mas    "<<endl;
  15.    cout<<"rapido de los gana.                                                        "<<endl<<endl<<endl<<endl<<endl;
  16.    system("pause");
  17. }

Con el primer vistazo me pareció un juego muy simple de hacer, pero los problemas con el ghosting y el getch() disparandose antes del Beep la cosa se complica bastante


Título: Re: Problema con un getch() indisciplinado
Publicado por: SCUMM en 29 Enero 2014, 00:42 am
Por cierto el tema del ghosting y el blocking es muy interesante ahora que lo mencionas, ya que la rapidez de cada jugador influye mucho en quien gana, tal vez se podría hacer que uno de los jugadores disparara con el ratón o con un joystick, así nos quitaríamos el problema de la disposición de las teclas en serie en la circuitería del teclado.
Esta solución tengo que admitir que es muy cutre pero, todo sea por quitarme este maldito trabajo de encim.


Título: Re: Problema con un getch() indisciplinado
Publicado por: BlackM4ster en 29 Enero 2014, 08:42 am
Si no he entendido mal, realmente tiene que esperar a la pulsacion de 2 teclas (1 para cada jugador) y procesarlas, para saber quien ha ganado, no?


Título: Re: Problema con un getch() indisciplinado
Publicado por: vangodp en 29 Enero 2014, 11:45 am
Si! así es black master.
La cosa es que incito a que haga unas pruebas con tu teclado.
Veras que cuando pulsas ambas al mismo tiempo y no hay que ser muy exacto siempre sale el mismo resultado eso es así por que imagine que tienes un cable con dos polos, positivo y negativo.
Bien ahora en ese cable añades interruptores.
Cual crees que va funcionar?El primer siempre.
Ya que para que funcione el segundo, el primer debe estar sin pulsar.
Eso es así por que los teclados fueron concebidos para eso(Una tecla a la vez), y funciona muy bien para su fin(No nos quejamos ¿No?).
Pero la cosa cambia con lo que el quiere hacer.
Como el juego que el quiere necesita respuestas muy altas y precisas, por mas que quieras nunca podemos pulsar 2 teclas a la vez, siempre tendría una diferencia de milésimas o ínfimas, pero casi imposible pulsar las 2 juntas(no somos maquinas :D).
Lo que comenta el no es mala idea: usar 2 dispositivos.
O uno que sea especifico para eso, dicen no lo se, que el puerto de serie/paralelo que antes se usaba para las impresoras no tiene este problema, pero desconozco si es correcto por que nunca lo probé.
Existen dispositivos como este que solucionan el problema:
(http://www.ultimarc.com/images/ipac2_top.jpg)
Estan echos para construir algo como eso:
(http://img534.imageshack.us/img534/4518/wiring3u.jpg)
http://www.dndw.com/arcadeaddiction/controlpanel4.htm (http://www.dndw.com/arcadeaddiction/controlpanel4.htm)
El problema que tiene aparte de el que comentas(programacion).
Es también la respuesta del dispositivo.
Teclado no es un dispositivo para juego, por eso su problema.
Para una sola persona el teclado funciona muy bien, pero cuando se junta 2 o mas la cosa cambia.
¿Has intentado pulsar 6 o mas teclas juntas? Haz un programa que capture strings, y pulsa varias teclas juntas, si logra capturar todas veras que el orden se va repetir muchas veces.
Si pulsas 2 juntas te va salir siempre una primero.
En fin, no es que sea un problema del teclado ya que para eso lo crearon, es que no le va a ir bien ni que hagas el mejor programa.
Tiene que hacer pruebas por que cada teclado lo diseñan de una manera, o usar 2 dispositivos como 2 teclados o un teclado y un mando, o destripar su teclado a ver que botones van en diferentes lineas si es que lo hacen, y si al pulsar va funcionar de manera correcta.
Todo una serie de problemas resolver.
Estuve un tiempo pensando en hacerme una recreativa de estas. ^^
Sueño de infancia.  :xD
La cosa es que no creo que el amigo quiera gastar dinero ya que es un trabajo de sus estudios o yo que se. Pero todos tenemos un par de teclados viejos al cual le podemos dar uso para cosillas como esta.
Suerte!


Título: Re: Problema con un getch() indisciplinado
Publicado por: BlackM4ster en 31 Enero 2014, 08:31 am
Si, tienes toda la razón, la limitación aqui es el hardware del teclado, pero como bien has dicho, no somos máquinas y, por lo tanto, nunca podremos apretar dos teclas a la vez, con lo cual, yo no veo problemas a la hora de crear el programa.

Con un código que detecte dos teclas, no debería haber problemas. Un ejemplo que he usado para hacer pruebas xD

Código
  1. #include <iostream>
  2. #include <conio.h>
  3.  
  4. int main(){
  5.  
  6. int A, B;
  7.  
  8. A = getch();
  9. B = getch();
  10.  
  11. std::cout << A << ", " << B;
  12.  
  13. getch();
  14. }


Título: Re: Problema con un getch() indisciplinado
Publicado por: SCUMM en 31 Enero 2014, 13:00 pm
El problema era que el programa hacía sonar una campana para avisar a los jugadores de pulsar un botón (Como un preparados, listos, ya) sin embargo si uno de los jugadores pulsaba su boton antes de la campana, el programa lo daba por bueno y, por ejemplo si el jugador uno pulsaba disparar antes de la campana, mataba al otro (haciendo trampas)
Al final lo he solucionado poniendo un game loop que "getchea" todas las acciones de los jugadores antes de la campana y las descarta.
--si considerais que esto es spam borrad el comentario sin problemas, pero quería decir dentro de poco hay una competición para desarolladores de videojuegos, si os interesa pasaos por la sección de Juegos del foro--


Título: Re: Problema con un getch() indisciplinado
Publicado por: vangodp en 31 Enero 2014, 13:43 pm
Te entiendo que se puede "hacer" lo que dices.
¿Pero me has entendido algo de lo que dije yo?

(http://imageshack.com/a/img835/5089/fdbw.jpg)
Digamos que el hilo verde es positivo y el rojo negativo. La corriente viene y donde se junte ambos sigue su curso hasta volver al chip, eso se produce en amarillo1. ¡Bien funciona! ¿No? ¡Si! De momento si funciona. Sigamos...
Ahora imagina que tenemos pulsado el amarillo1 y quiero pulsar el azul1 que es una continuacion del cable rojo. No funcionaria ya que esta siendo usado para juntar amarillo1(positivo y negativo).
No se que clase de señal envía, si continua o pulsos, si es continua no registraria la segunda si fuera pulsos registraría así: sdsdsdsdsdsdsdsdsdsdsd XD o puede que dddddddddddddd o sssssssssssssssss XD no tengo ni p**a idea jaja. Habría que hacer pruebas(Hackear el teclado) y paso.
El compañero explica que que necesita respuestas rápidas por que van a jugar 2 personas . Una sola no tiene este problema, eso ya lo sabemos.
Te incito a que hagas un código que imprima cual de ellas se pulsa antes no que imprima ambas juntas.
Primero que sabemos que si pulsamos una tecla y la sujetamos pasa eso :kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk XD. Mientras no la soltemos no va registrar lo que ha echo la segunda ¡Si! lo llega a hacer.
Después prueba apretar ambos botones a la ves, y vayas registrando los resultados.
O bien has tu un jueguillo así: 2 teclas, juega tu con un amigo o hermano, el que pulse primero sale ¡boum gana jugador 1!, ¡boum gana jugador 2!....
varias veces XD.
Veras que solo gana el 1, o el 2, si que aprietes las 2 mas o menos juntas, el resultado no se va decidir por rapidez sino por las disposiciones de las teclas"Hard".
Para joder aun mas cada teclado la cosa cambia. Si hago un código que use una tecla en particular a mi puede que hasta llegue a funcionar correctamente, pero cuando lo ejecutes tu, si tienes otro tipo de teclado la cosa cambia.
Hay varias personas mas entendidas que yo sobre el tema en este foro, pregunta les, o pruebas tu.
Aquí estoy seguro que cualquier programador medio decente es capaz de resolver el problema sobre la parte de programación. Quiero ver apañar el problema del hard, y mejor aun que funcione en todas las computadoras de manera igual. ¡Esta es la cuestión!
Si lanzara una playstation hoy por mas bueno que fuera tus programadores, los ingenieros de hard lo habrían liado parda, y tocaría tirar cientos de miles de plays a la basura jaja
Haz tu un código, que te paso el resultado jejej de haberlo ejecutado.
Puede que yo este hablando hasta chorradas por que a ti en tu teclado te vaya bien pero en el mio si pulso a y l me sale siempre a :/
Si te crees capaz de solucionar hazme un código y lo pruebo, estoy aquí para aprender ;)
Suerte!




Título: Re: Problema con un getch() indisciplinado
Publicado por: SCUMM en 31 Enero 2014, 14:14 pm
Es cierto que el jugador que juegue con a,s,d va a tener ventaja sobre el que juega cob b,n,m.(en el gráfico se puede ver que las teclas mas altas y a la izquierda son prioritarias)  sin embargo este no es un problema real, puesto que el ÚNICO caso en el que el orden de teclas cuenta es cuando disparan ambos a la vez (cosa que apenas pasa) Y ya hemos visto como se puede solucionar haciendo que alguno de los jugadores juegue con otro dispositivo de entrada(ratón, mando xbox, joystick)
Además, tengo varios controles de error por usuario, por ejemplo en el caso de que el primer getch() registre el mismo valor que el segundo, salta un mensaje que dice"Trampa, se repite el asalto", o si se pulsa una tecla que no corresponde con un control, el vaquero simplemente no hace nada, además de que cada jugador solo puede cargar tres balas en su revolver ya que una partida suele durar quince turnos de media y con mas balas se haría eterno(todos estos sistemas están implementados en void ResolverDuelo(char accionpri,char accionse) )

Así que básicamente, el tema está zanjado, muchas gracias por responder a mi primer post con tanta entrega ;)
¡¡¡ Por cierto, gracias por sacar el tema del ghosting, tendré que estudiarlo a fondo para conseguir diseñar un buen mapa de controles para mis futuros juegos!!!


Título: Re: Problema con un getch() indisciplinado
Publicado por: vangodp en 31 Enero 2014, 14:53 pm
De nada.
Recuerda, que no es lo mismo un teclado que otro.
También puedes hackear un mando viejo, o otro dispositivo que no uses mas.
Los mandos de las consolas suelen tener este problema resuelto ya que son dispositivos específicos para juegos.
Pero si piensas en hacer un juego que vayas distribuir al lo bestia debes tener eso en cuenta(y otros tantos problemas).
Este tema es muy interesante sobre el mapeado de un teclado:
Explica como elegir las mejores teclas para un teclado que tiene, como apalea el blocking y el ghosting, y según el consigue hasta 8 teclas sin esos problemas.
http://zonaarcade.forumcommunity.net/?t=44254872 (http://zonaarcade.forumcommunity.net/?t=44254872)
Que ponga aquí tus avances en el campo del juego ;).
Si tienes algún código echo sobre los botones me gustaría probarlo cuando lo tengas listo, o el juego mejor  ;D