Managed World

An Odyssey Through The Land Of Geekdom


News

Search this blog

My Stats

  • Posts - 462
  • Comments - 203
  • Trackbacks - 1465

Twitter












Recent Comments


Recent Posts


Article Categories


Archives


Post Categories


Blog Roll



Overview

The Console allows us to do a great number of things. We can issue various commands to our game, change game engine variables, etc. all while the game is still running. While on the surface the Console appears to be quite smart, under the hood it is actually not that intelligent. When a command has been entered into the Console, the Console simply passes the text on to the CommandManager to handle. Also, any game code that wishes can “print” to the Console. The Console simply displays everything that has been printed to it. There is very little validation at all in the Console. The majority of functionality within the Console is to handle the rendering of the Console. To see how the Console plugs into the CommandManager at design-time, please refer to the design section of the prior article.

Implementation

Since rendering is going to take up most of the article, let's go ahead and dive into the bones of the Console class. First of all, we have a couple of attributes to manage all the lines that have been printed to the Console, as well as attributes to manage details of our rendering capabilities.

     public sealed class Console : IDisposable
     {
          // Inner Types
          private enum ConsoleState
          {
               Closed,
               Closing,
               Opening,
               Open
          }

          // Attributes/Properties
          private float _currentConsolePercentage = 0.0f;
          private float _maxConsolePercentage = 30.0f;
          // no property accessors

          private ArrayList _entries = new ArrayList();
          // no property accessor

          private StringBuilder _entryLine = new StringBuilder(">");
          // no property accessor

          private ConsoleState _state = ConsoleState.Closed;
          // no property accessor

          private System.Drawing.Font _windowsFont;
          private Font _font;
          // no property accessors

          public bool IsVisible
          {
               get { return _state != ConsoleState.Closed; }
          }

          public int LineHeight
          {
               get { return (int)_windowsFont.Size * 2; }
          }

The ConsoleState enumeration is defined as an inner type because it is only used within the Console class itself. All the outside world knows about the Console is that its State can be toggled via ToggleState. _currentConsolePercentage and _maxConsolePercentage are the percentages that the console is currently open, and the maximum percentage it can open to, respectively. _entries are all the lines that have been printed to the Console and _entryLine is like the command line, where we can input various commands.

Notice that our fonts are not initialized in the constructor. This is because we cannot guarantee that our instance will be created before our Renderer instance. If the Console instance is created before the Renderer instance, our font initialization code would throw an “object reference not set“ error because the Device property of the Renderer would be null. Also in the Initialize function, we will initialize our commands like we did in the CommandManager.

          // Singleton Implementation
          public static readonly Console Instance = new Console();
          private Console()
          {   
          }

          public void Initialize()
          {
               _windowsFont = new System.Drawing.Font("Arial", 8.0f);
               _font = new Font(BattleEngine.Instance.Renderer.Device, _windowsFont);

               // add our needed commands
               CommandManager.Instance.AddCommand("consolesize", new CommandCallback(this.SetConsoleSize));
               CommandManager.Instance.AddCommand("clear", new CommandCallback(this.Clear));
          }

I think the various Print functions are pretty self explanatory. The few comments I have is that we only store the last 50 lines that were printed, and we only print print characters and strings to the entry line if we are visible (this does not prevent us from printing to the Console in general though). The PrintFormat function is provided simply for convenience.

          public void Print(string text)
          {
               _entries.Insert(0, text);
               while(_entries.Count > 50)
               {
                    _entries.RemoveAt(49); // 49 because of zero-based index
               }
          }

          public void PrintFormat(string text, params object[] args)
          {
               Print(string.Format(text, args));
          }

          public void PrintCharacterToEntryLine(char character)
          {
               if (IsVisible)
                    _entryLine.Append(character);

          }

          public void PrintStringToEntryLine(string text)
          {
               if (IsVisible)
                    _entryLine.Append(text);
          }

          public void Backspace()
          {
               if (_entryLine.Length > 1)
                    _entryLine.Remove(_entryLine.Length - 1, 1);
          }

If the Console is visible, and we hit enter, we tell the Console to process whatever is currently on the entry line. When we process the entry line, we simply pass off the text to the CommandManager's buffer and reset our entry line.

          public void ProcessEntryLine()
          {
               string text = _entryLine.ToString().Trim().Remove(0, 1);

               CommandManager.Instance.Buffer.AddLine(text);
               _entryLine = new StringBuilder(">");
          }

Next we want to implement the command callbacks for the commands we added in our initialization above (”clear” and “consolesize”). The “consolesize” command will allow us to control the maximum percentage of the window that the Console will take up when it is fully opened. Currently, the minimum is 5% and the maximum is 50% (the default is 30%). The “clear” commands deletes all entries that are currently in the Console and resets the entry line.

          #region Commands

          private void SetConsoleSize(string[] args)
          {
               try
               {
                    float newSize = float.Parse(args[0]);

                    if (newSize > 50.0f || newSize < 5.0f)
                    {
                         Print("consolesize must be between 5 and 50");
                    }
                    else
                    {
                         _maxConsolePercentage = newSize;
                         _currentConsolePercentage = _maxConsolePercentage;
                    }
               }
               catch
               {
                    Print("consolesize must be between 5 and 50");
               }
          }

          private void Clear(string[] args)
          {
               _entries.Clear();
               _entryLine = new StringBuilder(">");
          }

          #endregion

The reason that the SetConsoleSize method is surrounded by a try/catch block is because we do not wish to throw an error if the parameter is not valid (for example, the catch will catch (no pun intended) any errors that occur because the parameter is not a valid float). We will just print the usage of the command and ignore the error.

Now for the fun stuff. The first thing we want to ensure is that we are not rendering the Console when it is not visible. Once this has been ensured, then we can update the current percentage of the window that is displayed. We are incrementing the the current percentage slowly so the Console slides open rather than appearing out of thin air.

          public void Render()
          {
               if (IsVisible)
               {
                    // update console state
                    if (_state == ConsoleState.Opening && _currentConsolePercentage <= _maxConsolePercentage)
                    {
                         _currentConsolePercentage += 0.5f;

                         if (_currentConsolePercentage >= _maxConsolePercentage)
                         {
                              _currentConsolePercentage = _maxConsolePercentage;
                              _state = ConsoleState.Open;
                         }
                    }
                    else if (_state == ConsoleState.Closing && _currentConsolePercentage >= 0.0f)
                    {
                         _currentConsolePercentage -= 0.5f;

                         if (_currentConsolePercentage <= 0.0f)
                         {
                              _currentConsolePercentage = 0.0f;
                              _state = ConsoleState.Closed;
                         }
                    }

Pretty simple. Next we will try to render the Console. I am going to dissect this a piece at a time so I can explain everything that is going on properly. First, we are going to verify that the Console is opened far enough for a single line to display. If it is not, then we will not render. The line variable will store where on the Y-axis our current line to render is.

                    // render background
                    try
                    {
                         int line = (int)((_currentConsolePercentage / 100.0f) *
BattleEngine.Instance.TargetControl.Height) - this.LineHeight;
                         if (line > 5)
                         {

The reason that we divide by 100 is to get a true float percentage value (for example, since we are specifying 30% we need to multiply by 0.30 to get the correct percentage). So, the line variable stores where on the Y-axis our current position is minus the LineHeight of our font.

Next we figure out the current Console height as well as the height of the visible portion of the Console. Using these values, we will also need to determine where the rectangle for the background of the Console will be renderer (x position, y position, width, and height).

                              float consoleHeight = BattleEngine.Instance.TargetControl.Height * (_maxConsolePercentage / 100.0f);
                              float visibleHeight = BattleEngine.Instance.TargetControl.Height * (_currentConsolePercentage / 100.0f);

                              float x = 0;
                              float y = BattleEngine.Instance.TargetControl.Height + (consoleHeight - visibleHeight);
                              float width = BattleEngine.Instance.TargetControl.Width;
                              float height = consoleHeight;

Next we will actually render the background of the Console. The Rectangle class will be defined in a later article. All the rectangle class basically is, is a wrapper around a vertex buffer. With the Rectangle class, you just specify where you would like the rectangle drawn, how big it should be, and what color it should be. Remember, for this first delivery, we will only be dealing with programmer graphics. Once the game is operational, we will start adding our eye candy.

                              // draw background
                              Battle.Shapes.Rectangle consoleBackground = new Battle.Shapes.Rectangle(x, y, width, height, System.Drawing.Color.White);
                              Battle.Shapes.Rectangle consoleDivider = new Battle.Shapes.Rectangle(0, BattleEngine.Instance.TargetControl.Height - line + 2, width, 1, System.Drawing.Color.Black);
                              consoleBackground.Render();
                              consoleDivider.Render();

The only objects left to render are the entry line and the various stored entries that are currently in the Console. As we render the various lines, we adjust the line position as we go so that the text is rendered in the correct place.

                              // draw entry line
                              _font.DrawText(_entryLine.ToString(), new System.Drawing.Rectangle(2, line, 0, 0), DrawTextFormat.None, System.Drawing.Color.Black);
                              line -= this.LineHeight;

                              // draw stored entries
                              foreach(string entry in _entries)
                              {
                                   if (line > 5)
                                   {
                                        _font.DrawText(entry, new System.Drawing.Rectangle(2, line, 0, 0), DrawTextFormat.None, System.Drawing.Color.Black);
                                        line -= this.LineHeight;
                                   }
                              }
                         }
                    }
                    catch
                    {
                         Console.Instance.Print("could not render console");
                    }
               }
          }

The only thing left to implement functionality-wise in the Console class is the ability to toggle the state the console is in.

          public void ToggleState()
          {
               if (_state == ConsoleState.Closed || _state == ConsoleState.Closing)
                    _state = ConsoleState.Opening;
               else
                    _state = ConsoleState.Closing;
          }

          #endregion

The last thing we need to do in our Console class is to dispose of the fonts that we use to draw the text on the screen.

          public void Dispose()
          {
               _font.Dispose();
               _windowsFont.Dispose();
          }
     }

