1 {** Es la nave que será controlada por el jugador.<br>
\r
4 05/10/00: Se corrigió el método mAcelerar porque tenía algunos bugs cuando la velocidad llegaba a cero.
\r
5 01/12/00: Se implementan los disparon sobreescribiendo el método mDisparar de cNave y agregando algunos
\r
6 atributos (aArmaSelect, aDisparando y aLockeado) y algunos métodos (mIntentarDisparo,
\r
7 mSeleccionarArma, mSeleccionarArmaSig, mGetArmaSelect, mSetLockeado, mGetLockeado).
\r
8 Se cambiaron las dimensiones de la nave para que los disparos sean mas "jugables".
\r
9 Se cambia el orden de los argumentos de mDisparar para aprovechar los argumentos por defecto.
\r
10 Se arreglaron un par de BUGs con punteros que apuntaba a objetos destruidos (aLockeado).
\r
11 08/12/00: Se arregló una falla en el constructor que permitia crear la nave con una velocidad superior
\r
13 09/12/00: Se cambia el atributo disparando por un puntero a un arma que se disparara en el proximo turno.
\r
14 También se cambia los métodos que lo utilizan y en particular se convierte el método
\r
15 mIntentarDisparo en una función que devuelve dicho puntero para implementar la cámara en el arma.
\r
33 {** Es la nave que será controlada por el jugador.
\r
34 <u>Características:</u>
\r
36 Dimensión: 15 metros
\r
37 Potencia: 5 Cantidad de daño que hace por intervalo de tiempo
\r
38 Energía: 100 Cantidad de daño que soporta antes de ser destruída
\r
39 Velocidad máxima: 0,17 metros/milisegundos (612 km/h)
\r
41 Misiles Dirigidos: 5
\r
43 cNavePropia = class( cNave )
\r
45 aLockeado: cObjetoVolador; // Objeto Volador Lockeado
\r
46 aArmaSelec: tArma; // Arma seleccionada por el usuario
\r
47 aDisparando: cArma; // Indica si en este momento se esta disparando o no
\r
48 aLockFiltro: cFiltroLock; // Filtro para saber que objetos voladores se puede lockear
\r
50 {** Crea una nave controlada por un jugador}
\r
51 constructor create( pos: cVector = nil; vel: cVector = nil ); overload;
\r
52 {** Hace que se dispare un arma (todavía no está implementado)}
\r
53 function mDisparar( dT: tTiempo; ov : cObjetoVolador = nil ): cArma; override;
\r
54 {** Obtiene el objetivo lockeado}
\r
55 function mGetLockeado: cObjetoVolador;
\r
56 {** Setea el objetivo lockeado}
\r
57 procedure mSetLockeado( ov: cObjetoVolador );
\r
58 {** Cambia el objetivo lockeado}
\r
59 procedure mCambiarLockeado( lEnemigos: TList );
\r
60 {** Permite a la nave rotar a la izquierda sobre su eje X}
\r
61 procedure mRotarIzquierda( angulo: tAngulo );
\r
62 {** Permite a la nave rotar a la derecha sobre su eje X}
\r
63 procedure mRotarDerecha( angulo: tAngulo );
\r
64 {** Permite a la nave girar hacia la izquierda (sobre su eje Z)}
\r
65 procedure mGirarIzquierda( angulo: tAngulo );
\r
66 {** Permite a la nave girar hacia la derecha (sobre su eje Z)}
\r
67 procedure mGirarDerecha( angulo: tAngulo );
\r
68 {** Permite a la nave girar hacia arriba (sobre su eje Y)}
\r
69 procedure mGirarArriba( angulo: tAngulo );
\r
70 {** Permite a la nave girar hacia abajo (sobre su eje Y)}
\r
71 procedure mGirarAbajo( angulo: tAngulo );
\r
72 {** Aumenta el modulo de la velocidad (sin cambiar su dirección ni
\r
73 sentido y sin sobrepasar la velocidad maxima)}
\r
74 procedure mAcelerar( modulo: tLongitud );
\r
75 {** Disminuye el modulo de la velocidad (sin cambiar su dirección ni sentido)}
\r
76 procedure mDesacelerar( modulo: tLongitud );
\r
77 {** Intenta disparar. Si las condiciones son las correctas, el proximo turno
\r
78 saldrá el disparo, si no, no hace nada}
\r
79 function mIntentarDisparo: cArma;
\r
80 {** Selecciona un arma determinada. Si tiene municiones, la selecciona, si no,
\r
82 procedure mSeleccionarArma( a: tArma );
\r
83 {** Selecciona el proximo arma con municiones}
\r
84 procedure mSeleccionarArmaSig;
\r
85 {** Obtiene el arma seleccionada actualmente}
\r
86 function mGetArmaSelec: tArma;
\r
87 {** Obtiene un puntero a la último arma disparada}
\r
88 function mGetUltimoArmaDisparado: cArma;
\r
89 {** Método heredado, se sobreescribe porque se dibuja de forma distinta}
\r
90 function mDibujar: tObjetosVoladores; override;
\r
92 {** Devuelve una cadena de texto con el objeto serializado.}
\r
93 function mSerializar: string; override;
\r
94 {** Recrea el objeto a partir de una cadena de texto con el objeto
\r
96 procedure mDesSerializar( str: string ); override;
\r
104 SerializacionUtils,
\r
109 {** @param pos Posición Inicial
\r
110 @param vel Velocidad Inicial}
\r
111 constructor cNavePropia.create(pos: cVector; vel: cVector);
\r
113 if vel <> nil then // Si no es nula la velocidad ...
\r
114 vel.mSetModulo( 0.17 ); // Setea la velocidad como la máxima
\r
115 // La dimensión es 15 m de radio, la potencia 5, la energía 100, tiene 10 misiles comunes,
\r
116 // 5 dirigidos y su velocidad maxima es 0,17 m/mseg (612 km/h)
\r
117 // El retardo del laser es de .5 segundos.
\r
118 inherited create( pos, vel, 15 {dim}, 5 {pot}, 100 {ene}, 10 {mis}, 5 {misdir},
\r
119 0.17 {velmax}, 50 {retlas}, 1000 {retmis}, 2500 {retmisdir} );
\r
120 aArmaSelec := OV_LASER;
\r
121 aDisparando := nil;
\r
123 aLockFiltro := cFiltroLock.create( self {observador}, 0.8 {angulo}, 2000 {maximo} );
\r
126 {** Hace que aumente el modulo de la velocidad
\r
127 @param modulo Modulo de la velocidad a sumar}
\r
128 procedure cNavePropia.mAcelerar(modulo: tLongitud);
\r
130 modulo := mGetVelModulo + modulo;
\r
131 if modulo <= mGetVelMax then
\r
132 mSetVelModulo( modulo );
\r
135 {** Hace que disminuya el modulo de la velocidad
\r
136 @param modulo Modulo de la velocidad a restar}
\r
137 procedure cNavePropia.mDesacelerar(modulo: tLongitud);
\r
139 modulo := mGetVelModulo - modulo;
\r
140 mSetVelModulo( modulo );
\r
143 {** Método heredado, se sobreescribe porque se dibuja de forma distinta}
\r
144 function cNavePropia.mDibujar: tObjetosVoladores;
\r
146 result := OV_NAVEPROPIA;
\r
149 {** Hace que se dispare un arma
\r
150 @param ov Objetivo del disparo
\r
151 @param dT Intervalo de tiempo
\r
152 @return Arma disparada (o <i>nil</i> si no se puede disparar ningún arma)}
\r
153 function cNavePropia.mDisparar( dT: tTiempo; ov : cObjetoVolador ): cArma;
\r
156 mActualizarRetardadores( dT );
\r
157 if aDisparando <> nil then begin // Si esta disparando ...
\r
158 result := aDisparando; // Se devuleve el arma disparada
\r
159 aDisparando := nil; // Deja de disparar
\r
163 {** Permite a la nave girar hacia abajo (sobre su eje Y)
\r
164 @param angulo Ángulo a girar}
\r
165 procedure cNavePropia.mGirarAbajo(angulo: tAngulo);
\r
167 mRotarEnJ( - angulo ); // Rota el sistema de coordenadas
\r
170 {** Permite a la nave girar hacia arriba (sobre su eje Y)
\r
171 @param angulo Ángulo a girar}
\r
172 procedure cNavePropia.mGirarArriba(angulo: tAngulo);
\r
174 mRotarEnJ( angulo ); // Rota el sistema de coordenadas
\r
177 {** Permite a la nave girar hacia la derecha (sobre su eje Z)
\r
178 @param angulo Ángulo a girar}
\r
179 procedure cNavePropia.mGirarDerecha(angulo: tAngulo);
\r
181 mRotarEnK( - angulo ); // Rota el sistema de coordenadas
\r
184 {** Permite a la nave girar hacia la izquierda (sobre su eje Z)
\r
185 @param angulo Ángulo a girar}
\r
186 procedure cNavePropia.mGirarIzquierda(angulo: tAngulo);
\r
188 mRotarEnK( angulo ); // Rota el sistema de coordenadas
\r
191 {** Permite a la nave rotar hacia la derecha (sobre su eje I)
\r
192 @param angulo Ángulo a rotar}
\r
193 procedure cNavePropia.mRotarDerecha(angulo: tAngulo);
\r
195 mRotarEnI( angulo ); // Rota el sistema de coordenadas
\r
198 {** Permite a la nave rotar hacia la izquierda (sobre su eje I)
\r
199 @param angulo Ángulo a rotar}
\r
200 procedure cNavePropia.mRotarIzquierda(angulo: tAngulo);
\r
202 mRotarEnI( - angulo ); // Rota el sistema de coordenadas
\r
205 {** Intenta disparar. Si las condiciones son las correctas, el proximo turno
\r
206 saldrá el disparo, si no, no hace nada
\r
207 @return Arma proximamente disparada}
\r
208 function cNavePropia.mIntentarDisparo: cArma;
\r
214 if aDisparando = nil then // Si no esta disparando se fija si puede hacerlo
\r
216 OV_LASER: if mPuedeDispararLaser( nil ) then begin // si puede disparar...
\r
217 aDisparando := mCrearLaserDisparado;
\r
218 result := aDisparando;
\r
220 OV_MISIL: if mPuedeDispararMisil( nil ) then begin // si puede disparar...
\r
221 aDisparando := mCrearMisilDisparado;
\r
222 result := aDisparando;
\r
225 try // Prueba si aLockeado no fue destruido...
\r
226 ok := mPuedeDispararMisDir( aLockeado );
\r
228 on e: EAccessViolation do begin // Si el objetivo lockeado esta destruido...
\r
229 aLockeado := nil; // Lo setea a nil
\r
230 ok := mPuedeDispararMisDir( aLockeado ); // Se fija de nuevo si puede disparar
\r
233 if ok then begin // Si puede disparar ...
\r
234 aDisparando := mCrearMisDirDisparado( aLockeado ); // Utiliza como objetivo a aLockeado
\r
235 if aLockeado = nil then begin // Si no hay ninguno lockeado se setea la direccion
\r
236 vel := mGetI; // de la velocidad igual que la de la nave propia.
\r
237 aDisparando.mSetVelDir( vel );
\r
240 result := aDisparando;
\r
246 {** Selecciona un arma determinada. Si tiene municiones, la selecciona, si no,
\r
248 procedure cNavePropia.mSeleccionarArma(a: tArma);
\r
254 if mTieneMisil then
\r
257 if mTieneMisilDirigido then
\r
262 {** Selecciona el proximo arma con municiones}
\r
263 procedure cNavePropia.mSeleccionarArmaSig;
\r
267 if mTieneMisil then
\r
268 aArmaSelec := OV_MISIL
\r
269 else if mTieneMisilDirigido then
\r
270 aArmaSelec := OV_MISDIR;
\r
272 if mTieneMisilDirigido then
\r
273 aArmaSelec := OV_MISDIR
\r
275 aArmaSelec := OV_LASER;
\r
277 aArmaSelec := OV_LASER;
\r
281 {** Obtiene el arma seleccionada actualmente
\r
282 @return Arma seleccionada}
\r
283 function cNavePropia.mGetArmaSelec: tArma;
\r
285 result := aArmaSelec;
\r
288 {** Obtiene el objetivo lockeado
\r
289 @return Objeto volador lockeado}
\r
290 function cNavePropia.mGetLockeado: cObjetoVolador;
\r
292 result := aLockeado;
\r
293 if aLockeado <> nil then // Si no es nil...
\r
294 try // Primero se fija que no esté destruido
\r
297 on e: EAccessViolation do begin // Si lo está...
\r
298 aLockeado := nil; // Lo setea a nil
\r
299 result := aLockeado;
\r
304 {** Setea el objetivo lockeado
\r
305 @param ov Objeto volador lockeado}
\r
306 procedure cNavePropia.mSetLockeado(ov: cObjetoVolador);
\r
311 {** Cambia el objetivo lockeado}
\r
312 procedure cNavePropia.mCambiarLockeado(lEnemigos: TList);
\r
317 lFiltrados := aLockFiltro.mFiltrar( lEnemigos );
\r
318 if lFiltrados.Count = 0 then
\r
321 if aLockeado = nil then
\r
322 aLockeado := lFiltrados.First // Asigna el primero
\r
324 i := lFiltrados.IndexOf( aLockeado );
\r
325 if i < 0 then // No esta en la lista
\r
326 aLockeado := lFiltrados.First // Asigna el primero
\r
328 if i = (lFiltrados.Count - 1) then // Es el ultimo objeto de la lista
\r
329 aLockeado := lFiltrados.First // Asigna el primero
\r
331 aLockeado := lFiltrados.Items[i+1]; // Asigna el proximo
\r
336 {** Recrea el objeto a partir de una cadena de texto con el objeto
\r
338 @param str Cadena de texto con el objeto serializado.}
\r
339 procedure cNavePropia.mDesSerializar(str: string);
\r
343 inherited mDesSerializar( str ); // SIEMPRE el ID debe ser el PRIMER atributo
\r
344 r := TRegExpr.create;
\r
346 try // se fija si hay errores al extraer los datos
\r
347 r.Expression := '<lockeado\s+class=([\w\d]+)\s*>\s*(.+)\s*</lockeado>'; // contruye la expresion regular a buscar
\r
348 if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...
\r
349 if r.Match[1] <> '0' then // Si tiene una clase determinada...
\r
350 if aLockeado <> nil then // Si no es nulo
\r
351 // Puede caer en una EAccessViolation si esta destruido
\r
352 aLockeado.mDesSerializar( r.Match[2] ) // Lo deserializa
\r
354 aLockeado := restaurarObjeto( r.Match[1], r.Match[2] ) // lo crea segun su clase
\r
355 else // Si no tiene una clase determinada, entonces se lo pone en nil
\r
357 else // si no encontro la experesion...
\r
358 raise ESerializacion.create( 'No se encontro el objetivo lockeado' ); // cae en una excepcion
\r
359 except // Si hubieron errores ...
\r
360 on e: ESerializacion do begin // Si fueron de serializacion...
\r
361 r.Free; // libera memoria
\r
362 raise ESerializacion.create( ClassName + ': Error al deserializar el objetivo lockeado: ' + e.Message ); // cae en una excepcion
\r
364 on e: ERegExpr do begin // si fueron de expresiones regulares...
\r
365 r.Free; // libera memoria
\r
366 raise ESerializacion.create( ClassName + ': Error al extraer el objetivo lockeado utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion
\r
368 on e: EAccessViolation do begin // si el Objetivo fue destruido...
\r
369 aLockeado := restaurarObjeto( r.Match[1], r.Match[2] ) // lo crea segun su clase
\r
373 try // se fija si hay errores al extraer los datos
\r
374 r.Expression := '<armaselec>\s*(\d+)\s*</armaselec>'; // contruye la expresion regular a buscar
\r
375 if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...
\r
376 aArmaSelec := tArma( StrToInt( r.Match[1] ) )
\r
377 else // si no encontro la experesion...
\r
378 raise ESerializacion.create( 'No se encontro el arma seleccionada' ); // cae en una excepcion
\r
379 except // Si hubieron errores ...
\r
380 on e: ERegExpr do begin // si fueron de expresiones regulares...
\r
381 r.Free; // libera memoria
\r
382 raise ESerializacion.create( ClassName + ': Error al extraer el arma seleccionada utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion
\r
386 try // se fija si hay errores al extraer los datos
\r
387 r.Expression := '<lockfiltro>\s*(.+)\s*</lockfiltro>'; // contruye la expresion regular a buscar
\r
388 if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...
\r
389 if aLockFiltro <> nil then // Si no es nulo
\r
390 aLockFiltro.mDesSerializar( r.Match[1] ) // Lo deserializa
\r
392 aLockFiltro := cFiltroLock.crearDeSerializado( r.Match[1] ) // lo crea
\r
393 else // si no encontro la experesion...
\r
394 raise ESerializacion.create( ClassName + ': No se pudieron extraer el filtro de lockeo' ); // cae en una excepcion
\r
395 except // Si hubieron errores ...
\r
396 on e: ESerializacion do begin // Si fueron de serializacion...
\r
397 r.Free; // libera memoria
\r
398 raise ESerializacion.create( ClassName + ': Error al deserializar el filtro de lockeo: ' + e.Message ); // cae en una excepcion
\r
400 on e: ERegExpr do begin // si fueron de expresiones regulares...
\r
401 r.Free; // libera memoria
\r
402 raise ESerializacion.create( ClassName + ': Error al extraer el filtro de lockeo utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion
\r
405 // El observador del filtro va a ser siempre la nave propia, es por esto
\r
406 // que debemos eliminar la copia del observador que se creo y asignarle self
\r
407 aLockFiltro.mGetObservador.free;
\r
408 aLockFiltro.mSetObservador( self );
\r
412 {** Devuelve una cadena de texto con el objeto serializado.
\r
413 @return Cadena de texto con el objeto serializado.}
\r
414 function cNavePropia.mSerializar: string;
\r
418 meteorito: cMeteorito;
\r
420 // Si el objetivo es nil o está destruido, se setea el atributo class del
\r
421 // TAG objetivo como '0' y entre el TAG se indica que es nil. Si no se
\r
422 // setea como el nombre de la clase y su expresion serializada respectivamente
\r
425 if aLockeado <> nil then
\r
427 lockeado := aLockeado.mSerializar;
\r
428 clase := aLockeado.ClassName;
\r
429 except // Si esta destruido cambia la cadena de texto
\r
430 on e: EAccessViolation do begin
\r
435 // Hoy que modificar el observador del filtro porque de otra forma esta funcion
\r
436 // se volveria infinitamente recursiva, ya que cuando quiere serializar el
\r
437 // filtro, necesita serializar el observador quien necesita serializar el
\r
438 // filtro y asi ad infinitum.
\r
439 meteorito := cMeteorito.create;
\r
440 aLockFiltro.mSetObservador( meteorito );
\r
441 result := inherited mSerializar +
\r
442 '<lockeado class=' + clase + '>' + lockeado + '</lockeado>' +
\r
443 '<armaselec>' + IntToStr( ord( aArmaSelec ) ) + '</armaselec>' +
\r
444 '<lockfiltro>' + aLockFiltro.mSerializar + '</lockfiltro>';
\r
445 // Se vuelve a establecer como observador a la nave propia.
\r
446 aLockFiltro.mSetObservador( self );
\r
450 {** Obtiene un puntero a la último arma disparada
\r
451 @return Último arma disparado}
\r
452 function cNavePropia.mGetUltimoArmaDisparado: cArma;
\r
454 result := aDisparando;
\r
455 if aDisparando <> nil then // Si no es nil...
\r
456 try // Primero se fija que no esté destruido
\r
457 aDisparando.mGetID;
\r
459 on e: EAccessViolation do begin // Si lo está...
\r
460 aDisparando := nil; // Lo setea a nil
\r
461 result := aDisparando;
\r