Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Gráficos
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 27-02-2007
kakarotv5 kakarotv5 is offline
Miembro
 
Registrado: feb 2007
Posts: 162
Poder: 18
kakarotv5 Va por buen camino
Post Minitutorial de creación de un FPS sencillo

El día 22 de febrero de 2007 me instalé el GLScene, cuatro días después voy a intentar hacer un post sobre creación de un FPS sencillito, no espereis gran cosa, sólo voy a deciros como crear un espacio tridimensional por el que podéis moveros libremente y con un arma dando tiros. No voy a entrar (por lo menos de momento) en matar a otros personajes, ni en aplicar física ni nada, es como ya digo algo muy muy sencillo y primitivo.

Nota: Este manual está pensado para que el que lo lea sepa algo de programación y de Delphi, no es que se pidan muchos conocimientos pero no creo que sea fácil hacer ciertas cosas si nunca se ha visto nada de programación ni de Delphi ya que pueden aparecer errores y no se sepa solucionarlo, de todos modos voy a explicar muchas cosas que a lo mejor a los que sepan sobre el tema les parece un poco innecesario.

Iré actualizando el post hasta que lo tenga terminado, a ver que tal.

Uso Delphi 6 y la versión de GLScene que utilizo es RC 1.0.0.0714, sobre como instalar GLScene en Delphi 6 no voy a entrar pues ya hay información al respecto en estos foros.

Empecemos:

Lo primero es crear nuestro terreno de combate, para ello hay muchas opciones, yo he elegido usar un terreno renderizado (TGLTerrainRenderer) pero podría haber elegido un plano (TGLPlane) o un cubo (TGLCube) y ponerle sus propiedades profundidad a 500, altura a 0 y anchura a 500 para que pareciera un plano.
Más tarde veremos que si queremos aplicar física al juego lo mejor será crear el terreno en formato 3ds con Blender por ejemplo e importarle en Delphi (pero esto para más adelante).

Cualquier opción es válida pero me he decantado por un terreno renderizado porque da más juego ya que tiene montañas y es más vistoso que un plano sin altos ni bajos (más tarde veremos que si nos decantamos por la opción de crear el terreno en formato 3ds con Blender también tendremos altos y bajos, pero como ya digo esto para más adelante).

Lo primero en el formulario añadid un componente GLSceneViewer y le poneis como propiedad Align AlClient para que ocupe todo nuestro formulario.

Después añadid un componente GLScene, dad doble click sobre él y en Scene objects dad botón derecho Add object/Mesh objects/TerrainRenderer.

Ahora para generar un terreno con alturas necesitaremos un mapa de alturas, un mapa de alturas no es más que una imagen bmp en blanco y negro, donde el blanco es la altura máxima y el negro la altura mínima. Con esto haced vuestro propio mapa de alturas a vuestro gusto con el Paint por ejemplo. Recordad que la imagen debe de estar en formato bmp.

Vale, una vez que tenemos hecho nuestro mapa de alturas nos vamos a Delphi y añadimos al formulario el componente GLBitmapHDS (está en la pestaña GLScene Utils). Este componente sirve para cargar nuestro mapa de alturas. Nos vamos a la propiedad picture del componente GLBitmapHDS1 y en ella pinchamos en los puntos suspensivos y desde ahí cargamos el mapa de alturas que hemos creado.

Ahora que ya tenemos el GLBitmapHDS1 con el mapa de alturas cargado nos vamos al TerrainRenderer1 y en la propiedad HeightDataSource seleccionamos el GLBitmapHDS1.

Otro aspecto muy importante del terreno es la escala, esta propiedad se encarga de la escala las de dimensiones (X, Y y Z) que tendrá nuestro terreno, por defecto la propiedad Scale está así: X a 0, Y a 0 y Z a 0, esto quiere decir que no hay escalas, es decir nuestro terreno no se ve por ninguna parte. Hay que darle valores, probad con los valores que querais pero recomiendo que pongais X y Y un mismo valor menor que 10 y Z un valor menor que 0,5, como ya digo esto depende de dos cosas, de vuestro gusto y del mapa de alturas que hayais diseñado. Yo en concreto he puesto X a 3, Y a 3 y Z a 0,2.