Now that wasn't too hard was it? Now we just need to hook it into our current engine. All we need to do is update the Initialize and Render functions on the BattleEngine class in order to initialize and render the Console, respectively of course.

          public void Initialize(System.Windows.Forms.Control targetControl)
          {
               _targetControl = targetControl;

               // create subsystems
               _renderer = new Renderer(targetControl);

               // initialize subsystems
               CommandManager.Instance.Initialize();
               Console.Instance.Initialize();
          }

          private void Render()
          {
               _renderer.BeginScene();

               Console.Instance.Render();

               _renderer.EndScene();
          }

It's nothing special, but our game now has a console!

And another article has drawn to a close. I hope you all are having as much fun as I am having. All that is left for our input system in this simple 2D game is to gather keyboard input. In fact, keyboard input is our next article, so stay tuned. Same Bat Time, Same Bat Channel.


posted @ Monday, March 08, 2004 3:24 PM |

Comments

Gravatar # re: The One With All The Input - Console
Posted by Mr. Raybell on 3/16/2004 9:15 PM
Hey, great articles on good ol' DirectX... I've been following this and working and actually learning this rather well, but it would be nice to see some more. Case in point, the phantom Rectangle class that eludes me. I learn best on complete code, and obviously you have something complete with the screenshot shown here, if you have something more complete, it'd be be awesome if I could get it, just the base is all I need. :-)
Gravatar # re: The One With All The Input - Console
Posted by Jason Olson on 3/16/2004 10:52 PM
That was one of my worries when including the Rectangle class. I was waiting to hear if anyone raised their hand. Seeing that someone did, I will re-prioritize the rest of the articles to get the primitive shapes articles up before the UI framework article. Hopefully I will be able to write it and post it for you and the rest of the readers sometime this coming weekend.

