Posts Tagged ‘XNA’


chào các bạn

hôm nay mình sẽ hướng dẫn các bạn làm thế nào để load ảnh động (gif) vào XNA

mở đầu : như các bạn đã biết , mặc định XNA chỉ cho load ảnh tĩnh vào game dưới dạng 1 texture2D mà không cho load ảnh động . đơn giản là ảnh gif có nhiều frame và cấu trúc khác với ảnh tĩnh nên chúng không thể đứng chung đc. XNA framework cũng chẳng có thư viện mở rộng nào để cho phép load ảnh động (gif) cả.

may mắn thay trong một lần tình cờ lướt google, zstar mò được 1 thư viện cho phép làm việc này. thư viện đó tên là XNAGifAnimation do 1 người tên là Mahdi Khodadadi Fard xây dựng. thư viện mình đính kèm ở dưới. bao gồm 2 file XNAGifAnimationLibrary.dll vs XNAGifAnimationLibrary.Pipeline.dll

thân bài
chú ý : thư viện mình đính kèm ở dưới chỉ dùng với XNA 3.0

mình sẽ hướng dẫn các bạn sử dụng chúng như thế nào

bước 1 :
-các bạn tạo 1 project XNA 3.0
-các bạn add 2 file thư viện (đính kèm ở dưới)tương ứng vào reference của project và reference của Content (xem hình dưới sẽ rõ)
-add 1 ảnh gif bất kì vào Content. tôi ví dụ là add “explode.gif”

bước 2: code
-trong game1.cs

using XNAGifAnimationLibrary;

tạo đối tượng GifAnimation

private GifAnimation gif;

trong hàm loadcontent

protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
this.gif = Content.Load<GifAnimation>("Images\\explode");
}

trong hàm update

protected override void Update(GameTime gameTime)
{if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
this.gif.Update(gameTime.ElapsedGameTime.Ticks);
base.Update(gameTime);
}

trong hàm draw

protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(this.gif.GetTexture(),new Vector2(),Color.White);
spriteBatch.End();
base.Draw(gameTime);
}

kết quả :

kết luận
-mỗi phiên bản của thư viện này chỉ dùng đc cho 1 version của XNA. như tôi attach ở dưới là dùng với XNA 3.0
-có thư viện này tôi có thể load ảnh gif thoải mái như: ảnh gif minh họa 1 vụ nổ mà tôi ví dụ ở trên.giúp tiết kiệm khá nhiều thời gian để minh họa 1 vụ nổ và tận dụng được ảnh gif có sẵn
-ko nên dùng quá nhiều ảnh gif trong game. sẽ làm chậm game

download thư viện : http://www.4shared.com/file/C91_LeTa/XNA_gif_30.html

Advertisements

mục tiêu là làm 1 game bóng nẩy ,chạm vào thành là bật lại. Game chạy trên hệ điều hành window phone 7.

preview :

video demo : http://www.youtube.com/watch?v=Ji5sOrayM_M

1.chuẩn bị
-kiến thức về lập trình C#
-kiến thức về XNA framework
-Visual studio 2010
-window phone tool develop , cài cho VS2010 ,download ở trang chủ Microsoft
2. tạo project
-sau khi cài window phone tool cho VS2010 ,bộ tool này đã bao gồm emulator,XNA,silvelight. sau khi cài chúng sẽ được bổ sung vào menu new project của VS2010
-tạo project window phone game

thêm 1 số tài nguyên cần thiết
-images: add bình thường
-font : bạn chuột phải chọn add->new item->chọn spritefont->điền tên ->OK
bạn có thể mở file *.font để thay đổi kích cỡ,kiểu font
3. Code

Tạo đối tượng ball.cs

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.Input.Touch;
usingMicrosoft.Xna.Framework.Media;namespace Zstar_Ball_Game
{
public class Ball
{
private GraphicsDeviceManager graphics;
private Texture2D texture;//sprite bóng
private Vector2 location;//vị trí của bóng
private Point size = new Point(48, 48);//kích thước của bóng
private SpriteFont font;//font để vẽ chữ
private Vector2 direction;//hướng chuyển động của bóng
private float h = 0.5f;//bước chuyển động
public Ball(GraphicsDeviceManager g, Random rand)
{
this.graphics = g;
this.location = new Vector2(rand.Next(200), rand.Next(200));//random ngẫu nhiên vị trí bóng
this.direction = new Vector2(rand.Next(1, 3), rand.Next(1, 3));//random ngẫu nhiên hướng chuyển động
this.h = rand.Next(1, 5) * rand.Next(1, 3) * 0.5f;//random ngẫu nhiên bước chuyển động
}
public void LoadContent(ContentManager content, string path)
{
this.texture = content.Load<Texture2D>(path);
this.font = content.Load<SpriteFont>("Font/SpriteFont1");
}
public void Update()
{
MouseState mouse = Mouse.GetState();
if (mouse.LeftButton == ButtonState.Pressed)
{
this.Press = true;
}
else this.Press = false;
if (this.Press)
{
if (mouse.X > 0 && mouse.Y > 0 && mouse.X + size.X <= this.graphics.PreferredBackBufferWidth && mouse.Y + size.Y <= this.graphics.PreferredBackBufferHeight)
this.Location = new Vector2(mouse.X, mouse.Y);
}
//di chuyển
this.location += this.direction * h;
if (!outside())
{
if (location.X * location.Y < 0) this.location = new Vector2();
}
}
public bool outside()
{
if (this.Location.X < 0)
{
this.direction = new Vector2(-this.direction.X, this.direction.Y);
return true;
}
if (this.Location.Y < 0)
{
this.direction = new Vector2(this.direction.X, -this.direction.Y); return true;
}
if (this.Location.X + this.size.X > this.graphics.PreferredBackBufferWidth)
{
this.direction = new Vector2(-this.direction.X, this.direction.Y); return true;
}if (this.Location.Y + this.size.Y > this.graphics.PreferredBackBufferHeight)
{
this.direction = new Vector2(this.direction.X, -this.direction.Y);
return true;
} return false;
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(this.texture, this.location, Color.White);
//spriteBatch.DrawString(this.font, this.location.ToString(), this.location + new Vector2(0, -20), Color.White);
}
public Vector2 Location
{
get { return this.location; }
set { this.location = value; }
}
public bool Press
{
get;
set;
}}
}