En este momento ya tenemos nuestro terreno creado.

Bien, el paso siguiente es añadir una cámara para ver la escena que hemos creado, hacemos doble click en GLScene1 y en Cameras hacemos click con el botón derecho del ratón y damos a Add Camera. Ahora vamos al GLSceneViewer1 y seleccionamos la cámara que hemos creado en la propiedad Camera. En este momento nuestra cámara está en la posición (0,0,0) con lo que no veremos nada, para ello habrá que elevar la cámara cambiando sus propiedades, ponemos Z de Position a 4, para que mire hacia adelante ponemos Y de Direction a 1 y para decirle que es arriba y que es abajo ponemos Z de Up a 1. Resumiendo. Position = (0,0,4), Direction = (0,1,0) y Up = (0,0,1).

Podeis compilar con F9 y ver los resultados, pueden pasar varias cosas, puede que veais todo negro, esto es porque estais detrás de una montaña o puede que veais algo negro y un fondo gris, esto es que veis parte del suelo y parte del cielo.

Para poder distinguir el relieve del suelo lo suyo es aplicar una textura al terreno o iluminarle. Yo prefiero aplicarle una textura ya que es como más personalizado todo, buscad cualquier imagen en formato bmp o jpg (si es jpg hay que poner Jpeg en la cláusula Uses del programa). Para aplicar una textura añadid un componente de tipo GLMaterialLibrary al formulario, dad oble click en él y pulsad Add New (Ins) pinchamos en 0 - LibMaterial y en la propiedad Name le ponemos por ejemplo Suelo, ahora seleccionamos la propiedad Material y pinchamos en los puntos suspensivos, nos saldrá una ventana con Front Back y Texture, bien, nos vamos a Texture y pulsamos en los puntos suspensivos de Image y ahí seleccionamos la imagen que queremos que sea la textura de nuestro suelo, deshabilitamos Disabled y damos a aceptar. Ahora vamos al GLTerrainRenderer1, desplegad su propiedad Material y en MaterialLibrary seleccionar GLMaterialLibrary1 y en LibMaterialName pulsamos en los puntos suspensivos y seleccionamos Suelo (que hemos creado anteriormente). Podeis compilar y ver los efectos que tiene esto, ahora ya podemos distinguir el relieve del suelo pero aún queda mucho por hacer.

La otra forma de apreciar el relieve de nuestro suelo es como ya dije aplicar una luz, si quereis optar por este camino (es menos vistoso pero como vosotros veais) simplemente debeis de dar doble click en GLScene1 y en Scene objects botón derecho Add object/Light Source, haciendo esto añadimos una fuente de luz, nos vamos a sus propiedades, desplegamos Position y ponemos X a 12, Y a 12 y Z a 12 por ejemplo. Podeis compilar y ver los efectos que tiene esto, ahora ya podemos distinguir el relieve del suelo pero aún queda mucho por hacer.

Seguramente esteis deseando poder moveros por vuestro terreno. Para este cometido hay que usar el evento OnKeyDown para que Delphi interprete que se ha pulsado una tecla y actuar en consecuencia, aquí hay un pequeño problema, normalmente en los juegos para avanzar hacia adelante por ejemplo no pulsamos repetidamente la tecla w, simplemente la dejamos pulsada, para solucionar esto hay que usar el componente GLCadencer que cada cierto tiempo lanza un evento con el que Delphi sabrá que teclas hay pulsadas en cada momento y actuará en consecuencia. Bien, manos a la obra: añadid al formulario el componente Cadencer, en su propiedad Scene seleccionamos GLScene1. Ahora ya hemos creado por así decirlo el tiempo. Ahora como queremos total libertad de movimientos añadimos al formulario el componente GLNavigator de la pestaña GLScene Utils, nos vamos a sus propiedades y en MovingObject seleccionamos nuestra cámara, GLCamera1, esto quiere decir que lo que vamos a mover es la cámara con lo que en efecto podremos mover la cámara por todo nuestro terreno, imaginad que en vez de un personaje armado hasta los dientes de Quake 3 teneis una simple cámara que podeis mover por todo el escenario, ya nos meteremos con armas y personajes más tarde (aun no lo tengo claro del todo, he de investigar un poco más).