If it's not up by the end of the weekend, I promise to let you shoot me personally ;~). The last thing I want to do is stop in the middle of these articles when they have been received so well.

Thanks for the feedback!
Gravatar # re: The One With All The Input - Console
Posted by Mr. Raybell on 3/17/2004 4:31 PM
Hey, thanks a lot! :-) I'm currently making a game, mostly as an assignment for one of my classes (btw, the teacher is... insane), however, since his resulting outline for the game was lacking, I decided to go one step further. This way I can make a good game and actually learn something. Your articles on Managed DirectX are one of the elite few on the net, and as such, I notice that I rely on it heavily. I also learned a better, more simple, implementation of the Singleton Pattern, which was a plus. Keep up the good work.
Gravatar # re: The One With All The Input - Console
Posted by Jason Olson on 3/17/2004 8:01 PM
Wow! "Elite Few". Thanks a lot! It means a whole heck of a lot to hear that :).
Gravatar # re: The One With All The Input - Console
Posted by Mr. Raybell on 3/18/2004 1:51 PM
Speaking of the Singleton Pattern that you used, it doesn't seem very thread safe, have you ever thought of putting in locking?
Gravatar # re: The One With All The Input - Console
Posted by Jason Olson on 3/18/2004 4:07 PM
Well, I am not an expert on multi-threaded programming, so I won't even claim to know that much.

