/// <summary> /// Load the image associated with this page. /// </summary> /// <param name="graphics">Graphics instance</param> public void LoadImage(IGraphics graphics) { bmp = graphics.CreateBitmap(GameMain.GetFullPath(fileName), false); Debug.Assert(bmp != null, "Page.LoadImage: Failed to load bitmap"); }
/// <summary> /// Creates drawing that should be visualized. /// </summary> /// <param name="graphics">Graphics object used to create drawings.</param> /// <param name="width">Bitmap width.</param> /// <param name="height">Bitmap height.</param> /// <param name="data">Address of the pixels data.</param> /// <param name="channels">Channels in the bitmap.</param> /// <param name="dataType">Type of the single pixel channel value.</param> /// <param name="stride">Bitmap data stride.</param> /// <returns>Drawing object that should be visualized.</returns> public static IDrawing CreateDrawing(IGraphics graphics, int width, int height, NakedPointer data, ChannelType[] channels, BuiltinType dataType = BuiltinType.UInt8, int stride = 0) { switch (dataType) { case BuiltinType.Float32: return(graphics.CreateBitmap(width, height, channels, ReadPixels <float>(width, height, data, stride, channels.Length))); case BuiltinType.Float64: return(graphics.CreateBitmap(width, height, channels, ReadPixels <double>(width, height, data, stride, channels.Length))); case BuiltinType.Int8: return(graphics.CreateBitmap(width, height, channels, ReadPixels <sbyte>(width, height, data, stride, channels.Length))); case BuiltinType.Int16: return(graphics.CreateBitmap(width, height, channels, ReadPixels <short>(width, height, data, stride, channels.Length))); case BuiltinType.Int32: return(graphics.CreateBitmap(width, height, channels, ReadPixels <int>(width, height, data, stride, channels.Length))); case BuiltinType.NoType: case BuiltinType.Char8: case BuiltinType.Void: case BuiltinType.UInt8: return(graphics.CreateBitmap(width, height, channels, ReadPixels <byte>(width, height, data, stride, channels.Length))); case BuiltinType.UInt16: return(graphics.CreateBitmap(width, height, channels, ReadPixels <ushort>(width, height, data, stride, channels.Length))); default: throw new NotImplementedException($"Unknown image data type: {dataType}"); } }
/// <summary> /// Initialize a panel with the data contained in the DataRow. /// </summary> /// <param name="dr">DataRow that defines the panel</param> /// <param name="graphics">Graphics instance</param> public UIPanel(DataRow dr, IGraphics graphics) { Debug.Assert(dr != null, "UIPanel.UIPanel: Invalid DataTable"); x = int.Parse((string)dr["X"], CultureInfo.InvariantCulture); y = int.Parse((string)dr["Y"], CultureInfo.InvariantCulture); string fullName = GameMain.GetFullPath( @"Data\UI\" + (string)dr["FileName"]); bmp = graphics.CreateBitmap(fullName, false); Debug.Assert(bmp != null, "UIPanel.UIPanel: Failed to initialize UI panel bitmap"); }
/// <summary> /// Create an animation from a Bitmap stream. /// </summary> /// <param name="bmpData">Stream representing source bitmap</param> /// <param name="graphics">Graphics object, needed for bitmap loading /// </param> /// <param name="numberRows">Number of rows of cells in the animation /// </param> /// <param name="numberColumns">Number of columns of cells in the /// animation</param> /// <param name="startCell">Index from which to start animating /// </param> /// <param name="cellWidth">Width of individual animation cells /// </param> /// <param name="cellHeight">Height of individual animation cells /// </param> /// <param name="cellsPerSecond">Rate of animation in cells per /// second</param> public Animation(string fileName, IGraphics graphics, int numberRows, int numberColumns, int startCell, int cellWidth, int cellHeight, int cellsPerSecond) { initialized = false; // Initialize the cell information this.cellWidthValue = cellWidth; this.cellHeightValue = cellHeight; this.numberRows = numberRows; this.numberColumns = numberColumns; startCell = 0; endCell = numberRows * numberColumns - 1; // Load and initialize the Bitmap object bmp = graphics.CreateBitmap(fileName, true); if (bmp == null) { initialized = false; return; } allocated = true; // Initialize timing information this.cellsPerSecond = (float)cellsPerSecond; // Initialize the draw region rectangle sourceRegion.Width = cellWidth; sourceRegion.Height = cellHeight; // Validate information for drawing the first cell Update(0.0F); initialized = true; }
/// <summary> /// Initialize the level. /// </summary> /// <param name="ds">DataSet containing level data</param> /// <param name="graphics">Valid Graphics object</param> public Level(DataSet ds, IGraphics graphics) { // Store graphics Debug.Assert(graphics != null, "Level.Level: Invalid Graphics object"); this.graphics = graphics; // Validate the DataSet Debug.Assert(ds != null && ds.Tables != null, "Level.Level: Invalid DataSet"); // General DataTable dt = ds.Tables["General"]; DataRow drGen = dt.Rows[0]; screenEdgeBufferValue = float.Parse( (string)(drGen["ScreenEdgeBuffer"]), CultureInfo.InvariantCulture); FrameRateCheckRateValue = float.Parse( (string)(drGen["FrameRateCheckRate"]), CultureInfo.InvariantCulture); gravityValue = float.Parse((string)(drGen["Gravity"]), CultureInfo.InvariantCulture); // Images Debug.Assert(ds.Tables["Image"] != null && ds.Tables["Image"].Rows != null, "Level.Level: No images specified in level data"); dt = ds.Tables["Image"]; foreach (DataRow dr in dt.Rows) { IBitmap bmp = graphics.CreateBitmap(GameMain.GetFullPath( @"Data\Level\" + (string)dr["FileName"]), bool.Parse((string)dr["Transparency"])); Debug.Assert(bmp != null, string.Format(CultureInfo.InvariantCulture, "Failed to initialize bitmap {0}", @"Data\Level\" + (string)dr["FileName"])); images.Add(bmp); } // Layers dt = ds.Tables["Layer"]; foreach (DataRow dr in dt.Rows) { layers.Add(new Layer(dr, images)); } Debug.Assert(layers.Count >= 1, "Level does not contain 2 or more layers"); ds = null; // AI DataSet dsAI = new DataSet(); Debug.Assert(dsAI != null && dsAI.Tables != null, "Level.Level: Failed to initialize AI DataSet"); dsAI.Locale = CultureInfo.InvariantCulture; dsAI.ReadXml(GameMain.GetFullPath(@"Data\AI\ai.xml")); dt = dsAI.Tables["Definition"]; Debug.Assert(dt != null && dt.Rows != null, "Level.Level: Failed to load AI DataTable"); foreach (DataRow dr in dt.Rows) { AI ai = AIHandler.Create(dr); Debug.Assert(ai != null, "Level.Level: Failed to initialize AI"); this.ai.Add(ai); } dsAI = null; DataSet dsAnimations = new DataSet(); Debug.Assert(dsAnimations != null && dsAnimations.Tables != null, "Level.Level: Failed to initialize animation DataSet"); dsAnimations.Locale = CultureInfo.InvariantCulture; // Animations dsAnimations.ReadXml(GameMain.GetFullPath(@"Data\Animations\animations.xml")); dt = dsAnimations.Tables["Definition"]; Debug.Assert(dt != null && dt.Rows != null, "Level.Level: Failed to load animation DataTable"); foreach (DataRow dr in dt.Rows) { int numberRows = int.Parse((string)dr["Rows"], CultureInfo.InvariantCulture); int numberColumns = int.Parse((string)dr["Columns"], CultureInfo.InvariantCulture); int cellWidth = int.Parse((string)dr["CellWidth"], CultureInfo.InvariantCulture); int cellHeight = int.Parse((string)dr["CellHeight"], CultureInfo.InvariantCulture); Animation animation = new Animation(GameMain.GetFullPath( @"Data\Animations\" + (string)dr["FileName"]), graphics, numberRows, numberColumns, 0, cellWidth, cellHeight, 0); Debug.Assert(animation != null && animation.Init, "Level.Level: Failed to load animation"); animations.Add(animation); } dsAnimations = null; // Player DataSet dsPlayer = new DataSet(); Debug.Assert(dsPlayer != null, "Level.Level: Failed to initialize player DataSet"); dsPlayer.Locale = CultureInfo.InvariantCulture; dsPlayer.ReadXml(GameMain.GetFullPath(@"Data\Player\player.xml")); Player p = new Player(dsPlayer, graphics, animations); Debug.Assert(p != null, "Level.Level: Failed to initialize player"); worldObjectsValue.Add(p); dsPlayer = null; // World Objects DataSet dsWorldObjects = new DataSet(); Debug.Assert(dsWorldObjects != null && dsWorldObjects.Tables != null, "Level.Level: Failed to initialize world object DataSet"); dsWorldObjects.Locale = CultureInfo.InvariantCulture; dsWorldObjects.ReadXml(GameMain.GetFullPath(@"Data\WorldObjects\worldobjects.xml")); dt = dsWorldObjects.Tables["Instance"]; if (dt != null) { foreach (DataRow dr in dt.Rows) { WorldObject wo = new WorldObject(dr, this); Debug.Assert(wo != null, "Level.Level: Failed to initialize world object"); worldObjectsValue.Add(wo); } } }
/// <summary> /// Start the game. This method loads the game resources and /// runs the main game loop. /// </summary> public void Run() { // Load and validate the splash screen splash = graphics.CreateBitmap(GetFullPath(@"Data\Splash\splash.bmp"), false); Debug.Assert(splash != null, "GameMain.Run: Failed to initialized splash screen"); Debug.Assert(splash.Width <= graphics.ScreenWidth && splash.Height <= graphics.ScreenHeight, "GameMain.Run: Splash screen has invalid dimensions"); // Load the game ui now because it has font information that is // needed for drawing the 'Loading...' tag DataSet dsUI = new DataSet(); Debug.Assert(dsUI != null, "GameMain.LoadLevel: Failed to initialize UI DataSet"); dsUI.Locale = CultureInfo.InvariantCulture; // Load the ui xml file dsUI.ReadXml(GetFullPath(@"Data\UI\ui.xml")); // Load the resources specified in the xml file ui = new UserInterface(dsUI, graphics, level); Debug.Assert(ui != null, "GameMain.LoadLevel: Failed to initialize UI"); // Set the current update method as the splash screen updater update = new UpdateDelegate(UpdateSplash); // Loop until the game is done while (!done) { // Switch the update delegate if a switch was requested. switch (mode) { case ModeSwitch.UpdateLevel: gi.ClearKeyPresses(); update = new UpdateDelegate(UpdateLevel); numFrames = 0; secondsElapsedForCurrentFrames = 0; break; case ModeSwitch.UpdateCountdown: intro.Dispose(); intro = null; level.Update(gi); update = new UpdateDelegate(UpdateCountdown); break; case ModeSwitch.UpdateIntro: LoadLevel(); update = new UpdateDelegate(UpdateIntro); splash.Dispose(); splash = null; break; } mode = ModeSwitch.None; // Store the tick at which this frame started Int64 startTick = sw.CurrentTick(); // Check if the user pressed the exit key if (gi.KeyPressed((int)gi.HardwareKeys[Player.ButtonMap()[ (int)Player.Buttons.Quit]])) { done = true; } else if (levelLoaded && (level.Done || gi.KeyPressed( (int)gi.HardwareKeys[Player.ButtonMap()[ (int)Player.Buttons.ResetLevel]]))) { Reset(); Application.DoEvents(); continue; } // Update the game update(); // Check for pending events from the OS Application.DoEvents(); // Lock the framerate... Int64 deltaMS = sw.DeltaTimeMilliseconds(sw.CurrentTick(), startTick); Int64 minMS = (Int64)(1000.0F * MinSecondsPerFrame); Int64 maxMS = (Int64)(1000.0F * MaxSecondsPerFrame); // Check if the frame time was fast enough if (deltaMS <= minMS) { // Loop until the frame time is met do { if (gi.KeyPressed((int)gi.HardwareKeys[ Player.ButtonMap()[(int)Player.Buttons.Quit]])) { done = true; break; } // Thread.Sleep(0); Application.DoEvents(); deltaMS = sw.DeltaTimeMilliseconds(sw.CurrentTick(), startTick); } while (deltaMS < minMS); } // Increment the number of frames numFrames++; // Increment the overall time for these frames if (deltaMS < maxMS) { secondsElapsedForCurrentFrames += deltaMS / 1000.0F; } else { secondsElapsedForCurrentFrames += maxMS / 1000.0F; } // Make sure enough time has elapsed since the last check if (level != null && secondsElapsedForCurrentFrames > level.FrameRateCheckRate) { currentSecondsPerFrame = secondsElapsedForCurrentFrames / numFrames; numFrames = 0; secondsElapsedForCurrentFrames = 0; } } }