sexta-feira, 29 de julho de 2011

Baixe esse arquivo: http://www.megaupload.com/?d=JB5UCFGU

Nele tem dois arquivos de 8-Bits no formato .raw - Você pode usar o google imagens, procurar por imagens e preto e branco e depois salvar o arquivo no tipo .raw, eu uso o PhotoShop mas existem algumas ferramentas que fazer mapas para você, TerraGen e EathSculptor.

Extraia os arquivos onde quiser. Em tutorial1.Content(Content) crie uma nova pasta, chame-a de "Terrains", Clique com o botão direito sobre a pasta criada -> Add -> Existing itens e selecione as duas imagens.

Selecione cada uma de uma vez, abra a aba de propeiedades. Mude Build Action para "none" e CopyToOutputDirectory para Copy if newer. Isso acontece porque o XNA transforma as imagens para 32Bits, o que não queremos.

Volte no arquivo "Terrain.cs" adicione a seguinte using "using System.IO;", no Método Load() apague as seguintes linhas


"Random random = new Random();" e

"//Definimos o tamanho total do mapa, usando parametros anteriormente declarados
int heightMapSize = vertexCountX * vertexCountZ;
heightMap = new byte[heightMapSize];
//Geramos valores aleatórios para a alutura de nooso mapa
for (int i = 0; i < heightMapSize; i++) heightMap[i] = (byte)random.Next(0, 30);" e cole o seguinte código:
// Carrega o arquivo do mapa de altura
FileStream fileStream = File.OpenRead(Game.Content.RootDirectory + "/Terrains/" + heightmapFileName + ".raw");

int heightmapSize = vertexCountX * vertexCountZ;
heightMap = new byte[heightmapSize];
fileStream.Read(heightMap, 0, heightmapSize);
fileStream.Close();

Agora altere os parametros do método Load para
public void Load(string heightmapFileName, int vertexCountX, int vertexCountZ, float blockScale, float heightScale) - Adicionamos o

"string heightmapFileName"

No inicio dos parametros.

No arquivo "Game1.cs" Ache novamente o método terrain.Load() e mude-o para:

terrain.Load("Terrain1", 256, 256, 1.0f, 0.1f); ou
terrain.Load("Australia", 256, 256, 1.0f, 0.1f);

Por Ultimo vamos alterar a cor, no método CreateTerrainVertices mude a altura de cada cor para

if((int)heightMap[vertexCount] < 80) vertices[vertexCount].Color = Color.Green; if ((int)heightMap[vertexCount] > 200)
vertices[vertexCount].Color = Color.Red;

Você pose mudar o FillMode para Solid no método Initialize();

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Tutorial1.GameBase.Cameras;
using System.IO;