But, I believe the actual implementation of the Singleton Pattern is thread safe. That is not to say that the actual Console class is thread safe, because it isn't. However, since the Singleton implementation is defined as static, readonly, it will be constructed at right when the application is started, not the first time it is used. and since the singleton variable is static, it will never be re-assigned to, so you do not need to lock it.

However, if you meant that the Console class, in general, is not thread safe. You would be correct, I believe. I was thinking of perhaps introducing multi-threaded functionality in a later article. Ideally, the Console class, as well as the Battle Engine class (and probably any other class with a Singleton pattern) should be thread safe.

Just let me know if I misunderstood you or I am wrong here. After all, the only thing I know for sure is that I know nothing :).

C'iao
Gravatar # re: The One With All The Input - Console
Posted by Jason Olson on 3/18/2004 4:08 PM
Geez, my English was horrible there. Sorry :$
Gravatar # re: The One With All The Input - Console
Posted by Mr. Raybell on 3/18/2004 6:13 PM
Okay, I see...
Gravatar # re: The One With All The Input - Console
Posted by Gary on 3/25/2004 10:08 AM
I'm using the DirectX 9 SDK, but it complains about the _font.DrawText, saying it does not take 4 params.

Any ideas?


Gravatar # re: The One With All The Input - Console
Posted by Jason Olson on 3/25/2004 11:05 AM
Gary, I would make sure that you are using the Font class that can be found in the Microsoft.DirectX.Direct3D namespace, and not the GraphicsFont wrapper class that is used in some of the SDK exampled. When I look at the method signature for DrawText in the Microsoft.DirectX.Direct3D namespace, I see two overloads, both with 4 parameters (one takes an int for color, and one takes a Color for color). I hope this helps! Let me know.
Gravatar # re: The One With All The Input - Console
Posted by Gary on 3/26/2004 5:12 AM
Hi, the DrawText I have takes 5 parameters, the first being of type Microsoft.DirectX.Direct3D.Sprint, and yes the _font is of type private Microsoft.DirectX.Direct3D.Font _font; as you can see I fully qualified it to make sure.

The version of DirectX I am using is 1.0.1901.0

