1 {** Clase abstracta, implementa todas las funcionalidades básicas de los objetos voladores.
\r
2 De esta van a derivar la mayor parte del resto de las clases.<br>
\r
5 05/10/00: Se agregaron los métodos mGetDistancia y mColisiono. De esta manera se deja
\r
6 a los objetos voladores manejar las colisiones mas intuitivamente.
\r
7 30/10/00: Se agregó un atributo <b>aCoordenadas</b> para que se pueda orientar al objeto volador.
\r
8 02/11/00: Se agregaron métodos para cambiar solamente el modulo de la velocidad, para cambiar solo
\r
9 la direccion de la velocidad y para extraer directamente copias de los versores i, j, k y
\r
10 para rotar el objeto volador en todas direcciones.
\r
11 Los nuevos métodos son: mSetVelModulo, mSetVelDir, mGetVelModulo,
\r
12 mGetI, mGetJ, mGetK, mRotarEnI,
\r
13 mRotarEnJ, mRotarEnK
\r
14 07/11/00: Se agrega un nuevo método (mSetPosicion) y se hace a público otro (mSetVelocidad) para
\r
15 que se pueda cambiar la configuración (es temporal, se planea cambiar el sistema de
\r
16 configuración del juego para que esto no sea necesario)
\r
17 29/11/00: Se arregla un BUG en mSetVelModulo que no modificaba el modulo si la velocidad pasada
\r
18 como argumento era menor que cero. En este caso el modulo de la velocidad se setea en 0.
\r
19 02/12/00: Se cambio el dato que devuelve el método mDibujar. Ahora devuelve un tipo de dato enumerado
\r
20 tObjetosVoladores. Todas sus subclases fueron actualizadas también.
\r
21 08/12/00: Se agregan menúes para manejar la nueva vistas con varias camaras. Se agrega la opcion de
\r
22 alta calidad en el menú vista. Se carga un escenario por defecto (si existe) al iniciar el
\r
23 juego, el nombre de dicho escenario debe ser 'comun.eaw'.
\r
24 Se agrega una nueva tecla para cambiar de cámara ('C'), además de las que se provee con las
\r
38 {** Clase abstracta, implementa todas las funcionalidades básicas de los objetos voladores.
\r
39 De esta van a derivar la mayor parte del resto de las clases.}
\r
40 cObjetoVolador = class( cObjetoPersistente )
\r
42 aPosicion: cVector; // Posicion del objeto volador en el espacio
\r
43 aVelocidad: tLongitud; // Velocidad del objeto volador (en modulo)
\r
44 aPotencia: tEnergia; // Potencia del objeto volador (la cantidad de daño que hace por impacto)
\r
45 aEnergia: tEnergia; // Energía del objeto volador (la cantidad de daño que soporta antes de ser destruido)
\r
46 aDimension: tLongitud; // La dimesión del objeto volador (es el radio de una esfera)
\r
47 // Agregado 30/10/00
\r
48 aCoordenadas: cCoordenadas; // Sistema de coordenadas del objeto volador (para tener nocion de la orientación)
\r
49 // El versor i es la direccion de la velocidad
\r
51 {** Método para establecer la energía}
\r
52 function mSetEnergia( ene: tEnergia ): cObjetoVolador;
\r
53 {** Rota el objeto volador sobre el eje i
\r
54 (el sentido positivo es de j a k)}
\r
55 function mRotarEnI( dAngulo: tAngulo ): cObjetoVolador;
\r
56 {** Rota el objeto volador sobre el eje j
\r
57 (el sentido positivo es de i a k)}
\r
58 function mRotarEnJ( dAngulo: tAngulo ): cObjetoVolador;
\r
59 {** Rota el objeto volador sobre el eje k
\r
60 (el sentido positivo es de i a j)}
\r
61 function mRotarEnK( dAngulo: tAngulo ): cObjetoVolador;
\r
64 constructor create( pos: cVector = nil; vel: cVector = nil; dim: tLongitud = 5; pot: tEnergia = 1; ene: tEnergia = 100 ); overload;
\r
65 {** Constructor que copia los atributos de un Objeto volador existente}
\r
66 constructor create( ov: cObjetoVolador ); overload;
\r
67 {$IFDEF DebugAlgoWars}
\r
68 {** Método heredado que devuelve un string con el estado del Objeto. Se utiliza para depurar
\r
69 y la información entregada depende del parámetro tDebugInfo.}
\r
70 function mGetDebugInfo( debugLevel: tDebugInfo = DI_MINI ): string; override;
\r
72 {** Mueve el objeto volador basandose en su posicion, su velocidad y un intervalo de tiempo}
\r
73 procedure mMover( dT: tTiempo ); virtual;
\r
74 {** Calcula la distancia a otro objeto volador}
\r
75 function mGetDistancia( ov: cObjetoVolador ): tLongitud;
\r
76 {** Devuelve true si colisionaron los objetos voladores}
\r
77 function mColisiono( ov: cObjetoVolador ): boolean;
\r
78 {** Obtiene la velocidad del objeto volador}
\r
79 function mGetVelocidad: cVector;
\r
80 {** Obtiene el modulo de la velocidad del objeto volador}
\r
81 function mGetVelModulo: tLongitud;
\r
82 {** Obtiene la Posicion del objeto volador}
\r
83 function mGetPosicion: cVector;
\r
84 {** Obtiene la Potencia del objeto volador}
\r
85 function mGetPotencia: tEnergia;
\r
86 {** Obtiene la Energia del objeto volador}
\r
87 function mGetEnergia: tEnergia;
\r
88 {** Obtiene la Dimension del objeto volador}
\r
89 function mGetDimension: tLongitud;
\r
90 {** Obtiene el sistema de coordenadas de la nave}
\r
91 function mGetCoordenadas: cCoordenadas;
\r
92 {** Obtiene el versor i del sistema de coordenadas de la nave}
\r
93 function mGetI: cVector;
\r
94 {** Obtiene el versor j del sistema de coordenadas de la nave}
\r
95 function mGetJ: cVector;
\r
96 {** Obtiene el versor k del sistema de coordenadas de la nave}
\r
97 function mGetK: cVector;
\r
98 {** Método para establecer la posición}
\r
99 function mSetPosicion( posicion: cVector ): cObjetoVolador;
\r
100 {** Método para establecer la velocidad}
\r
101 function mSetVelocidad( velocidad: cVector ): cObjetoVolador; virtual;
\r
102 {** Método para establecer el modulo de la velocidad}
\r
103 function mSetVelModulo( velocidad: tLongitud ): cObjetoVolador; virtual;
\r
104 {** Método para establecer la direccion de la velocidad}
\r
105 function mSetVelDir( velocidad: cVector ): cObjetoVolador;
\r
106 {** Resta energia al objeto volador}
\r
107 function mRestarEnergia( ene: tEnergia ): cObjetoVolador;
\r
108 {** Método abstracto, se sobreescribira en las subclases porque van a ser
\r
109 dibujadas de forma diferente}
\r
110 function mDibujar: tObjetosVoladores; virtual; abstract;
\r
112 destructor destroy; override;
\r
114 {** Devuelve una cadena de texto con el objeto serializado.}
\r
115 function mSerializar: string; override;
\r
116 {** Recrea el objeto a partir de una cadena de texto con el objeto
\r
118 procedure mDesSerializar( str: string ); override;
\r
130 @param ov Objeto volador del cual extraer los datos para inicializar en actual}
\r
131 constructor cObjetoVolador.create( ov: cObjetoVolador );
\r
135 // Crea el objeto basandose en los atributos del parametro
\r
137 aPosicion := ov.mGetPosicion;
\r
138 vel := ov.mGetVelocidad;
\r
139 aVelocidad := vel.mGetModulo;
\r
141 aDimension := ov.mGetDimension;
\r
142 aPotencia := ov.mGetPotencia;
\r
143 aEnergia := ov.mGetEnergia;
\r
144 aCoordenadas := ov.mGetCoordenadas;
\r
148 @param pos Posicion inicial
\r
149 @param vel Velocidad inicial
\r
150 @param dim Dimensión del objeto volador (radio, en metros)
\r
151 @param pot Potencia del objeto volador (cantidad de daño que hace por intervalode tiempo)
\r
152 @param ene Energía del objeto volador(cantidad de daño que soporta antes de ser destruido)}
\r
153 constructor cObjetoVolador.create(pos: cVector = nil; vel: cVector = nil;
\r
154 dim: tLongitud = 5; pot: tEnergia = 1; ene: tEnergia = 100);
\r
160 aCoordenadas := cCoordenadas.create;
\r
161 // Si la posicion es nula crea una nueva
\r
163 aPosicion := cVector.create( 0, 0, 0 )
\r
165 aPosicion := cVector.create( pos );
\r
166 // Si la velocidad es nula crea una nueva
\r
170 aVelocidad := vel.mGetModulo;
\r
171 aCoordenadas.mSetI( vel );
\r
175 {** Mueve el objeto volador basandose en su posicion, su velocidad y un intervalo de tiempo
\r
176 @param dT Intervalo de tiempo}
\r
177 procedure cObjetoVolador.mMover( dT: tTiempo );
\r
181 v := cVector.create( mGetVelocidad );
\r
182 aPosicion.mModificarCon( v, dT );
\r
186 {** Establece la velocidad del objeto volador
\r
187 @param velocidad Nuevo vector velocidad}
\r
188 function cObjetoVolador.mSetVelocidad( velocidad: cVector ): cObjetoVolador;
\r
190 aVelocidad := velocidad.mGetModulo;
\r
191 // Agregado 30/10/00 para que mantenga las coordenadas
\r
192 aCoordenadas.mSetI( velocidad );
\r
196 {** Obtiene la velocidad del objeto volador
\r
197 @return Vector velocidad}
\r
198 function cObjetoVolador.mGetVelocidad: cVector;
\r
200 result := aCoordenadas.mGetI.mMultiplicar( aVelocidad );
\r
203 {** Obtiene la posición del objeto volador
\r
204 @return Vector posición}
\r
205 function cObjetoVolador.mGetPosicion: cVector;
\r
207 result := cVector.create( aPosicion );
\r
210 {** Obtiene la dimensión del objeto volador
\r
211 @return Dimensión (radio, en metros)}
\r
212 function cObjetoVolador.mGetDimension: tLongitud;
\r
214 result := aDimension;
\r
218 destructor cObjetoVolador.destroy;
\r
220 // Libera los atributo objeto
\r
226 {** Obtiene la potencia del objeto volador
\r
227 @return Potencia (cantidad de daño que realiza por intervalo de tiempo)}
\r
228 function cObjetoVolador.mGetPotencia: tEnergia;
\r
230 result := aPotencia;
\r
233 {** Obtiene la e del objeto volador
\r
234 @return Energía (cantidad de daño que soporta antes de ser destruido)}
\r
235 function cObjetoVolador.mGetEnergia: tEnergia;
\r
237 result := aEnergia;
\r
240 {$IFDEF DebugAlgoWars}
\r
241 {** Devuelve el estado del objeto basandose en la cantidad de datos requeridos.
\r
242 @return Cadena de texto con el estado del Objeto.
\r
243 @param debugLevel Cantidad de información requerida}
\r
244 function cObjetoVolador.mGetDebugInfo( debugLevel: tDebugInfo = DI_MINI ): string;
\r
246 // Construye la cadena dependiendo de la cantidad de informacion que se quiera obtener
\r
247 result := 'Posición: ' + aPosicion.mGetDebugInfo( debugLevel );
\r
248 if debugLevel > DI_MINI then
\r
249 result := result + #13 + #10 +
\r
250 'Energia: ' + FloatToStrF( aEnergia, ffNumber, 5, 5 );
\r
251 if debugLevel > DI_NORMAL then
\r
252 result := result + ' | Potencia: ' + FloatToStrF( aPotencia, ffNumber, 5, 5 ) +
\r
253 ' | Dimension: ' + FloatToStrF( aDimension, ffNumber, 5, 5 ) + #13 + #10 +
\r
254 'Velocidad: ' + mGetVelocidad.mGetDebugInfo( debugLevel ) + #13 + #10 +
\r
255 'Coordenadas: ' + #13 + #10 + aCoordenadas.mGetDebugInfo;
\r
259 {** Resta energía al objeto volador
\r
260 @param ene Energía a restar}
\r
261 function cObjetoVolador.mRestarEnergia(ene: tEnergia): cObjetoVolador;
\r
263 aEnergia := aEnergia - ene;
\r
267 {** Setea la energía del objeto volador a un valor arbitrario
\r
268 @param ene Nueva energía}
\r
269 function cObjetoVolador.mSetEnergia(ene: tEnergia): cObjetoVolador;
\r
275 {** Calcula la distancia a otro objeto volador
\r
276 @return Distancia al otro objeto volador
\r
277 @param ov Objeto volador al que se calcula la distancia}
\r
278 function cObjetoVolador.mGetDistancia(ov: cObjetoVolador): tLongitud;
\r
280 v: cVector; // Vector temporal
\r
282 v := ov.mGetPosicion; // obtiene la posicion de ov
\r
283 result := v.mGetDistancia( aPosicion ); // obtiene la distancia
\r
284 v.free; // Libera al vector temporal
\r
287 {** Devuelve true si colisionaron los objetos voladores
\r
288 @return <i>true<i> si colisionaron, <i>false</i> si no lo hicieron
\r
289 @param ov Objeto volador con el que se evalua si colisiono}
\r
290 function cObjetoVolador.mColisiono(ov: cObjetoVolador): boolean;
\r
292 // true si la distancia es menor a la suma de las dimensiones
\r
293 result := ( mGetDistancia( ov ) <= ( aDimension + ov.mGetDimension ) );
\r
296 {** Obtiene el sistema de coordenadas de la nave
\r
297 @return Sistema de coordenadas de la nave}
\r
298 function cObjetoVolador.mGetCoordenadas: cCoordenadas;
\r
300 result := cCoordenadas.create( aCoordenadas );
\r
303 {** Método para establecer el modulo de la velocidad
\r
304 @param velocidad Nuevo módulo de la velocidad}
\r
305 function cObjetoVolador.mSetVelModulo( velocidad: tLongitud ): cObjetoVolador;
\r
307 if velocidad > 0 then
\r
308 aVelocidad := velocidad
\r
314 {** Método para establecer la direccion de la velocidad
\r
315 @param velocidad Nueva dirección de la velocidad}
\r
316 function cObjetoVolador.mSetVelDir( velocidad: cVector ): cObjetoVolador;
\r
318 aCoordenadas.mSetI( velocidad );
\r
322 {** Obtiene el modulo de la velocidad del objeto volador
\r
323 @return Módulo de la velocidad}
\r
324 function cObjetoVolador.mGetVelModulo: tLongitud;
\r
326 result := aVelocidad;
\r
329 {** Obtiene el versor i del sistema de coordenadas de la nave
\r
330 @return Versor i, que representa la direccion en la que viaja el objeto}
\r
331 function cObjetoVolador.mGetI: cVector;
\r
333 result := aCoordenadas.mGetI;
\r
336 {** Obtiene el versor j del sistema de coordenadas de la nave
\r
337 @return Versor j, que representa la direccion en la que está la izquierda del objeto}
\r
338 function cObjetoVolador.mGetJ: cVector;
\r
340 result := aCoordenadas.mGetJ;
\r
343 {** Obtiene el versor k del sistema de coordenadas de la nave
\r
344 @return Versor k, que representa la direccion en la que está el "techo" del objeto}
\r
345 function cObjetoVolador.mGetK: cVector;
\r
347 result := aCoordenadas.mGetK;
\r
350 {** Rota el objeto volador sobre el eje i
\r
351 (el sentido positivo es de j a k)}
\r
352 function cObjetoVolador.mRotarEnI( dAngulo: tAngulo ): cObjetoVolador;
\r
354 aCoordenadas.mRotarEnI( dAngulo );
\r
358 {** Rota el objeto volador sobre el eje j
\r
359 (el sentido positivo es de i a k)}
\r
360 function cObjetoVolador.mRotarEnJ( dAngulo: tAngulo ): cObjetoVolador;
\r
362 aCoordenadas.mRotarEnJ( dAngulo );
\r
366 {** Rota el objeto volador sobre el eje k
\r
367 (el sentido positivo es de i a j)}
\r
368 function cObjetoVolador.mRotarEnK( dAngulo: tAngulo ): cObjetoVolador;
\r
370 aCoordenadas.mRotarEnK( dAngulo );
\r
374 {** Método para establecer la posición
\r
375 @param velocidad Nuevo vector posición}
\r
376 function cObjetoVolador.mSetPosicion(posicion: cVector): cObjetoVolador;
\r
378 aPosicion := cVector.create( posicion );
\r
382 {** Recrea el objeto a partir de una cadena de texto con el objeto
\r
384 @param str Cadena de texto con el objeto serializado.}
\r
385 procedure cObjetoVolador.mDesSerializar(str: string);
\r
389 inherited mDesSerializar( str ); // SIEMPRE el ID debe ser el PRIMER atributo
\r
390 r := TRegExpr.create;
\r
392 try // se fija si hay errores al extraer los datos
\r
393 r.Expression := '<posicion>\s*(.+)\s*</posicion>'; // contruye la expresion regular a buscar
\r
394 if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...
\r
395 if aPosicion <> nil then // Si no es nulo
\r
396 aPosicion.mDesSerializar( r.Match[1] ) // Lo deserializa
\r
398 aPosicion := cVector.crearDeSerializado( r.Match[1] ) // lo crea
\r
399 else // si no encontro la experesion...
\r
400 raise ESerializacion.create( 'No se encontro la posicion' ); // cae en una excepcion
\r
401 except // Si hubieron errores ...
\r
402 on e: ESerializacion do begin // Si fueron de serializacion...
\r
403 r.Free; // libera memoria
\r
404 raise ESerializacion.create( ClassName + ': Error al deserializar la posicion: ' + e.Message ); // cae en una excepcion
\r
406 on e: ERegExpr do begin // si fueron de expresiones regulares...
\r
407 r.Free; // libera memoria
\r
408 raise ESerializacion.create( ClassName + ': Error al extraer la posicion utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion
\r
412 try // se fija si hay errores al extraer los datos
\r
413 r.Expression := '<velocidad>\s*([+\-]?\d+(\,\d+)?([eE][+\-]?\d+)?)\s*</velocidad>'; // contruye la expresion regular a buscar
\r
414 if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...
\r
415 aVelocidad := StrToFloat( r.Match[1] )
\r
416 else // si no encontro la experesion...
\r
417 raise ESerializacion.create( 'No se encontro la velocidad' ); // cae en una excepcion
\r
418 except // Si hubieron errores ...
\r
419 on e: ERegExpr do begin // si fueron de expresiones regulares...
\r
420 r.Free; // libera memoria
\r
421 raise ESerializacion.create( ClassName + ': Error al extraer la velocidad utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion
\r
425 try // se fija si hay errores al extraer los datos
\r
426 r.Expression := '<potencia>\s*([+\-]?\d+)\s*</potencia>'; // contruye la expresion regular a buscar
\r
427 if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...
\r
428 aPotencia := StrToInt( r.Match[1] )
\r
429 else // si no encontro la experesion...
\r
430 raise ESerializacion.create( 'No se encontro la potencia' ); // cae en una excepcion
\r
431 except // Si hubieron errores ...
\r
432 on e: ERegExpr do begin // si fueron de expresiones regulares...
\r
433 r.Free; // libera memoria
\r
434 raise ESerializacion.create( ClassName + ': Error al extraer la potencia utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion
\r
438 try // se fija si hay errores al extraer los datos
\r
439 r.Expression := '<energia>\s*([+\-]?\d+)\s*</energia>'; // contruye la expresion regular a buscar
\r
440 if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...
\r
441 aEnergia := StrToInt( r.Match[1] )
\r
442 else // si no encontro la experesion...
\r
443 raise ESerializacion.create( 'No se encontro la energia' ); // cae en una excepcion
\r
444 except // Si hubieron errores ...
\r
445 on e: ERegExpr do begin // si fueron de expresiones regulares...
\r
446 r.Free; // libera memoria
\r
447 raise ESerializacion.create( ClassName + ': Error al extraer la energia utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion
\r
451 try // se fija si hay errores al extraer los datos
\r
452 r.Expression := '<dimension>\s*([+\-]?\d+(\,\d+)?([eE][+\-]?\d+)?)\s*</dimension>'; // contruye la expresion regular a buscar
\r
453 if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...
\r
454 aDimension := StrToFloat( r.Match[1] )
\r
455 else // si no encontro la experesion...
\r
456 raise ESerializacion.create( 'No se encontro la dimension' ); // cae en una excepcion
\r
457 except // Si hubieron errores ...
\r
458 on e: ERegExpr do begin // si fueron de expresiones regulares...
\r
459 r.Free; // libera memoria
\r
460 raise ESerializacion.create( ClassName + ': Error al extraer la dimension utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion
\r
464 try // se fija si hay errores al extraer los datos
\r
465 r.Expression := '<coordenadas>\s*(.+)\s*</coordenadas>'; // contruye la expresion regular a buscar
\r
466 if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...
\r
467 if aCoordenadas <> nil then // Si no es nulo
\r
468 aCoordenadas.mDesSerializar( r.Match[1] ) // Lo deserializa
\r
470 aCoordenadas := cCoordenadas.crearDeSerializado( r.Match[1] ) // lo crea
\r
471 else // si no encontro la experesion...
\r
472 raise ESerializacion.create( ClassName + ': No se pudieron extraer las coordenadas' ); // cae en una excepcion
\r
473 except // Si hubieron errores ...
\r
474 on e: ESerializacion do begin // Si fueron de serializacion...
\r
475 r.Free; // libera memoria
\r
476 raise ESerializacion.create( ClassName + ': Error al deserializar las coordenadas: ' + e.Message ); // cae en una excepcion
\r
478 on e: ERegExpr do begin // si fueron de expresiones regulares...
\r
479 r.Free; // libera memoria
\r
480 raise ESerializacion.create( ClassName + ': Error al extraer las coordenadas utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion
\r
486 {** Devuelve una cadena de texto con el objeto serializado.
\r
487 @return Cadena de texto con el objeto serializado.}
\r
488 function cObjetoVolador.mSerializar: string;
\r
490 result := inherited mSerializar +
\r
491 '<posicion>' + aPosicion.mSerializar + '</posicion>' +
\r
492 '<velocidad>' + FloatToStrF( aVelocidad, ffGeneral, 18, 0 ) + '</velocidad>' +
\r
493 '<potencia>' + FloatToStrF( aPotencia, ffGeneral, 18, 0 ) + '</potencia>' +
\r
494 '<energia>' + FloatToStrF( aEnergia, ffGeneral, 18, 0 ) + '</energia>' +
\r
495 '<dimension>' + FloatToStrF( aDimension, ffGeneral, 18, 0 ) + '</dimension>' +
\r
496 '<coordenadas>' + aCoordenadas.mSerializar + '</coordenadas>';
\r