1 ページ
Li nói u Ước mơ viết 1 game cho riêng mình , rộng ra thì viết 1 game cho VN mở mặt với thế giới. Ước mơ của mình là muốn VN chúng ta có một ngành CN giải trí điện tử lớn mạnh ngang tầm tụi Hàn chẳng hạn và rồi sẽ có ngày bọn tây, tàu đến VN xin mua bản quyền game đem về nc nó phát hành laị JJJJ . Hiện nay có vô số công cụ, Ngôn ngữ, môi trường phát triển game, mình chọn XNA bởi các lý do sau: -Các ưu điểm đã nêu trong forum, trên internet... -Của Microsoft mà mình tín nhiệm thằng này. -Môi trường làm việc chuyên nghiệp, quản lý tốt. free khi làm game trên windows. Khỏi lo sau này lôi kéo nhau ra toà. -NNLT C# đơn giản, tư nhiên, dễ học và hiểu nhanh hơn so với các NNLT khác. Bài tut này nhằm mục đích nâng cao tay nghề cho bản thân và mình muốn phổ biến những kiến thức cơ bản nhất về XNA cho mọi người. Sau này nếu có các dự án lớn trên forum thì chắc mọi người đều là các programmer online cả rồi. Tương lai là điều rất khó đoán, thế nên ta nên học từ ngay bây giờ đi, sau này nhất định sẽ có lúc cần, nhất là các bạn theo IT và tính cả các bạn đam mê IT nữa. Một game Nhập vai trực tuyền nhiều người chơi nếu chỉ dựa vào tut này thì ko thể nhưng viết những game nhỏ tặng bạn bè, bồ bịch hay chuẩn bị cho những dự án lớn hơn (có thể trong tương lai các bạn là người mình muốn cộng tác đấy) thì mình tin tài liệu này sẽ có ích. Đối với nhiều người, lập trình và công việc nhàm chán, tắm mình trong 1 đống code, thế nhưng muốn viết game phải biết lập trình, bạn hãy nhớ công đoạn thú vị nhất khi lập trình game là lập trình chúng (ngoài ra LT ra còn có viết ý tưởng, thuật toán, debug... ) Lập trình không chỉ là công việc đó là nghệ thuật còn Lập trình viên là nghệ sĩ, tất nhiên rồi :D Bài viết dựa trên tài liệu: Beginning XNA 3.0 Game Programming From Novice to Professionalnhà ca xut bn APRESS. Bài viết không thể tránh khỏi sai sót, mọi gọi ý thắc mắc kiện cáo j, các bạn bỏ hết vào đây thanh_vinh648@yahoo.com (nếu bận mình ko online thường xuyên, các bạn có thể dùng số DĐ sau: 01649120185-Nghiêm cấm nhá máy J ) Tác Giả Vũ Thành Vinh (Huyết sát) ThiNganHang.com
2 ページ
Giới thiệu sơ luợc về XNA và C#: XNA Không cần giới thiệu chi cho rườm rà, bạn chỉ cần có Visual Studio và bộ XNA GSE 3.0 là ok. Chuẩn bị môi trường phát triển : - Nâng cấp Visual Studio : Các phiên bản VS ñược XNA hỗ trợ : Trích dẫn: * Visual C# 2005 Express Edition * Visual Studio 2005 Standard Edition * Visual Studio 2005 Professional Edition * Visual Studio 2005 Tools for the Microsoft Office System * Visual Studio 2005 Team Edition for Software Architects * Visual Studio 2005 Team Edition for Software Developers * Visual Studio 2005 Team Edition for Software Testers * Visual Studio 2005 Team Edition for Database Professionals * Visual Studio 2005 Team Suite + Nếu bạn ñang xài VS C# Express thì down cái này (24.3MB) : Trích dẫn: http://download.microsoft.com/downlo...9-X86-INTL.exe Nếu ko xài C# mà xài các ngôn ngữ khác thì xem thêm tại Trích dẫn: http://www.microsoft.com/downloads/d...ng=en#filelist ThiNganHang.com
3 ページ
) + Nếu bạn ñang xài các phiên bản VS khác (ko phải Express) thì down cái này (431.7MB - khủng khiếp T_T): Trích dẫn: http://download.microsoft.com/downlo...01-X86-ENU.exe - Tiếp ñó là download XNA (98.6MB): Trích dẫn: http://download.microsoft.com/downlo...GS20_setup.exe Nếu ñọc ñược tiếng Anh, bạn có thể tham khảo phần hướng dẫn của MSDN Làm quen với XNA Bây giờ ta sẽ tiến hành tạo một XNA Project mới Khởi ñộng C#, bạn chọn New Project -> Windows Game , rồi gõ tên Project vào, nhấn OK là tạo xong :-D Bạn build ra rồi chạy thử sẽ ñược như hình : ThiNganHang.com
4 ページ
=> Ra cái cửa sổ xanh lè và không có con chuột là OK! Nguồn: ko biết nữa nhưng thấy ñầy rẫy trên mạng, Thanks tác giả. ThiNganHang.com
5 ページ
ðể hiểu mã lệnh bắt buộc các bạn phải học qua C#, tự học, online j cũng ñc, mình không giải thích nhiều về C#,mà chủ yếu là các thành phần của XNA. Thường những cái ñã giải thích , lession sau mình bỏ qua hoặc nói sơ sơ... Nội dung bài viết chủ yếu về thuật toán và mã lệnh File mã lệnh gồm có Game1.cs và prỏgram.cs và những thứ tự viết... Nội dung game1.cs: ðây là file chứa những mã lệnh giúp 1 game có thể chạy ñc bình thường, tất nhiên cấu thành nó gồm nhiều Component và DrawableGameComponent (class sẵn có trong XNA) ... ðây là giới thiệu cơ bản, tuy ñơn giản nhưng các bạn nên ñọc qua >= 1 lần using System; using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Media; using Microsoft.Xna.Framework.Net; using Microsoft.Xna.Framework.Storage; //Những thứ XNA sử dụng bạn ko cần using hết mà tuỳ từng trường hợp mà sử dụng namespace WindowsGame1 { /// <summary> /// Đây là những thiết lập ban đầu cho 1 SpriteBatch đặc biệt gọi là SpriteBatch và đò họa, tất cả đều dựa trên mã nguồn của XNA /// </summary> public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } /// <summary> /// Cho phép game có thể bắt đầu thiết lập truớc khi bắt đầu chạy /// Đây là nơi bạn khai báo biến, load Tài nguyên, hàm không fải đồ họa (đồ họa sẽ có hàm khác load) ... /// Thiết lập cho các thành phần của game /// </summary> ThiNganHang.com
6 ページ
protected override void Initialize() { // Thêm vào thiết lập logic ở đây, thuờng cũng k cần lắm base.Initialize(); } /// <summary> /// hàm LoadContent sẽ được gọi 1 làn khi chạy game và nó sẽ load toàn bộ những content trong game của bạn /// </summary> protected override void LoadContent() { // tạo một SpriteBatch mới, nó được dùng để vẽ texture. spriteBatch = new SpriteBatch(GraphicsDevice); } /// <summary> /// hàm UnloadContent đc gọi 1 làn trong game khi bạn out /// nó xóa sạch nội dung chứa trong game /// </summary> protected override void UnloadContent() { // không bắt buộc fải có, trừ dự án lớn hoặc khi bạn siêng năng. } /// <summary> /// hàm Update() hàm kt ĐK của game khi chạy /// kiểm tra kiểm tra va chạm, input (mouse, keyboard), và chơi nhạc protected override void Update(GameTime gameTime) { // cho phep game out (trên Xbox) if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); // thêm vào logic của game ở đây base.Update(gameTime); //GameTime là 1 biến đặc biệt chỉ thời gian chạy game } /// <summary> /// Hàm gọi khi cần vẽ thì hàm sẽ hiện lên /// </summary> protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); //xóa màn hình và thêm màn nền (Color.CornflowerBlue) // thêm vào mã lệnh đồ họa. base.Draw(gameTime); } } } ThiNganHang.com
7 ページ
ðây là nội dung cơ bản của XNA, Nhiệm vụ của nó là hiện lên cái màn hình xanh lè: Trong ñây chỉ có hàm Draw() là thể hiện File mã lệnh thứ 2 là program.cs: using System; namespace XNADemo { static class Program { /// <summary> /// The main entry point for the application. /// </summary> static void Main(string[] args) { using (Game1 game = new Game1()) { game.Run(); } } } } //cái nài thì cứ để yên thế, không nên đụng tay vô J ThiNganHang.com
8 ページ
Các file mã lệnh: class do user tự Đ/N, cái này do mình viết và nó ko hề ít đâu LLLL Bài 1 : Đưa Đối tuợng lên Màn hình Tài nguyên: một texture (image) 64x64 có tên ball Đầu tiên khi viết game là Object phải được đưa lên screen, nghe thì đơn giản nhưng trong XNA đây là việc kha khá đâu đầu, đồi hỏi sự phối hợp giữa các hàm trong Game1.cs Đầu tiên bạn khởi taọ project mới.cho nó 1 tài nguyên (image chẳng hạn) Tại cửa sổ project, bạn click phải chuột vào mục Content, chọn Add -> Existing Item, hộp thoại Add Existing Item mở ra và bạn tìm ñến file cần ñưa vào project, add nó vào Phần mã lệnh: I Một đối tuợng đưa lên monitor thì cần các yếu tố sau: SpriteBatch : một Sprite đặc biệt , nó đại diện cho một hoặc các sprite khác trong XNA. Nó có sẵn hay tự tạo đều được. Texture: Đại loại là một bức ảnh 2D (cũng có texture3D) bao phủ lên Sprite trong game (thuờng là bao theo hình chữ nhật). Class: lớp là thành phần không thể thiếu của C# vì đây là ngôn ngữ huớng đối tuợng hoàn toàn, bất kẻ sprite nào muốn thể hiện điều phải có class rieng của nó. Phần I: class cho clsSprite Tính hợp thành của OOP (Composition): Tất cả object chạy trên chương trình đều có mã lệnh hoạt động riêng của nó đc viết lại thành các hàm, method, thuộc tính trong class của nó, tất cả chúng hợp thành lên class cho object. Nó có thể thừa kế từ nhiều nguồn khác nhau, sau này sẽ nói thêm. Tạm thế đã, đầu tiên chúng ta đi từ cái đơn giản nhất, mã lệnh cho một sprite đơn giản thể hiện trên màn hình: Tạo một file *.cs đặt trong thư mục chứa project, hay add => class cung đc Câu lệnh using sử dụng code sẵn có của XNA: using Microsoft.Xna.Framework.Graphics; // for Texture2D using Microsoft.Xna.Framework; // for Vector2 ThiNganHang.com
9 ページ
Cấu trúc: Namespace => class =>function... Sau class là phần tên lớp, đặt jì là tùy bạn, mình lấy clsSprite class clsSprite { } 1.Khai báo Sau đó là phần khai báo biến, cũng là các thành phần của class: Vector2 là cái j?, nó là 1 cặp (2 cái) biến có liên quan đến nhau trong game, bạn nhận thấy vị trí của vật gồm có thuộc tính X và Y, tốc độ của sprite cũng thế có thể theo trong Ox hoac Oy, (như SpeedX, SpeedY)... tùm lum thứ có thể VD. Do đó, chúng ta sử dụng vector2 cho các thuộc tính size (height, width) Tuơng tự cho tọa độ position (X,Y) Texture thì bắt buộc rồi: public Texture2D texture { get; set; } // sprite texture, read-only property public Vector2 position { get; set; } // sprite position on screen public Vector2 size { get; set; } // sprite size in pixel 2.Nhập dữ liệu Một hàm trùng tên với class sẽ đảm nhận vai trò này: rất đơn giản thôi, nó nhận texture, position và size của từ bên ngoài làm của nó public clsSprite (Texture2D newTexture, Vector2 newPosition, Vector2 newSize){ texture = newTexture; position = newPosition; size = newSize; } 3.Hàm đồ họa Nhiệm vụ của sprite là thể hiện trên screen, thế nên hàm chức năng của nó chỉ cần Draw là đủ: public void Draw(SpriteBatch spriteBatch) ThiNganHang.com
10 ページ
{ spriteBatch.Draw(texture, position, Color.White); } Các yếu tố cơ bản như texture, vị trí, màu khi vẽ nhưng texture sẽ đè lên cái White đó, bạn khỏi lo, thêm mấy cái { nữa là xong class... Phần II: Hoàn thiện cho Game1.cs: Game1 sử dụng: #region Using Statements using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Storage; using System.Linq; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Media; using Microsoft.Xna.Framework.Net; #endregion Cứ bỏ hết vào cũng đc, thừa > thiếu Game1 kế thừ từ Microsoft.Xna.Framework.Game Class Game1 cần đc bổ sung, bắt đầu là khai báo các biến sẽ dùng: GraphicsDeviceManager graphics; clsSprite mySprite1; SpriteBatch spriteBatch; Một đồ họa, sử dụng cái sẵn có của XNA Mổt Spite, cái chúng ta đã viết class. SpriteBatch, cái để đại diện sprite. Game1 không cần nhập dữ liệu từ bên ngoài như clsSprite nhưng chúng ta vẫn viết hàm Game1() để thiết lập cho nó: public Game1() { graphics = new GraphicsDeviceManager(this); // Sử dụng đồ họa cho chính nó (game1) graphics.PreferredBackBufferWidth = 500; graphics.PreferredBackBufferHeight = 300; //Chiều rộng cửa sổ game Content.RootDirectory = "Content"; ThiNganHang.com
11 ページ
//Thư mục gốc chứa tài nguyên là “content” } Tiếp theo một hàm để load tài nguyên cho game protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); // Load a 2D texture sprite mySprite1 = new clsSprite(Content.Load<Texture2D>("ball"), new Vector2(0f, 0f), new Vector2(64f, 64f)); } mySpite1 sẽ đc load texture lên trên nó, file name là ball bạn add vào tài nguyên của game (project=>add=>existing items) file này có size 64x64 pixcel //câu lệnh trên có nghĩa texture bắt đầu lấy từ tọa độ 0,0 của ball và kick cỡ là 64x64 (tức là cả file ball đó) Tiếp là một hàm unload nhằm xóa các thành phần khỏi bộ nhớ khi close game: protected override void UnloadContent() { // Free the previously alocated resources mySprite1.texture.Dispose( ); spriteBatch.Dispose(); } Hàm Update cứ giữ nguyên thế vì trong quá trình chạy, chả có quái j thay đổi cả. ThiNganHang.com
12 ページ
Hàm đồ họa: đây là cái quan trọng nhất nó sẽ đưa Sprite lên bằng một texture ball tại vị trí nhất định: protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(SpriteBlendMode.AlphaBlend); mySprite1.Draw(spriteBatch); spriteBatch.End(); base.Draw(gameTime); } Chế độ tô kiểu AlphaBlend này sẽ cho phép chúng ta vẽ các bức ảnh có chỗ trống (một số chuơng trình như photóshop làm đc) Sprite của chúng ta là mySpite1 sẽ lấy spriteBatch mà vẽ cho nó, truớc một hàm Draw luôn có lệnh Begin(kiểu tô) và End(); Xong rùi, F5 nào J Lưu ý file mẫu: có thể máy bạn ko nhận ra file ball.bmp vì khác đg dẫn, nếu thế cứ xoá file ball cũ đi, add mới nó vào ở mục content (kick phải chọn add existing item) tương tự cho các lession sau, nếu nó báo thiếu file, file not found thì cứ xoá hết rồi add lại ThiNganHang.com
13 ページ
Bài 2 : Di chuyển Đối tuợng trên màn hình Các bạn có thể dùng tiếp project cũ để hoàn thành lession này. Phần I: bổ sung cho lớp clsSprite: Vật muốn di chuyển, ta thêm vận tốc cho nó: vector2 velocity Thêm kick thuớc screen để check collided (va chạm): vector2 screenSize Thuộc tính tọa độ điểm trung tâm của Sprite (đoạn sau dùng nó để viết thuật tóan va chạm) Vector2 center Thuộc tính bán kinh sprite(sau dùng nó để viết thuật tóan va chạm) float radius public Texture2D texture { get; set; } // sprite texture, read-only property public Vector2 position { get; set; } // sprite position on screen public Vector2 size { get; set; } // sprite size in pixels public Vector2 velocity { get; set; } // sprite velocity private Vector2 screenSize { get; set; } // screen size public Vector2 center{ get{ return position + (size/2);} } // sprite center public float radius { get { return size.X / 2; } } // sprite radius Thêm vào phần nhập dữ liệu: public clsSprite (Texture2D newTexture, Vector2 newPosition, Vector2 newSize, int ScreenWidth, int ScreenHeight){ texture = newTexture; position = newPosition; size = newSize; screenSize = new Vector2(ScreenWidth, ScreenHeight); } Chúng ta chỉ thêm một dữ liệu là chiều dài và rộng của screen. Viết thêm một hàm bool trả về true nếu có trùng giữa 2 sprite clsSprite và false nếu nguợc lại: public bool Collides(clsSprite otherSprite) { // check if two sprites intersect return (this.position.X + this.size.X > otherSprite.position.X && this.position.X < otherSprite.position.X + otherSprite.size.X && ThiNganHang.com
14 ページ
this.position.Y + this.size.Y > otherSprite.position.Y && this.position.Y < otherSprite.position.Y + otherSprite.size.Y); } Nó tính toán tọa độ và kick thước 2 sprite xem chúng có trùng nhau không, return trả về true nếu biếu thức trong () đuợc thỏa mãn. Để biểu diễn các bạn có thể xem hình duới đây: Hàm này không cần thiết lắm vì chúng ta sử dụng nó trong lession3, chi viết để mang tính minh họa môt cách kiểm tra va chạm khác thôi, bạn không thêm nó vào cũng đc Sau này chúng ta có cách khác để kiểm tra va chạm, đó là vẽ lên 1 hcn xung quanh mỗi sprite và kt va cham thông qua 2 hcn đó. Thêm một hàm để kiểm tra va chạm biên của 2 sprite, so sánh khoảng cách giữa trung tâm 2 sprite và tổng bán kính của chúng: trả về true nếu biếu thức trong return() đuợc thỏa mãn. Chung ta sử dụng hàm này để kiểm tra va chạm 2sprite trong quá trình chay game. public bool CircleCollides(clsSprite otherSprite) { // Check if two circle sprites collided return (Vector2.Distance(this.center, otherSprite.center) < this.radius + otherSprite.radius); } ThiNganHang.com
15 ページ
Một hàm ñể kiểm tra có va chạm với biên hay không? Nếu có ñảo giá trị velocity.X hoặc velocity.Y. nếu không thì sprite di chuyển (position tăng theo velocity của nó) public void Move() { // if we´ll move out of the screen, invert velocity // checking right boundary if (position.X + size.X + velocity.X > screenSize.X) velocity = new Vector2(-velocity.X, velocity.Y); // checking bottom boundary if (position.Y + size.Y + velocity.Y > screenSize.Y) velocity = new Vector2(velocity.X, -velocity.Y); // checking left boundary if (position.X + velocity.X < 0) velocity = new Vector2(-velocity.X, velocity.Y); // checking bottom boundary if (position.Y + velocity.Y < 0) velocity = new Vector2(velocity.X, -velocity.Y); // since we adjusted the velocity, just add it to the current position position += velocity; } Hàm cuối cùng là hàm ñồ họa thể hiện của sprite, rất quen thuộc: public void Draw(SpriteBatch spriteBatch) { spriteBatch.Draw(texture, position, Color.White); ThiNganHang.com
16 ページ
} Phan II: bổ sung cho Game1.cs Chúng ta tạo ra 2 sprite lấy tên mySpite1 và mySprite2 clsSprite mySprite1; clsSprite mySprite2; Loadcontent cũng có 2sprite (load texture) khởi tạo giá trị tốc độ cho nó, theo 2 trục x và y: protected override void LoadContent() { // Load a 2D texture sprite mySprite1 = new clsSprite(Content.Load<Texture2D>("ball"), new Vector2(0f, 0f), new Vector2(64f, 64f), graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight); mySprite2 = new clsSprite(Content.Load<Texture2D>("ball"), new Vector2(218f, 118f), new Vector2(64f, 64f), graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight); // Create a SpriteBatch to render the sprite spriteBatch = new SpriteBatch(graphics.GraphicsDevice); // set the speed the sprites will move mySprite1.velocity = new Vector2(5, 5); mySprite2.velocity = new Vector2(3, -3); } Bổ sung thêm hàm unLoad: protected override void UnloadContent() { // Free the previously alocated resources mySprite1.texture.Dispose(); mySprite2.texture.Dispose(); spriteBatch.Dispose(); } Bổ sung thuộc tính chiều dài và rộng của screen graphics.PreferredBackBufferWidth = 500; graphics.PreferredBackBufferHeight = 300; 2Sprite không chỉ di chuyển mà còn tương tác với nhau:Chúng ta kiểm tra va chạm trong hàm Update, bởi lẽ hàm Update sẽ kiểm tra game trong quá trình chạy để thay đổi nó, nó sẽ biết khi nào 2 sprite chạm nhau, chạm screenBound hoặc là không. Nếu 2 sprite chạm nhau, chúng sẽ đảo tốc độ của nhau (vận tốc của sprite 1 sẽ chuỷen qua sprite2 và ngược lại) ThiNganHang.com
17 ページ
Diều này nghiệm đúng ĐL bảo toàn động lượng trong vật lý J protected override void Update(GameTime gameTime) { // Move the sprites mySprite1.Move(); mySprite2.Move(); if (mySprite1.CircleCollides(mySprite2)) { Vector2 tempVelocity = mySprite1.velocity; mySprite1.velocity = mySprite2.velocity; mySprite2.velocity = tempVelocity; } base.Update(gameTime); } Cơ bản là xong thêm hàm đồ họa nữa, nó sẽ vẽ sprite1 và sprite2 lên screen: protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.CornflowerBlue); // TODO: Add your drawing code here spriteBatch.Begin(SpriteBlendMode.AlphaBlend); mySprite1.Draw(spriteBatch); mySprite2.Draw(spriteBatch); spriteBatch.End(); base.Draw(gameTime); } Xong rùi, F5 nào J . ThiNganHang.com
18 ページ
Bài 3: INPUT cho OBJECT bằng MOUSE và KEYBOARD Bài3 này chúng ta sử dụng thuật tóan KT va chạm khác, đã nói qua ở lession 2 Bạn có thể sử dụng project của lession trước + một và sửa đổi ở đây: Phần I: từ lớp clsSprite: 1.chung ta không cần thuộc tính center và radius nữa. 2.Sử dụng hàm va chạm: public bool Collides(clsSprite otherSprite) { // check if two sprites intersect if (this.position.X + this.size.X > otherSprite.position.X && this.position.X < otherSprite.position.X + otherSprite.size.X && this.position.Y + this.size.Y > otherSprite.position.Y && this.position.Y < otherSprite.position.Y + otherSprite.size.Y) return true; else return false; } Hàm này trả về false nếu 2 sprite (giống lession 2) không va chạm và ngược lại sẽ trả về true. Hàm đã nói ở lession2. Các hàm Move() và Draw() không thay đổi. Phần II : từ lớp Game1.cs 1.khai báo: sau class Game1:Microsoft.Xna.Framework.Game; Chúng ta cần 2 sprite như lession trước. Mục Load content tải đồ họa cho các sprite và thiết lập vận tốc cho sprite1, còn sprite2 không cần thiết lập tốc độ (velocity) vì chúng ta sẽ điều khiển nó từ mouse hoặc keyboard. Khai báo: public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; // Sprite objects clsSprite mySprite1; clsSprite mySprite2; ThiNganHang.com
19 ページ
Hàm LoadContent: protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); mySprite1 = new clsSprite(Content.Load<Texture2D>("ball"), new Vector2(0f, 0f), new Vector2(64f, 64f), graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight); mySprite2 = new clsSprite(Content.Load<Texture2D>("ball"), new Vector2(218f, 118f), new Vector2(64f, 64f), graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight); // set the speed the sprites will move mySprite1.velocity = new Vector2(5, 5); } Hàm checkKeyboard() nằm trong hàm Update() sẽ có nhiệm vụ kiểm tra phím đc nhấn trong thgời gian chạy game. Nói chung cái j cần kt trong khi run game đều put trong hàm Update() này. Chúng ta ĐK sprite2 protected void checkKeyboard() { KeyboardState keyboardState = Keyboard.GetState(); Khởi tạo bàn phím if (keyboardState.IsKeyDown(Keys.Up)) mySprite2.position += new Vector2(0, -5); Vị trí thay đổi khi nhấn xuống (press) với tọa độ thay đổi là 5, tùy theo hứong phím mũi tên mà tọa độ thay đổi thích hợp bạn cần nhớ trục tọa độ của XNA là hệ Oxy với tâm O nằm trên góc trên cùng bên trái bạn, Ox // mặt đất và Oy Vuông góc mặt đất. if (keyboardState.IsKeyDown(Keys.Down)) mySprite2.position += new Vector2(0, 5); if (keyboardState.IsKeyDown(Keys.Left)) mySprite2.position += new Vector2(-5, 0); if (keyboardState.IsKeyDown(Keys.Right)) mySprite2.position += new Vector2(5, 0); if (mySprite1.Collides(mySprite2)) Hàm mySpite1.Collides sẽ xác định va chạm với sprite2 trả về true nếu có. { mySprite1.velocity *= -1; Đảo chiều chuyển động của sprite1 } ThiNganHang.com
20 ページ
} } Tiếp là một hàm điều khiển sprite2 bằng mouse, khi chạy 1 hoặc 2 điều đc nhưng tốt nhất bạn chọn lấy 1 trong 2 hàm cho đỡ lộn xộn. protected void checkMouse() { // Hàm lệnh sẽ giúp sprite2 di chuyển đến tọa độ của mouse if (mySprite2.position.X < Mouse.GetState().X) mySprite2.position += new Vector2(5, 0); if (mySprite2.position.X > Mouse.GetState().X) mySprite2.position += new Vector2(-5, 0); if (mySprite2.position.Y < Mouse.GetState().Y) mySprite2.position += new Vector2(0, 5); if (mySprite2.position.Y > Mouse.GetState().Y) mySprite2.position += new Vector2(0, -5); Vector2 là 1 cặp biến nghĩa là khi sử dụng vector ta cũng phải dùng với 1 cặp giá trị. if (mySprite1.Collides(mySprite2)) { mySprite1.velocity *= -1; } } Trong file mẫu có thêm hàm cho tay cầm của Xbox rung, nhưng trong bài viết mình remove rồi, vì hiện tại chưa có con Xbox nào để test cả J . Xong rồi đấy, F5 và thử con chuột hay bàn phím đi nào . Lưu ý , file mẫu có 2 code cho việc control bằng mouse hay keyboard, mouse đang ở phần ghi chú (tức là có // trước câu) muốn test các bạn enable đoạn code cho mouse đó là đc, (khi đó nên disable code cho keyboard cho dễ thấy) ThiNganHang.com
コメント (0)
まだコメントはありません。最初のコメントを書きましょう!