I notice I also have version 1.0.900.0 installed, and it indeed has a Font taking only 4 parameters...

Gary
Gravatar # re: The One With All The Input - Console
Posted by Gary on 3/26/2004 5:13 AM
Hi, the DrawText I have takes 5 parameters, the first being of type Microsoft.DirectX.Direct3D.Sprint, and yes the _font is of type private Microsoft.DirectX.Direct3D.Font _font; as you can see I fully qualified it to make sure.

The version of DirectX I am using is 1.0.1901.0

I notice I also have version 1.0.900.0 installed, and it indeed has a DrawText taking only 4 parameters...

Gary
Gravatar # re: The One With All The Input - Console
Posted by Geoff Stockham on 3/29/2004 5:07 AM
Gary, I just stuck a null as the first parameter and it worked. The elusive rectangle class means that I have no background to my console yet though...
Gravatar # re: The One With All The Input - Console
Posted by Jason Olson on 3/29/2004 9:04 PM
Sorry Geoff, I dropped the ball here. I've been focusing on an article that I am writing and, obviously, not devoted enough time to write the article on the primitive type "wrappers" used in the game. I will try to make the time in the evenings during the week this week. Sorry for the hang-up. Hopefully I'll see you soon (or, rather, you'll see my articles soon) :). Thanks!
Gravatar # re: The One With All The Input - Console
Posted by Jason Olson on 3/29/2004 9:04 PM
Of course this means that someone now has the permission to actually shoot me. So hopefully I will get the article up before I am shot. Thanks :)
Gravatar # re: The One With All The Input - Console
Posted by Geoff Stockham on 3/30/2004 12:04 AM
Sorry Jason, I hope it didn't sound like a criticism! The articles are great and you mention that the Rectangle is a "simple wrapper around a vertex buffer" so I have created one, but I haven't got it to display correctly. As I can still see the text on the console I've decided I'll come back to it later!
Gravatar # BANG
Posted by Mr. Raybell on 4/1/2004 1:49 AM
You're grazed, consider that a warning... :P~
Gravatar # Microsoft.DirectX.Direct3D.Font
Posted by Mike Frey on 4/5/2004 8:28 PM
For some reason VS.Net cannot find Microsoft.DirectX.Direct3D.Font. It says that Font is not a member of the Direct3D namespace. Am I missing something? Can anyone help?
Gravatar # re: The One With All The Input - Console
Posted by Jason Olson on 4/5/2004 9:25 PM
Hey Mike, which version of DirectX are you using? Have you ensured that you have all the references you need (i.e. Microsoft.DirectX, Microsoft.DirectX.Direct3D, Microsoft.DirectX.Direct3DX, and Microsoft.DirectX.DirectInput). Also make sure that the references are pointing to C:\WINDOWS\Microsoft.NET\Managed DirectX\.
Gravatar # re: The One With All The Input - Console
Posted by Jason Olson on 4/5/2004 9:27 PM
Double checking this, I believe Font resides in the Microsoft.DirectX.Direct3DX assembly because when I remove that reference, I get the same error you describe. I hope this helps! Ciao.
Gravatar # re :Microsoft.DirectX.Direct3D.Font
Posted by Mike Frey on 4/7/2004 7:32 AM
I didnt have a reference to Microsoft.DirectX.Direct3DX.

Thanks for the help! The articles are great. Keep up the good work!

Mike
Gravatar # re: The One With All The Input - Console
Posted by Inkog on 4/19/2004 11:32 AM
I was very troubled by this example because of 8-12 FPS rendering with absoultly no objects drawn to the screen. After testing other basic "loop/render" engines, I discovered that the poor FPS I was observing was due to having AA & AF enabled on my GPU and not due to the game loop implementation, rendering proccess, etc. Any thoughts on why this occurs? I'm guessing you need specific code to handle AA & AF? I'm pretty sure it's not hardware related, as my P4 3GHz - 1GB rdram - 533FSB - ATI Radeon 9700 Pro, system doesn't miss a beat with the most taxing games, much less a empty D3D form... Any input would be great!

Thanks,

~Inkog
Gravatar # re: The One With All The Input - Console
Posted by James Gregory on 5/24/2004 3:22 PM
Hi, I would like to say thank you for these articles you've written. I've been coding a "Game Engine" for quite sometime now and have just decided to make the jump to D3D. Your articles are, in my opinion, the best around. I've not seen any others with the sheer quality and simplicity as yours, they've been a immense help. So thank you and I can't wait to read the next one!

Keep up the excellent work.
James.
Gravatar # re: The One With All The Input - Console
Posted by Bradley Hicken on 7/9/2004 7:37 PM
Any Luck with the Rectangel Class yet? Or maybe for those of us who would like to play the "figure it out for your self game" a hint to go in the right direction....

By the way Great articles....
Gravatar # re: The One With All The Input - Console
Posted by Jason Olson on 7/11/2004 7:57 PM
All -

I am looking at posting the article on Primitives in the coming week or two and that should take care of the Rectangle class. Thanks!
Gravatar # re: The One With All The Input - Console
Posted by Roman Wannenmacher on 8/20/2004 12:21 PM
Wow! Great article! Easy to read and easy to understand, but in detail very complex.

One question: When do you deliver the rectangle class?
Thanks for this article!
Wanne

Gravatar # re: The One With All The Input - Console
Posted by Jason Olson on 8/20/2004 5:54 PM
Hey! Thanks, Wanne! That means a lot. I was planning on throwing up the Rectangle class article before I re-write all the articles for post-Summer update. However, I still go back and forth. I'm wondering if I should spend the time to whip up the article if I'm just going to be tossing all the articles anyways.
Gravatar # re: The One With All The Input - Console
Posted by Pablo Alvarez on 9/7/2004 4:53 PM
Cool series.. hope you go on with them. Just one thought: I get the idea that you use that good ol' Rectangle class to wrap a vertex Buffer, so you are probably drawing a rectangle polygon... mmm... Wouldn't it be faster using just one Sprite? the Rectangle class being a wrapper for a 2D sprite?

I am a total newbie of DirectX, but i've finished my console implementation this way and i think it is more performant and easier, and given we are never going to rotate the console, it seems ok for me... just my two cents :)

Keep on the great work Jason, and thanks again...
Pablo
Gravatar # re: The One With All The Input - Console
Posted by Jason Olson on 9/7/2004 5:11 PM
Hey Pablo, thanks for the kind words. Be aware that the Rectangle class is meant for simple primitives :). I am not going to be using that class for any of my sprites. For the sprites, I will be using one common vertex buffer with only enough vertices for a single polygon. All the sizing and positioning and such with the sprites will be done via matrix transformations. With how little we should really be using the Rectangle class, the performance shouldn't be that much of an issue.
Gravatar # re: The One With All The Input - Console
Posted by Pablo Alvarez on 9/8/2004 9:25 AM
You are right, performance is not an issue at all in this concrete problem, but well, I am an absolute newbie with DirectX and just felt better asking or another oppinion and trying different ways of achieving the things.

Another point I wished to state is that you keep creating, in the Console.Render() method, 6 float values in each call, wich can lead to a sooner promotion ob Gen.0 to Gen.1 objects in the GC.. shouldn't we take care of that, especialy in 'per-frame' methods? In my actual implementation I promoted that metod variables to class attributes to grant there will be no new memory reserves there.

Thanks again, hope the series continue soon :)
Pablo
Gravatar # re: The One With All The Input - Console
Posted by Ben Scheirman on 12/5/2004 10:06 PM
Just wondering when we could expect the article for the Shapes class. I've been hooked on these articles and I don't want to stop!

Keep up the good work.