tạo đôi tượng BallManager.cs
mục đích của lớp này là quản lí bóng cho dễ,có thể thêm nhiều bóng rất dễ dàng

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.Input.Touch;
usingMicrosoft.Xna.Framework.Media;namespace Zstar_Ball_Game
{
public class BallManager
{
private Random rand = new Random();
private Ball[] balls;
private int num = 6;
private string[] paths = new string[] { "Images/ball4", "Images/ball2", "Images/ball3" };
public BallManager(GraphicsDeviceManager graphics, Random rand)
{
balls = new Ball[num];
for (int i = 0; i < balls.Length; i++)
{
balls[i] = new Ball(graphics, rand);
}
}
public void LoadContent(ContentManager content)
{
for (int i = 0; i < balls.Length; i++)
{
balls[i].LoadContent(content, paths[rand.Next(paths.Length)]);
}
}
public void Draw(SpriteBatch spriteBatch)
{
for (int i = 0; i < balls.Length; i++)
{
balls[i].Draw(spriteBatch);
}
}
public void Update()
{
for (int i = 0; i < balls.Length; i++)
{
balls[i].Update();
}
}
}
}

code ở Game1.cs

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.Input.Touch;
usingMicrosoft.Xna.Framework.Media;namespace Zstar_Ball_Game
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
private GraphicsDeviceManager graphics;
private SpriteBatch spriteBatch;
private BallManager ballManager;
private SpriteFont font;
private string s = "Hello Zstar !\nWelcome to Window phone OS Emulator";
private Random rand = new Random();
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
this.ballManager = new BallManager(graphics, rand);
s += "\nScreen : (" + this.graphics.PreferredBackBufferWidth + "," + this.graphics.PreferredBackBufferHeight + ")";TargetElapsedTime = TimeSpan.FromTicks(333333);
}protected override void Initialize()
{
base.Initialize();
}protected override void LoadContent()
{spriteBatch = new SpriteBatch(GraphicsDevice);
this.ballManager.LoadContent(Content);
this.font = Content.Load<SpriteFont>("Font/SpriteFont1");
}protected override void UnloadContent()
{}protected override void Update(GameTime gameTime)
{

if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
this.ballManager.Update();
base.Update(gameTime);
}

protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.DarkCyan);

// TODO: Add your drawing code here
spriteBatch.Begin();
this.ballManager.Draw(spriteBatch);
spriteBatch.DrawString(font, s, new Vector2(), Color.Orange);
spriteBatch.End();
base.Draw(gameTime);
}
}
}


sau đó F5, chạy thử ta được kết quả :
video demo : http://www.youtube.com/watch?v=Ji5sOrayM_M

…………………………………… sau đây là phần giải thích chi tiết
như vậy là chúng ta có 3 lớp Ball.cs,BallManager.cs,Game1.cs
mấy lệnh trong if sẽ quyết định đến sự bật trở lại của bóng, tôi sẽ giải thích kĩ hơn trong hình sau :vector màu đỏ là vector hướng chuyển động
1. hàm update trong ball.cs
-ý của tôi là khi nhấn “chuột trái” (chuột trái ở emulator trên computer tương đương nhấn tay vào màn hình touch trên window phone 7) thì các bóng sẽ được set lại vị trí tại chuột

public void Update()
{
MouseState mouse = Mouse.GetState();
if (mouse.LeftButton == ButtonState.Pressed)
{
this.Press = true;
}
else this.Press = false;
if (this.Press)
{
if (mouse.X > 0 && mouse.Y > 0 && mouse.X + size.X <= this.graphics.PreferredBackBufferWidth && mouse.Y + size.Y <= this.graphics.PreferredBackBufferHeight)
this.Location = new Vector2(mouse.X, mouse.Y);
}
//di chuyển
this.location += this.direction * h;
if (!outside())
{
if (location.X * location.Y < 0) this.location = new Vector2();
}
}

this.graphics.PreferredBackBufferWidth
this.graphics.PreferredBackBufferHeight