Ahora en el evento OnProgress de GLCadencer1 (haced doble click en él) escribir lo siguiente:

Código Delphi [-]
var
 velocidad: real;
begin
 velocidad := 50;
 if IsKeyDown(VK_UP) or IsKeyDown('w') then
  GLNavigator1.MoveForward(velocidad*deltaTime);
 if IsKeyDown(VK_DOWN) or IsKeyDown('s') then
  GLNavigator1.MoveForward(-velocidad*deltaTime);
 if IsKeyDown(VK_RIGHT) or IsKeyDown('d') then
  GLNavigator1.StrafeHorizontal(velocidad*deltaTime);
 if IsKeyDown(VK_LEFT) or IsKeyDown('a') then
  GLNavigator1.StrafeHorizontal(-velocidad*deltaTime);
 if IsKeyDown(VK_PRIOR) then
  GLNavigator1.StrafeVertical(velocidad*deltaTime);
 if IsKeyDown(VK_NEXT) then
  GLNavigator1.StrafeVertical(-velocidad*deltaTime);
end;

y añadid KeyBoard a la cláusula Uses del programa. Como veis le decimos a Delphi el espacio que ha de avanzar ya que multiplicamos el valor que hemos definido para velocidad por deltaTime que es el tiempo que ha pasado desde que se disparó el anterior evento OnProgress del Cadencer. Podeis compilar y ver los efectos que tiene esto, ahora ya podemos avanzar por el escenario.

Ahora vamos a completar esto un poco para poder mirar con el ratón a donde queramos, para ello añadid al formulario el componente GLUserInterface, nos vamos a sus propiedades y en GLNavigator ponemos GLNavigator1, en GLVertNavigator ponemos GLNavigator1 y en su propiedad MouseSpeed ponemos le ponemos la velocidad que queremos que tenga el ratón, yo creo que una buena velocidad está entre 20 y 30. Poned por ejemplo 30. Ahora hay que decirle a Delphi que vamos a usar el ratón y que le tenga en cuenta, para ello incluimos el siguiente código en el evento OnCreate del formulario:

Código Delphi [-]
GLUserInterface1.MouseLookActivate;

Si compilais vereis que ya no aparece el puntero del ratón cuando lo pasais por la aplicación pero tampoco hace nada (la cámara no se mueve), bien esto simplemente quiere decir que Delphi ya tiene en cuenta el movimiento del ratón pero la cámara no se mueve porque no hemos puesto por ningún lado que esta se haya de mover (a partir de ahora para terminar nuestra aplicación pulsar Alt + F4). Para que la cámara se mueva hemos de añadir el siguiente código en el OnProgress del Cadencer:

Código Delphi [-]
GLUserInterface1.MouseUpdate;
GLUserInterface1.MouseLook;

Bueno pues en este momento ya tenemos lo más básico, tenemos un terreno tridimensional por el que podemos movernos libremente y mirar libremente por el escenario.

Añadid esta línea de código en el código del evento OnProgress de GLCadencer1 para salir de la aplicación pulsando Escape es más rápido que hacer Alt + F4 todo el rato:

Código Delphi [-]
if IsKeyDown(VK_ESCAPE) then Close;

Ya tenemos lo básico, pero hemos de mejorar ahora ciertos aspectos, por ejemplo:
- Poner un cielo en condiciones y quitar el feo fondo gris.
- Eliminar la posibilidad de atravesar las paredes.
- Aumentar la distancia de visión.