namespace Tutorial1.GameBase.Shapes
{
public class Terrain : DrawableGameComponent
{
#region Variáveis
//Variável que guardará a altura do mapa
byte[] heightMap;

//Variáveis de renderização
VertexBuffer vertexBuffer;
IndexBuffer indexBuffer;

//Guarda o número de Vértices e de triângulos
int numVertices;
int numTriangles;

//Quantidade de vértices nos eixos X e Z
int vertexCountX;
int vertexCountZ;

//Escala do nosso mapa
float blockScale;
float heightScale;

//Efeito que será usado na cena
BasicEffect effect;

//Serviços necessários
bool isInitialized;
CameraManager cameraManager;

#endregion

#region Construtor()
public Terrain(Game game)
: base(game)
{
isInitialized = false;
}
#endregion

#region initialize()
//Inicializa todos os nossos serviços e depois de iniciado defini nossa flag como true, permitindo que outros
//métodos possam se executar sem perda de dados
public override void Initialize()
{
cameraManager = Game.Services.GetService(typeof(CameraManager)) as CameraManager;

//Define o nosso RenderState
//Rasterize.FillMode =
//Pode variar entre FillMode.Solid - Para mostrar os objetos da cena de momo completo
//FillMode.WireFrame - Para mostrar os triângulod que formam os objetos na cena
RasterizerState rasterizeState = new RasterizerState();
rasterizeState.FillMode = FillMode.WireFrame;
Game.GraphicsDevice.RasterizerState = rasterizeState;

isInitialized = true;

base.Initialize();
}
#endregion

#region Load()
public void Load(string heightmapFileName, int vertexCountX, int vertexCountZ, float blockScale, float heightScale)
{
//Cuida para que tudo seja iniciado
if (!isInitialized)
Initialize();


//Passamos alguns parametros para definir o tamanho do Mapa em X e Z e tambem a escala de
//Tamanho e de altura
this.vertexCountX = vertexCountX;
this.vertexCountZ = vertexCountZ;
this.blockScale = blockScale;
this.heightScale = heightScale;

// Carrega o arquivo do mapa de altura
FileStream fileStream = File.OpenRead(Game.Content.RootDirectory + "/Terrains/" + heightmapFileName + ".raw");

int heightmapSize = vertexCountX * vertexCountZ;
heightMap = new byte[heightmapSize];
fileStream.Read(heightMap, 0, heightmapSize);
fileStream.Close();

GenerateTerrainMesh();

effect = new BasicEffect(Game.GraphicsDevice);
effect.VertexColorEnabled = true;
}
#endregion

#region GenerateTerrainMesh()
private void GenerateTerrainMesh()
{
//Vamos definir o número de vértices e triângulo para renderizar todos eles
numVertices = vertexCountX * vertexCountZ;
numTriangles = (vertexCountX - 1) * (vertexCountZ - 1) * 2;

//Criando nosso índices
int[] indices = GenerateTerrainIndices();

VertexPositionColor[] vertices = GenerateTerrainVertices(indices);

//Vamos criar a declaração dos vértices
VertexDeclaration decl = new VertexDeclaration(VertexPositionColor.VertexDeclaration.GetVertexElements());

// Cria o buffer de vertices
vertexBuffer = new VertexBuffer(GraphicsDevice, decl, numVertices, BufferUsage.WriteOnly);

//Adiciona nossos vértices ao Buffer
vertexBuffer.SetData(vertices);

//Cria o Buffer de índices
indexBuffer = new IndexBuffer(Game.GraphicsDevice, typeof(int), indices.Length, BufferUsage.WriteOnly);

//Adiciona nossos índices ao Buffer
indexBuffer.SetData(indices);
}
#endregion

#region GenerateTerrainIndices()
private int[] GenerateTerrainIndices()
{
//Cria todos os índices, como cada triângulo possui 3 vértices
int numIndices = numTriangles * 3;
int[] indices = new int[numIndices];

int indicesCount = 0;

//Cria dois indices no mesmo segmento de indices e outro indice no próximo segmento
//Faz isso 2 vezes, com dois triângulos formando um quadrado
for (int i = 0; i < (vertexCountZ - 1); i++) { for (int j = 0; j < (vertexCountX - 1); j++) { int index = j + i * vertexCountZ; indices[indicesCount++] = index; indices[indicesCount++] = index + 1; indices[indicesCount++] = index + vertexCountX + 1; indices[indicesCount++] = index + vertexCountX + 1; indices[indicesCount++] = index + vertexCountX; indices[indicesCount++] = index; } } return indices; } #endregion #region GenerateTerrainVertices() private VertexPositionColor[] GenerateTerrainVertices(int[] terrainIndices) { float halfTerrainWidth = (vertexCountX - 1) * blockScale * 0.5f; float halfTerrainDepth = (vertexCountZ - 1) * blockScale * 0.5f; int vertexCount = 0; VertexPositionColor[] vertices = new VertexPositionColor[vertexCountX * vertexCountZ]; // Define a posicao dos vertices e a coordenada de textura for (float i = -halfTerrainDepth; i <= halfTerrainDepth; i += blockScale) { for (float j = -halfTerrainWidth; j <= halfTerrainWidth; j += blockScale) { vertices[vertexCount].Position = new Vector3(j, heightMap[vertexCount] * heightScale, i); vertices[vertexCount].Color = Color.Yellow; if((int)heightMap[vertexCount] < 80) vertices[vertexCount].Color = Color.Green; if ((int)heightMap[vertexCount] > 200)
vertices[vertexCount].Color = Color.Red;

vertexCount++;
}

}

return vertices;
}
#endregion

#region Update()
public override void Update(GameTime gameTime)
{
effect.View = cameraManager.ActiveCamera.View;
effect.Projection = cameraManager.ActiveCamera.Projection;
base.Update(gameTime);
}
#endregion

#region Draw()
public override void Draw(GameTime gameTime)
{

//Adicionamos o nossos indices e vertices ao nosso dispositivso para desenhar
Game.GraphicsDevice.SetVertexBuffer(vertexBuffer);
Game.GraphicsDevice.Indices = indexBuffer;

foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
//Adiciona e aplica o efeito
pass.Apply();
//Desenha a lista de linhas
Game.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, numVertices, 0, numTriangles);
}

base.Draw(gameTime);
}
#endregion
}
}

Nenhum comentário:

Postar um comentário