<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://ilovevb.net/Web/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title type="html">Nimble2D</title><subtitle type="html">&lt;img src="http://www.mwgames.com/_uimages/Nimble2D_Logo_Small.jpg" alt="" align="right" /&gt;A 2D game development blog using VB.Net.</subtitle><id>http://ilovevb.net/Web/blogs/nimble2d/atom.aspx</id><link rel="alternate" type="text/html" href="http://ilovevb.net/Web/blogs/nimble2d/default.aspx" /><link rel="self" type="application/atom+xml" href="http://ilovevb.net/Web/blogs/nimble2d/atom.aspx" /><generator uri="http://communityserver.org" version="3.1.20917.1142">Community Server</generator><updated>2008-01-21T22:41:00Z</updated><entry><title>It's All About the Cameras</title><link rel="alternate" type="text/html" href="http://ilovevb.net/Web/blogs/nimble2d/archive/2009/03/21/it-s-all-about-the-cameras.aspx" /><id>http://ilovevb.net/Web/blogs/nimble2d/archive/2009/03/21/it-s-all-about-the-cameras.aspx</id><published>2009-03-21T17:41:00Z</published><updated>2009-03-21T17:41:00Z</updated><content type="html">&lt;p&gt;&lt;i&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;strong&gt;Organization of the Core&lt;/strong&gt;&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;&lt;i&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;/i&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;The structure of the Nimble2D library is based on the idea of a central &amp;quot;Core&amp;quot; object that contains references to all of the major component objects and gives a coordinated means for all objects to be able to work off the same hub.&lt;/span&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;The organization structure looks like this:&lt;/span&gt; 
&lt;ul&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Core&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt; - The main object and &amp;quot;central hub&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Log&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt; - A log file writing class&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Trig&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt; - An instance of the &amp;quot;QuickTrig&amp;quot; class I&amp;#39;ve written about previously&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;R&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt; - A central instance of a random number generator&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;GameClock&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt; - The GameClock, based on the class I&amp;#39;ve written about previously&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;GameSpace&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt; - a list of GameSpace objects used to organize game objects&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;LayerList&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt; - a list of layers within the GameSpace, which control the order that game objects are drawn in and which cameras can &amp;quot;see&amp;quot; those objects&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;GameObjects&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt; - a list of objects on the Layer within the GameSpace&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;MainScreen&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt; - The access point into how things are drawn to the screen&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;TargetPictureBox&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt; - The picture box being drawn to&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;CameraList&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt; - A list of Camera Objects (these are the key to a lot of things)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Input&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt; - The NimbleInput class&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;RawKey&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt; - an array of the low-level key up/down values&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;KeyState&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt; - an abstracted value for each key to allow for testing of down, double-down (like double-clicking for the mouse), first time down and for &amp;quot;clearing&amp;quot; keys (reporting it being &amp;quot;up&amp;quot; until the user releases and re-presses the key)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Mouse&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt; - organization around mouse information, such as location on the screen, location within the current GameSpace, and left/mid/right button states&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Action&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt; - a layer abstracted above key and mouse states to define a game action and the input states that will trigger it&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Trigger List&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt; - a list of defined input states that will trigger the action&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Sound&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt; - A class to control music and sound effects (not yet built)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;The main way to use the library will generally go as follows:&lt;/span&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;span style="mso-tab-count:1;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; 
&lt;ol&gt;
&lt;li&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Create an instance of the &amp;quot;Core&amp;quot; object&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Setup GameSpaces &amp;amp; game objects as needed&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Define Input Actions as needed&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Launch the MainScreen&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Set Cameras on GameSpaces&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Loop:&lt;/span&gt;&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Core.UpdateAll&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;AI &amp;amp; Physics&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Core.DrawAll&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt;
&lt;p&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;strong&gt;&lt;i&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Why is it &amp;quot;All About the Cameras&amp;quot;?&lt;/span&gt;&lt;/i&gt;&lt;/strong&gt;&lt;/p&gt;&lt;strong&gt;&lt;i&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;/i&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;So, how does everything come back to the Camera objects?&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;The Cameras are what put a frame around the things being seen on screen.&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;This frame is what the Input class will use to translate screen coordinates into GameSpace coordinates for the mouse.&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;It will also be involved in the Sound class to determine stereo panning for dynamic sound location.&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;And it will cooperate with GameSpace Layers to determine what is actually drawn to the screen and in what order.&lt;/span&gt; 
&lt;p&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;It does this by acting as a miniature backbuffer ... everything &amp;quot;in the Camera&amp;quot; is drawn to the Camera&amp;#39;s buffer, and then all of the active Cameras&amp;#39; buffers are drawn to the screen.&amp;nbsp;&amp;nbsp;&lt;/span&gt;The&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt; properties that are important to translating between GameSpace and Screen space are:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;strong&gt;Height &amp;amp; Width&lt;/strong&gt; -- The size of the Camera&amp;#39;s buffer that will be drawn on the screen ... if the Camera is locked to the full screen, these will be the same as the MainScreen&amp;#39;s Height and Width&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;strong&gt;ScreenX &amp;amp; ScreenY&lt;/strong&gt; -- The upper-left corner of where the Camera&amp;#39;s buffer will be drawn onto the screen&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;strong&gt;CurrentX &amp;amp; CurrentY&lt;/strong&gt; -- The current position&amp;nbsp;of the Camera&amp;#39;s center point within the GameSpace&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/span&gt;
&lt;p&gt;&lt;strong&gt;&lt;i&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Translating &amp;quot;Screen Space&amp;quot; to &amp;quot;GameSpace&amp;quot;&lt;/span&gt;&lt;/i&gt;&lt;/strong&gt;&lt;/p&gt;&lt;strong&gt;&lt;i&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;/i&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Consider this sort of setup ...&lt;/span&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;img height="300" alt="Example Nimble2D Camera Setup" src="http://www.frontiernet.net/~mattandbritt/CameraExample.jpg" width="400" border="0" /&gt;&lt;/span&gt; 
&lt;ul&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;The main screen is 400 x 300 and 3 cameras are used:&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Camera 0 - the &amp;quot;score board&amp;quot; area of the screen is drawing just layer 0 from GameSpace 0 and is not used to translate the mouse position&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Camera 1 - the &amp;quot;Main UI&amp;quot; area of the screen is drawing just layer 1 from GameSpace 0 and is not used to translate the mouse position&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;Camera 2 - the &amp;quot;Game Play&amp;quot; area; it is locked to the full size of the main screen and *is* used to translate the mouse position&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;
&lt;p&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;As the mouse is moved around the screen, its current screen position is stored within the Core.Input.Mouse structure.&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;Those values alone might work just fine in a lot of circumstances.&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;In our example, a user&amp;#39;s interaction within the &amp;quot;Main UI&amp;quot; area of the screen would likely just use the mouse&amp;#39;s screen coordinates to figure out if the user is over a button.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;However, in a moving environment -- such as most video games use -- where the game play may be scrolling around the screen, it is much better to have some way to tell where in the GameSpace the mouse pointer is currently pointing.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;To accomplish this, the NimbleInput class steps through each of the active Camera objects that have their &amp;quot;UseForMouse&amp;quot; property set to True.&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;If the Mouse&amp;#39;s screen location is within the area of the screen that the Camera is drawing to, then it uses the Camera&amp;#39;s current GameSpace location, its size, and the position it draws to the screen to calculate the Mouse&amp;#39;s GameSpace X and Y values.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;The code that does the work looks something like this:&lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span style="FONT-SIZE:8pt;FONT-FAMILY:Arial;"&gt;Mouse.GameSpaceX = Camera.CurrentX - Camera.Width / 2 + (Mouse.ScreenX - Camera.ScreenX)&lt;/span&gt;&lt;/p&gt;&lt;span style="FONT-SIZE:8pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;span style="FONT-SIZE:8pt;FONT-FAMILY:Arial;"&gt;Mouse.GameSpaceY = Camera.CurrentY - Camera.Height / 2 + (Mouse.ScreenY - Camera.ScreenY)&lt;/span&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&amp;nbsp;&lt;/span&gt; &lt;/blockquote&gt;
&lt;p class="MsoNormal" style="MARGIN:0in 0in 0pt;mso-pagination:none;mso-layout-grid-align:none;"&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;And with that, Nimble2D will provide easy-to-access information on where in your game world the mouse is currently located.&lt;/span&gt;&lt;/p&gt;&lt;img src="http://ilovevb.net/Web/aggbug.aspx?PostID=174" width="1" height="1"&gt;</content><author><name>MattWorden</name><uri>http://ilovevb.net/Web/members/MattWorden.aspx</uri></author><category term="Nimble2D" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Nimble2D/default.aspx" /><category term="GameSpace" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/GameSpace/default.aspx" /><category term="Cameras" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Cameras/default.aspx" /><category term="NimbleInput" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/NimbleInput/default.aspx" /></entry><entry><title>Another Look at the Pixel-Plotting Tests</title><link rel="alternate" type="text/html" href="http://ilovevb.net/Web/blogs/nimble2d/archive/2009/02/11/another-look-at-the-pixel-plotting-tests.aspx" /><id>http://ilovevb.net/Web/blogs/nimble2d/archive/2009/02/11/another-look-at-the-pixel-plotting-tests.aspx</id><published>2009-02-12T05:14:00Z</published><updated>2009-02-12T05:14:00Z</updated><content type="html">&lt;p&gt;Thanks to codeimp&amp;#39;s comment on my previous post, I went back to my pixel-plotting test app to add-in a LockBits method to see how it would stand up to the pure GDI+ methods.&lt;/p&gt;
&lt;p&gt;As it turns out, I found that a poorly-placed &amp;quot;End If&amp;quot; was causing the code to not draw 100,000 pixels per test ... but only 10,000 per test.&amp;nbsp; Once I corrected that, I noticed that there was some time gaps starting to show between the methods.&amp;nbsp; So, I jacked up the test amount to 1 million pixels per test and I added-in the LockBits approach as an 8th way to go about things.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;On my ancient game dev laptop (1GHz P3), I got the following results (in seconds):&lt;/p&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;1 - DrawRectangle: 52.10&lt;br /&gt;&lt;strong&gt;2 - FillRectangle: 42.90&lt;br /&gt;&lt;/strong&gt;3 - DrawEllipse: 59.34&lt;br /&gt;4 - FillEllipse: 52.03&lt;br /&gt;5 - DrawLine: 48.83&lt;br /&gt;&lt;em&gt;6 - DrawImage: 119.28&lt;br /&gt;&lt;/em&gt;7 - DrawString: 79.32&lt;br /&gt;&lt;strong&gt;8 - LockBits: 24.07&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;The relative speed of the LockBits is impressive.&amp;nbsp; However, I was surprised that the DrawImage approach was the slowest way to go.&amp;nbsp; And, FillRectangle looks to be the best of the standard GDI+ routines.&lt;/p&gt;
&lt;p&gt;Now, keep in mind that these times are for 1 million plots, pausing every 1000 to invalidate the target PicBox and run a DoEvents to update the screen.&amp;nbsp; In a normal game situation, you&amp;#39;re likely to only need to draw a few thousand specks (at most) and you won&amp;#39;t be pausing in the middle of it to make sure the screen updates.&lt;/p&gt;
&lt;p&gt;There were a couple other asthetic things that I noticed as well. The Rect methods are incapable of drawing a true single pixel ... their definition forces both methods to draw a 2x2 square instead.&amp;nbsp; Both Ellipse methods and the DrawLine method make 2-pixel long lines.&amp;nbsp; This leaves the last 3 methods for being the only ones to give you true single pixels per plot.&lt;/p&gt;
&lt;p&gt;LockBits comes out looking pretty good.&amp;nbsp; The negative is that it takes a special bulk routine to make it efficient ... can&amp;#39;t have each individual dot work as its own object that draws itself when requested.&amp;nbsp; The GDI+ routines do allow for individual drawing at the expense of speed (and some asthetics).&lt;/p&gt;&lt;img src="http://ilovevb.net/Web/aggbug.aspx?PostID=173" width="1" height="1"&gt;</content><author><name>MattWorden</name><uri>http://ilovevb.net/Web/members/MattWorden.aspx</uri></author><category term="GDI+" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/GDI_2B00_/default.aspx" /><category term="Efficiencies" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Efficiencies/default.aspx" /></entry><entry><title>Interesting Pixel-Plotting Efficiency Test Results</title><link rel="alternate" type="text/html" href="http://ilovevb.net/Web/blogs/nimble2d/archive/2009/02/09/interesting-pixel-plotting-efficiency-test-results.aspx" /><id>http://ilovevb.net/Web/blogs/nimble2d/archive/2009/02/09/interesting-pixel-plotting-efficiency-test-results.aspx</id><published>2009-02-10T02:20:00Z</published><updated>2009-02-10T02:20:00Z</updated><content type="html">&lt;p&gt;I recently ran a little experiment to see which would be the fastest way to plot a bunch of single pixels using the methods available in the System.Drawing namespace.&amp;nbsp; It turns out, for those who haven&amp;#39;t looked, that there is no set-pixel type method because everything is built to work with various unit scales -- some of which have no use for single-pixel work.&lt;/p&gt;
&lt;p&gt;I tested DrawRectangle, FillRectangle, DrawEllipse, FillEllipse, DrawLine, DrawImage (using a 1x1 rectangle from a memory bitmap that had been pre-built to have a bunch of randomly colored pixels), and even DrawString (at the right point size, the period is essentially a single pixel).&amp;nbsp; I ran each one through 100,000 pixels and stopwatch timed each one ... turns out that they were all within a couple tenths of a second of one another (less than 1% difference), except for DrawString -- that one was a couple seconds slower across 100,000 dots than the others.&lt;/p&gt;
&lt;p&gt;So, I guess that means it really doesn&amp;#39;t matter how you go about doing it ... just pick the method that fits the best into the code and gives the best on screen results.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(btw, I am still working on the &amp;quot;It&amp;#39;s All About the Cameras&amp;quot; post that I promised last time ...)&lt;/em&gt;&lt;/p&gt;&lt;img src="http://ilovevb.net/Web/aggbug.aspx?PostID=170" width="1" height="1"&gt;</content><author><name>MattWorden</name><uri>http://ilovevb.net/Web/members/MattWorden.aspx</uri></author><category term="GDI+" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/GDI_2B00_/default.aspx" /><category term="Efficiencies" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Efficiencies/default.aspx" /></entry><entry><title>NimbleInput Overview</title><link rel="alternate" type="text/html" href="http://ilovevb.net/Web/blogs/nimble2d/archive/2008/11/27/nimbleinput-overview.aspx" /><id>http://ilovevb.net/Web/blogs/nimble2d/archive/2008/11/27/nimbleinput-overview.aspx</id><published>2008-11-27T15:47:00Z</published><updated>2008-11-27T15:47:00Z</updated><content type="html">&lt;p&gt;One of the first things I like to think through is how user input will be provided in a game, and how I want to manage that within my game code.&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve become fond of working at the higher abstraction level of &amp;quot;user actions&amp;quot; within the game code itself.&amp;nbsp; I&amp;#39;d rather write my code to respond to a &amp;quot;main weapons fire&amp;quot; action than tie it directly to a certain key or mouse button press.&amp;nbsp; This allows more flexibility in user control setup, and sometimes allows a block of response code to be written before the user control details are nailed down.&lt;/p&gt;
&lt;p&gt;However, you can&amp;#39;t get actions without working through how a system will read and report the lower level input.&amp;nbsp; With this GDI-based library, I expect to be making smaller windowed games that use keyboard and mouse input.&amp;nbsp; No need at this time to get gamepad/joystick support in place ... but I&amp;#39;ll leave open some hooks to add it later, if needed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;Keyboard&lt;/u&gt;&lt;/strong&gt;&lt;br /&gt;Each update cycle, Nimble will grab the current state of all the keys on the keyboard and will do some calculations to handle situations such as &amp;quot;double hits&amp;quot; and &amp;quot;first time down&amp;quot;.&amp;nbsp; There will be some methods to test the current state of each key.&amp;nbsp; But, primarily, these states will feed into the action system.&lt;/p&gt;
&lt;p&gt;So far, I have not been able to find any built-in methods within the .Net framework to allow me to check the current state of any key on the keyboard.&amp;nbsp; (If anyone knows how to do this in standard .Net, please point me in the right direction.)&amp;nbsp; So, I will be using InterOp to tap into the same Windows API I used in the VB6 days to get the key states.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;Mouse&lt;/u&gt;&lt;/strong&gt;&lt;br /&gt;Happily, .Net does have nice real-time mouse-handling methods available, including one to get the mouse position relative to the upper-left of any form or control you supply to it.&amp;nbsp; And, the key state method mentioned above will also get the status of the mouse buttons.&amp;nbsp; So, mouse buttons will be handled as if they were just a few more keyboard keys.&lt;/p&gt;
&lt;p&gt;Once the X &amp;amp; Y of the mouse can be determined for the main screen object -- a picturebox control, in Nimble2D&amp;#39;s case -- it then has to be translated to the corresponding position within the GameSpace being shown.&amp;nbsp; So, the NimbleInput.Mouse object will have ScreenX, ScreenY, GameSpace, GameSpaceX, and GameSpaceY properties available (among others).&lt;/p&gt;
&lt;p&gt;The ability to translation to GameSpace coordinates will rely on how GameSpaces, Layers, and Cameras are setup and used within Nimble2D.&amp;nbsp; This means that I need to flesh-out the basic functions of those objects before I can implement the mouse-related input items.&amp;nbsp; And, that sets up the next post nicely.&amp;nbsp; Watch for &amp;quot;It&amp;#39;s All About the Cameras&amp;quot; to explain how that piece all works.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;Actions&lt;/u&gt;&lt;/strong&gt;&lt;br /&gt;As I mentioned at the start of this post, &amp;quot;user actions&amp;quot; are higher abstraction of the actual input being received.&amp;nbsp; The game&amp;#39;s code will be able to define typical actions needed in the game -- &amp;quot;run right&amp;quot;, &amp;quot;jump&amp;quot;, &amp;quot;fire main&amp;quot;, &amp;quot;fire secondary&amp;quot;, etc. -- and then ask NimbleInput if that action is currently &amp;quot;on&amp;quot;.&lt;/p&gt;
&lt;p&gt;Low-level input states are assigned to an action, which is what NimbleInput actually checks for to report whether an action is on or not.&amp;nbsp; This will allow for flexibility in assigning user controls at run-time, and for allowing multiple keys to trigger the same action.&amp;nbsp; For example, a game that needs a simple 4-key control method (&amp;quot;up&amp;quot;, &amp;quot;down&amp;quot;, &amp;quot;left&amp;quot;, &amp;quot;right&amp;quot;) could allow for both the traditional arrow keys, plus the W-A-S-D keys to provide that control ... or even to allow the user to select his/her own keys controls for each action needed.&lt;/p&gt;
&lt;p&gt;Taking that example to a finer detail level ... The game code could define an action of &amp;quot;Up&amp;quot; and assign both the &amp;quot;Up Arrow&amp;quot; and &amp;quot;W&amp;quot; keys to that action.&amp;nbsp; During the game loop, a request for the status of the &amp;quot;Up&amp;quot; action would have NimbleInput checking the states of both the assigned keys.&amp;nbsp; If either key is currently down, then a &amp;quot;TRUE&amp;quot; value would be passed back to indicate that the action is currently on.&lt;/p&gt;
&lt;p&gt;There will be different action assignment methods available to cover situations such as single key presses, double key presses (&amp;quot;double clicks&amp;quot;), absolute mouse locations and relative mouse locations.&amp;nbsp; The mouse location assignments should make things easier for handling mouse-over of menu items or mouse-steering.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;General Methods&lt;/u&gt;&lt;/strong&gt;&lt;br /&gt;A few basic general methods will also be provided, such as clearing all keys (makes them all read as &amp;quot;up&amp;quot; until they are pressed again later) and checking for &amp;quot;any key pressed&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;More Details Coming&lt;/u&gt;&lt;/strong&gt;&lt;br /&gt;As I mentioned in the &amp;quot;mouse&amp;quot; section above, some of the basic graphical objects and features need to be put in place before we can work out the mouse location.&amp;nbsp; So, once the GameSpaces, Layers, Main Screen, and Cameras are worked out, I&amp;#39;ll come back with a more detailed look (including code) at NimbleInput.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://ilovevb.net/Web/aggbug.aspx?PostID=166" width="1" height="1"&gt;</content><author><name>MattWorden</name><uri>http://ilovevb.net/Web/members/MattWorden.aspx</uri></author><category term="NimbleOverview" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/NimbleOverview/default.aspx" /><category term="NimbleInput" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/NimbleInput/default.aspx" /></entry><entry><title>Using the clsGameClock Class</title><link rel="alternate" type="text/html" href="http://ilovevb.net/Web/blogs/nimble2d/archive/2008/10/20/using-the-clsgameclock-class.aspx" /><id>http://ilovevb.net/Web/blogs/nimble2d/archive/2008/10/20/using-the-clsgameclock-class.aspx</id><published>2008-10-21T00:23:00Z</published><updated>2008-10-21T00:23:00Z</updated><content type="html">&lt;p&gt;The previous post introduced the Game Clock class that I&amp;#39;ll be using with the Nimble libraries and walked through a few concepts that were considered in putting the class together.&amp;nbsp; I mentioned in that post that I wanted the system to be flexible enough to fit the style of the programmer using it -- allowing everything from lock-frame timing to simple delta-time to handling split update/present cycles.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Simple Delta-Time - &lt;/strong&gt;The simplest way to use the Game Clock is simple delta-time, with a single update and present on each game loop.&amp;nbsp; It is as simple as this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#39;Declarations&lt;br /&gt;Private GameClock as New clsGameClock()&lt;br /&gt;&amp;#39;----------&lt;/p&gt;
&lt;p&gt;&amp;#39;In Game Loop ...&lt;br /&gt;GameClock.Update&lt;/p&gt;
&lt;p&gt;UpdateGameObjects()&lt;/p&gt;
&lt;p&gt;DrawAllGameObjects()&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;Inside your &amp;quot;UpdateGameObjects&amp;quot;, you would use GameClock.DeltaTime and GameClock.DeltaTime_Raw as the multiplier for any physics math.&amp;nbsp; During &amp;quot;DrawAllGameObjects&amp;quot;, you can use GameClock.CPS to show the cycles-per-second rate of the game.&amp;nbsp; Finally, GameClock.SpeedFactor can be adjusted to speed up and slow down the on-screen action.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lock-Frame - &lt;/strong&gt;It&amp;#39;s quite easy to switch to a lock-frame approach.&amp;nbsp; Just adjust the GameClock.MinimumDelta value to fit the number of frames to be targetted each second:&lt;/p&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#39;In Setup&lt;br /&gt;&amp;#39;&amp;nbsp;&amp;nbsp;&amp;nbsp; To Target 50 frames-per-second&lt;br /&gt;GameClock.MinimumDelta = 1/50&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;Of course, when using lock-frame, you may not want to use the .DeltaTime values ... just update the same amount each loop.&amp;nbsp; But then you lose the added benefit of having an automated SpeedFactor available if you have a need to add slow-down effects.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Splitting Update/Present -&lt;/strong&gt; And that brings us to a more complex idea ... splitting your game logic update cycles from your presentation frames.&amp;nbsp; The concept is to cycle through your game logic as many times as possible while still leaving enough time to draw everything once within a target frame rate.&amp;nbsp; This done by getting an estimate of how long it is taking to draw everything and how much time it takes to get through a single game logic update cycle.&amp;nbsp; There is a check against the target total time wanted to take for a complete loop ... and if there is enough time left to work in another game logic cycle then we do.&lt;/p&gt;
&lt;p&gt;In both cases, we base our estimates on the previous loop ... and, as a failsafe, we give ourselves a way to trigger the system to pair a single logic loop with the next draw loop.&amp;nbsp; This single-cycle trigger would be used in a case where we&amp;#39;ve drastically changed the number of objects that need to be updated and/or drawn.&amp;nbsp; Maybe we&amp;#39;ve switched from a menu to the start of the next level.&amp;nbsp; Or, maybe there was an explosion and we&amp;#39;ve just popped 100 new objects onto the screen.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s look at the code, and then walk through things ...&lt;/p&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#39;Declarations&lt;br /&gt;Private TargetLoopTime As Double&lt;br /&gt;Private LastDrawStart As Double, LastLoopStart As Double&lt;br /&gt;Private SingleCycleOnce As Boolean&lt;br /&gt;&amp;#39;----------&lt;/p&gt;
&lt;p&gt;&amp;#39;In Setup&lt;br /&gt;&amp;#39;&amp;nbsp;&amp;nbsp; To Target drawing a new frame 40 times per second&lt;br /&gt;TargetLoopTime = 1/40&lt;/p&gt;
&lt;p&gt;&amp;#39;Set the system to only do a single update loop the first time&lt;br /&gt;SingleCycleOnce = True&lt;br /&gt;&amp;#39;----------&lt;/p&gt;
&lt;p&gt;&amp;#39;In Game Loop ...&lt;/p&gt;
&lt;p&gt;&amp;#39; === Game Logic Update Loops&lt;br /&gt;Do&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;#39;Update Clock&lt;br /&gt;&amp;nbsp;&amp;nbsp; myGameClock.Update()&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;#39;Record update loop&amp;#39;s start time&lt;br /&gt;&amp;nbsp;&amp;nbsp; LastLoopStart = myGameClock.GameTime&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp; UpdateGameObjects()&lt;/p&gt;
&lt;p&gt;Loop Until SingleCycleOnce Or _&lt;br /&gt;&amp;nbsp;&amp;nbsp; (((myGameClock.GameTime_Live - LastDrawStart) + _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (myGameClock.GameTime_Live - LastLoopStart)) &amp;gt;= myTargetLoopTime)&lt;/p&gt;
&lt;p&gt;&amp;#39;Reset Single Cycle Once flag&lt;br /&gt;SingleCycleOnce = False&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&amp;#39; === Draw to Game Screen&lt;/p&gt;
&lt;p&gt;&amp;#39;Wait if we are drawing too early in the total cycle&lt;br /&gt;Do&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;#39;Nothing&lt;br /&gt;Loop Until myGameClock.GameTime_Live - LastDrawStart &amp;gt;= myTargetLoopTime&lt;/p&gt;
&lt;p&gt;&amp;#39;Capture GameTime before Draw Starts&lt;br /&gt;LastDrawStart = GameClock.GameTime_Live&lt;/p&gt;
&lt;p&gt;DrawAllGameObjects()&lt;/p&gt;
&lt;p&gt;&amp;#39;Let GameClock know about screen refresh&lt;br /&gt;GameClock.FrameDrawn()&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;We first pick a target for how long it should take before drawing the next frame.&amp;nbsp; As an example, to refresh the game screen 40 times per second, we set our TargetLoopTime to 1/40.&amp;nbsp; With that timeframe set, we have our guide in which to fit our multiple logic loops plus a single draw loop.&lt;/p&gt;
&lt;p&gt;Then we start our game logic loops.&amp;nbsp; The game clock is updated to get the latest delta and to keep count&amp;nbsp;of the&amp;nbsp;cycles, and we record the game time at the start of our logic updates.&amp;nbsp; We allow all of the objects to update themselves and we check if we have enough time to make another loop.&amp;nbsp; Also, if we&amp;#39;ve had a reason to drop out of the logic looping early, it will do that as well.&lt;/p&gt;
&lt;p&gt;The SingleCycleOnce flag allows the program code to catch situations where the logic and/or draw cycles will take longer than they have been.&amp;nbsp; Perhaps a new wave of enemies has just hit the gamespace, or a large particle effect, etc.&amp;nbsp; In that case, we simply need to set SingleCycleOnce to TRUE to get the update/draw loop to run as quickly as possible and re-evaluate the time needed to get everything done.&lt;/p&gt;
&lt;p&gt;Once the updates are done, the game time that the Draw cycle starts is captured to be used during the next set of logic loops.&amp;nbsp; Finally, we let the GameClock know that a frame has been drawn in order to let it track FPS separately from CPS.&lt;/p&gt;
&lt;p&gt;You&amp;#39;ll notice that this system is very conservative -- only gaining extra logic loops when it is fairly sure to have enough time to get them in.&amp;nbsp; The reasoning is that having a steady FPS is very important for a nice player experience ... it&amp;#39;s better to sacrifice one extra logic loop than to have it drop to a slower framerate.&amp;nbsp; At its slowest, the system ensures 1 logic cycle and 1 draw cycle -- the same as running on simple delta time.&lt;/p&gt;
&lt;p&gt;I&amp;#39;ll be working a system similar to this into Nimble2D&amp;#39;s Core class.&amp;nbsp; It will be initially setup to default to a straight, simple delta-time system with a single logic cycle followed by a single draw cycle -- CPU will be the same as FPU.&amp;nbsp; However, with a few simple changes, the game can be running on a split cycle system with measurements for each cycle rate.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://ilovevb.net/Web/aggbug.aspx?PostID=163" width="1" height="1"&gt;</content><author><name>MattWorden</name><uri>http://ilovevb.net/Web/members/MattWorden.aspx</uri></author><category term="Nimble2D" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Nimble2D/default.aspx" /><category term="Timing &amp;amp; Interactions" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Timing+_2600_amp_3B00_+Interactions/default.aspx" /></entry><entry><title>Tick-Tock Game Clock</title><link rel="alternate" type="text/html" href="http://ilovevb.net/Web/blogs/nimble2d/archive/2008/10/20/tick-tock-game-clock.aspx" /><id>http://ilovevb.net/Web/blogs/nimble2d/archive/2008/10/20/tick-tock-game-clock.aspx</id><published>2008-10-20T16:58:00Z</published><updated>2008-10-20T16:58:00Z</updated><content type="html">&lt;p&gt;There are some things needed in a game that are independent of the graphics system.&amp;nbsp; One of them is the system used to keep track of time passing as the game runs.&amp;nbsp; I prefer to work with a delta-time based system.&amp;nbsp; This means that we figure out how much time has passed since the last loop and use that -- whatever it may be -- to handle our logic, physics calcs, collision detection, etc.&amp;nbsp; The other traditional way of doing things is to lock on to a consistent loop rate and then you can assume things will be happen in the same amounts each loop.&lt;/p&gt;
&lt;p&gt;It&amp;#39;s also a good idea to separate game logic (object movement &amp;amp; changes, AI, physics, etc.) from user presentation (graphics and sound).&amp;nbsp; To give a realistic experience, you only need to update the presentation about 30 frames per second.&amp;nbsp; (However, updating more often can give a more intense experience.)&amp;nbsp; Game logic can usually benefit from looping as quickly as possible -- small time deltas allow for easier and more responsive collision checks, physics and AI.&amp;nbsp; The approach would then be to cycle through the game logic as many times as possible while still leaving enough time to draw everything at the wanted presentation rate.&lt;/p&gt;
&lt;p&gt;I would like Nimble2D to provide ways to take any of these approaches.&amp;nbsp; And this all starts with how the game clock system works.&amp;nbsp; Let&amp;#39;s walk through a few concepts to get to our complete clsGameClock class to see what&amp;#39;s going on there.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Concept 1 - DeltaTime -&lt;/strong&gt; VB.Net provides a very nice Stopwatch object that works very similarly to a handheld stopwatch.&amp;nbsp; It can be started, stopped, reset, and asked for the current elapsed time.&amp;nbsp; If a high precision timer is available through the OS, it will use that.&amp;nbsp; The elapsed time can be reported in milliseconds, seconds, and several other deliminations.&amp;nbsp; The general idea with a game clock is to get a Stopwatch running, and then check how much time has elapsed on each game logic loop.&amp;nbsp; The difference from one loop to the next will be your &amp;quot;delta time&amp;quot;.&amp;nbsp; It is used with your game objects&amp;#39; velocity, acceleration, etc., to update their positions.&lt;/p&gt;
&lt;p&gt;For example, if an object is moving at 300 pixels per second and your DeltaTime is captured in seconds, then in a single game loop the object will move a distance of 300 * DeltaTime.&lt;/p&gt;
&lt;p&gt;Our DeltaTime-finding code would look like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#39;Declarations ...&lt;br /&gt;Private SW As Stopwatch&lt;br /&gt;Private myLastTime As Double, myDeltaTime as Double&lt;br /&gt;&amp;#39;----------&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#39;In the Constructor ...&lt;br /&gt;SW = New Stopwatch()&lt;br /&gt;SW.Start()&lt;br /&gt;myLastTime = 0.0F&lt;br /&gt;myDeltaTime = 0.0F&lt;br /&gt;&amp;#39;----------&lt;/p&gt;
&lt;p&gt;&amp;#39;In the Update method ...&lt;br /&gt;myDeltaTime = SW.Elapsed.TotalSeconds - myLastTime&lt;br /&gt;myLastTime = SW.Elapsed.TotalSeconds&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Concept 2 - Careful with Data Types -&lt;/strong&gt; In the previous post, I mentioned wanting to avoid data type conversions whenever possible.&amp;nbsp; The Stopwatch uses a Double time to give the best possible precision to the elapsed time when working in seconds.&amp;nbsp; However, GDI generally likes to work with Single data types.&amp;nbsp; So, once we capture our DeltaTime, we will convert it to a Single data type and provide that for anything that needs a DeltaTime value.&amp;nbsp; This will mean that object variables for velocities, accelerations, etc., should be held as Singles and multiplied by the Single DeltaTime to get a Single result (such as a position) which can be used by GDI without having to do extra data type conversions along the way.&amp;nbsp; In other words, we&amp;#39;re purposely doing 1 data conversion per loop to avoid multiple conversions per object per loop.&lt;/p&gt;
&lt;p&gt;This adds the following things to our code:&lt;/p&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#39;Declaration ...&lt;br /&gt;Private sngDelta As Single&lt;br /&gt;&amp;#39;----------&lt;/p&gt;
&lt;p&gt;&amp;#39;In the Update method, after the value for myDeltaTime is found&lt;br /&gt;sngDelta = CSng(myDeltaTime)&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Concept 3 - Minimum DeltaTime -&lt;/strong&gt; There are a lot of reasons to have an assumed &amp;quot;smallest possible delta time&amp;quot;.&amp;nbsp; For true DeltaTime users, having a minimum DeltaTime will avoid problems on very, very fast machines providing extremely small DeltaTime values, which may play havoc with phyics math.&amp;nbsp; For those who like locked frame rates, you can use a larger minimum DeltaTime (such as 1/40 for 40 frames-per-second) to cause the gameclock to be the governor of the frame timing.&amp;nbsp; While waiting for the minimum DeltaTime, we should allow the application to DoEvents so that form events can be responded to.&lt;/p&gt;
&lt;p&gt;To make this happen, the following code elements are added:&lt;/p&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#39;Declaration ...&lt;br /&gt;Private myMinDelta As Double&lt;br /&gt;&amp;#39;----------&lt;/p&gt;
&lt;p&gt;&amp;#39;In the Constructor ...&lt;br /&gt;&amp;#39;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; A Minimum DeltaTime can be passed as a parameter&lt;br /&gt;Public Sub New(Optional ByVal MinimumDelta As Double = 0.0001F)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; myMinDelta = MinimumDelta&lt;br /&gt;&amp;#39;----------&lt;/p&gt;
&lt;p&gt;&amp;#39;In the Update method, replace what we&amp;#39;ve already done with ...&lt;br /&gt;Do&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Application.DoEvents()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; myDeltaTime = SW.Elapsed.TotalSeconds - myLastTime&lt;br /&gt;Loop Until myDeltaTime &amp;gt;= myMinDelta&lt;/p&gt;
&lt;p&gt;myLastTime = SW.Elapsed.TotalSeconds&lt;br /&gt;sngDelta = CSng(myDeltaTime)&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Concept 4 - Speed Factor -&lt;/strong&gt; To allow for special effects along the lines of slowing everything down (&amp;quot;bullet time&amp;quot;) or speeding everything up at the same time, we can include a &amp;quot;speed factor&amp;quot; to be applied to the DeltaTime.&amp;nbsp; Normally, this will just be at a value of 1.0f.&amp;nbsp; However, for example, it could be adjusted to 0.5f to slow things down to half-speed, or to 2.0f for double-time.&amp;nbsp; If our DeltaTime is going to be adjusted by this SpeedFactor value, then we should also provide a &amp;quot;raw&amp;quot; version of DeltaTime for those things that should be moving at normal speed at all times (like camera movement ... or a main character during a &amp;quot;timewarp&amp;quot; effect).&lt;/p&gt;
&lt;p&gt;It only take a little extra code to make this work:&lt;/p&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#39;Declarations ...&lt;br /&gt;Private mySpeedFactor As Double&lt;br /&gt;Private sngDeltaRaw As Double&lt;br /&gt;&amp;#39;----------&lt;/p&gt;
&lt;p&gt;&amp;#39;In the Update method, change the DeltaTime setting to ...&lt;br /&gt;sngDelta = CSng(myDeltaTime * mySpeedFactor)&lt;br /&gt;sngDeltaRaw = CSng(myDeltaTime)&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Concept 5 - CPS -&lt;/strong&gt; The game clock is a great place to put cycles-per-second tracking code.&amp;nbsp; This is a pretty typical measurement used by game programmers to monitor just how fast things are working.&amp;nbsp; (Normally, this is referred to as &amp;quot;frames per second&amp;quot;, but since we might be tracking game logic cycles separate from frame drawing cycles, I&amp;#39;m giving this the more generic &amp;quot;cycles-per-second&amp;quot; label.)&amp;nbsp; This can be done by simply counting the number of times the Update method is called during the past second, then storing that value for reporting.&lt;/p&gt;
&lt;p&gt;The code looks like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#39;Declarations&lt;br /&gt;Private CycleTime As Double, CycleCount As Integer, CurCPS As Integer&lt;br /&gt;&amp;#39;----------&lt;/p&gt;
&lt;p&gt;&amp;#39;In the Update method, the following code is added at the end ...&lt;br /&gt;CycleTime = CycleTime + myDeltaTime&lt;br /&gt;CycleCount = CycleCount + 1&lt;/p&gt;
&lt;p&gt;If CycleTime &amp;gt; 1.0F Then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CurCPS = CycleCount&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CycleCount = 0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CycleTime = CycleTime - 1.0F&lt;br /&gt;End If&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;This wraps up the major concepts.&amp;nbsp; Add in some Properties for exposing information that will be useful to the rest of the game, and some code for pausing, restarting, and resetting ... and you&amp;#39;ll get the entire clsGameClock class.&amp;nbsp; Get the full VB file here: &lt;a class="" title="clsGameClock Class VB Code" href="http://ilovevb.net/Web/files/folders/nimble2d/entry162.aspx" target="_blank"&gt;LINK&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This doesn&amp;#39;t yet address how to go about splitting your game logic loops from your drawing loops.&amp;nbsp; That will be covered in the next post about how to make use of the clsGameclock class.&lt;br /&gt;&lt;/p&gt;&lt;img src="http://ilovevb.net/Web/aggbug.aspx?PostID=161" width="1" height="1"&gt;</content><author><name>MattWorden</name><uri>http://ilovevb.net/Web/members/MattWorden.aspx</uri></author><category term="Nimble2D" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Nimble2D/default.aspx" /><category term="Efficiencies" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Efficiencies/default.aspx" /><category term="Timing &amp;amp; Interactions" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Timing+_2600_amp_3B00_+Interactions/default.aspx" /></entry><entry><title>Making GDI+ Nimble</title><link rel="alternate" type="text/html" href="http://ilovevb.net/Web/blogs/nimble2d/archive/2008/10/16/making-gdi-nimble.aspx" /><id>http://ilovevb.net/Web/blogs/nimble2d/archive/2008/10/16/making-gdi-nimble.aspx</id><published>2008-10-16T19:58:00Z</published><updated>2008-10-16T19:58:00Z</updated><content type="html">&lt;p&gt;One thing that the GDI+ (System.Drawing namespace in VB.Net) system is *not* is overly quick.&amp;nbsp; It does a great job of certain things required by a more general, modern OS-based drawing system -- fonts, alpha, lines &amp;amp; shapes, etc.&amp;nbsp; But it isn&amp;#39;t game-graphics quick.&lt;/p&gt;
&lt;p&gt;Mainly, it uses the CPU to do its work (as opposed to the graphics card&amp;#39;s GPU, like DirectX and OpenGL use) ... and the CPU is already busy trying to take care of overthing else going on (memory management, math calculations, input/output routing, etc.).&amp;nbsp; So, there are some things that we&amp;#39;ll want to keep in mind when working in the GDI for game graphics.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Read Up:&lt;/strong&gt;&amp;nbsp; First, read up on how the GDI works.&amp;nbsp; Here&amp;#39;s a great site for higher-level overviews and some lower-level tips and tricks: &lt;a class="" title="Bob Powell&amp;#39;s GDI+ FAQ" href="http://www.bobpowell.net/gdiplus_faq.htm" target="_blank"&gt;http://www.bobpowell.net/gdiplus_faq.htm&lt;/a&gt; ... Also, Microsoft&amp;#39;s very own official doco page is here: &lt;a class="" title="Microsoft MSDN GDI+ Doco Page" href="http://msdn.microsoft.com/en-us/library/ms533798.aspx" target="_blank"&gt;http://msdn.microsoft.com/en-us/library/ms533798.aspx&lt;/a&gt;.&amp;nbsp; These in-depth resources will be useful when you&amp;#39;re trying to squeeze the last couple performance drops out of the GDI.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Keep Things Compact:&lt;/strong&gt;&amp;nbsp; One of the best things for speeding up the GDI is keeping things as small as possible while still being able to deliver the game experience you&amp;#39;re looking for.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Play Area:&lt;/em&gt;&amp;nbsp; The size of the &amp;quot;play area&amp;quot; (the on-screen window used to show what&amp;#39;s going on in the game) will have an overall effect on speed.&amp;nbsp; The bigger it is, the longer it takes to clear, the more surface area available to draw game objects too, and the longer it takes to draw the backbuffer to the screen object.&amp;nbsp; While not impossible to go 800x600 (a pretty traditional size for retro-style games) on your play area, it will simply mean that the CPU requirement for your end-users will need to be bumped up.&amp;nbsp; Doing &amp;quot;mini-games&amp;quot; at 500x500 or 640x480 (another traditional size) is very doable.&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Game Object Sizes:&lt;/em&gt;&amp;nbsp; Similar to the impact of size on the play area, the size of your actual in-screen game object graphics will matter.&amp;nbsp; Drawing screen-sized backgrounds will have a greater impact than clearing the game screen to a solid color and drawing just a few smaller items in as the background.&amp;nbsp; Keeping items that appear in number (particles, explosions, bullets, HUD and UI items, etc.) smaller is even more important.&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Game Object Counts:&lt;/em&gt;&amp;nbsp; Limiting the number of game objects being drawn on screen in any particular loop is an area of important balance.&amp;nbsp; You want to provide the player with a certain type of game experience.&amp;nbsp; Sometimes, this requires a lot of stuff happening on-screen at the same time.&amp;nbsp; But the &amp;quot;feel&amp;quot; of the game will be diminished if it becomes chunky and slow while all of those things are happening.&amp;nbsp; So, balancing the two (and keeping an eye on the CPU horsepower requirements) will be a good challenge for a game programmer using GDI.&amp;nbsp; One quick solution is to have a (moveable) cap on particles and other things that appear in bulk but are mainly for eye candy.&amp;nbsp; When we get into putting some particles on the screen, I&amp;#39;ll show a &amp;quot;particle manager&amp;quot; class that handles the limiting by ditching older particles for newer ones when its at the limit.&amp;nbsp; We&amp;#39;ll also work through how to auto-test and auto-adjust these systems to be able to give those with better computers a &amp;quot;thicker&amp;quot; experience and still allow those with slower machines to play the game in an enjoyable manner.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Testing for Gaphics Efficiency:&amp;nbsp; &lt;/strong&gt;In a lot of cases, there may be 2 or more ways to accomplish a similar effect.&amp;nbsp; If it seems that it might be a routine that is called often enough, it would be best to find the fastest way to deliver what you&amp;#39;re after.&amp;nbsp; What&amp;#39;s the fastest way to draw a 2x2 solid colored square?&amp;nbsp; DrawRectangle?&amp;nbsp; FillRectangle?&amp;nbsp; DrawLine?&amp;nbsp; DrawImage (with a 2x2 bitmap)?&amp;nbsp; To be honest, I&amp;#39;m not really sure ... but I plan to test these things as I come across them.&amp;nbsp; I&amp;#39;ll do some searching for other&amp;#39;s advice and I&amp;#39;ll run some tests similar to what Almar Joling used to do on his VBfibre site (&lt;a class="" title="Almar Joling&amp;#39;s VBfibre website" href="http://www.persistentrealities.com/vbfibre" target="_blank"&gt;http://www.persistentrealities.com/vbfibre&lt;/a&gt;).&amp;nbsp; Once I have my answer, I&amp;#39;ll code that as my go-to routine for that effect.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Coding for Efficiency Everywhere Else:&lt;/strong&gt;&amp;nbsp; There are typical programming things that can be done to speed up the rest of your code, freeing up extra cycles for graphics drawing (and making things smoother overall).&amp;nbsp; Avoiding type conversions or heavy calcs inside loops, etc.&amp;nbsp; These are the typical good coding practices that we should be doing anyway ... but now we have an extra reason.&amp;nbsp; (Full disclosure:&amp;nbsp; I am *not* well brushed up on good coding practices in general ... so, feel free to help me out and point our areas where I can improve ... seriously!)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Beware the Garbage Collector:&amp;nbsp; &lt;/strong&gt;Garbage Collectors are nice, helpful and good things.&amp;nbsp; But you just don&amp;#39;t want them to come calling mid-game-loop ... they seem to want to show up when your right in a very intense moment in the game.&amp;nbsp; When they do their thing, they steal CPU cycles away from your game and usually cause it to give a big hitch.&amp;nbsp; This can really mess with your physics and logic calcs and generally makes the game look chunk and slow, if only for a fraction of a second.&amp;nbsp; To avoid this, use a create-hold-dispose approach for objects, where the drawing objects it needs (brushes, pens, bitmaps, paths, etc.) are created when the object is first instantiated.&amp;nbsp;&amp;nbsp;They&amp;#39;re held for the life of the object, and then finally properly disposed of when the object is being destroyed.&amp;nbsp; It&amp;#39;s also important that you are careful of when you create and destroy your game objects.&amp;nbsp; Use &amp;quot;manager&amp;quot; classes to pre-create the number of game objects you will likely need during the intense part of the game ... then release them during &amp;quot;between level&amp;quot; and other slower times in the game.&lt;/p&gt;
&lt;p&gt;The (lack of) speed of the GDI+ system was raised in a comment on my previous post ... and it&amp;#39;s a valid concern.&amp;nbsp; But there are advantages to using GDI+ -- mainly having to do with compatibility and ease of development and deployment.&amp;nbsp; If a&amp;nbsp;fun game can be made made quickly and easily distributed to work on a lot of machines, that&amp;#39;s a good thing.&amp;nbsp; The trick is keeping a realistic viewpoint -- we won&amp;#39;t be creating monster games ... but it should be the perfect fit for small games.&lt;/p&gt;&lt;img src="http://ilovevb.net/Web/aggbug.aspx?PostID=160" width="1" height="1"&gt;</content><author><name>MattWorden</name><uri>http://ilovevb.net/Web/members/MattWorden.aspx</uri></author><category term="GDI+" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/GDI_2B00_/default.aspx" /><category term="Efficiencies" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Efficiencies/default.aspx" /></entry><entry><title>Done Pondering, Shifting Gears</title><link rel="alternate" type="text/html" href="http://ilovevb.net/Web/blogs/nimble2d/archive/2008/09/22/done-pondering-shifting-gears.aspx" /><id>http://ilovevb.net/Web/blogs/nimble2d/archive/2008/09/22/done-pondering-shifting-gears.aspx</id><published>2008-09-23T03:24:00Z</published><updated>2008-09-23T03:24:00Z</updated><content type="html">&lt;p&gt;As my last post detailed (a couple of months ago), I came to a crossroads and have figured out a direction to go.&amp;nbsp; The games I hope to make in the near future are not very complex and do not require amazing graphics capabilities.&amp;nbsp; So, I will take this blog down a more generic path in 2D game programming.&lt;/p&gt;
&lt;p&gt;Although I plan to use VB.Net and the .Net framework&amp;#39;s built-in 2D Graphics capabilities, I hope to keep things at a more drawing-system-agnostic level.&amp;nbsp; This can&amp;#39;t be done completely, because your choice drawing system determines a lot of the detailed options available for drawing things ... and that will determine how to track and organize some data.&lt;/p&gt;
&lt;p&gt;My rate of posting will not be very fast either.&amp;nbsp; If I can average a post or two per month, then I&amp;#39;ll be a happy guy.&amp;nbsp; If I get some games completed, I&amp;#39;ll be even happier! ;-)&lt;/p&gt;
&lt;p&gt;So, keep an eye out and see what I have to offer here.&lt;/p&gt;
&lt;p&gt;Thanks for reading!&lt;/p&gt;&lt;img src="http://ilovevb.net/Web/aggbug.aspx?PostID=156" width="1" height="1"&gt;</content><author><name>MattWorden</name><uri>http://ilovevb.net/Web/members/MattWorden.aspx</uri></author><category term="NimbleOverview" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/NimbleOverview/default.aspx" /><category term="Nimble2D" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Nimble2D/default.aspx" /></entry><entry><title>Pondering Pause</title><link rel="alternate" type="text/html" href="http://ilovevb.net/Web/blogs/nimble2d/archive/2008/06/29/pondering-pause.aspx" /><id>http://ilovevb.net/Web/blogs/nimble2d/archive/2008/06/29/pondering-pause.aspx</id><published>2008-06-29T20:47:00Z</published><updated>2008-06-29T20:47:00Z</updated><content type="html">&lt;p&gt;So, it&amp;#39;s been a few months since I posted here.&amp;nbsp; But, it&amp;#39;s not like I&amp;#39;ve been slacking.&amp;nbsp; I&amp;#39;ve even fleshed out some of the start-up sequence code for Nimble (I ended up changing one of my dev machines, and that caused me to need to do some extra caps checks and respond properly to what was found).&amp;nbsp; And then there is work and a half-dozen other &amp;quot;free time&amp;quot; projects (won&amp;#39;t go into a list here).&lt;/p&gt;
&lt;p&gt;&amp;nbsp;But, now we&amp;#39;ve come to a point where I need to stop and ponder a few things.&amp;nbsp; First, &lt;a class="" title="SlimDX June 2008 Release" href="http://code.google.com/p/slimdx/wiki/Downloads?tm=2" target="_blank"&gt;SlimDX has their June 2008 release&lt;/a&gt; out, which changes a few things ... and I think it would be best to bring Nimble up to the latest-and-greatest.&amp;nbsp; Second, I&amp;#39;ve been thinking through the games I&amp;#39;d like to get to making.&amp;nbsp; The responses I&amp;#39;ve gotten from the &lt;a class="" title="Air Rally Ace Tech Demo" href="http://ilovevb.net/Web/files/folders/nimble2d/entry115.aspx" target="_blank"&gt;ARA Tech Demo&lt;/a&gt; (plus some of my own re-tinkering) have made that fade from my mind as my &amp;quot;next big project&amp;quot;.&amp;nbsp; I find myself sliding back to my strategy/board gaming roots.&amp;nbsp; And those sorts of games wouldn&amp;#39;t really require a full Nimble2D-type engine to get to coding them ... in fact, they could probably be done using straight Graphics.Drawing calls.&amp;nbsp; Finally, I&amp;#39;ve found myself paying some attention to &lt;a class="" href="http://forums.indiegamer.com/showpost.php?p=157689&amp;amp;postcount=8" target="_blank"&gt;some wise advice&lt;/a&gt; I received from one of the folks hanging out at the &lt;a class="" title="Indiegamer Forums" href="http://forums.indiegamer.com/index.php" target="_blank"&gt;Indiegamers Forums&lt;/a&gt; -- find/build an engine to use quickly, so that games can get made.&lt;/p&gt;
&lt;p&gt;And now I&amp;#39;m off on a week&amp;#39;s vacation ... and I plan to do some pondering.&amp;nbsp; Advice and comments are always welcome! :-)&lt;/p&gt;&lt;img src="http://ilovevb.net/Web/aggbug.aspx?PostID=150" width="1" height="1"&gt;</content><author><name>MattWorden</name><uri>http://ilovevb.net/Web/members/MattWorden.aspx</uri></author><category term="NimbleOverview" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/NimbleOverview/default.aspx" /><category term="KudosToOthers" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/KudosToOthers/default.aspx" /><category term="SlimDX" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/SlimDX/default.aspx" /></entry><entry><title>My "QuickTrig" Helper Class</title><link rel="alternate" type="text/html" href="http://ilovevb.net/Web/blogs/nimble2d/archive/2008/03/08/my-quot-quicktrig-quot-helper-class.aspx" /><id>http://ilovevb.net/Web/blogs/nimble2d/archive/2008/03/08/my-quot-quicktrig-quot-helper-class.aspx</id><published>2008-03-08T17:22:00Z</published><updated>2008-03-08T17:22:00Z</updated><content type="html">&lt;p&gt;I&amp;#39;ve uploaded a ZIP file that contains the source code for the &amp;quot;QuickTrig&amp;quot; helper class that I&amp;#39;ve mentioned a couple of times now.&amp;nbsp; You can get it by &lt;a class="" title="QuickTrig Helper Class Source Code" href="http://ilovevb.net/Web/files/folders/nimble2d/entry110.aspx" target="_blank"&gt;clicking this link&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For those curious, looking through that should help explain how I can handle my angles primarily in degrees (as mentioned in my previous post).&lt;/p&gt;
&lt;p&gt;Feel free to give it a look ... and use it if it helps you out.&amp;nbsp; Performance-wise, I&amp;#39;ve found the COS and SIN look-up functions to take half the time of the comparable Math.Cos and Math.Sin traditional functions.&amp;nbsp; While the speed increase is nice, being able to just work in degrees with the rest of my code is the biggest help given by this class.&lt;/p&gt;
&lt;p&gt;-Matt&lt;/p&gt;&lt;img src="http://ilovevb.net/Web/aggbug.aspx?PostID=111" width="1" height="1"&gt;</content><author><name>MattWorden</name><uri>http://ilovevb.net/Web/members/MattWorden.aspx</uri></author><category term="Nimble2D" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Nimble2D/default.aspx" /></entry><entry><title>Units of Measure</title><link rel="alternate" type="text/html" href="http://ilovevb.net/Web/blogs/nimble2d/archive/2008/02/22/units-of-measure.aspx" /><id>http://ilovevb.net/Web/blogs/nimble2d/archive/2008/02/22/units-of-measure.aspx</id><published>2008-02-23T03:21:00Z</published><updated>2008-02-23T03:21:00Z</updated><content type="html">&lt;p&gt;I&amp;#39;ve been working through some auto-moving sprite functionality, and have wandered a bit further down that road than I&amp;nbsp;originally expected to at this point&amp;nbsp;... so now I need to back up a bit to get back on the main route of progress.&amp;nbsp; Here is my list of current things to do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div&gt;Finish fleshing-out my auto-move sprite class (going to set it up to work like a cross between a simple-but-somewhat-intelligent game object and a particle)&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Crop things down into a &amp;quot;base&amp;quot; sprite class ... and change the auto-move sprite to inherit from the base&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Build the primative (circle, rectangle, triangle, line) sprites from the base sprite&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Finish the initial camera functionality (sprite-following, defined bounds, and defined viewports -- leading to multiple cameras in a GameSpace and &amp;quot;split screens&amp;quot; ... &lt;em&gt;btw: thanks once again to the &lt;/em&gt;&lt;a class="" title="XNA Machine Blog" href="http://xnamachine.blogspot.com/2008/02/2d-scenecamera-near-completion.html"&gt;&lt;em&gt;XNA Machine Blog&lt;/em&gt;&lt;/a&gt;&lt;em&gt;&amp;nbsp;who is taking a slightly different approach to similar terrain -- and that&amp;#39;s helping me see things in new ways as well&lt;/em&gt;)&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Once I get that far, I should be ready to compile a quick demo on how the camera and sprite basics work.&lt;/p&gt;
&lt;p&gt;But I wanted to be sure to touch upon a couple units-of-measure that I will be using throughout the library ... and since I don&amp;#39;t have something productive to show from my code at this point, I figured now might be as good a point as any. ;-)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;Angles In Degrees&lt;/u&gt;&lt;/strong&gt; -- I prefer my angles to be measured in degrees.&amp;nbsp; Something about my old-fashioned American math training just won&amp;#39;t let go of me ... so, I like my circles to start at 0 degrees at top, increase in a clockwise fashion -- 90 degrees is to the right, 180 degrees is down -- until you end up at the top again at 360 degrees.&amp;nbsp; So, if you see a property or function that is returning an angle (names like &amp;quot;Heading&amp;quot;, &amp;quot;Facing&amp;quot;, &amp;quot;Aiming&amp;quot;, &amp;quot;GetAngle&amp;quot;, etc.), it will be in degrees.&amp;nbsp; However, for properties, I will likely have an equivalently named property with a &amp;quot;_InRadians&amp;quot; suffix (such as &amp;quot;Heading_InRadians&amp;quot;) to give something to work with if someone wants to use Windows functions that prefer radians.&amp;nbsp; The &amp;quot;QuickTrig&amp;quot; helper functions in &lt;em&gt;Nimble2D&lt;/em&gt; operate in degrees -- so, making use of those is very easy with this degrees-friendly approach.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;Time in Seconds&lt;/u&gt;&lt;/strong&gt; --&amp;nbsp;I&amp;#39;ve found it traditional for game programmers to deal with time in milliseconds, for a number of different reasons.&amp;nbsp; However, I&amp;#39;ve found over time that I always need to convert those into true seconds to do things related to time-based programming (X = X + VX * (DeltaMS / 1000), etc.).&amp;nbsp; So, with this library, I&amp;#39;ve decided to always deal in actual seconds ...&amp;nbsp;usually of type Double.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;Space Measurements in &amp;quot;GameSpace Pixels&amp;quot;&lt;/u&gt;&lt;/strong&gt; -- Position and spacial measurements will essentially still be in pixels, with the normal caviats thrown in when dealing with current 3D programming: It&amp;#39;s a pixel if everything is at a 1.0 scale.&amp;nbsp; And everything will be relative to each other within the GameSpace ... so, basically, the camera&amp;#39;s position will determine what will be showing up on screen.&amp;nbsp; Having a position of (800, -16372) may be in the middle of the screen, if the camera is moved into the right place ... and something at (805, -16372) will be 5 pixels to the right of the first object, assuming a scale of 1.0.&amp;nbsp; When I combine these two things, I like to think of these units as &amp;quot;GameSpace Pixels&amp;quot;, as it reminds me of the relativity between all things within the GameSpace.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;Rates are &amp;quot;per Second&amp;quot;&lt;/u&gt;&lt;/strong&gt; -- Any rate-style measurement -- &amp;quot;Linear Speed&amp;quot;, &amp;quot;Acceleration&amp;quot;, &amp;quot;Rotational Speed&amp;quot;, &amp;quot;Alpha Fade Rate&amp;quot;, etc. -- will be in a &amp;quot;per second&amp;quot; format.&amp;nbsp; Linear Speed, for example, is in &amp;quot;GameSpace Pixels per Second&amp;quot; ... Acceleration is &amp;quot;GameSpace Pixels per Second per Second&amp;quot; ... Rotational Speed is &amp;quot;Degrees per Second&amp;quot; ... Alpha Fade Rate is in &amp;quot;Values per Second&amp;quot; (where a &amp;quot;value&amp;quot; is each&amp;nbsp;integer in the 0-to-255 range).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;&amp;quot;ColorOnly&amp;quot; versus &amp;quot;Color&amp;quot;&lt;/u&gt;&lt;/strong&gt; -- There are times when I like to separate the Alpha channel out by itself from the rest of what would normally be an ARGB-style System.Drawing.Color.&amp;nbsp; Also, there are cases (such as background color) where the Alpha channel just doesn&amp;#39;t matter.&amp;nbsp; As an example of the former, sprites will have a &amp;quot;SpriteAlpha&amp;quot; property that can hold a value of 0 (completely transparent) to 255 (completely opaque) and a separate &amp;quot;SpriteColorOnly&amp;quot; that, while still being of type System.Drawing.Color, will only make use of the Red, Green, and Blue channels to color-shade the sprite.&amp;nbsp; If something contains just the word &amp;quot;Color&amp;quot; (and not the &amp;quot;Only&amp;quot;), then all 4 channels will be used for whatever purpose that property or function is up to.&lt;/p&gt;
&lt;p&gt;Those are the main ones that I&amp;#39;ve run into so far ... I&amp;#39;m sure there will be more, so I reserve the right to re-visit this topic (and maybe even change what&amp;#39;s been stated here). ;-)&lt;/p&gt;
&lt;p&gt;-Matt&lt;/p&gt;&lt;img src="http://ilovevb.net/Web/aggbug.aspx?PostID=103" width="1" height="1"&gt;</content><author><name>MattWorden</name><uri>http://ilovevb.net/Web/members/MattWorden.aspx</uri></author><category term="NimbleOverview" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/NimbleOverview/default.aspx" /><category term="KudosToOthers" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/KudosToOthers/default.aspx" /><category term="Nimble2D" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Nimble2D/default.aspx" /></entry><entry><title>Doing 2D in SlimDX</title><link rel="alternate" type="text/html" href="http://ilovevb.net/Web/blogs/nimble2d/archive/2008/02/12/doing-2d-in-slimdx.aspx" /><id>http://ilovevb.net/Web/blogs/nimble2d/archive/2008/02/12/doing-2d-in-slimdx.aspx</id><published>2008-02-13T01:22:00Z</published><updated>2008-02-13T01:22:00Z</updated><content type="html">&lt;p&gt;Now that I&amp;#39;ve had a couple of weeks to play around with 2D programming in Direct3D9 via SlimDX, here are a few things that I&amp;#39;ve found.&lt;/p&gt;
&lt;p&gt;After creating the Direct3D Device (as explained in the &amp;quot;&lt;a class="" title="Graphics Enumeration and Launching the Game Form" href="http://ilovevb.net/Web/blogs/nimble2d/archive/2008/01/21/graphics-enumeration-and-launching-the-game-form.aspx"&gt;Graphics Enumeration and Launching the Game Form&lt;/a&gt;&amp;quot; post), I create a Direct3D Sprite object (which I will be calling a &amp;quot;Sprite Batch&amp;quot; object):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;varSB = New Direct3D9.Sprite(varD3D_Device)&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;This will be passed through the main Nimble2D object to each of the 2D objects that will be drawing themselves to the screen.&lt;/p&gt;
&lt;p&gt;The magical math-thingy that makes the whole thing work is how Matrices and Matrix Transformations are used to determine where and how 2D sprites are drawn.&amp;nbsp; As mentioned earlier, all objects within a gamespace (including cameras) will have a location (simply a &amp;quot;Current X&amp;quot; and &amp;quot;Current Y&amp;quot;)&amp;nbsp;within &amp;quot;game space&amp;quot;, which essentially is&amp;nbsp;a way to measure their positions relative to each other.&amp;nbsp; They will also have a &amp;quot;Facing&amp;quot; angle and a &amp;quot;Scale&amp;quot;.&amp;nbsp; These are the main pieces used within SlimDX&amp;#39;s nifty Transformation2D function to get the matrix needed to draw things how they should appear on screen.&lt;/p&gt;
&lt;p&gt;First, the camera:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;varActualMatrix = SlimDX.Matrix.Transformation2D(New SlimDX.Vector2(varWidth / 2, varHeight / 2), 0, &lt;/em&gt;&lt;em&gt;New SlimDX.Vector2(varScale), New SlimDX.Vector2(varWidth / 2, varHeight / 2), varN2D.QuickTrig.DegreesToWinRadians(varFacing), New SlimDX.Vector2(varCurX, varCurY))&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;varInverseMatrix = SlimDX.Matrix.Invert(varActualMatrix)&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The parameters of that function are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div&gt;&lt;strong&gt;scalingCenter&lt;/strong&gt;&amp;nbsp;- A Vector2&amp;nbsp;around which to scale things (set to the middle of the&amp;nbsp;screen)&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;strong&gt;scalingRotation&lt;/strong&gt; - A Single that indicates rotating the X/Y scaling away from the identity angle&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;strong&gt;scaling&lt;/strong&gt; - A Vector2 that gives the actual X/Y scaling (1.0 = original size)&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;strong&gt;rotationCenter&lt;/strong&gt; - A Vector2 around which to rotate things&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;strong&gt;rotation&lt;/strong&gt; - The angle to rotate (I like to work with angles in degrees ... DirectX and Windows trig functions prefer radians ... so I have a translator function)&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;strong&gt;translation&lt;/strong&gt; - A Vector2 to relocate everything in X/Y space&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;The first line sets the camera&amp;#39;s actual matrix ... the second line uses that to create the inverse of it, which will be passed to the sprites within the gamespace to relocate them in relation to the camera.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;So, the sprites go like so:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Me.varMyTransform = SlimDX.Matrix.Transformation2D(New SlimDX.Vector2(varCurX, varCurY), 0, New SlimDX.Vector2(varSourceScale.X * varScale, varSourceScale.Y * varScale), New SlimDX.Vector2(varCurX, varCurY), varN2D.QuickTrig.DegreesToWinRadians(varFacing), New SlimDX.Vector2(0))&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;(For my sprites, I have a &amp;quot;SourceScale&amp;quot; that indicates if the initial source image is always to be stretched.)&lt;/p&gt;
&lt;p&gt;To draw things, the following steps are taken:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;div&gt;Begin Scene &amp;amp; Clear to Background color (Direct3D Device) &lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Cycle through all layers ...&lt;/div&gt;&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;div&gt;Begin Drawing Sprites (Sprite Batch)&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Cycle through all sprites ...&lt;/div&gt;&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;div&gt;Transform the Sprite Batch Matrix&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Draw the sprite&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;li&gt;
&lt;div&gt;End Drawing Sprites&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;li&gt;
&lt;div&gt;End Scene&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Present to Screen&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;In this system, these steps are scattered through several objects, but put together, they look something like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; varD3D_Device.BeginScene()&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; varD3D_Device.Clear(ClearFlags.Target, varCurGameSpace.BackgroundColorOnly, 1, 0)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; varN2D.SpriteBatch.Begin(SpriteFlags.AlphaBlend Or SpriteFlags.DoNotSaveState)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; varN2D.SpriteBatch.Transform = SlimDX.Matrix.Multiply(varMyTransform, LayerTransform)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; varN2D.SpriteBatch.Draw(varSourceTexture, varSourceRect, New SlimDX.Vector3(varOrigin.X, varOrigin.Y, 0), New SlimDX.Vector3(varCurX, varCurY, 0), Color.FromArgb(varAlpha, varColorOnly))&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; varN2D.SpriteBatch.End()&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; varD3D_Device.EndScene()&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; varD3D_Device.Present()&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;I have other code bits in between things here and there to handle stuff like allowing for additive blending effects, full-screen fade in/out, writing &amp;quot;screen info&amp;quot; (screen size,&amp;nbsp;camera position, FPS) to the screen, etc.&lt;/p&gt;
&lt;p&gt;What I&amp;#39;m working through now is the sprite-based primary shapes (filled rectangles, circles, and triangles, lines, empty rectangles, filled rectangles with borders, and empty polygons using lines).&amp;nbsp; I hope to give some details about&amp;nbsp;the lookup-table trig system being used at some point as well.&lt;/p&gt;
&lt;p&gt;-Matt&lt;/p&gt;&lt;img src="http://ilovevb.net/Web/aggbug.aspx?PostID=96" width="1" height="1"&gt;</content><author><name>MattWorden</name><uri>http://ilovevb.net/Web/members/MattWorden.aspx</uri></author><category term="Nimble2D" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Nimble2D/default.aspx" /><category term="Sprites" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Sprites/default.aspx" /><category term="Cameras" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Cameras/default.aspx" /><category term="SlimDX" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/SlimDX/default.aspx" /></entry><entry><title>A GDI-based Screenshot Method</title><link rel="alternate" type="text/html" href="http://ilovevb.net/Web/blogs/nimble2d/archive/2008/01/25/a-gdi-based-screenshot-method.aspx" /><id>http://ilovevb.net/Web/blogs/nimble2d/archive/2008/01/25/a-gdi-based-screenshot-method.aspx</id><published>2008-01-25T15:08:00Z</published><updated>2008-01-25T15:08:00Z</updated><content type="html">&lt;p&gt;I was struggling with trying to make&amp;nbsp;an easy screenshot method using SlimDX.&amp;nbsp; Looking at MDX samples, the standard method was to grab the Backbuffer into a surface (Device.GetBackbuffer), then use the SurfaceLoader.Save helper method to save that surface to a file.&amp;nbsp; I have not been able to find that SurfaceLoader.Save method anywhere within SlimDX.&amp;nbsp; (I have added it to the SlimDX &amp;quot;issues&amp;quot; list as an enhancement request.)&lt;/p&gt;
&lt;p&gt;In the meantime, I was looking for a way to make it work.&amp;nbsp; An internet acquaintence of mine (and a hyper-good coder also working on a SlimDX-based project), &lt;a class="" title="CodeImp&amp;#39;s Project: DoomBuilder" href="http://sourceforge.net/projects/doombuilder/" target="_blank"&gt;CodeImp&lt;/a&gt;, suggested that I lock the surface and transfer the data to a GDI bitmap and use the Bitmap&amp;#39;s ability to save-to-file.&amp;nbsp; I also wondered about using the SlimDX&amp;#39;s Texture.FromStream method to create a texture from the surface, then do a Texture.SaveToFile ... but none of these worked.&amp;nbsp; For some reason, once I locked the rectangle on the surface, that LockedRect&amp;#39;s Stream wasn&amp;#39;t able to get its own length -- so it kept throwing errors.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;So, my next attempt was to use the surface&amp;#39;s GetDC to see if I could create a GDI Graphics device from that DC and do something with it that way.&amp;nbsp; That&amp;#39;s where the &amp;quot;looky what I found&amp;quot; happened ... GDI Graphics devices have a method called &amp;quot;CopyFromScreen&amp;quot;, which does exactly what it says.&amp;nbsp; This made me drop any SlimDX-related code and go pure GDI, with great results.&lt;/p&gt;
&lt;p&gt;Here are the steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;div&gt;Determine your Top, Left, Width, and Height to capture ... if in full screen, these are 0,0,ScreenWidth,ScreenHeight ... if in windowed, these are the Top, Left, Width, Height of your Game Form&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Create a new Bitmap using Width and Height&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Create a Graphics Device from the new Bitmap&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Do Graphics.CopyFromScreen&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Do Bitmap.Save&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Dispose the Graphics Device and Bitmap&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;So, it&amp;#39;s not quite the 3-step process available with MDX, but this pure-GDI process should work no matter what your drawing system is.&amp;nbsp; Here&amp;#39;s the actual VB.Net code:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tempBMP = New Bitmap(tempWidth, tempHeight)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; G = System.Drawing.Graphics.FromImage(tempBMP)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; G.CopyFromScreen(tempLeft, tempTop, 0, 0, New Size(tempWidth, tempHeight))&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tempFileName = &amp;quot;Screenshot_&amp;quot; &amp;amp; Date.Now.ToString(&amp;quot;yyyyMMdd_hhmmss&amp;quot;) &amp;amp; &amp;quot;.png&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tempBMP.Save(tempFileName, System.Drawing.Imaging.ImageFormat.Png)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; G.Dispose()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tempBMP.Dispose()&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;This routine names the file using the current date and time (down to the second) and saves it as a PNG.&amp;nbsp; It seems to work fine in both windowed and fullscreen mode.&lt;/p&gt;
&lt;p&gt;-Matt&lt;/p&gt;&lt;img src="http://ilovevb.net/Web/aggbug.aspx?PostID=83" width="1" height="1"&gt;</content><author><name>MattWorden</name><uri>http://ilovevb.net/Web/members/MattWorden.aspx</uri></author><category term="KudosToOthers" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/KudosToOthers/default.aspx" /><category term="SlimDX" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/SlimDX/default.aspx" /></entry><entry><title>Laying Out the Graphics Approach</title><link rel="alternate" type="text/html" href="http://ilovevb.net/Web/blogs/nimble2d/archive/2008/01/24/laying-out-the-graphics-approach.aspx" /><id>http://ilovevb.net/Web/blogs/nimble2d/archive/2008/01/24/laying-out-the-graphics-approach.aspx</id><published>2008-01-24T17:33:00Z</published><updated>2008-01-24T17:33:00Z</updated><content type="html">&lt;p&gt;I won&amp;#39;t be able to do much more coding until the weekend.&amp;nbsp; So, I figured I should give a quick overview of how I&amp;#39;m going to approach the main graphics drawing routine.&amp;nbsp; I&amp;#39;ll start high-level and work downward, then spiral back upward, and then back down a little bit before popping up into the atmosphere to wrap everything together.&lt;/p&gt;
&lt;p&gt;It would be interesting to me to be able to approach displaying a game as if it were a live-action TV show.&amp;nbsp; You would have different sets (I&amp;#39;m going to call them &amp;quot;Game Spaces&amp;quot;) for different sort of things.&amp;nbsp; Think about a normal local newscast&amp;nbsp;-- you have the &amp;quot;main anchor desk&amp;quot; set, the &amp;quot;weather map&amp;quot; set, the &amp;quot;sports report&amp;quot; set, the &amp;quot;investigative reporter&amp;quot; set, etc.&amp;nbsp; For a game, this might translate into things like a main menu, a configuration menu, a high scores list, the pre-level briefing, the main gameplay space, the post-level results, and a game over screen.&amp;nbsp; Each set would have 1 or more cameras trained on it, and you would play the director ... &amp;quot;switch to set 1, camera 1&amp;quot; ... &amp;quot;zoom camera 2&amp;quot; ... &amp;quot;switch to camera 2&amp;quot; ... &amp;quot;prepare camera 1 on set 2&amp;quot; ... &amp;quot;move things around on set 2&amp;quot; ... &amp;quot;switch to set 2, camera 1&amp;quot; ... etc.&lt;/p&gt;
&lt;p&gt;Now, when programming 2D games, I&amp;#39;ve always logically grouped my graphics into layers.&amp;nbsp; There&amp;#39;s usually some sort of background layer which consists of your ground-level surface or a starfield or something else that is simply going to be behind everything else.&amp;nbsp; It may scroll around, but it will otherwise not really interact with anything else in the game and it&amp;#39;s just there for your eyes and brain to have a backdrop on which to make sense of the rest of the game.&amp;nbsp; Then there is usually one or more layers of game objects (these are usually called &amp;quot;Sprites&amp;quot;, and I don&amp;#39;t plan to stray from that norm).&amp;nbsp; These layers might consist of a map layer and a layer for ships and weapons, etc.&amp;nbsp; Basically, I try to group the sprites that may interact with each other (and probably won&amp;#39;t overlap in 2D space) into the same layer.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s use &lt;em&gt;&lt;a class="" title="Gem Raider Webpage" href="http://www.mwgames.com/gemraider.asp" target="_blank"&gt;Gem Raider&lt;/a&gt;&lt;/em&gt; as a quick example.&amp;nbsp; Look at this screenshot (click it for a big version):&lt;/p&gt;
&lt;p&gt;&lt;a class="" title="Same Screenshot of Game Raider" href="http://www.frontiernet.net/~mattandbritt/GR7_SingleBlackWithOrange.jpg" target="_blank"&gt;&lt;img height="150" alt="Example Screenshot of Gem Raider" src="http://www.mwgames.com/_uimages/GR7_SingleBlackWithOrange_sm.jpg" width="200" align="top" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this game, I had 6 layers (starting back to front) ...&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;div&gt;The grid-like backdrop surface&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;The &amp;quot;under the walls&amp;quot; explosion layer&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;The &amp;quot;walls&amp;quot; layer for the main static map structures&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;The &amp;quot;moving objects&amp;quot; layer for the player ship, the gems, and all of the weapons&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;The &amp;quot;above everything&amp;quot; explosions layer&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;The UI layer to show the score and the quick key listing&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;Each layer becomes, essentially, a collection of sprites.&amp;nbsp; Especially if you treat your primatives (drawn circles, rectangles, lines) and text as sprites, which I plan to do.&amp;nbsp; Sprites move around freely in game space.&amp;nbsp; Layers are drawn from back to front, and the current camera determines what part of that game space actually makes it to be displayed on the player&amp;#39;s screen.&lt;/p&gt;
&lt;p&gt;So, why put things in layers?&amp;nbsp; Why not just assign each sprite a &amp;quot;z&amp;quot; (or depth) value and allow DirectX to sort the order to draw things in?&amp;nbsp; Because I would like the programmer to easily be able to apply logic to all sprites in a layer at the same time.&amp;nbsp; Also, it will make for a logical grouping within which to breakup update and draw processes, if the game programmer wishes.&amp;nbsp; While &lt;em&gt;Nimble2D&lt;/em&gt; will be designed to very easily draw everything on screen, it will still allow the programmer some capability to mix in some of their own drawing code if they wish (perhaps to render a true 3D object in amongst the layers somewhere).&lt;/p&gt;
&lt;p&gt;Just as sprites will be able to move around, rotate and scale, cameras will be able to move around, rotate and scale/zoom ... and this will be reflected in how the sprites are drawn to the screen.&amp;nbsp; However, there will also be some &amp;quot;over layers&amp;quot; available within a game space that will not be impacted by the camera.&amp;nbsp; These over layers will be used to render UI components and messages onto the screen (after the camera shot is drawn) and always have them show up in the same screen location, no matter what is going on with the camera.&lt;/p&gt;
&lt;p&gt;For most of what I&amp;#39;ll be doing with &lt;em&gt;Nimble2D&lt;/em&gt; to start, I&amp;#39;m just going to work with a single camera per game space, which will be drawing directly to the backbuffer.&amp;nbsp; However, I will also be keeping in mind that this system will eventually allow for multiple cameras in a game space, which will draw to their own render targets and those resulting graphics will be assembled onto the screen by the game space ... this will make it easy to do split screens for player-versus-player type games or games which might need to track multiple locations in the game space at the same time.&lt;/p&gt;
&lt;p&gt;At the highest level -- the Nimble2D class itself -- each game space that is created will be tracked by the system.&amp;nbsp; A call to Nimble2D.UpdateAll will push update calls down through the camera, layers and sprites of the current game space (and every game space that is setup to do &amp;quot;background updates&amp;quot;, which I will get into at a different time).&amp;nbsp; Drawing everything in the current game space to the screen will be done with Nimble2D.DrawAll, and switching between screens will be as easy as setting a different game space as Nimble2D.CurrentGameSpace.&amp;nbsp; As mentioned, there will also be finer-grain controls available to allow the programmer to update and draw just the pieces as is needed.&amp;nbsp; This also sets a nice framework for easily allowing full-screen fade-in and fade-out and other fun stuff.&lt;/p&gt;
&lt;p&gt;For now, let&amp;#39;s put it all together with this graphic of a single game space:&lt;/p&gt;
&lt;p&gt;&lt;img height="400" alt="Nimble2D Game Space Visualization" src="http://www.frontiernet.net/~mattandbritt/GraphicsLayers.jpg" width="400" align="top" border="0" /&gt;&lt;/p&gt;
&lt;p&gt;It shows multiple layers resulting in a collection of sprites within the game space.&amp;nbsp; A camera presents a portion of the game space to the screen.&amp;nbsp; And over layers are added to give the player a single frame of the game.&lt;/p&gt;
&lt;p&gt;2D game programmers will need to shift their thinking a bit from managing things within the scope of &amp;quot;screen space&amp;quot; to managing things within &amp;quot;game space&amp;quot; and grouping those things into layers ... and to how they wish to position the camera to show the game to the player.&amp;nbsp; (This also presents a programming challenge for the NimbleInput class -- giving mouse coordinates in both screen and game space ... but that&amp;#39;s exactly where a library like this is supposed to make things easy on the game programmer, right?)&lt;/p&gt;
&lt;p&gt;There is a lot of class skeletons and methods to get into place just to draw some simple sprites on the screen.&amp;nbsp; But once those are in place, the actual game code writing should become much easier, and we can then start fleshing things out to add value quickly.&lt;/p&gt;
&lt;p&gt;-Matt&lt;/p&gt;&lt;img src="http://ilovevb.net/Web/aggbug.aspx?PostID=80" width="1" height="1"&gt;</content><author><name>MattWorden</name><uri>http://ilovevb.net/Web/members/MattWorden.aspx</uri></author><category term="Nimble2D" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Nimble2D/default.aspx" /><category term="GameSpace" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/GameSpace/default.aspx" /><category term="Layers" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Layers/default.aspx" /><category term="Sprites" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Sprites/default.aspx" /><category term="Cameras" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Cameras/default.aspx" /></entry><entry><title>Graphics Enumeration and Launching the Game Form</title><link rel="alternate" type="text/html" href="http://ilovevb.net/Web/blogs/nimble2d/archive/2008/01/21/graphics-enumeration-and-launching-the-game-form.aspx" /><id>http://ilovevb.net/Web/blogs/nimble2d/archive/2008/01/21/graphics-enumeration-and-launching-the-game-form.aspx</id><published>2008-01-22T03:41:00Z</published><updated>2008-01-22T03:41:00Z</updated><content type="html">&lt;p&gt;When it comes time to write a new game, I&amp;#39;d like to be able to tell my graphics library the various screen styles that the game wants to make available to the player and then have the library figure out which ones are supported by the player&amp;#39;s computer.&amp;nbsp; This will be how Nimble2D does things ... receive a list of requested screen styles, look at each available adapter for support for the requested style, and provide back a list of available screen styles.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;Here&amp;#39;s how the graphics enumeration testing app starts things off:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Nimble2D = New clsNimble2D()&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;At least 1 video adapter is needed to continue ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If Nimble2D.Adapters_Count &amp;lt; 1 Then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Application.Exit()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Exit Sub&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; End If&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;--- Change this list to reflect requested screen styles ---&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Nimble2D.AddRequestedScreenStyle(800, 600, False)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Nimble2D.AddRequestedScreenStyle(800, 600, True, clsNimble2D.enumColorDepth.CD_32bit)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Nimble2D.AddRequestedScreenStyle(800, 600, True, clsNimble2D.enumColorDepth.CD_16bit)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Nimble2D.AddRequestedScreenStyle(900, 400, False)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Nimble2D.AddRequestedScreenStyle(1024, 768, True, clsNimble2D.enumColorDepth.CD_32bit)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Nimble2D.AddRequestedScreenStyle(1024, 768, True, clsNimble2D.enumColorDepth.CD_16bit)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;---&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Then the start-up form cycles through the available styles for the selected adapter:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;Load Screen Styles List Box&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If modGame.Nimble2D.AvailableScreenStyles_Count(Me.cboAdapters.SelectedIndex) &amp;gt; 0 Then&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; For j As Integer = 0 To&amp;nbsp;&lt;/em&gt;&lt;em&gt;modGame.Nimble2D.AvailableScreenStyles_Count(Me.cboAdapters.SelectedIndex) - 1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Me.lstScreenStyle.Items.Add(modGame.Nimble2D.AvailableScreenStyleName(Me.cboAdapters.SelectedIndex, j))&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Next&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Me.lstScreenStyle.SelectedIndex = 0&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; End If&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;That gets us this far:&amp;nbsp; &lt;img height="204" alt="Nimble2D Graphic Enumeration Startup Form" src="http://www.frontiernet.net/~mattandbritt/Nimble2D_GfxEnum_1_small.jpg" width="228" align="top" border="0" /&gt;&lt;/p&gt;
&lt;p&gt;Once the&amp;nbsp;player selects the adapter and screen style and clicks &amp;quot;Launch&amp;quot;, the game&amp;#39;s code creates an instance of a game form and asks Nimble2D to launch it on the requested adapter in the requested screen style:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GameForm = New frmGame()&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Nimble2D.LaunchGameScreen(GameForm, AdapterIndex, ScreenStyleIndex)&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Which results in this:&amp;nbsp;&amp;nbsp; &lt;img height="200" alt="Nimble2D Graphics Enumeration Launched Game Form" src="http://www.frontiernet.net/~mattandbritt/Nimble2D_GfxEnum_2_small.jpg" width="450" align="top" border="0" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;So ... how&amp;#39;s it done?&amp;nbsp; Well, SlimDX (which is what Nimble2D uses to access DirectX) makes a number of enumeration functions and properties available.&amp;nbsp; The available adapters are grabbed when Nimble2D is first constructed, using this code:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Direct3D.Initialize()&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Me.varAdapters_Count = Direct3D.AdapterCount()&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; For j As Integer = 0 To Me.varAdapters_Count - 1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Me.varAdapter(j) = Direct3D.GetAdapterIdentifier(j).Description&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Next&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The handling of requested screen styles is a bit more complicated.&amp;nbsp; So, instead of giving code here, I&amp;#39;ll walk through the steps.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;div&gt;The supplied parameters for screen style are:&amp;nbsp; Width, Height, FullScreen, and ColorDepth&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;If FullScreen = False, then the ColorDepth is assumed to be whatever the primary adapter is currently set to, and the screen style will be considered available as long as the Width and Height are smaller than the current screen size&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;If FullScreen = True, then each adapter is run through the various formats for the given ColorDepth in preference order.&amp;nbsp; As soon as a supported format in the given Width and Height is found, then it is marked as available for that adapter.&amp;nbsp; The first-found supported format is noted to be used later if that screen style is selected for the launch.&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;When the game requests for the game form to be launched, Nimble2D resizes the supplied game form to the width and height of the selected screen style, shows the form, and creates the Direct3D Device:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GameForm.Size = New Size(varSelectedScreenStyle.Width, varSelectedScreenStyle.Height)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GameForm.Show()&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim presentparams As New PresentParameters&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; presentparams.BackBufferWidth = varSelectedScreenStyle.Width&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; presentparams.BackBufferHeight = varSelectedScreenStyle.Height&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If varSelectedScreenStyle.FullScreen Then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; presentparams.BackBufferFormat = varSelectedScreenStyle.BackBufferFormat&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; presentparams.Windowed = False&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; presentparams.Windowed = True&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; End If&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; presentparams.DeviceWindowHandle = GameForm.Handle&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; varD3D_Device = New Device(AdapterIndex, DeviceType.Hardware, GameForm.Handle, CreateFlags.HardwareVertexProcessing, presentparams)&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The next thing to tackle is the main skeleton structure that will be used to get graphics on the screen ... Game Spaces (and their cameras), Layers, and Sprites.&lt;/p&gt;
&lt;p&gt;-Matt&lt;/p&gt;
&lt;p&gt;p.s. When requesting a screen style that is full screen, only 16- and 32-bit color depths are allowed.&amp;nbsp; The various formats (5 to 6 in each color depth) are checked in order of &amp;quot;preference&amp;quot;.&amp;nbsp; If someone reading this has strong knowledge about graphics formats and in what order preference should be given, please post a comment or send me an e-mail ... I have some questions for you. ;-)&lt;/p&gt;&lt;img src="http://ilovevb.net/Web/aggbug.aspx?PostID=78" width="1" height="1"&gt;</content><author><name>MattWorden</name><uri>http://ilovevb.net/Web/members/MattWorden.aspx</uri></author><category term="Nimble2D" scheme="http://ilovevb.net/Web/blogs/nimble2d/archive/tags/Nimble2D/default.aspx" /></entry></feed>