Empecemos por el cielo. Hacemos doble click en GLScene1, click derecho en Scene objects, Add object/Environment objects/SkyDome esto añadirá nuestra bóveda celeste a nuestra escena. Una cosa importante es asegurarse de que el cielo es lo primero que hay en Scene objects, si no es lo primero las montañas quedarán cortadas y se verá mal, para que el cielo sea lo primero que haya en la escena simplemente seleccionar el GLSkyDome1 haciendo click en él y pulsar el botón verde con dos flechas para arriba para anteponer el GLSkyDome1 al GLTerrainRenderer1. Ahora si compilamos y ejecutamos vemos que hay cielo y tierra pero aun se ve fondo gris, esto es porque el cielo comienza muy arriba, hemos de hacer que el cielo comience más abajo, para ello pinchamos en los puntos suspensivos de la propieda Bands de GLSkyDome1 y nos aparecerán dos bandas, seleccionamos la primera y ponemos StartAngle -10, StopAngle 25 y en la segunda banda StartAngle 25 y StopAngle lo dejamos como está. Esto depende del terreno pero de momento esto debería de bastar para que el cielo fuese algo mejor que antes. Podeis añadir las bandas que querais y de los colores que querais, esto que os digoe es simplemente una orientación, luego está el gusto de cada uno.

Ahora vamos a eliminar la posibilidad de eliminar paredes. Para esto vamos a imponer una restricción, esta será que si la altura de la cámara en un momento dado es menor que 4 unidades más que la altura del terreno entonces elevamos la altura de la cámara en 4 unidades, esto lo hacemos para estar siempre por encima del terreno. Esto lo hacemos usando la función InterpolatedHeight del terreno que nos da la altura en un punto determinado, por tanto añadimos el siguiente código al OnProgress del Cadencer:

Código Delphi [-]
altura:=GLTerrainRenderer1.InterpolatedHeight(GLCamera1.Position.AsVector);
if GLCamera1.Position.Z < altura + 5 then
 GLCamera1.Position.Z := altura + 5;

no olvideis declarar la variable altura de tipo real en las variables locales del método.

si lo que quereis es andar en vez de volar como en los First Person Shooter convencionales poned este código:

Código Delphi [-]
altura:=GLTerrainRenderer1.InterpolatedHeight(GLCamera1.Position.AsVector);
if GLCamera1.Position.Z <> altura + 5 then
 GLCamera1.Position.Z := altura + 5;

Ahora andareis y ya no podremos volar por el escenario, así que no nos servirá de nada usar RePág ni AvPág, es lo que tiene andar...

Ahora hay que aumentar la distancia de visión, para ello simplemente hay que aumentar el valor de la propiedad DepthOfView de la cámara, por defecto este valor está a 100, probad a poner 10000 y vereis que se ve de lujo pero va lentísimo (esto es un gran esfuerzo para el ordenador), poned 1000 que también se ve bien y va a una velocidad aceptable.

Vale, llegados a este punto lo que tenemos entre manos es una cámara que sigue nuestras órdenes, la podemos mover por todo el escenario a nuestro gusto y podemos hacer que apunte a cualquier dirección.

El paso siguiente es usar un arma, os recomiendo que busqueis una en formato 3ds por internet.

¿Ya teneis el arma? Vale, pasemos a la acción. Dad doble click en GLScene1, click derecho en Scene objects/Add object/DummyCube. Tenemos ahora un DummyCube, es lo que vamos a mover por el escenario, ya no vamos a mover la cámara sino el GLDummyCube1. Arrastrad el componente GLCamera1 al GLDummyCube1 de manera que GLCamera1 quede como un hijo de GLDummyCube1,

Un dato importante es el orden de los objetos de Scene objects, aseguraros de que primero va el cielo, luego el escenario y por último el DummyCube1, esto se hace para que primero se pinte el cielo y encima se pinte el terreno y encima de todo esto se pinte lo que haya en el DummyCube, es lógico que sea así porque si no se hace así quedaría todo muy raro ¿no creeis?.