xác định kích thước của màn hình window phone, lệnh if dài loằng ngoằng ở trên có nghĩa là nếu dí chuột vào phạm vi màn hình thì mới set lai vị trí bóng
vì bóng có kích thước , nên xuất hiện lượng size trong đoạn if trên

2. hàm outside trong ball.cs

hàm này xác định xem bóng có còn ở trong khung màn hình hay không ?

public bool outside()
{
if (this.Location.X < 0)
{
this.direction = new Vector2(-this.direction.X, this.direction.Y);
return true;
}
if (this.Location.Y < 0)
{
this.direction = new Vector2(this.direction.X, -this.direction.Y); return true;
}
if (this.Location.X + this.size.X > this.graphics.PreferredBackBufferWidth)
{
this.direction = new Vector2(-this.direction.X, this.direction.Y); return true;
}if (this.Location.Y + this.size.Y > this.graphics.PreferredBackBufferHeight)
{
this.direction = new Vector2(this.direction.X, -this.direction.Y);
return true;
} return false;
}
đó là lí do tại sao tôi code trong hàm if như thế 3.lớp ballmanager.cslớp này thì đơn giản rồi, tôi tạo 1 mảng đối tượng ball(6 quả), viết hàm update chung,draw chung,load content chung
vì thế bạn thấy game1.cs code đơn giản hơn, ít rối rắm
kết luận :
-mình ko có thời gian viết chi tiết, ai thắc mắc cứ hỏi
-có thể đọc thêm các tut xna trước mà tôi đã viết
-window phone OS dùng silverlight,XNA để phát triển ứng dụng,game- nếu run mà game ko hiện ra thì làm như sau

XNA – project đầu tiên

Posted: 06/05/2011 in XNA Game
Tags:

giới thiệu sơ sơ :C# – XNA là 1 công nghệ làm game, phiên bản XNA mới nhất là 3.0 , XNA cho phép làm game chạy trên hệ điều hành window mobile, làm game cho Xbox 360 và game chạy trên hệ điều hành window

yêu cầu đầu tiên máy phải cài NET frame work 3.5 , Visual studio 2008, XNA frame work 3.0, bạn phải biết ngôn ngữ C#
sau khi cài cái đống trên ta sẽ làm 1 project game đầu tiên ,project đầu tiên là 1 game bóng nẩy (chạm vào thành sẽ nẩy ra)

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
Hình ảnh
Bạn build (F5) , chạy thử sẽ được như hình :
Hình ảnh
=> Ra cái cửa sổ xanh lè và không có con chuột là OK!

Lưu ý : Có thể bạn sẽ gặp lỗi không chạy được (build đc nhưng chạy ko đc), có thể là do máy bạn không đáp ứng đủ các yêu cầu sau :
+ Windows XP Sp2
+ Card màn hình phải hỗ trợ DirectX9c và PixelShader 1.1 trở lên
+ Không chạy trên hệ thống 64-bit
Gặp trường hợp này thì có lẽ bạn nên nâng cấp máy trước rồi mới tính đến chuyện xài XNA sau , nhưng đa số máy P4 mua từ sau năm 2002 là chơi đc món này rồi, nên bạn yên tâm

làm việc với resource

Trong game, điều cần thiết nhất là tài nguyên (tất nhiên ), khi dùng XNA, bạn không thể liên kết trực tiếp đến 1 file data nằm bên ngoài được mà phải đưa file đó vào Project, sau đó khi biên dịch, XNA sẽ chuyển các file đó thành dạng .xnb

Bây giờ ta sẽ thử đưa 1 đối tượng hình ảnh vào xem sao nhé.

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
Hình ảnh
sau khi add thành công thì cửa sổ project sẽ thêm 1 item mới như hình
Hình ảnh
Đối với các file khác (âm thanh, dữ liệu khác,…) bạn cũng làm tương tự để đưa nó vào project
Lưu ý :Bạn phải set thuộc tính Content Root Directory của mục Content là “.” (không có dấu nháy, như trong hình trên) thì mới chạy được!!!
Thao tác với Sprite
Sprite là một đối tượng thể hiện hình ảnh lên màn hình, và khi chạy game, nó sẽ là các nhân vật, đối tượng trong game, sprite có thể là đối tượng động (animate-sprite) hoặc đối tượng tĩnh (sprite).

Trong bài này, ta sẽ tìm hiểu cách tạo và vẽ một sprite ra màn hình, làm cho nó chuyển động, kiểm tra va chạm, … (kiểm tra va chạm là một hiệu ứng vật lý đơn giản nhất mà bất cứ game nào cũng có)

Bạn hãy tạo một project mới với tên là Creatinga2DSprite
Hình ảnh
Bạn có thể thay đổi màu nền của cửa sổ game bằng cách thay đổi giá trị Color trong dòng lệnh sau tại thủ tục Draw() nằm trong file Game1.cs – Draw là thủ tục đảm nhận việc vẽ tất cả mọi thứ lên màn hình.

graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

Bây giờ, ta sẽ add vào project một file hình để làm sprite
Hình ảnh

chú ý đoạn có dòng code

GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;

