1. Trang chủ
  2. » Công Nghệ Thông Tin

Visual C# Game Programming for Teens phần 2 pdf

47 434 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 47
Dung lượng 475,71 KB

Nội dung

//random line ends int x = rand.Next(1, this.Size.Width - 50); int y = rand.Next(1, this.Size.Height - 50); Rectangle rect = new Rectangle(x, y, 50, 50); //draw the rectangle device.DrawRectangle(pen, rect); //refresh the drawing surface pb.Image = surface; } private void timer_Tick(object source, EventArgs e) { drawRect(); } } Drawing Text We will need to draw text onto the game screen using any desired font, and the Graphics class gives us this ability too, via the DrawString() function. There are several versions of the function with various sets of parameters, but we will be using the simplest version that just needs a String (for the words we want to print out), a custom Font object, the color, and the coordinates. Figure 2.4 shows the result of this example program. using System; using System.Drawing; using System.Windows.Forms; public partial class Form1 : Form { string[] text = { "AVATAR!", "Know that Brittania has entered into a new age of", "enlightenment! Know that the time has finally come", "for the one true Lord of Brittania to take his place", "at the head of his people. Under my guidance, Brit-", "tania will flourish. And all of the people shall", "rejoice and pay homage to their new guardian!", "Know that you, too, shall kneel before me, Avatar.", Drawing Text 29 "You, too, will soon acknowledge my authority. For I", "shall be your companion your provider and your", "master!", "", "Ultima VII: The Black Gate", "Copyright 1992 by Electronic Arts" }; PictureBox pb; Bitmap surface; Graphics device; Random rand; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) Figure 2.4 Printing text using a custom font and color. 30 Chapter 2 n Drawing Shapes and Bitmaps with GDI+ { //initialize this.Text = "Text Drawing Demo"; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle. FixedSingle; this.MaximizeBox = false; this.Size = new Size(600, 500); rand = new Random(); //create a new picturebox pb = new PictureBox(); pb.Parent = this; pb.Dock = DockStyle.Fill; pb.BackColor = Color.Black; //create graphics device surface = new Bitmap(this.Size.Width, this.Size.Height); pb.Image = surface; device = Graphics.FromImage(surface); //make a new font Font font = new Font("Times New Roman", 26, FontStyle.Regular, GraphicsUnit.Pixel); //draw the text for (int n = 0; n < text.Length; n++) { device.DrawString(text[n], font, Brushes.Red, 10, 10 + n*28); } //refresh the drawing surface pb.Image = surface; } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { device.Dispose(); surface.Dispose(); } } Drawing Text 31 There are other shapes in addition to lines, rectangles, and text that the Graphics class can draw. Now that you have a foundation, see if you can modify the program to use any of the following functions: n DrawArc n DrawBezier n DrawCurve n DrawEllipse n DrawPie n DrawPolygon Trick To simplify the code in this C# project, I have removed the default namespace that Visual C# automatically added to the new project. In a larger project with many source code files and libraries, we would want to use a namespace, but for simple examples like this it is okay to skip the namespace. Dissecting Bitmaps Learning to draw a bitmap is the first step toward creating a 2D game like our impending Dungeon Crawler game. When we have the ability to draw just one bitmap, then we can extend that to animation by drawing one frame after another in a timed sequence—and presto, sprite animation becomes a reality! We will focus on sprite animation in Chapter 3, and work on the basics of bitmap drawing now as a prerequisite. Drawing on the code we learned about earlier in the chapter, a Bitmap object, a PictureBox, and a Graphics object work in tandem to represent a rendering device capable of drawing vector shapes as well as bitmaps. Once again for reference, we have to declare the two variables: Bitmap surface; Graphics device; and then, assuming we have a PictureBox control called pictureBox1, create the objects. The PictureBox control can be created at runtime or we can just add it to the form manually. 32 Chapter 2 n Drawing Shapes and Bitmaps with GDI+ surface = new Bitmap(this.Size.Width, this.Size.Height); pictureBox1.Image = surface; device = Graphics.FromImage(surface); So, we already knew this startup code, but—just to lay the groundwork—this is what is needed up front as a rendering device to draw a bitmap. Loading a Bitmap File We can load a bitmap in C# by using the Bitmap class. But there is no Bitmap. Load() function (unfortunately!) so we have to use the constructor instead by passing the bitmap filename when the object is created. Bitmap bmp; bmp = new Bitmap("image.bmp"); Definition A constructor is a class function (also called a method) that runs when an object is first created. This is where class variables (also called properties) are initialized. A destructor is a class function that runs when the object is being destroyed: via object.Dispose() or object = null. Although both approaches work, and we can even pass a string rather than hard coding the filename, there is the very serious problem of error handling: if the file does not exist, an exception error will crash the program. Missing files are fairly common (usually due to their being in the wrong folder), and we want to display a friendly error message rather than watch the program crash. The solution is to wrap the bitmap loading code in a try catch block. Here is an example: try { bmp = new Bitmap(filename); } catch (Exception ex) { } This code will not crash if the file is missing or if some other error occurs while reading the file. So, let’s put it into a reusable function that returns a Bitmap if the file exists or Nothing (null) if it fails. One caveat: be sure to free memory used by the bitmap when the program ends. public Bitmap LoadBitmap(string filename) { Dissecting Bitmaps 33 Bitmap bmp = null; try { bmp = new Bitmap(filename); } catch (Exception) { } return bmp; } If the file does not exist, then LoadBitmap() will return Nothing as the object pointer rather than crashing with an exception error. This is a very handy little function! And it demonstrates the power of code reuse and customization— whatever features we need that are not al ready in an SDK or library we can just write ourselves. One might even go so far as to write their own new Bitmap wrapper class (called something like CBitmap?) with a Load() function. You could easily do this yourself with just the small amount of code we have used so far. I’m just going to skip this step, though, and add bitmap loading in the Sprite class when we get to it in Chapter 3. Hint To ensure that created objects are properly disposed of when the program ends, I recommend putting the Form1_FormClosed() function at the top of the source code, just below the variable declarations, where it will be quick and easy to write the code needed to free an object. Always write creation/deletion code together in pairs to avoid memory leaks! Drawing a Bitmap There are several versions of the Graphics.DrawImage() function; the alternate versions are called overloaded functions in “OOP speak. ” The simplest version of the function calls for just a Bitmap or Image parameter and then the X and Y position. For example, this line device.DrawImage(bmp, 0, 0); will draw the bitmap bmp at pixel coordinates 0,0. Figure 2.5 shows an example. We can optionally use a Point with the X and Y coordinates combined into one object, or use floating-point Single variables. There are also scaling features that make it possible to resize the image. By passing additional width and height 34 Chapter 2 n Drawing Shapes and Bitmaps with GDI+ parameters, we can define a new target size for the image. Figure 2.6 shows another example with the addition of this line, which draws another copy of the bitmap scaled down to a smaller size. device.DrawImage(planet, 400, 10, 64, 64); Rotating and Flipping a Bitmap The Bitmap class has some helper functions for manipulating the image and even its individual pixels. The Bitmap.RotateFlip() function will rotate a bitmap in 90-degree increments (90, 180, and 270 degrees), as well as flip the bitmap vertically, horizontally, or both. Here is an example that rotates the bitmap 90 degrees: planet.RotateFlip(RotateFlipType.Rotate90FlipNone); Figure 2.5 Drawing an image loaded from a bitmap file. Dissecting Bitmaps 35 The RotateFlipType options are as follows: n Rotate180FlipNone n Rotate180FlipX n Rotate180FlipXY n Rotate180FlipY n Rotate270FlipNone n Rotate270FlipX n Rotate270FlipXY n Rotate270FlipY n Rotate90FlipNone n Rotate90FlipX n Rotate90FlipXY n Rotate90FlipY Figure 2.6 Drawing a scaled bitmap. 36 Chapter 2 n Drawing Shapes and Bitmaps with GDI+ n RotateNoneFlipX n RotateNoneFlipXY n RotateNoneFlipY The Bitmap Drawing demo has several buttons on the form to let you explore rotating and flipping a bitmap in various ways, as you can see in Figure 2.7. In addition to calling RotateFlip(), we still need to draw the image again and refresh the PictureBox like usual: image.RotateFlip(RotateFlipType.Rotate180FlipNone); device.DrawImage(planet, 0, 0); pictureBox1.Image = surface; Accessing Bitmap Pixels We can also examine and modify the pixel buffer of a bitmap directly using functions in the Bitmap class. The Bitmap.GetPixel() function retrieves the pixel of a bitmap at given X,Y coordinates, returning it as a Color variable. Likewise, Figure 2.7 Rotating and flipping a bitmap. Dissecting Bitmaps 37 the Bitmap.SetPixel() will change the color of a pixel at the given coordinates. The following example reads every pixel in the planet bitmap and changes it to green by setting the red and blue components of the color to zero, which leaves just the green color remaining. Figure 2.8 shows the Bitmap Drawing demo with the pixels modified—not very interesting but it does a good job of showing what you can do with this capability. for (int x = 0; x < image.Width - 1; x++) { for (int y = 0; y < image.Height - 1; y++) { Color pixelColor = image.GetPixel(x, y); Color newColor = Color.FromArgb(0, pixelColor.G, 0); image.SetPixel(x, y, newColor); } } Figure 2.8 Modifying the color value of pixels in a bitmap. 38 Chapter 2 n Drawing Shapes and Bitmaps with GDI+ [...]... System; using System.Drawing; using System.Windows.Forms; public partial class Form1 : Form { public Game game; public Bitmap planet; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { //set up the form this.Text = "Framework Demo"; //create game object game = new Game( this, 600, 500); //load bitmap planet = game. LoadBitmap("planet.bmp"); if (planet == null)... bitmap game. Device.DrawImage(planet, 10, 10); game. Device.DrawImage(planet, 400, 10, 100, 100); game. Update(); Level Up! } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { //delete game object game = null; } } Eliminating any reusable source code by moving it into a support file is like reducing a mathematical formula, rendering the new formula more powerful than it was before Any... welcome to remove after you get what it’s doing public Game( Form1 form, int width, int height) { Trace.WriteLine( "Game class constructor"); //set form properties p_frm = form; p_frm.FormBorderStyle = FormBorderStyle.FixedSingle; p_frm.MaximizeBox = false; p_frm.Size = new Size(width, height); //create a picturebox p_pb = new PictureBox(); 43 44 Chapter 2 n Drawing Shapes and Bitmaps with GDI+ p_pb.Parent... easily accessible First, we’ll create a new source code file called Game. cs, which will contain the source code for the Game class Then, we’ll copy this Game. cs file into the folder of any new project we create and add it to that project The goal is to simplify the whole process of creating a new game project and make most of our C# game code reusable Let’s get started: using using using using using... Color.FromArgb (25 5, 25 5, 25 5); Color black = Color.FromArgb(0, 0, 0); for (int x = 0; x < image.Width - 1; x++) { for (int y = 0; y < image.Height - 1; y++) { if (image.GetPixel(x,y) == white) image.SetPixel(x, y, black); } } device.DrawImage(image, 0, 0); pictureBox1.Image = surface; } private void button16_Click(object sender, EventArgs e) { for (int x = 0; x < image.Width - 1; x++) { for (int y =... your artwork and other game resources inside bin\Debug while working on your game When your game is finished and ready for release, then copy all of the files together into a new folder with the executable Animating a Sprite After you have written a few games, you’ll most likely find that many of the sprites in your games have similar behaviors, to the point of predictability For instance, if you have... initialized at this point It’s good programming practice to set the initial values for the properties on our own public Sprite(ref Game game) { p _game = game; p_position = new PointF(0, 0); Animating a Sprite p_velocity = new PointF(0, 0); p_size = new Size(0, 0); p_bitmap = null; p_alive = true; p_columns = 1; p_totalFrames = 1; p_currentFrame = 0; p_animationDir = AnimateDir.FORWARD; p_animationWrap = AnimateWrap.WRAP;... really should be run from the fastest part of the game loop whenever possible, and only real drawing should take place in Game_ Draw() due to timing considerations If you were to put all of the gameplay code in Game_ Draw() and 61 62 Chapter 3 n Sprites and Real-Time Animation hardly anything in Game_ Update(), which is the fast-running function, then the game would slow down quite a bit We will also need... frames that are each 128 Â 128 pixels in size, but I have enlarged the sprite sheet so the dragon is twice as large as normal This isn’t a great idea for a game, because we can resize the sprite at runtime (with the Bitmap.DrawBitmap() method), but it was a simple solution to make it appear bigger for the sake of illustration Improving the Game Class It is completely possible to make a game within the source... store your game s files inside the main folder of the project because when it runs (inside bin\Debug, for instance) it will not know where the files are located, and the program will crash You can hard-code the path into your game (like C: \Game) , but this is a bad idea because then anyone who tries to play your game will have to create the exact same directory that you did when you created the game Instead, . it’s doing. public Game( Form1 form, int width, int height) { Trace.WriteLine(" ;Game class constructor"); //set form properties p_frm = form; p_frm.FormBorderStyle = FormBorderStyle.FixedSingle; p_frm.MaximizeBox. Rotate270FlipNone n Rotate270FlipX n Rotate270FlipXY n Rotate270FlipY n Rotate90FlipNone n Rotate90FlipX n Rotate90FlipXY n Rotate90FlipY Figure 2. 6 Drawing a scaled bitmap. 36 Chapter 2 n Drawing. the new Game class, the source code is much, much shorter! Take a look. using System; using System.Drawing; using System.Windows.Forms; public partial class Form1 : Form { public Game game; public

Ngày đăng: 14/08/2014, 01:20

TỪ KHÓA LIÊN QUAN