Cambiad las propiedades de GLCamera1 con los valores siguientes:

Direction a (X,Y,Z) = (0,0,1)
Position a (X,Y,Z) = (1,5, 1,5, -3)
Up a (X,Y,Z) = (0,1,0)

Poned estos valores a las propiedades del GLDummyCube1:

Direction a (X,Y,Z) = (0,0,1)
Position a (X,Y,Z) = (0,4,0)
Up a (X,Y,Z) = (0,1,0)

Como lo que movemos ahora es el DummyCube vamos a las propiedades de GLNavigator1 y cambiamos la propiedad MovingObject a GLDummyCube1.

Ahora doble click en GLCadencer1 y cambiamos el código:

Código Delphi [-]
altura:=GLTerrainRenderer1.InterpolatedHeight(GLCamera1.Position.AsVector);
if GLCamera1.Position.Z < altura+5 then
 GLCamera1.Position.Z:=altura+5;

por

Código Delphi [-]
altura:=GLTerrainRenderer1.InterpolatedHeight(GLDummyCube1.Position.AsVector);
if GLDummyCube1.Position.Z<>altura+5 then
 GLDummyCube1.Position.Z:=altura+5;

esto lo hacemos porque lo que movemos ahora es el DummyCube y no la cámara con lo que esto ha de cambiar también.

Bueno después de hacer todo esto compilamos y vemos que el resultado es el mismo que antes nada ha cambiado aparentemete. La verdad es que si que ha cambiado, ahora controlamos un DummyCube, esto es mucho mejor que controlar sólo la cámara, os pongo un ejemplo, imginad que el DummyCube tiene una cámara, un personaje, un arma y una mochila como hijos, pues nosotros podemos mover todo eso por el escenario símplemente moviendo el DummyCube.

El siguiente paso es añadir el arma, dad doble click en GLScene1, click derecho en Scene objects/Add object/Mesh objects/FreeForm

Cambiad la propiedad Name de GLFreeForm1 por Escopeta (por ejemplo), cambiad también su propiedad Scale a (X,Y,Z) = (0,02, 0,02, 0,02) y ahora en el evento OnCreate del formulario añadid el siguiente código:

Código Delphi [-]
Escopeta.LoadFromFile('C:\Archivos de programa\eMule\Incoming\rifle1_mrealms.3ds'); //Cambiad la ruta por la ruta en la que se encuentre vuestro arma.

Vale, esto ya se va pareciendo a un First Person Shooter, no es que sea el Doom3 pero bueno...

Ahora deberíamos de poder disparar con nuestra escopeta, vamos a ello.

No se realmente como harán los juegos comerciales un disparo, imagino que será algo muy complejo pero yo he considerado que la mejor forma de simular un disparo es que salga de la punta de la escopeta una esfera (la bala) con una velocidad y en una dirección y se pierda en el infinito, de momento esto lo tengo así supongo que luego con el tiempo lo mejoraré algo, cambiaré la esfera por algo parecido a una bala y aplicaré algo de física al disparo.

Dad doble click en GLScene1, click derecho en Scene objects/Add object/DummyCube y cambiarle su propiedad Name por Municion.

Añadid el atributo privado Cadencia_disparo de tipo double al formulario.

Añadid el siguiente código al principio del evento OnProgress del GLCadencer1:

Código Delphi [-]
Cadencia_disparo := Cadencia_disparo + deltatime;
for i := 0 to Municion.Count-1 do
 Municion.Children[i].Move(deltatime*200);

No olvideis declarar la variable i de tipo integer en la sección de variables del evento.

Añadid el siguiente código en el evento OnProgress del GLCadencer1:

Código Delphi [-]
if ((IsKeyDown(VK_LBUTTON)) and (Cadencia_disparo>0.2)) then
 begin
  Cadencia_disparo := 0.0;
  Balazo:=TGLSphere(Municion.AddNewChild(TGLSphere));
  Balazo.AbsolutePosition := Escopeta.AbsolutePosition; 
  Balazo.AbsoluteDirection := GLCamera1.AbsoluteDirection;
  Balazo.Move(7); //Para que el proyectil salga de la punta de la escopeta
 end;