Chúng ta sẽ tiến hành khai báo các đối tượng, giá trị ở đây

//Đối tượng Texture
Texture2D mTexture;
//Điểm bắt đầu của texture
int mTextureStartX = 0;
//Đối tượng dùng để vẽ Sprite
SpriteBatch mSpriteBatch;
//Tọa độ X, Y của sprite
int mSpriteX = 0;
int mSpriteY = 0;
//Tốc độ di chuyển ngang dọc cho sprite
int mHorizontalSpeed = 3;
int mVerticalSpeed = 3;

Tại thủ tục LoadContent() bạn cho đoạn code này vào

//Khởi tạo mSpriteBatch
mSpriteBatch = new SpriteBatch(this.graphics.GraphicsDevice);//Đưa hình vào đối tượng mTexture
ContentManager aLoader = new ContentManager(Services);
mTexture = aLoader.Load<Texture2D>("JumpingJelly") as Texture2D;

Dòng cuối cùng bạn sẽ thấy tham số của hàm Load là “JumpingJelly”, file hình ảnh đưa vào làm sprite có tên là JumpingJelly.png, tương tự khi bạn add file vào và muốn load, chỉ cần ghi phần tên file, không cần đưa vào phần đuôi mở rộng của file.
Tại thủ tục Update() , cho thêm vào 2 dòng

CheckKeyboardInput();
UpdateSprite();

Sau đó viết hàm CheckKeyboardInput như sau :

protected void CheckKeyboardInput()
{
//Khởi tạo bàn phím
KeyboardState aKeyboard = Keyboard.GetState();
//Mảng lưu các phím đang được nhấn
Keys[] aCurrentKeys = aKeyboard.GetPressedKeys();for (int aCurrentKey = 0; aCurrentKey < aCurrentKeys.Length; aCurrentKey++)
{
//Nhấn nút qua trái thì sprite chạy qua bên trái
if (aCurrentKeys[aCurrentKey] == Keys.Left)
{
if (mHorizontalSpeed > 0)
{
mHorizontalSpeed *= -1;
}
mSpriteX += mHorizontalSpeed;
}//Nhấn qua phải thì sprite chạy qua phải
if (aCurrentKeys[aCurrentKey] == Keys.Right)
{
if (mHorizontalSpeed < 0)
{
mHorizontalSpeed *= -1;
}
mSpriteX += mHorizontalSpeed;
}//Nhấn nút lên thì sprite chạy lên
if (aCurrentKeys[aCurrentKey] == Keys.Up)
{
if (mVerticalSpeed > 0)
{
mVerticalSpeed *= -1;
}
mSpriteY += mVerticalSpeed;
}//Nhấn nút xuống thì sprite chạy xuống
if (aCurrentKeys[aCurrentKey] == Keys.Down)
{
if (mVerticalSpeed < 0)
{
mVerticalSpeed *= -1;
}
mSpriteY += mVerticalSpeed;
}

//Thoát game khi nhấn nút ESC
if (aCurrentKeys[aCurrentKey] == Keys.Escape)
{
this.Exit();
}
}
}

Hàm này dùng để kiểm tra phím nào được nhấn và nhấn phím gì thì làm cái gì
Sau đó viết hàm UpdateSprite

void UpdateSprite()
{
//Tự di chuyển sprite theo tốc độ
mSpriteX += mHorizontalSpeed;
mSpriteY += mVerticalSpeed;//Nếu mà sprite đụng cạnh màn hình
if (CheckBoundaryCollision() == true)
{
//Nếu đụng rồi thì sẽ làm những gì, bạn đưa vào trong này
}
}

viết thêm hàm CheckBoundaryCollision() để kiểm tra va chạm

protected Boolean CheckBoundaryCollision()
{
//Biến trả về khi có va chạm
Boolean aCollision = false;
//Đặt tọa độ cho cạnh màn hình
int aMaxX = Window.ClientBounds.Width - 50;
int aMinX = 0;
int aMaxY = Window.ClientBounds.Height - 50;
int aMinY = 0;//Kiểm tra xem đụng chưa, nếu đụng rồi thì aCollision set bằng true
if (mSpriteX > aMaxX)
{
mHorizontalSpeed *= -1;
mSpriteX = aMaxX;
aCollision = true;
}
else if (mSpriteX < aMinX)
{
mHorizontalSpeed *= -1;
mSpriteX = aMinX;
aCollision = true;
}
if (mSpriteY > aMaxY)
{
mVerticalSpeed *= -1;
mSpriteY = aMaxY;
aCollision = true;
}
else if (mSpriteY < aMinY)
{
mVerticalSpeed *= -1;
mSpriteY = aMinY;
aCollision = true;
}
return aCollision;
}

Rồi, bây giờ tại thủ tục Draw() bạn đưa đoạn code sau vào dưới cái dòng chú thích //TODO…

mSpriteBatch.Begin(SpriteBlendMode.AlphaBlend); //Bắt đầu vẽ
//Vẽ
mSpriteBatch.Draw(mTexture, new Rectangle(mSpriteX, mSpriteY, 50, 50), new Rectangle(mTextureStartX, 0, 256, 256), Color.White);
mSpriteBatch.End(); //Kết thúc

những lệnh vẽ bạn phải đặt vào giữa đoạn Begin-End, hình nào được vẽ trước sẽ nằm phía dưới, hình nào vẽ sau sẽ nằm ở trên.

Xong rồi, giờ chạy thử bạn sẽ được như hình :

Hình ảnh
Nhấn các phím mũi tên thì sprite nó sẽ di chuyển, nhấn ESC sẽ thoát.


đây là tài liệu XNA mình up lên chia sẻ với mọi người

XNA intergrations http://www.4shared.com/file/142610308/37ef5746/XNA_GSE_integration_in_XSI.html


đây là Game đồ án môn học trí tuệ nhân tạo của mìnhTính năng chính :
1. Play game(Game gồm 5 level,mỗi level có timeout)
2. Tạo Map (new map,edit map,save map)
3. Import map (import 1 map có sẵn để chơi)
Game gồm 5 level,mỗi level có timeout
Giải thuật
Game sử dụng gải thuật Astar (A*) trong việc tìm đường đi
Hỗ trợ :
bàn phím : các phím mũi tên để di chuyển
chuột : chọn điểm đến (ứng dụng Giải thuật Astar)
Công cụ sử dụng
C#,XNA frame work 3.0,Photoshop,
Cài đặt để chạy chuơng trình
– cần .Net Frame work 3.0
– cần XNA redistribute 3.0
– sau khi cài đặt 2 cái trên các bạn chạy file setup để cài Game
– chạy game ở biểu tượng trên desktop
download file setup : http://www.4shared.com/file/251279836/5a391899/Microstar_Maze_Game.html
Một số hình ảnh về Game
Menu chính

Hình ảnh
level 1

Hình ảnh
bonus point

Hình ảnh
Tạo map

Hình ảnh
save map

Hình ảnh


yêu cầu : trước khi đọc tut2 này thì cần phải đọc tut1 này đã
https://zstar2.wordpress.com/2011/05/06/xnachuy%E1%BB%83n-d%E1%BB%99ng-c%E1%BB%A7a-nhan-v%E1%BA%ADt-trong-xna-ph%E1%BA%A7n-1/
vì tut2 này mình phát triển từ tut1 lên (ngại code lại)
………………………………………….. …
map là gì ?
nôm na củ chuối thì nó bao gồm tất cả các item hiển thị trên game,các item mà bạn có thể nhìn thấy …..

vấn đề cuộn map trong game (2D)
-đặt vấn đề : cuộn map là gì ? giả sử cửa sổ game của bạn bé tí , còn map rộng bao trùm ra ngoài cửa sổ rất nhiều..vì vậy muốn nhân vật đi đến map nằm ngoài cửa sổ thì sẽ phải cuộn map…

cuộn như thế nào

xin nhắc lại trong tut1 1 chút , ở trong tut1 mình đã cho tọa độ của nhân vật thay đổi khi ấm phím <- ^ -> , còn tọa độ để biểu diễn map thì vẫn như vậy ,ko thay đổi => nhân vật chỉ đi được trong khung cửa sổ mà thôi, đi ra ngoài thì chịu,mà đi ra ngoài đc thì cũng mất hút luôn…

vậy với 1 map rộng thì ta ko làm như thế mà làm ngược lại, tức là cho nhân vật đứng yên, map thay đổi tọa độ nhân vật chỉ cho loe ngoe chân tay cho vui thôi , muốn nhân vật di chuyển sang phải thì map phải di chuyển sang trái…túm lại là muốn nhân vật di chuyển hướng nào thì map phải di chuyển theo hướng ngược lại

để làm đc điều này thì cần phải sửa đổi gì trong tut1 ??
-set tọa độ nhân vật cố định , new point(400,400) chẳng hạn,có thể tính toán để nó nằm ở giữa cửa sổ game
-Các item khác còn lại trong game(trừ nhân vật), phải cộng tọa độ của nó với 1 lượng tham số Point pt….vì sao lại thế ? đơn giản thôi , khi tôi muốn tất cả các item dịch sang trái chẳng hạn, tôi chỉ cần giảm pt.X là xong (nên nhớ nhân vật ko cộng với lượng này nên nó vẫn trơ trơ giữa cửa sổ)

-từ đó muốn nhân vật di chuyển sang trái (cảm giác đánh lừa mắt thôi nhé) 1 đoạn h pixels thì chỉ cần cho map chạy sang phải 1 đoạn h pixels=> tức là pt.X=pt.X+h …tương tự như vậy cho chiều Y

về code thì các lớp vẫn có các lớp như tut1
nhưng nội dung thay đổi như sau
lớp nhanvat.cs


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;

namespace chuyen_dong_nhan_vat
{
public class NhanVat
{
private Game1 Game;
private Texture2D text;//sprite nhan vat
private Point khungnhin=new Point(0,0);//vi tri khung nhin
private Point gioihan=new Point(5,4);//gioi han khung nhin
private byte kichthuoc=60;//kich thuoc khung nhin 60x60
private int buocChay = 5;//do dai moi buoc nhan vat
public Point viTri = new Point(0,0);//vi tri nhan vat tren man hinh
public HuongChuyenDong huongChuyenDong;
private bool dangChay = false;
private System.Windows.Forms.Timer capNhat_X;


public NhanVat(Game1 game,Point toadomoi)
{

this.Game = game;
this.capNhat_X = new System.Windows.Forms.Timer();
this.capNhat_X.Interval = 100;
this.capNhat_X.Enabled = true;
capNhat_X.Tick += new EventHandler(capNhat_X_Tick);
//cho nhan vat vao gua man hinh
this.viTri = new Point(Game.Window.ClientBounds.Width/2-kichthuoc/2,Game.Window.ClientBounds.Height/2-kichthuoc/2);
}

private void capNhat_X_Tick(object sender, EventArgs e)
{
//X chay tu 0->4
//cap nhat dong tac nhan vat
if (dangChay)
{
if (this.khungnhin.X < this.gioihan.X - 1)
{
this.khungnhin.X += 1;
}
else this.khungnhin.X = 0;
}
else this.khungnhin.X = 0;
}
public void LoadContent(ContentManager Content)
{
this.text = Content.Load<Texture2D>("man");
}
public void Update(ref Point toadomoi)
{
KeyboardState keys = Keyboard.GetState();
if (keys.IsKeyDown(Keys.Left))
{
//di chuyen tu phai qua trai
huongChuyenDong = HuongChuyenDong.PhaiQuaTrai;
DiChuyen(ref toadomoi);
return;
}
if (keys.IsKeyDown(Keys.Right))
{
//di chuyen tu trai qua phai
huongChuyenDong = HuongChuyenDong.TraiQuaPhai;
DiChuyen(ref toadomoi);
return;
}
if (keys.IsKeyDown(Keys.Up))
{
//di chuyen tu duoi len tren
huongChuyenDong = HuongChuyenDong.DuoiLenTren;
DiChuyen(ref toadomoi);
return;
}
if (keys.IsKeyDown(Keys.Down))
{
//di chuyen tu tren xuong
huongChuyenDong = HuongChuyenDong.TrenXuongDuoi;
DiChuyen(ref toadomoi);
return;
}
this.dangChay = false;
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(this.text, new Rectangle(this.viTri.X, this.viTri.Y,this.kichthuoc,this.kichthuoc), new Rectangle(this.khungnhin.X * this.kichthuoc, this.khungnhin.Y * this.kichthuoc,this.kichthuoc,this.kichthuoc), Color.White, 0, Vector2.Zero, SpriteEffects.None, 0);
}
private void DiChuyen(ref Point toadomoi)
{
this.dangChay = true;
//Y chay tu 0->3


//cap nhat huong chay
if (huongChuyenDong == HuongChuyenDong.DuoiLenTren)
{
//this.viTri.Y -= this.buocChay;
//toadomoi.Y += this.buocChay;
toadomoi = new Point(toadomoi.X, toadomoi.Y + 1);
this.khungnhin.Y = 0;
}
else if (huongChuyenDong == HuongChuyenDong.TrenXuongDuoi)
{
//this.viTri.Y += this.buocChay;
toadomoi = new Point(toadomoi.X, toadomoi.Y - 1);
this.khungnhin.Y = 2;
}
else if (huongChuyenDong == HuongChuyenDong.TraiQuaPhai)
{
//this.viTri.X += this.buocChay;
toadomoi = new Point(toadomoi.X-1, toadomoi.Y);
this.khungnhin.Y = 1;
}
else if (huongChuyenDong == HuongChuyenDong.PhaiQuaTrai)
{
//this.viTri.X -= this.buocChay;
toadomoi = new Point(toadomoi.X+1, toadomoi.Y);
this.khungnhin.Y = 3;
}
raNgoaiBanDo(ref toadomoi);

}
private void raNgoaiBanDo(ref Point toadomoi)
{
//int xMax = this.Game.Window.ClientBounds.Width;
//int yMax = this.Game.Window.ClientBounds.Height;
//if (viTri.X < 0) this.viTri.X += buocChay;
//if (viTri.X > xMax-kichthuoc) this.viTri.X -= buocChay;
//if (viTri.Y < 0) this.viTri.Y += buocChay;
//if (viTri.Y + buocChay > yMax-kichthuoc) this.viTri.Y -= buocChay;

//ra ngoai ban do bay gio thuc ra phai chech toa do cua map so voi nhan vat

Point map = new Point(1315,864);//kich thuoc cua nen
if (toadomoi.X > this.viTri.X) toadomoi.X -= buocChay;
if (toadomoi.Y > this.viTri.Y) toadomoi.Y -= buocChay;
if (toadomoi.X + map.X < this.viTri.X) toadomoi.X += buocChay;
if (toadomoi.Y + map.Y < this.viTri.Y) toadomoi.Y += buocChay;


}


}
}

game1.cs

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;

namespace chuyen_dong_nhan_vat
{

public class Game1 : Microsoft.Xna.Framework.Game
{
private GraphicsDeviceManager graphics;
private SpriteBatch spriteBatch;
private NhanVat nhanVat;
private Texture2D nen;
private Texture2D tree;
private SpriteFont font;
//
private Point toadomoi = new Point();
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
nhanVat = new NhanVat(this,this.toadomoi);
}

protected override void Initialize()
{

base.Initialize();
}


protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
this.nen = Content.Load<Texture2D>("nen");
this.tree = Content.Load<Texture2D>("tree");
this.font = Content.Load<SpriteFont>("font1");
this.nhanVat.LoadContent(this.Content);//load sprite cua nhan vat
}

protected override void UnloadContent()
{

}


protected override void Update(GameTime gameTime)
{

if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
this.nhanVat.Update(ref toadomoi);//update chuyen dong nhan vat
base.Update(gameTime);
}


protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
spriteBatch.Draw(this.nen,new Vector2(toadomoi.X,toadomoi.Y),Color.White);

spriteBatch.DrawString(font, "Nhan vat :" + this.nhanVat.huongChuyenDong.ToString(), new Vector2(this.nhanVat.viTri.X - 20, this.nhanVat.viTri.Y - 25), Color.Red);
this.nhanVat.Draw(this.spriteBatch);//ve nhan vat len man hinh
//ve nhieu cay cung luc
spriteBatch.Draw(this.tree, new Vector2(toadomoi.X + 20, toadomoi.Y + 90), Color.White);
spriteBatch.Draw(this.tree, new Vector2(toadomoi.X + 100, toadomoi.Y + 530), Color.White);
spriteBatch.Draw(this.tree, new Vector2(toadomoi.X + 400, toadomoi.Y + 330), Color.White);
spriteBatch.Draw(this.tree, new Vector2(toadomoi.X + 50, toadomoi.Y + 200), Color.White);
spriteBatch.Draw(this.tree, new Vector2(toadomoi.X + 10, toadomoi.Y + 700), Color.White);
spriteBatch.Draw(this.tree, new Vector2(toadomoi.X + 400, toadomoi.Y + 430), Color.White);
spriteBatch.Draw(this.tree, new Vector2(toadomoi.X + 420, toadomoi.Y + 130), Color.White);
spriteBatch.Draw(this.tree, new Vector2(toadomoi.X + 300, toadomoi.Y + 10), Color.White);
//
spriteBatch.End();
base.Draw(gameTime);
}
}
}

kết quả :


làm 1 ứng dụng game đập nhện


bài này mình sẽ hướng dẫn các bạn tạo chuyển động cho nhân vật trong XNA
Bài 1 : tìm hiểu về chuyển động của Nhân vật trong Game

1.chuẩn bị
download XNA game studio 3.1 từ trang của Microsoft ,cài đặt cho Visual studio 2008

tạo 1 project mới : Visual C#->XNA 3.1->Windows game->OK

Hình ảnh

2.Sprite image 2D là gì ?
Sprite image 2D thực chất là 1 image tập hợp tất cả các tư thế cơ bản của nhân vật theo một qui luật nào đó
ví dụ về Sprite image
Hình ảnh

3.phân tích ví dụ trên
– Hàng 1 : là tập hợp các tư thế cơ bản của nhân vật khi nhân vật chuyển động từ dưới lên trên
– Hàng 2 : là tập hợp các tư thế cơ bản của nhân vật khi nhân vật chuyển động từ trái qua phải
– Hàng 3 : là tập hợp các tư thế cơ bản của nhân vật khi nhân vật chuyển động từ trên xuống dưới
– Hàng 4 : là tập hợp các tư thế cơ bản của nhân vật khi nhân vật chuyển động từ phải qua trái

4.Làm sao để tạo chuyển động từ Sprite ?
-Nhân vật hiển thị trong Game được cắt từ 1 trong các tư thế ở trong Sprite image ở trên.Tạm gọi là khung cắt
-Do các tư thế xếp cách đều nhau nên việc xác định chính xác khung cắt hết sức dễ dàng.Cả sprite image được xem như 1 ma trận 2 chiều các tư thế
-Khi cần nhân vật chuyển động. giả sử cần nhân vật chuyển động từ dưới lên trên.Ta sẽ cho chỉ số dòng của khung cắt bằng 0 đồng thời cho chỉ số cột lặp lại từ 0->4 và chỉ stop khi nhận được lệnh stop từ chương trình.
-Như vậy tập hợp các tư thế nhân vật chuyển động từ dưới lên được load trong thời gian ngắn làm cho chúng ta có cảm giác nhân vật bước đi từ dưới lên như thật vậy.
-Với các hướng chuyển động khác thì cũng làm tương tự nhưng phải thay đổi chỉ số dòng của khung cần cắt cho đúng với hướng chuyển động mà ta mong muốn

Bài 2 : Code chuyển động nhân vật trong XNA

trong cửa sổ Solution Explorer tìm đến Content ->Chuột Phải->Add->Existing item->chọn 1 cái image nền(nen.png)+chọn sprite trên(man.png)

Xây dựng lớp NhanVat.cs

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;namespace chuyen_dong_nhan_vat
{
public class NhanVat
{
private Game1 Game;
private Texture2D text;//sprite nhan vat
private Point khungnhin=new Point(0,0);//vi tri khung nhin
private Point gioihan=new Point(5,4);//gioi han khung nhin
private byte kichthuoc=60;//kich thuoc khung nhin 60x60
private int buocChay = 3;//do dai moi buoc nhan vat
private Point viTri = new Point(0,0);//vi tri nhan vat tren man hinh
private HuongChuyenDong huongChuyenDong;
private bool dangChay = false;
private System.Windows.Forms.Timer capNhat_X;

public NhanVat(Game1 game)
{
this.Game = game;
this.capNhat_X = new System.Windows.Forms.Timer();
this.capNhat_X.Interval = 100;
this.capNhat_X.Enabled = true;
capNhat_X.Tick += new EventHandler(capNhat_X_Tick);
}

private void capNhat_X_Tick(object sender, EventArgs e)
{
//X chay tu 0->4
//cap nhat dong tac nhan vat
if (dangChay)
{
if (this.khungnhin.X < this.gioihan.X - 1)
{
this.khungnhin.X += 1;
}
else this.khungnhin.X = 0;
}
else this.khungnhin.X = 0;
}
public void LoadContent(ContentManager Content)
{
this.text = Content.Load<Texture2D>("man");
}
public void Update()
{
KeyboardState keys = Keyboard.GetState();
if (keys.IsKeyDown(Keys.Left))
{
//di chuyen tu phai qua trai
huongChuyenDong = HuongChuyenDong.PhaiQuaTrai;
DiChuyen();
return;
}
if (keys.IsKeyDown(Keys.Right))
{
//di chuyen tu trai qua phai
huongChuyenDong = HuongChuyenDong.TraiQuaPhai;
DiChuyen();
return;
}
if (keys.IsKeyDown(Keys.Up))
{
//di chuyen tu duoi len tren
huongChuyenDong = HuongChuyenDong.DuoiLenTren;
DiChuyen();
return;
}
if (keys.IsKeyDown(Keys.Down))
{
//di chuyen tu tren xuong
huongChuyenDong = HuongChuyenDong.TrenXuongDuoi;
DiChuyen();
return;
}
this.dangChay = false;
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Begin();
spriteBatch.Draw(this.text, new Rectangle(this.viTri.X, this.viTri.Y,this.kichthuoc,this.kichthuoc), new Rectangle(this.khungnhin.X * this.kichthuoc, this.khungnhin.Y * this.kichthuoc,this.kichthuoc,this.kichthuoc), Color.White, 0, Vector2.Zero, SpriteEffects.None, 0);
spriteBatch.End();
}
private void DiChuyen()
{
this.dangChay = true;
//Y chay tu 0->3

//cap nhat huong chay
if (huongChuyenDong == HuongChuyenDong.DuoiLenTren)
{
this.viTri.Y -= this.buocChay;
this.khungnhin.Y = 0;
}
else if (huongChuyenDong == HuongChuyenDong.TrenXuongDuoi)
{
this.viTri.Y += this.buocChay;
this.khungnhin.Y = 2;
}
else if (huongChuyenDong == HuongChuyenDong.TraiQuaPhai)
{
this.viTri.X += this.buocChay;
this.khungnhin.Y = 1;
}
else if (huongChuyenDong == HuongChuyenDong.PhaiQuaTrai)
{
this.viTri.X -= this.buocChay;
this.khungnhin.Y = 3;
}
raNgoaiBanDo();

}
private void raNgoaiBanDo()
{
int xMax = this.Game.Window.ClientBounds.Width;
int yMax = this.Game.Window.ClientBounds.Height;
if (viTri.X < 0) this.viTri.X += buocChay;
if (viTri.X > xMax-kichthuoc) this.viTri.X -= buocChay;
if (viTri.Y < 0) this.viTri.Y += buocChay;
if (viTri.Y + buocChay > yMax-kichthuoc) this.viTri.Y -= buocChay;

}
}
}

xây dựng enum HuongChuyenDong.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace chuyen_dong_nhan_vat
{
public enum HuongChuyenDong
{
TraiQuaPhai,
PhaiQuaTrai,
TrenXuongDuoi,
DuoiLenTren,
}
}

code trong Game1.cs như sau


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;

namespace chuyen_dong_nhan_vat
{

public class Game1 : Microsoft.Xna.Framework.Game
{
private GraphicsDeviceManager graphics;
private SpriteBatch spriteBatch;
private NhanVat nhanVat;
private Texture2D nen;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
nhanVat = new NhanVat(this);
}

protected override void Initialize()
{

base.Initialize();
}

protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
this.nen = Content.Load<Texture2D>("nen");
this.nhanVat.LoadContent(this.Content);//load sprite cua nhan vat
}

protected override void UnloadContent()
{

}

protected override void Update(GameTime gameTime)
{

if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
this.nhanVat.Update();//update chuyen dong nhan vat
base.Update(gameTime);
}

protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(this.nen,new Vector2(0,0),Color.White);
spriteBatch.End();
this.nhanVat.Draw(this.spriteBatch);//ve nhan vat len man hinh
base.Draw(gameTime);
}
}
}

xong rồi ! đây là kết quả
bây giờ nhấn các phím <- ^ -> nhân vật sẽ chuyển động rất mượt

Hình ảnh