/// <summary> /// Reload level /// </summary> /// <param name="setLevel">Level</param> internal void ReloadLevel(RacingGameManager.Level setLevel) { level = setLevel; // Load track based on the level selection, do this after // we got all the height data because the track might be adjusted. if (track == null) { track = new Track("Track" + level.ToString(), this); } else { track.Reload("Track" + level.ToString(), this); } // Load replay for this track to show best player bestReplay = new Replay((int)level, false, track); newReplay = new Replay((int)level, true, track); // Kill brake tracks brakeTracksVertices.Clear(); brakeTracksVerticesArray = null; // Set car at start pos SetCarToStartPosition(); // Begin game with red start light startLightObject.ChangeModel(landscapeModels[0]); }
/// <summary> /// Create game screen /// </summary> public GameScreen(RacingGameManager.Level mapName) { // Load level RacingGameManager.LoadLevel(mapName); // Reset player variables (start new game, reset time and position) RacingGameManager.Player.Reset(); // Fix light direction (was changed by CarSelection screen!) // LightDirection will normalize BaseGame.LightDirection = LensFlare.DefaultLightPos; // Start gear sound Sound.StartGearSound(); // Play game music Sound.Play(Sound.Sounds.GameMusic); RacingGameManager.InputInterface.Escape += InputInterface_Escape; }
/// <summary> /// Create landscape. /// This constructor should only be called /// from the RacingGame main class! /// </summary> /// <param name="setLevel">Level we want to load</param> internal Landscape(RacingGameManager.Level setLevel) { #region Load map height data Stream file = TitleContainer.OpenStream( "Content\\LandscapeHeights.data"); byte[] heights = new byte[GridWidth * GridHeight]; file.Read(heights, 0, GridWidth * GridHeight); file.Close(); mapHeights = new float[GridWidth, GridHeight]; #endregion #region Build tangent vertices // Build our tangent vertices for (int x = 0; x < GridWidth; x++) { for (int y = 0; y < GridHeight; y++) { // Step 1: Calculate position int index = x + y * GridWidth; Vector3 pos = CalcLandscapePos(x, y, heights);//texData); mapHeights[x, y] = pos.Z; vertices[index].pos = pos; //if (x == 0) // Log.Write("vertices " + y + ": " + pos); // Step 2: Calculate all edge vectors (for normals and tangents) // This involves quite complicated optimizations and mathematics, // hard to explain with just a comment. Read my book :D Vector3 edge1 = pos - CalcLandscapePos(x, y + 1, heights); Vector3 edge2 = pos - CalcLandscapePos(x + 1, y, heights); Vector3 edge3 = pos - CalcLandscapePos(x - 1, y + 1, heights); Vector3 edge4 = pos - CalcLandscapePos(x + 1, y + 1, heights); Vector3 edge5 = pos - CalcLandscapePos(x - 1, y - 1, heights); // Step 3: Calculate normal based on the edges (interpolate // from 3 cross products we build from our edges). vertices[index].normal = Vector3.Normalize( Vector3.Cross(edge2, edge1) + Vector3.Cross(edge4, edge3) + Vector3.Cross(edge3, edge5)); // Step 4: Set tangent data, just use edge1 vertices[index].tangent = Vector3.Normalize(edge1); // Step 5: Set texture coordinates, use full 0.0f to 1.0f range! vertices[index].uv = new Vector2( //x / (float)(GridWidth - 1), //y / (float)(GridHeight - 1)); y / (float)(GridHeight - 1), x / (float)(GridWidth - 1)); } } #endregion #region Smooth normals // Smooth all normals, first copy them over, then smooth everything Vector3[,] normalsForSmoothing = new Vector3[GridWidth, GridHeight]; for (int x = 0; x < GridWidth; x++) { for (int y = 0; y < GridHeight; y++) { int index = x + y * GridWidth; normalsForSmoothing[x, y] = vertices[index].normal; } } // Time to smooth to normals we just saved for (int x = 1; x < GridWidth - 1; x++) { for (int y = 1; y < GridHeight - 1; y++) { int index = x + y * GridWidth; // Smooth 3x3 normals, but still use old normal to 40% (5 of 13) Vector3 normal = vertices[index].normal * 4; for (int xAdd = -1; xAdd <= 1; xAdd++) { for (int yAdd = -1; yAdd <= 1; yAdd++) { normal += normalsForSmoothing[x + xAdd, y + yAdd]; } } vertices[index].normal = Vector3.Normalize(normal); // Also recalculate tangent to let it stay 90 degrees on the normal Vector3 helperVector = Vector3.Cross( vertices[index].normal, vertices[index].tangent); vertices[index].tangent = Vector3.Cross( helperVector, vertices[index].normal); } } #endregion #region Set vertex buffer // Set vertex buffer // fix //vertexBuffer = new VertexBuffer( // BaseGame.Device, // typeof(TangentVertex), // vertices.Length, // ResourceUsage.WriteOnly, // ResourceManagementMode.Automatic); //vertexBuffer.SetData(vertices); vertexBuffer = new VertexBuffer( BaseGame.Device, typeof(TangentVertex), vertices.Length, BufferUsage.WriteOnly); vertexBuffer.SetData(vertices); #endregion #region Calc index buffer // Calc index buffer (Note: have to use uint, ushort is not sufficiant // in our case because we have MANY vertices ^^) uint[] indices = new uint[(GridWidth - 1) * (GridHeight - 1) * 6]; int currentIndex = 0; for (int x = 0; x < GridWidth - 1; x++) { for (int y = 0; y < GridHeight - 1; y++) { // Set landscape data (Note: Right handed) indices[currentIndex + 0] = (uint)(x * GridHeight + y); indices[currentIndex + 2] = (uint)((x + 1) * GridHeight + (y + 1)); indices[currentIndex + 1] = (uint)((x + 1) * GridHeight + y); indices[currentIndex + 3] = (uint)((x + 1) * GridHeight + (y + 1)); indices[currentIndex + 5] = (uint)(x * GridHeight + y); indices[currentIndex + 4] = (uint)(x * GridHeight + (y + 1)); // Add indices currentIndex += 6; } } #endregion #region Set index buffer // fix //indexBuffer = new IndexBuffer( // BaseGame.Device, // typeof(uint), // (GridWidth - 1) * (GridHeight - 1) * 6, // ResourceUsage.WriteOnly, // ResourceManagementMode.Automatic); indexBuffer = new IndexBuffer( BaseGame.Device, typeof(uint), (GridWidth - 1) * (GridHeight - 1) * 6, BufferUsage.WriteOnly); indexBuffer.SetData(indices); #endregion #region Load track (and replay inside ReloadLevel method) // Load track based on the level selection and set car pos with // help of the ReloadLevel method. ReloadLevel(setLevel); #endregion #region Add city planes // Just set one giant plane for the whole city! foreach (LandscapeObject obj in landscapeObjects) { if (obj.IsBigBuilding) { cityPlane = new PlaneRenderer( obj.Position, new Plane(new Vector3(0, 0, 1), 0.1f), cityMat, Math.Min(obj.Position.X, obj.Position.Y)); break; } } #endregion }
/// <summary> /// Reload level /// </summary> /// <param name="setLevel">Level</param> internal void ReloadLevel(RacingGameManager.Level setLevel) { level = setLevel; // Load track based on the level selection, do this after // we got all the height data because the track might be adjusted. if (track == null) track = new Track("Track" + level.ToString(), this); else track.Reload("Track" + level.ToString(), this); // Load replay for this track to show best player bestReplay = new Replay((int)level, false, track); newReplay = new Replay((int)level, true, track); // Kill brake tracks brakeTracksVertices.Clear(); brakeTracksVerticesArray = null; // Set car at start pos SetCarToStartPosition(); }