No olvideis declarar la variable Balazo de tipo TGLSphere en la sección de variables del evento.

Llegados a este punto ya tenemos un arma que dispara esferas y que podemos moverla por el escenario a nuestro antojo así como apuntar a cualquier lado. Faltarían muchas más cosas como las colisiones y en base a eso hacer más cosas, aun tengo que investigar más a fondo y repasar que todo el tutorial esté bien pero de momento está aceptable.

Para completar un poco, si quereis ver los frames por segundo de vuestro juego añadid un Timer de la pestaña System a vuestro formulario, cambiad su propiedad Name a FPSTemporizador por ejemplo, dejad su propiedad Interval a 1000 y en su evento OnTimer poned el siguiente código:

Código Delphi [-]
Caption := GLSceneViewer1.FramesPerSecondText;
GLSceneViewer1.ResetPerformanceMonitor;

Los comentarios y las aportaciones serán vienvenidos. Si algo no os funciona no dudeis en preguntármelo por el foro, os resolveré la duda. Un saludo.

<<CONTINUARÁ, AUN FALTA IMPLEMENTAR COLISIONES>>

Última edición por kakarotv5 fecha: 28-12-2007 a las 01:56:59.
Responder Con Cita
  #2  
Antiguo 27-02-2007
mierda mierda is offline
Miembro
 
Registrado: may 2006
Posts: 129
Poder: 18
mierda Va por buen camino
hola nen ....

Hola tio ... me parece muy interesante tu propuesta ... pero por ejemplo podias decir que delphi y que version de glscene utilizas y donde bajarse el glscene ... yo por lo menos te voy a seguir ... ya q soy un enamorado de los fps ... sobre todo del inigualable quake 3 arena

Un saludo.
Responder Con Cita
  #3  
Antiguo 27-02-2007
urixiv urixiv is offline
Miembro
 
Registrado: sep 2006
Posts: 23
Poder: 0
urixiv Va por buen camino
Pues yo tambien me apunto y te voy a seguir!!!!!
Responder Con Cita
  #4  
Antiguo 28-02-2007
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.275
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Fantástico!!
Espero que sigas adelante.

NOTA: Recuerda que tenemos un espacio (FTP público) donde subimos componentes, documentación, ejemplos,...
Recuerda lo que tienes a tu disposición.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #5  
Antiguo 05-03-2007
urixiv urixiv is offline
Miembro
 
Registrado: sep 2006
Posts: 23
Poder: 0
urixiv Va por buen camino
duda

Hola, estaba siguiendo tu tutorial y decirte que esta muy bien, pero simplemente una cosilla, a ver si sabes que puede ser.
He puesto el código que comentas para movernos por el escenario como si estuvieramos andando, y el efecto es que parece que ya no se mueva nada.....
sabes que puede ser?
muchas gracias
Responder Con Cita
  #6  
Antiguo 06-03-2007
Avatar de Caral
[Caral] Caral is offline
Miembro Premium
 
Registrado: ago 2006
Posts: 7.659
Poder: 25
Caral Va por buen camino
Hola
Este es nada mas para seguir el cursillo que me parece muy interesante.
Gracias por la aportacion.
Saludos
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
problema sencillo en una consulta ddd_ddd SQL 5 26-01-2007 00:09:47
Sencillo: crear button sortilodio OOP 8 20-12-2006 13:32:31
Buscar y Encontrarlo es sencillo.... anghell77 Humor 7 04-10-2006 08:40:43
ayudita please, sencillo Otei OOP 3 18-11-2005 22:25:10
Un link a firebird 1.5 (sencillo) Jorge Taveras Firebird e Interbase 1 28-04-2004 22:08:57


La franja horaria es GMT +2. Ahora son las 23:02:46.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi