|
電腦遊戲製作開發設計論壇 任何可以在PC上跑的遊戲都可以討論,主要以遊戲之製作開發為主軸,希望讓台灣的遊戲人有個討論、交流、教學、經驗傳承的園地
|
上一篇主題 :: 下一篇主題 |
發表人 |
內容 |
babu61509 散播福音的祭司
註冊時間: 2007-08-26 文章: 142
681.01 果凍幣
|
發表於: 2007-10-26, PM 8:25 星期五 文章主題: [XNA] vol 2.5 SpriteFormat 介紹... (未完成) |
|
|
這是一個我自己寫的小Class,方便 SpriteBatch 的 Draw 函數用。
裡面除了包含了必要的 Draw 用傳入值,還有自動切換圖片和方框碰撞功能,雖然寫的不算很好,不過也不錯用了!
我會用這個Class來介紹 Draw 函數還有跟大家說怎麼切換圖片和判斷方框碰撞。
note : Class程式碼在最後面.
------------------------------------------------------------------ [SpriteFormat結構簡介]
先來介紹 FrameFormat 的結構如下 :
代碼: |
public struct FrameFormat
|
|----- public int Width; // Frame 寬度
|----- public int Height; // Frame 高度
|----- public int MaxFrame; // Frame 最大值
|----- public int NowFrame; // 現在的 Frame
|----- public int MinFrame; // Frame 最小值
|----- public int FramePerSecond; // 每秒顯示幾張 Frame
|----- public Boolean AutoChange; // 是否自動更新 Frame
|
這個代表 Frame 的資料,程式會根據 Frame 的資料來更新顯示.
note : 連環圖就是由許多 Frame 組成的,例如走路、跳等等連續的動作,這裡我用的是將一個動作連環圖 Frame 放在一張圖片,再根據這個設定來切換.
SpriteFormat 的結構如下 :
代碼: |
public class SpriteFormat
|
|----- public Vector2 Location; // Sprite 位置
|----- public Rectangle sourceRectangle; // Sprite 取得圖檔內位置及大小
|----- public Vector2 Center; // Sprite 中心點
|----- public float Rotation; // Sprite 旋轉弧度
|----- public float RotationW; // Sprite 旋轉弧動量
|----- public float Scale; // Sprite 縮放大小
|----- public float ScaleW; // Sprite 縮放動量
|----- public Vector2 SpriteSpeed; // Sprite 位移
|----- public SpriteEffects SpriteEffect; // Sprite 的 SpriteEffect
|----- public Rectangle CollisionBox; // Sprite 的碰撞位置及大小(位置以Location為基準)
|----- public float layerDepth; // Sprite 景深 (0為最前,1為最後)
|----- public Color color; // Sprite 顏色
|----- public FrameFormat mFrame; // Sprite 的 Frame
|----- public Boolean Remove; // 是否移除 Sprite
|----- private double UpdateTime; // 計算時間
|
|=== public SpriteFormat() // 建構式,設定屬性初始值
|=== public void Update(GameTime gameTime) // 更新 Sprite
|=== public Boolean IsCollision(SpriteFormat SF) // 檢查是否碰撞
|=== public void SetByTexture2D(Texture2D Pic) // 由 Texture2D 建立資料
|=== public void Set(.......太多自己看= =) // 設定屬性用函式
|=== public void SetFrame(.......太多自己看= =) // 設定Frame用函式
|=== public void Draw(SpriteBatch DrawPic, Texture2D texture) // 以 texture 左上點為基準的繪圖
|=== public void DrawCenter(SpriteBatch DrawPic, Texture2D texture) // 以 texture 中心點為基準的繪圖
|
------------------------------------------------------------------ [使用流程]
1. 用Set 和 SetFrame 設定屬性.
2. 用 Update 更新資料.
3. 用 Draw 來畫.
------------------------------------------------------------------ [Class 原始碼]
代碼: |
#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;
#endregion
namespace catchit
{
//
// Sprite Format ver 0.65 Alpha
//
//
public struct FrameFormat
{
public int Width; // Frame 寬度
public int Height; // Frame 高度
public int MaxFrame; // Frame 最大值
public int NowFrame; // 現在的 Frame
public int MinFrame; // Frame 最小值
public int FramePerSecond; // 每秒顯示幾張 Frame
public Boolean AutoChange; // 是否自動更新 Frame
}
public class SpriteFormat
{
public Vector2 Location; // Sprite 位置
public Rectangle sourceRectangle; // Sprite 取得圖檔內位置及大小
public Vector2 Center; // Sprite 中心點
public float Rotation; // Sprite 旋轉弧度
public float RotationW; // Sprite 旋轉弧動量
public float Scale; // Sprite 縮放大小
public float ScaleW; // Sprite 縮放動量
public Vector2 SpriteSpeed; // Sprite 位移
public SpriteEffects SpriteEffect; // Sprite 的 SpriteEffect
public Rectangle CollisionBox; // Sprite 的碰撞位置及大小(位置以Location為基準)
public float layerDepth; // Sprite 景深 (0為最前,1為最後)
public Color color; // Sprite 顏色
public FrameFormat mFrame; // Sprite 的 Frame
public Boolean Remove; // 是否移除 Sprite
public char CollisionSide; // N為無碰撞,T為上方,R為右方,B為下方,L為左方
private double UpdateTime; // 計算時間
// 建構式
public SpriteFormat()
{
// 設定初始值
Location = Vector2.Zero;
sourceRectangle = Rectangle.Empty;
Center = Vector2.Zero;
Rotation = 0.0f;
RotationW = 0.0f;
Scale = 1.0f;
ScaleW = 0.0f;
SpriteSpeed = Vector2.Zero;
SpriteEffect = SpriteEffects.None;
CollisionBox = Rectangle.Empty;
layerDepth = 0.0f;
color = Color.White;
Remove = false;
mFrame.Width = 0;
mFrame.Height = 0;
mFrame.MaxFrame = 0;
mFrame.MinFrame = 0;
mFrame.NowFrame = 0;
}
// 更新 Sprite 函數
public void Update(GameTime gameTime)
{
// 更新旋轉弧度
Rotation += RotationW;
// 更新縮放大小
Scale += ScaleW;
// 更新位置
Location = new Vector2(SpriteSpeed.X + Location.X, SpriteSpeed.Y + Location.Y);
// 如果自動更新 Frame 為真就計算時間
if (mFrame.AutoChange)
UpdateTime += gameTime.ElapsedGameTime.Milliseconds;
else
// 否就 歸零
UpdateTime = 0.0d;
// 判斷 FramePerSecond 不等於 0 且 時間達到 要換 Frame
if (mFrame.FramePerSecond != 0 && UpdateTime >= (1000.0 / mFrame.FramePerSecond))
{
// Frame + 1
mFrame.NowFrame++;
UpdateTime -= 1000.0 / mFrame.FramePerSecond;
// 如果大於最大 Frame
if (mFrame.NowFrame > mFrame.MaxFrame)
// Frame = 最小 Frame
mFrame.NowFrame = mFrame.MinFrame;
}
}
Boolean checkCollision(SpriteFormat A, SpriteFormat B)
{
// 檢查 左軸 的 X 是否在 B 碰撞框範圍內
if (A.Location.X + A.CollisionBox.X >= B.Location.X + B.CollisionBox.X &&
A.Location.X + A.CollisionBox.X <= B.Location.X + B.CollisionBox.X + B.CollisionBox.Width)
{
// 判斷左上角是否在 B 內
// 檢查 Y 是否在 B 碰撞框範圍內
if (A.Location.Y + A.CollisionBox.Y >= B.Location.Y + B.CollisionBox.Y &&
A.Location.Y + A.CollisionBox.Y <= B.Location.Y + B.CollisionBox.Y + B.CollisionBox.Height)
// 有就傳回真
return true;
// 判斷左下角是否在 B 內
// 檢查 Y 是否在 B 碰撞框範圍內
if (A.Location.Y + A.CollisionBox.Y + A.CollisionBox.Height >= B.Location.Y + B.CollisionBox.Y &&
A.Location.Y + A.CollisionBox.Y + A.CollisionBox.Height <= B.Location.Y + B.CollisionBox.Y + B.CollisionBox.Height)
// 有就傳回真
return true;
}
// 檢查 右軸 的 X 是否在 B 碰撞框範圍內
if (A.Location.X + A.CollisionBox.X + A.CollisionBox.Width >= B.Location.X + B.CollisionBox.X &&
A.Location.X + A.CollisionBox.X + A.CollisionBox.Width <= B.Location.X + B.CollisionBox.X + B.CollisionBox.Width)
{
// 判斷左上角是否在 B 內
// 檢查 Y 是否在 B 碰撞框範圍內
if (A.Location.Y + A.CollisionBox.Y >= B.Location.Y + B.CollisionBox.Y &&
A.Location.Y + A.CollisionBox.Y <= B.Location.Y + B.CollisionBox.Y + B.CollisionBox.Height)
// 有就傳回真
return true;
// 判斷左下角是否在 B 內
// 檢查 Y 是否在 B 碰撞框範圍內
if (A.Location.Y + A.CollisionBox.Y + A.CollisionBox.Height >= B.Location.Y + B.CollisionBox.Y &&
A.Location.Y + A.CollisionBox.Y + A.CollisionBox.Height <= B.Location.Y + B.CollisionBox.Y + B.CollisionBox.Height)
// 有就傳回真
return true;
}
// 都沒有就傳回假
return false;
}
// 檢查是否碰撞
public Boolean IsCollision(SpriteFormat SF)
{
// 各自檢查2方頂點是否在對方範圍內
if (checkCollision(this, SF) || checkCollision(SF, this))
// 有就傳回真
return true;
else
// 沒有就假
return false;
}
// 由 Texture2D 建立資料
public void SetByTexture2D(Texture2D Pic)
{
// 設定取得圖檔內位置及大小
sourceRectangle = new Rectangle(0, 0, Pic.Width, Pic.Height);
// 更新中心位置
Center = new Vector2(sourceRectangle.Width / 2, sourceRectangle.Height / 2);
}
// 使用函數設定資料
public void Set(Texture2D Pic, Vector2 Location, float Rotation, float RotationW, float Scale, float ScaleW, Vector2 SpriteSpeed, SpriteEffects SpriteEffect, Rectangle CollisionBox)
{
this.RotationW = RotationW;
this.ScaleW = ScaleW;
this.Set(Pic, Location, Rotation, Scale, SpriteSpeed, SpriteEffect, CollisionBox);
}
public void Set(Texture2D Pic, Vector2 Location, float Rotation, float Scale, Vector2 SpriteSpeed, SpriteEffects SpriteEffect, Rectangle CollisionBox)
{
this.SpriteSpeed = SpriteSpeed;
this.SpriteEffect = SpriteEffect;
this.Set(Pic, Location, Rotation, Scale, CollisionBox);
}
public void Set(Texture2D Pic, Vector2 Location, float Rotation, float Scale, Rectangle CollisionBox)
{
this.Location = Location;
this.Rotation = Rotation;
this.Scale = Scale;
this.CollisionBox = CollisionBox;
this.SetByTexture2D(Pic);
}
public void SetFrame(int Width, int Height, int MaxFrame, int MinFrame, int NowFrame, Boolean AutoChange)
{
this.mFrame.Width = Width;
this.mFrame.Height = Height;
this.mFrame.MaxFrame = MaxFrame;
this.mFrame.MinFrame = MinFrame;
this.mFrame.NowFrame = NowFrame;
this.mFrame.AutoChange = AutoChange;
}
// 以 texture 左上點為基準的繪圖
public void Draw(SpriteBatch DrawPic, Texture2D texture)
{
DrawPic.Draw(texture, Location, sourceRectangle, color, Rotation, Vector2.Zero, Scale, SpriteEffect, layerDepth);
}
// 以 texture 中心點為基準的繪圖
public void DrawCenter(SpriteBatch DrawPic, Texture2D texture)
{
DrawPic.Draw(texture, Location, sourceRectangle, color, Rotation, Center, Scale, SpriteEffect, layerDepth);
}
}
}
|
_________________ 已經畢業了!!
babu61509 在 2008-5-24, PM 1:53 星期六 作了第 5 次修改 |
|
回頂端 |
|
|
vamper 對這略感興趣的新人
註冊時間: 2007-06-23 文章: 29 來自: 台灣 18.82 果凍幣
|
發表於: 2007-10-28, PM 7:36 星期日 文章主題: Re: [XNA] vol 3 SpriteFormat 介紹... (未完成) |
|
|
babu61509 寫到: |
代碼: | // 檢查是否碰撞
public Boolean IsCollision(SpriteFormat SF)
{
Rectangle check = SF.CollisionBox;
// 判斷是否為較小的碰撞框
if (CollisionBox.Width <= check.Width)
{
// 左x軸判斷
if (CollisionBox.X <= check.X + check.Width && CollisionBox.X >= check.X)
{
// 判斷是否為較小的碰撞框
if (CollisionBox.Height <= check.Height)
{
// 上y軸判斷 (左上角)
if (CollisionBox.Y >= check.Y && CollisionBox.Y <= check.Y + check.Height)
return true;
// 下y軸判斷 (左下角)
if (CollisionBox.Y + CollisionBox.Height >= check.Y && CollisionBox.Y + CollisionBox.Height <= check.Y + check.Height)
return true;
}
else if (check.Height < CollisionBox.Height)
{
// 用較小的來判斷
return SF.IsCollision(this);
}
}
else if (check.Width < CollisionBox.Width)
{
// 用較小的來判斷
return SF.IsCollision(this);
}
// 沒碰到
return false;
} |
|
我有個問題喔~我先針對一下這兩行:
代碼: | if (CollisionBox.Width <= check.Width)
{
.....
}
else if (check.Width < CollisionBox.Width)
{
.....
}
return false ;
|
A:CollisionBox.Width 。假設:x = 20 , y = 40 , width = 40 , hegiht = 50
B:check.Width。假設:x = 10 , 20 , width = 100 , height = 10
A <= B 則反之,必 A > B (B < A)
Run 第:
1. 代碼: |
if ( A <= B ) //CollisionBox.Width <= check.Width
{
if( A <= B ) // CollisionBox.Height <= check.Height
{
}
else if ( B < A ) //check.Height < CollisionBox.Height
{
//呼叫SF.IsCollision(this); <---this就是A,B就是SF吧?
}
}
else if ( B < A ) // check.Width < CollisionBox.Width
{
//不會呼叫SF.IsCollision(this);
}
|
Run 第:
2.因為先前呼叫SF.IsCollision(this);所以角色互換
A:CollisionBox.Width 。假設:x = 10 , 20 , width = 100 , height = 10
B:check.Width。假設:x = 20 , y = 40 , width = 40 , hegiht = 50
代碼: | if ( A <= B ) //CollisionBox.Width <= check.Width
{
}
else if ( B < A ) // check.Width < CollisionBox.Width
{
呼叫SF.IsCollision(this); <---this就是A,B就是SF吧?
}
|
Run第:
3. 跟Run第1一樣!?
這樣不就永遠跑不到return false !?
我沒測試過,但是我看一下流程,覺得怪怪的。希望給個解答 |
|
回頂端 |
|
|
babu61509 散播福音的祭司
註冊時間: 2007-08-26 文章: 142
681.01 果凍幣
|
發表於: 2007-10-29, AM 2:01 星期一 文章主題: |
|
|
姆...的確會無限迴圈呢@_@
晚一點改好再放上來- - _________________ 已經畢業了!! |
|
回頂端 |
|
|
|
|
您 無法 在這個版面發表文章 您 無法 在這個版面回覆文章 您 無法 在這個版面編輯文章 您 無法 在這個版面刪除文章 您 無法 在這個版面進行投票 您 可以 在這個版面附加檔案 您 可以 在這個版面下載檔案
|
|