-Ben
Gravatar # re: The One With All The Input - Console
Posted by Stephen Els on 1/10/2005 2:55 AM
Like Ben posted, this is a good series of articles, the only bummer is when are we going to see the Shpes classes. Could you not just add it in a seperate post to complete this section?

Stephen
Gravatar # re: The One With All The Input - Console
Posted by Jason Olson on 1/12/2005 2:46 PM
Hey Stephen, Ben, and everyone else. Yeah, I'll go ahead and add the shapes section in another article as soon as I can whip it up. I haven't done it yet mostly because these articles are actually going to be moved and re-written over on my new managed directx website, <a href="http://www.managed-world.com">Managed World</a>. I'll at least post one more here though so people can actually write the code. Stay tuned.
Gravatar # re: The One With All The Input - Console
Posted by Joe Smith on 4/21/2005 6:26 AM
This is a superb set of articles. Any news on the update with the shapes in?

-Joe S
Gravatar # Writing a 2D Game with C# and DirectX 9
Posted by IndieGameDev on 5/11/2005 1:44 PM
Jason "<span style="font-style: italic;">From the Soup to the Nuts</span>"
Olson has aposted a series of articles that walk through the ...
Gravatar # re: The One With All The Input - Console
Posted by A Murthy on 1/28/2008 12:44 PM
Hello Jason,

Thanks for your very helpful series of articles.

In response to the questions above for the "Shapes" class, I have implemented the "Render" function in "Console.cs" using "DrawRectangle" and "FillRectangle" calls instead.

There is some flashing, in the console area, but it works quite well with the rest of your superb code.

-- thx again

Gravatar # re: The One With All The Input - Console
Posted by Drew on 4/27/2008 6:52 PM
I implemented my own Rectangle class, and it seems to work the way it should. However, I had to edit the Render method that he posted to make mine display properly.

Thanks for the otherwise great articles, it's too bad you'll never finish them.

Modified Render lines:
float x = 0;
float y = 0;
float width = BattleEngine.Instance.TargetControl.Width;
float height = visibleHeight;

Battle.Shapes.Rectangle consoleBackground = new Battle.Shapes.Rectangle(x, y, width, height, System.Drawing.Color.White);
Battle.Shapes.Rectangle consoleDivider = new Battle.Shapes.Rectangle(0, line - 2, width, 1, System.Drawing.Color.Black);
consoleBackground.Render();
consoleDivider.Render();

font.DrawText(null, entryLine.ToString(), new System.Drawing.Rectangle(2, line, 0, 0), DrawTextFormat.NoClip, System.Drawing.Color.Black);

line -= this.LineHeight;

foreach (string entry in entries)
{
if (line > 5)
{
font.DrawText(null, entry, new System.Drawing.Rectangle(2, line, 0, 0), DrawTextFormat.NoClip, System.Drawing.Color.Black);
line -= this.LineHeight;
}
}


Rectangle.cs:
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX;

namespace Battle.Shapes
{
class Rectangle
{
private CustomVertex.TransformedColored[] vertices;

public Rectangle(float x, float y, float width, float height, System.Drawing.Color color)
{
vertices = new CustomVertex.TransformedColored[4];
vertices[0].Position = new Vector4(x, y + height, 0f, 0f);
vertices[0].Color = color.ToArgb();
vertices[1].Position = new Vector4(x, y, 0f, 0f);
vertices[1].Color = color.ToArgb();
vertices[2].Position = new Vector4(x + width, y + height, 0f, 0f);
vertices[2].Color = color.ToArgb();
vertices[3].Position = new Vector4(x + width, y, 0f, 0f);
vertices[3].Color = color.ToArgb();
}

public void Render()
{
BattleEngine.Instance.Renderer.Device.DrawUserPrimitives(Microsoft.DirectX.Direct3D.PrimitiveType.TriangleStrip, 2, vertices);
}
}
}

Post a comment





 

Please add 1 and 3 and type the answer here: