Desarrollo de Videojuegos
|
|
Juegos de Aventuras
Diseñando una aventura conversacional
|
|
Artículo realizado por
Spellcaster.
Traducción y adaptación de
Daniel Cárdenas.
Capítulo 3.
Mirar una localidad.
Veamos, una de las primeras cosas que tu conversacional
debe hacer es el 'mirar' la localidad inicial
Por 'mirar
una localidad' quiero decir 'describir la habitación actual'.
Al describir una localidad, lo que se hace es sacar por pantalla
tanto la descripción de la misma, como los objetos, monstruos
y PSI's que puedan haber. Como de momento no trataremos ni monstruos,
ni objetos, ni tampoco PSI's, nos limitaremos a escribir la descripción
de la habitación, la cual la tenemos almacenada en el array
Localizaciones[].Desc
Construyamos el procedimiento 'mirar'
(look).
Procedure Mirar(NumeroLoc:Word);
Var A:Byte;
Begin
Writeln;
A:=1;
While (A<11) And (Localizaciones[NumeroLoc].Desc[A]<>'*') Do
Begin
Writeln(Localizaciones[NumeroLoc].Desc[A]);
Inc(A);
End;
Writeln;
End;
Quizá te preguntes porque no hacemos simplemente
un bucle for para escribir la descripción de 10
líneas. La razón es que la descripción podría
tener menos de 10 líneas, y que de ser así, la última
línea tendrá un único carácter (un '*').
Ooopsss
Casi me olvido de describir las salidas
Para hacerlo, añade las siguientes líneas:
Writeln('Salidas visibles:');
If Rooms[NumeroLoc].Norte<>0 Then Write('Norte');
If Rooms[NumeroLoc].Sur<>0 Then Write('Sur');
If Rooms[NumeroLoc].Este<>0 Then Write('Este');
If Rooms[NumeroLoc].Oeste<>0 Then Write('Oeste');
Writeln;
Si quieres añadirle un poco de colorido, usa otro color diferente.
Prueba a añadir lo siguiente antes de describir la localidad:
TextColor(White);
Y antes de dar las salidas:
TextColor(Yellow);
Y quedará mucho mejor
:)
Si queremos usarlo, tendrás que implementar
la procedure 'Jugar', que constituirá el cuerpo principal
del juego
De momento, 'Jugar' se limitará a describir
la localidad
Procedure Jugar;
Var Fin:Boolean;
Begin
Fin:=False;
Mirar(LocalidadActual);
Repeat
Until Fin;
End;
El booleano Fin controla el final del juego
cuando se ponga a cierto (true), la partida se dará por terminada.
Ésto deberá ocurrir cuando por ejemplo el jugador desee
abandonar o finalice con éxito la aventura
Así pues, tendrás que añadir
al programa principal una llamada a esta rutina, y también
definir e inicializar la variable LocalidadActual
En LocalidadActual guardaremos la posición actual
del jugador en el juego, yo la declaro de tipo Word
Y la
inicializo al valor 22, porque esta es precisamente la localidad
de comienzo en Fanglore
Házlo en la rutina Init.
La Entrada de comandos y el parser
Ha llegado la hora de recibir las ordenes del usuario
Es aquí donde muchos juegos fallan
Y por qué?
Pues porque su parser la caga.
¿Qué se entiende por parser? Pues no
es más que una rutina (más bien un montón
de ellas) que cogen la entrada del usuario, la procesan (separando
comandos y nombres) y ejecuta las instrucciones que correspondan
Bien, creo que esto es algo complicado para el principiante, así que
intentaré explicarlo bien.
Antes de nada tienes que recoger la entrada (o input)
del usuario
Lo haremos llamando a Readln (la mayoría
de las aventuras tienes sus propias rutinas para leer la entrada
del jugador, pero es algo un tanto complejo como para explicarlo
aquí).
ReadLn(Comando);
Pónlo en el la rutina Play, a continuación
de la llamada a Mirar. Define además la variable Comando
como un string
En el programa Fanglore.Pas le añado color:
TextColor(LightRed);
Y también le he puesto un mensaje (el prompt),
para que el que juegue sepa que el juego está a la espera
de comandos:
TextColor(White);
Writeln('¿Cuál es la oferta, maestro?');
El siguiente paso es el dividir el string en sus
componentes. Dado un string como 'Coger la máscara', obtendríamos
solamente las palabras 'coger' y 'máscara'
El artículo
'la', al igual que todos los artículos que pudieran haber, desaparecería.
Hágamos una rutina que dado un string, nos
devuelva un array con las palabras separadas:
Procedure Parse(S:String;Var Parsed:Array[1..10] Of String);
Usamos una rutina con un parámetro Var en
vez de una función, porque una función no puede
devolver un array
Y de hecho tampoco sería posible hacer lo
de más arriba, sino que deberás definir un tipo:
Type ParsedTipo:Array[1..10] Of String;
De esta manera podrás definir la rutina así:
Procedure Parse(S:String;Var Parsed:ParsedType);
Ahora, lo primero que tenemos que hacer es dividir
la entrada en sus componentes
Lo haremos buscando el primer
espacio, y cogiendo todo lo que estuviera desde el comienzo hasta
el espacio, y guardándolo en el array, y así sucesivamente
La rutina sería algo como:
Procedure Parse(S:String;Var Parsed:TipoParsed);
Var IndiceArray:Byte;
IndiceString:Byte;
SiguienteEspacio:Byte;
Begin
IndiceArray:=1;
IndiceString:=0;
SiguienteEspacio:=EncuentraEspacio(S,IndiceString);
While (IndiceString<=Length(S)) And (IndiceArray<11) Do
Begin
NextSpace:=EncuentraEspacio(S,IndiceString);
Parsed[IndiceArray]:=ObtieneString(S,IndiceString,SiguienteEspacio);
IndiceString:=SiguienteEspacio;
Inc(IndiceArray);
End;
End;
Esto parseará el string
Usa dos funciones,
EncuentraEspacio y ObtieneString, cuyo código viene a continuación
La primera función se encarga de buscar el siguiente espacio dada una
posición de comienzo, mientras que la segunda copia una
parte del string.
Function EncuentraEspacio(S:String;Inicio:Byte):Byte;
Begin
While (S[Inicio+1]<>' ') And (Inicio<Length(S)) Do Inc(Inicio);
EncuentraEspacio:=Inicio;
End;
Function ObtieneString(S:String;Inicio,Final:Byte):String;
Var A:Byte;
Tmp:String;
Begin
Tmp:='';
For A:=Inicio+1 To Final Do Tmp:=Tmp+S[A];
ObtieneString:=Tmp;
End;
No te olvides de llamar a la rutina Parse después de leer el comando:
Parse(Comando,Parsed);
Y acuérdate de declarar también el array Parsed:
Var Parsed:TipoParsed;
Ahora lo que tenemos es un array con la entrada parseada
Lo que hay que hacer es pasarlo todo a mayúsculas
¿Por qué? Pues bien, porque lo que no querrás es
que el programa te mande a paseo si alguien escribe 'coger' o 'Coger'
en lugar de 'COGER'. Ten en cuenta que para el ordenador
resultan muy diferentes las mayúsculas de las minúsculas
Usaremos la rutina PasarAMayusculas para tal fin:
Function PasarAMayusculas(S:String):String;
Var Tmp:String;
A:Byte;
Begin
Tmp:='';
For A:=1 To Length(S) Do Tmp:=Tmp+UpCase(S[A]);
Upper:=Tmp;
End;
La función Upcase es una función
estándar de Pascal que convierte una minúscula
en mayúscula, sin afectar a los simbolos especiales, ni
tampoco a las mayúsculas
Llama a la rutina PasarAMayusculas
por cada elemento del array Parsed, después de parsear
la entrada.
Próxima Entrega:
En nuestro próximo capítulo continuaremos con el desarrollo
del parser, y abordaremos el movimiento del jugador.
Nota del traductor: En los primeros números
de 'The Mag' se realizó un cursillo de Pascal la mar de
majo. Como comprenderéis no es cuestión de que lo
reproduzcamos aquí, después de todo esto es una
revista sobre aventuras, y no de programación. A los que
no conozcáis Pascal y sepáis inglés os remito
directamente a 'The Mag'.
A los demás buscaos un buen tutorial en castellano, que
seguro que los habrá perdidos en algún rincón
de la red o miraros alguno de esos CD-ROMS que regalan las revistas,
que puede que venga algun tutorial o cursillo interactivo de Pascal.
Si el Pascal no os va, o simplemente conocéis algún
otro lenguaje (BASIC, no gracias) no os será nada complicado
el pasarlo.
ÚLTIMA REVISIÓN EN FEBRERO DE 1999
DESARROLLO DE VIDEOJUEGOS
|
|