最近搬家了 搬到天空部落格 以後這裡不會維護了,
有興趣的朋友換這裡看看吧 http://blog.yam.com/xnaOgre
那裡會以推廣XNA與OGRE為主
星期二, 6月 26, 2007
[XNA]很棒的視覺化開發環境
Blade3D是一個使用XNA開發的視覺化開發環境,支援許多特效,介面也頗為人性化,強烈推薦抓下來玩看看,現在只是Beta版,所以不用錢,XNA也能夠做出很專業的東西,雖然SimpleRacer Starter Kit推出就已經看得出來了,最近對XNA是越來越有興趣。
星期四, 6月 14, 2007
[OGRE]Fantastic GUI
星期六, 9月 02, 2006
[心得]XNA Game Express beta release
8/30當天也就是台北時間8/31午夜12點,MS發佈了XNA Game Express beta version,企圖打造一個跨PC與XBOX360的遊戲開發工具,說穿了,也就是集成MDX1.1,MDX2.0 beta與.net framework 2.0,稱作XNA framework,並且與GarageGames Inc.合作,使用Torque Engine作為視覺化開發工具,也就是說GarageGamesTGB,TSE,TGE寫了一份C#的版本稱作Torque X,讓開發出來的元件可以透過XNA framework在XBOX 360上run,這次的beta version無法在xbox360上跑,要等到明年推出pro version才有較為完整的架構。XNA計畫已經推行一段時間,從2004年的GDC大會上就已經公佈一些細節,前陣子也釋出"Mesh Commander 2"的source code,幫助使用者了解XNA的架構以及開發流程。MS算盤的打得很精,企圖讓彽成本開發公司可以取得開品質的跨平台開發工具;以及深入校園,讓遊戲相關科系的單位使用這套工具,養肥他們,未來就難脫離MS的控制,再者用自家C#語言開發,可謂一魚多吃;其實MS最大的夢想,是想打造遊戲界的Youtube,讓light core玩家也可以自行創造遊戲在xbox360或者pc上,向朋友炫耀。目前在PC上的Release並不用錢,但是在XBOX360上則是需要加入Club,並且繳交年費,但也不貴,有興趣的朋友可以先熟悉架構,未來就開發遊戲可以放到XBOX360上run。
為了嘗鮮,特別去載下來玩玩,這次beta version只能在Visual C# 2005 express,所以要特別去下載,還好可以跟Visuall Studio.net 2005 team suite同時存在,所以安裝上也沒有問題,另外就是要裝2006 August DirectX SDK,由於之前也裝過,所以這點就省略,裝完之後迅速瀏覽一遍,只有一個感覺,那就是把MDX的東西重新封裝,放到XNA namespace下,簡化一些MDX的render手續,Component部分也只有Graphic,好處是文件寫淂很詳細,也有step by step的教學,但還是看不出有什麼特別之處,Torque X連個影都沒看過,大概這版還沒有,上網在仔細看了一下,原來未來DirectX SDK 中的MDX不會再更新了,也就是說MDX 2.0 beta已經夭折,將移到XNA上繼續復活(但是不會叫MDX),覺得有點可惜,MDX是個好物,尤其與.net framework配合的很好,開發速度快上不少,如今,只能揮手跟它說再見了。so long,my friend.
官網
http://msdn.microsoft.com/directx/xna/。
對岸的XNA中文推廣網站
http://xna.everdocument.com/wiki/。
新聞介紹
http://gamezone.qq.com/a/20060815/000172.htm。
為了嘗鮮,特別去載下來玩玩,這次beta version只能在Visual C# 2005 express,所以要特別去下載,還好可以跟Visuall Studio.net 2005 team suite同時存在,所以安裝上也沒有問題,另外就是要裝2006 August DirectX SDK,由於之前也裝過,所以這點就省略,裝完之後迅速瀏覽一遍,只有一個感覺,那就是把MDX的東西重新封裝,放到XNA namespace下,簡化一些MDX的render手續,Component部分也只有Graphic,好處是文件寫淂很詳細,也有step by step的教學,但還是看不出有什麼特別之處,Torque X連個影都沒看過,大概這版還沒有,上網在仔細看了一下,原來未來DirectX SDK 中的MDX不會再更新了,也就是說MDX 2.0 beta已經夭折,將移到XNA上繼續復活(但是不會叫MDX),覺得有點可惜,MDX是個好物,尤其與.net framework配合的很好,開發速度快上不少,如今,只能揮手跟它說再見了。so long,my friend.
官網
http://msdn.microsoft.com/directx/xna/。
對岸的XNA中文推廣網站
http://xna.everdocument.com/wiki/。
新聞介紹
http://gamezone.qq.com/a/20060815/000172.htm。
星期日, 8月 06, 2006
[設計模式]裝飾者模式
最近想包一個簡單好用的2D動畫程式,以前寫c++時遺留的產物該讓它消失了,C#的在物件導向的編寫上的確有著一定的優勢,雖然這個例子中不會顯示出來,但用純物件導向語言來實現設計模式是再適合不過了。
一直傷腦筋要怎樣才能設計一個相依性低,擴充又方便的動畫類別呢?當時腦中就想到Decorator這個好用的設計模式,也就是裝飾者模式,只是當時在趕案子就把它擱在一旁,現在有時間就好好把它完成。何謂裝飾者模式,用一個最簡單說法,就是你現在想要實現一個主要的功能,但是它可以附加許多小功能,這些小功能就是所謂的裝飾者,怎麼樣?是不是猜到如何應用到動畫程式上。典型的2D動畫程式,不外乎就是讓圖片動;而秀圖就是我們的主要功能,因為無論怎麼動都是要秀圖吧,但要怎麼動?動法有很多種,有換圖片、透明度變化,平移、旋轉、縮放‧‧等,anyway,這些都是使用者可以去做延伸,很明顯的,這些動法就是我的們附加功能,今天我想要縮放加平移,或是我想要透明度高低變化加上換圖片,這些都可以透過裝飾者模式來達成,覺得很神奇嗎?看看範例就知道實踐上一點都不難。
//裝飾者模式
using System;
namespace Decorator
{
///
/// 裝置者模式主要是包裹被裝飾者,可以用來將附加功能抽離
///
///
//可以是抽象類別或是介面
public abstract class Animation
{
public Animation()
{
}
public virtual void Perform()
{
}
}
//裝飾者類別
public abstract class Decorator:Animation
{
//有一個父類別的參考
public Animation anim;
//建構時 指向實體
public Decorator(Animation a)
{
anim=a;
}
//整個範例的精隨 覆寫執行方法
public override void Perform()
{
//會去呼叫指到實體的方法
anim.Perform();
}
}
//繼承動畫類別 假設這是要做2D動畫
public class Animation2D:Animation
{
public Animation2D()
{}
//一樣覆寫執行方法
public override void Perform()
{
Console.WriteLine("最後由我來畫圖\n");
}
}
//平移類別 繼承裝飾者類別
public class Translate:Decorator
{
public Translate(Animation anim):base(anim)
{}
//一樣覆寫執行方法
public override void Perform()
{
Console.WriteLine("我作了平移\n");
//要注意的是這行 他會去呼叫Dector所指向實體的方法 也就是說會去呼叫上一層的執行方法 類似遞迴的作法
base.Perform();
}
};
//旋轉類別 繼承裝飾者類別
public class Rotate:Decorator
{
public Rotate(Animation anim):base(anim)
{}
//同平移
public override void Perform()
{
Console.WriteLine("我作了旋轉\n");
base.Perform();
}
};
//縮放類別 繼承裝飾者類別
public class Scale:Decorator
{
public Scale(Animation anim):base(anim)
{}
//同平移
public override void Perform()
{
Console.WriteLine("我作了縮放\n");
base.Perform();
}
};
class Client
{
///
/// 應用程式的主進入點。
///
[STAThread]
static void Pause()
{
Console.WriteLine("Press Enter To Continue....");
Console.ReadLine();
}
static void Main(string[] args)
{
//很簡單的應用 我生成了一個動畫物件 我打包了旋轉 縮放 平移 而且這個動畫物件是2D的
//如此一來我就可以很方便的選取這個動畫需要哪些功能,就跟點菜一樣方便,不要的時候也可以抽離
Animation anim=new Rotate(new Scale(new Translate(new Animation2D())));
anim.Perform();
Pause();
}
}
}
//建議您載下來完整編譯執行看看會更了解。
一直傷腦筋要怎樣才能設計一個相依性低,擴充又方便的動畫類別呢?當時腦中就想到Decorator這個好用的設計模式,也就是裝飾者模式,只是當時在趕案子就把它擱在一旁,現在有時間就好好把它完成。何謂裝飾者模式,用一個最簡單說法,就是你現在想要實現一個主要的功能,但是它可以附加許多小功能,這些小功能就是所謂的裝飾者,怎麼樣?是不是猜到如何應用到動畫程式上。典型的2D動畫程式,不外乎就是讓圖片動;而秀圖就是我們的主要功能,因為無論怎麼動都是要秀圖吧,但要怎麼動?動法有很多種,有換圖片、透明度變化,平移、旋轉、縮放‧‧等,anyway,這些都是使用者可以去做延伸,很明顯的,這些動法就是我的們附加功能,今天我想要縮放加平移,或是我想要透明度高低變化加上換圖片,這些都可以透過裝飾者模式來達成,覺得很神奇嗎?看看範例就知道實踐上一點都不難。
//裝飾者模式
using System;
namespace Decorator
{
///
/// 裝置者模式主要是包裹被裝飾者,可以用來將附加功能抽離
///
///
//可以是抽象類別或是介面
public abstract class Animation
{
public Animation()
{
}
public virtual void Perform()
{
}
}
//裝飾者類別
public abstract class Decorator:Animation
{
//有一個父類別的參考
public Animation anim;
//建構時 指向實體
public Decorator(Animation a)
{
anim=a;
}
//整個範例的精隨 覆寫執行方法
public override void Perform()
{
//會去呼叫指到實體的方法
anim.Perform();
}
}
//繼承動畫類別 假設這是要做2D動畫
public class Animation2D:Animation
{
public Animation2D()
{}
//一樣覆寫執行方法
public override void Perform()
{
Console.WriteLine("最後由我來畫圖\n");
}
}
//平移類別 繼承裝飾者類別
public class Translate:Decorator
{
public Translate(Animation anim):base(anim)
{}
//一樣覆寫執行方法
public override void Perform()
{
Console.WriteLine("我作了平移\n");
//要注意的是這行 他會去呼叫Dector所指向實體的方法 也就是說會去呼叫上一層的執行方法 類似遞迴的作法
base.Perform();
}
};
//旋轉類別 繼承裝飾者類別
public class Rotate:Decorator
{
public Rotate(Animation anim):base(anim)
{}
//同平移
public override void Perform()
{
Console.WriteLine("我作了旋轉\n");
base.Perform();
}
};
//縮放類別 繼承裝飾者類別
public class Scale:Decorator
{
public Scale(Animation anim):base(anim)
{}
//同平移
public override void Perform()
{
Console.WriteLine("我作了縮放\n");
base.Perform();
}
};
class Client
{
///
/// 應用程式的主進入點。
///
[STAThread]
static void Pause()
{
Console.WriteLine("Press Enter To Continue....");
Console.ReadLine();
}
static void Main(string[] args)
{
//很簡單的應用 我生成了一個動畫物件 我打包了旋轉 縮放 平移 而且這個動畫物件是2D的
//如此一來我就可以很方便的選取這個動畫需要哪些功能,就跟點菜一樣方便,不要的時候也可以抽離
Animation anim=new Rotate(new Scale(new Translate(new Animation2D())));
anim.Perform();
Pause();
}
}
}
//建議您載下來完整編譯執行看看會更了解。
星期六, 7月 08, 2006
如何用d3d讀取非2冪次的圖
1.偷懶的解法就是,在loadTexture時,在需要填寬高的參數,預設通常是填0,你把它填入原圖的寬,就可以正常顯示,但不建議使用,因為較舊的顯示卡是不支援的,如果你只是要自己測試倒是可以。
2.用程式建立大一級圖,例如512X512,然後把原來的圖畫上去,如果你是用正交投影顯示需要換算出UV,如果是用sprite可以直接指定需要顯示的範圍,這方法比較浪費記憶體,不過是挺容易的作法。
3.在美術做圖的時候,請他做成2次方圖形。
4.用切割的方式,將原圖等比例切割例如32X32或是依照原圖大小,按照比例來切割,256*256、256*128、128*64等等,然後自行寫演算法秀圖,這方法是最推薦的作法,不過相關演算法要自己思考一下。
5.另外寫讀圖程式,作成自己的格式,然後lock surface去blit,這部份是比較進階。
2.用程式建立大一級圖,例如512X512,然後把原來的圖畫上去,如果你是用正交投影顯示需要換算出UV,如果是用sprite可以直接指定需要顯示的範圍,這方法比較浪費記憶體,不過是挺容易的作法。
3.在美術做圖的時候,請他做成2次方圖形。
4.用切割的方式,將原圖等比例切割例如32X32或是依照原圖大小,按照比例來切割,256*256、256*128、128*64等等,然後自行寫演算法秀圖,這方法是最推薦的作法,不過相關演算法要自己思考一下。
5.另外寫讀圖程式,作成自己的格式,然後lock surface去blit,這部份是比較進階。
星期三, 5月 31, 2006
[設計模式]狀態模式
//狀態模式
using System;
namespace State
{
///
/// Client 的摘要描述。
/// 主控台測試部分
///
class Client
{
///
/// 應用程式的主進入點。
///
[STAThread]
static void Main(string[] args)
{
//建立主遊戲
MainGame main=new MainGame();
while(true)
{
//繪圖
main.FrameRender();
//運算
main.FrameMove();
}
}
}
//主狀態介面
interface MajorState
{
//每個狀態都有有兩個動作
//負責運算
void FrameMove();
//負責繪圖
void FrameRender();
}
//開始實做狀態介面
//建立狀態
class MS_Create: MajorState
{
//每個都有一個mainGame物件
MainGame mainGame;
public MS_Create(MainGame mainGame){this.mainGame=mainGame;}
public void FrameMove()
{
//改變狀態 取得mainGame的中的下個狀態然後再設給mainGame
mainGame.SetCurrentState(mainGame.GetMainMenuState());
}
public void FrameRender()
{
Console.WriteLine("程式被建立\n");
}
};
//下面如法泡製
//主選單狀態
class MS_MainMenu: MajorState
{
MainGame mainGame;
public MS_MainMenu(MainGame mainGame){this.mainGame=mainGame;}
public void FrameMove()
{
Console.ReadLine();
mainGame.SetCurrentState(mainGame.GetMainGameState());
}
public void FrameRender()
{
Console.WriteLine("我在主選單\n");
}
};
//主遊戲狀態
class MS_MainGame: MajorState
{
MainGame mainGame;
public MS_MainGame(MainGame mainGame){this.mainGame=mainGame;}
public void FrameMove()
{
Console.ReadLine();
mainGame.SetCurrentState(mainGame.GetDestoryState());
}
public void FrameRender()
{
Console.WriteLine("我在主遊戲\n");
}
};
//摧毀狀態
class MS_Destory: MajorState
{
MainGame mainGame;
public MS_Destory(MainGame mainGame){this.mainGame=mainGame;}
public void FrameMove()
{
Console.WriteLine("Press Enter To Continue....\n");
Console.ReadLine();
Environment.Exit(0);
}
public void FrameRender()
{
Console.WriteLine("摧毀遊戲\n");
Console.ReadLine();
}
};
//主遊戲的類別
class MainGame
{
//先宣告所有狀態類別
private MajorState ms_Create;
private MajorState ms_MainMenu;
private MajorState ms_MainGame;
private MajorState ms_Destory;
//記錄目前的狀態
private MajorState currentState;
public MainGame()
{
//把自己跟狀態綁定
ms_Create=new MS_Create(this);
ms_MainMenu=new MS_MainMenu(this);
ms_MainGame=new MS_MainGame(this);
ms_Destory=new MS_Destory(this);
//一開始預設就是先建立狀態
currentState=ms_Create;
}
//一旦呼叫FrameMove就執行當時狀態的FrameMove
public void FrameMove()
{
currentState.FrameMove();
}
//一旦呼叫FrameRender就執行當時狀態的FrameRender
public void FrameRender()
{
currentState.FrameRender();
}
//取得各個狀態
public MajorState GetCreateState(){return ms_Create;}
public MajorState GetMainMenuState(){return ms_MainMenu;}
public MajorState GetMainGameState(){return ms_MainGame;}
public MajorState GetDestoryState(){return ms_Destory;}
//設定狀態
public void SetCurrentState(MajorState state){currentState=state;}
};
}
using System;
namespace State
{
///
/// Client 的摘要描述。
/// 主控台測試部分
///
class Client
{
///
/// 應用程式的主進入點。
///
[STAThread]
static void Main(string[] args)
{
//建立主遊戲
MainGame main=new MainGame();
while(true)
{
//繪圖
main.FrameRender();
//運算
main.FrameMove();
}
}
}
//主狀態介面
interface MajorState
{
//每個狀態都有有兩個動作
//負責運算
void FrameMove();
//負責繪圖
void FrameRender();
}
//開始實做狀態介面
//建立狀態
class MS_Create: MajorState
{
//每個都有一個mainGame物件
MainGame mainGame;
public MS_Create(MainGame mainGame){this.mainGame=mainGame;}
public void FrameMove()
{
//改變狀態 取得mainGame的中的下個狀態然後再設給mainGame
mainGame.SetCurrentState(mainGame.GetMainMenuState());
}
public void FrameRender()
{
Console.WriteLine("程式被建立\n");
}
};
//下面如法泡製
//主選單狀態
class MS_MainMenu: MajorState
{
MainGame mainGame;
public MS_MainMenu(MainGame mainGame){this.mainGame=mainGame;}
public void FrameMove()
{
Console.ReadLine();
mainGame.SetCurrentState(mainGame.GetMainGameState());
}
public void FrameRender()
{
Console.WriteLine("我在主選單\n");
}
};
//主遊戲狀態
class MS_MainGame: MajorState
{
MainGame mainGame;
public MS_MainGame(MainGame mainGame){this.mainGame=mainGame;}
public void FrameMove()
{
Console.ReadLine();
mainGame.SetCurrentState(mainGame.GetDestoryState());
}
public void FrameRender()
{
Console.WriteLine("我在主遊戲\n");
}
};
//摧毀狀態
class MS_Destory: MajorState
{
MainGame mainGame;
public MS_Destory(MainGame mainGame){this.mainGame=mainGame;}
public void FrameMove()
{
Console.WriteLine("Press Enter To Continue....\n");
Console.ReadLine();
Environment.Exit(0);
}
public void FrameRender()
{
Console.WriteLine("摧毀遊戲\n");
Console.ReadLine();
}
};
//主遊戲的類別
class MainGame
{
//先宣告所有狀態類別
private MajorState ms_Create;
private MajorState ms_MainMenu;
private MajorState ms_MainGame;
private MajorState ms_Destory;
//記錄目前的狀態
private MajorState currentState;
public MainGame()
{
//把自己跟狀態綁定
ms_Create=new MS_Create(this);
ms_MainMenu=new MS_MainMenu(this);
ms_MainGame=new MS_MainGame(this);
ms_Destory=new MS_Destory(this);
//一開始預設就是先建立狀態
currentState=ms_Create;
}
//一旦呼叫FrameMove就執行當時狀態的FrameMove
public void FrameMove()
{
currentState.FrameMove();
}
//一旦呼叫FrameRender就執行當時狀態的FrameRender
public void FrameRender()
{
currentState.FrameRender();
}
//取得各個狀態
public MajorState GetCreateState(){return ms_Create;}
public MajorState GetMainMenuState(){return ms_MainMenu;}
public MajorState GetMainGameState(){return ms_MainGame;}
public MajorState GetDestoryState(){return ms_Destory;}
//設定狀態
public void SetCurrentState(MajorState state){currentState=state;}
};
}
星期一, 5月 29, 2006
[設計模式]觀察者模式
//觀察者模式
using System;
using System.Collections;
namespace Observer
{
///
/// Class1 的摘要描述。
/// 主控台測試部分
///
class Client
{
///
/// 應用程式的主進入點。
///
[STAThread]
static void Pause()
{
Console.WriteLine("Press Enter To Continue....");
Console.ReadLine();
}
static void Main(string[] args)
{
//這是負責顯示正常模式的物件
ShowNormal normal;
//這是負責顯示特殊模式的物件
ShowSpecial special;
// 球員資料
PlayerData playerData=new PlayerData();
//現在我把球員資料給綁定到觀察者
normal =new ShowNormal(playerData);
//現在我把球員資料給綁定到另一個觀察者
special =new ShowSpecial(playerData);
//一但球員資料有所變更 就會通知之前綁定的觀察者 而依序顯示出來 如此可以鬆綁兩者之間的關係
//這就是整個模式的關鍵 許多GUI也是用這種方式實做 一個當作listener 一但有所變更 立刻通知所有人
//如此即可讓資料一次更新並做處理
playerData.SetData("王大蠻",100);
//移除其中一個觀察者也沒問題
normal.Destory();
Pause();
}
}
//觀察者介面
interface Observer
{
void Update(string name,int skill);
void Destory();
}
//把顯示的介面另外獨立出來 因為要爭對介面寫程式
interface Display
{
void Show();
}
//
//實作觀察者與顯示介面
//
//正常顯示
class ShowNormal:Observer,Display
{
private string playerName;
private int playerSkill;
private Subject subject;
//將資料綁定 表示說向他註冊 有變更通知我
public ShowNormal(Subject subject)
{
this.subject=subject;
this.subject.Add(this);
}
//資料一但有變動就會呼叫這個更新
public void Update(string name,int skill)
{
playerName=name;
playerSkill=skill;
//這放其他地方會更好
Show();
}
//看要對資料做什麼處理 這裡暫時以顯示取代
public void Show()
{
Console.WriteLine("我顯示正常格式");
Console.WriteLine("使用者名稱"+playerName);
Console.WriteLine("技能"+playerSkill);
Console.WriteLine("");
}
//表示不要再綁定了 解除註冊
public void Destory()
{
subject.Remove(this);
Console.WriteLine("我ShowNormal被移除了\n");
}
}
//特出顯示
class ShowSpecial:Observer,Display
{
private string playerName;
private int playerSkill;
private Subject subject;
public ShowSpecial(Subject subject)
{
this.subject=subject;
this.subject.Add(this);
}
public void Update(string name,int skill)
{
playerName=name;
playerSkill=skill;
Show();
}
public void Show()
{
Console.WriteLine("我顯示特殊格式");
Console.WriteLine("使用者名稱*****"+playerName+"*******");
Console.WriteLine("技能~~~~~~~"+playerSkill+"~~~~~~~");
Console.WriteLine("");
}
public void Destory()
{
subject.Remove(this);
Console.WriteLine("我ShowSpecial被移除了");
}
}
//主題的介面 也就是可觀察的observable
interface Subject
{
void Add(Object ob);
void Notify();
void Remove(Object ob);
};
//實作主題 假設是球員資料
class PlayerData:Subject
{
private string playerName;
private int playerSkill;
ArrayList data;
public PlayerData()
{
data=new ArrayList();
}
//別人註冊會呼叫這個
public void Add(Object ob)
{
data.Add(ob);
}
//有變更就通知大家
public void Notify()
{
for (int a=0;a< data.Count;a++)
{
Observer observer =(Observer)data[a];
observer.Update(playerName,playerSkill);
}
}
//哪個想被移除就呼叫這個
public void Remove(Object ob)
{
data.Remove(ob);
}
//資料變更的地方
public void SetData(string name,int skill)
{
playerName=name;
playerSkill=skill;
Notify();
}
}
}
using System;
using System.Collections;
namespace Observer
{
///
/// Class1 的摘要描述。
/// 主控台測試部分
///
class Client
{
///
/// 應用程式的主進入點。
///
[STAThread]
static void Pause()
{
Console.WriteLine("Press Enter To Continue....");
Console.ReadLine();
}
static void Main(string[] args)
{
//這是負責顯示正常模式的物件
ShowNormal normal;
//這是負責顯示特殊模式的物件
ShowSpecial special;
// 球員資料
PlayerData playerData=new PlayerData();
//現在我把球員資料給綁定到觀察者
normal =new ShowNormal(playerData);
//現在我把球員資料給綁定到另一個觀察者
special =new ShowSpecial(playerData);
//一但球員資料有所變更 就會通知之前綁定的觀察者 而依序顯示出來 如此可以鬆綁兩者之間的關係
//這就是整個模式的關鍵 許多GUI也是用這種方式實做 一個當作listener 一但有所變更 立刻通知所有人
//如此即可讓資料一次更新並做處理
playerData.SetData("王大蠻",100);
//移除其中一個觀察者也沒問題
normal.Destory();
Pause();
}
}
//觀察者介面
interface Observer
{
void Update(string name,int skill);
void Destory();
}
//把顯示的介面另外獨立出來 因為要爭對介面寫程式
interface Display
{
void Show();
}
//
//實作觀察者與顯示介面
//
//正常顯示
class ShowNormal:Observer,Display
{
private string playerName;
private int playerSkill;
private Subject subject;
//將資料綁定 表示說向他註冊 有變更通知我
public ShowNormal(Subject subject)
{
this.subject=subject;
this.subject.Add(this);
}
//資料一但有變動就會呼叫這個更新
public void Update(string name,int skill)
{
playerName=name;
playerSkill=skill;
//這放其他地方會更好
Show();
}
//看要對資料做什麼處理 這裡暫時以顯示取代
public void Show()
{
Console.WriteLine("我顯示正常格式");
Console.WriteLine("使用者名稱"+playerName);
Console.WriteLine("技能"+playerSkill);
Console.WriteLine("");
}
//表示不要再綁定了 解除註冊
public void Destory()
{
subject.Remove(this);
Console.WriteLine("我ShowNormal被移除了\n");
}
}
//特出顯示
class ShowSpecial:Observer,Display
{
private string playerName;
private int playerSkill;
private Subject subject;
public ShowSpecial(Subject subject)
{
this.subject=subject;
this.subject.Add(this);
}
public void Update(string name,int skill)
{
playerName=name;
playerSkill=skill;
Show();
}
public void Show()
{
Console.WriteLine("我顯示特殊格式");
Console.WriteLine("使用者名稱*****"+playerName+"*******");
Console.WriteLine("技能~~~~~~~"+playerSkill+"~~~~~~~");
Console.WriteLine("");
}
public void Destory()
{
subject.Remove(this);
Console.WriteLine("我ShowSpecial被移除了");
}
}
//主題的介面 也就是可觀察的observable
interface Subject
{
void Add(Object ob);
void Notify();
void Remove(Object ob);
};
//實作主題 假設是球員資料
class PlayerData:Subject
{
private string playerName;
private int playerSkill;
ArrayList data;
public PlayerData()
{
data=new ArrayList();
}
//別人註冊會呼叫這個
public void Add(Object ob)
{
data.Add(ob);
}
//有變更就通知大家
public void Notify()
{
for (int a=0;a< data.Count;a++)
{
Observer observer =(Observer)data[a];
observer.Update(playerName,playerSkill);
}
}
//哪個想被移除就呼叫這個
public void Remove(Object ob)
{
data.Remove(ob);
}
//資料變更的地方
public void SetData(string name,int skill)
{
playerName=name;
playerSkill=skill;
Notify();
}
}
}
星期五, 5月 26, 2006
[設計模式]策略模式
//策略模式
using System;
namespace Strategy
{
///
/// Class1 的摘要描述。
/// 主控台測試部分
///
class Client
{
///
/// 應用程式的主進入點。
///
[STAThread]
static void Pause()
{
Console.WriteLine("Press Enter To Continue....");
Console.ReadLine();
}
static void Main(string[] args)
{
//建立一位打者叫做barryBonds
BaseballPlayer player1=new BarryBonds();
//可以改變它的行為模式
//player1.SetSwingPosture(new NormalPosture());
//揮棒
player1.Swing();
Pause();
}
}
//抽象類別 野手類別
abstract class BaseballPlayer
{
protected SwingPosture posture;
public void Swing()
{
posture.Swing();
}
public void SetSwingPosture(SwingPosture posture)
{
this.posture=posture;
}
}
//繼承類別 有個叫做barrybonds的野手
class BarryBonds:BaseballPlayer
{
//設定他的打擊姿勢
public BarryBonds()
{
posture=new StarPosture();
}
};
//
//把容易變動的部份抽出來 利如揮棒姿勢 許多人都不一樣 但是也有一樣的 所以另外封裝
//
//揮棒姿勢的介面
interface SwingPosture
{
void Swing();
};
//實作揮棒姿勢 這是正常的揮棒姿勢
class NormalPosture:SwingPosture
{
#region SwingPosture 成員
public void Swing()
{
Console.WriteLine("我用正常姿勢揮棒");
}
#endregion
}
// 這是明星的揮棒姿勢
class StarPosture:SwingPosture
{
#region SwingPosture 成員
public void Swing()
{
Console.WriteLine("我用明星姿勢揮棒");
}
#endregion
}
}
using System;
namespace Strategy
{
///
/// Class1 的摘要描述。
/// 主控台測試部分
///
class Client
{
///
/// 應用程式的主進入點。
///
[STAThread]
static void Pause()
{
Console.WriteLine("Press Enter To Continue....");
Console.ReadLine();
}
static void Main(string[] args)
{
//建立一位打者叫做barryBonds
BaseballPlayer player1=new BarryBonds();
//可以改變它的行為模式
//player1.SetSwingPosture(new NormalPosture());
//揮棒
player1.Swing();
Pause();
}
}
//抽象類別 野手類別
abstract class BaseballPlayer
{
protected SwingPosture posture;
public void Swing()
{
posture.Swing();
}
public void SetSwingPosture(SwingPosture posture)
{
this.posture=posture;
}
}
//繼承類別 有個叫做barrybonds的野手
class BarryBonds:BaseballPlayer
{
//設定他的打擊姿勢
public BarryBonds()
{
posture=new StarPosture();
}
};
//
//把容易變動的部份抽出來 利如揮棒姿勢 許多人都不一樣 但是也有一樣的 所以另外封裝
//
//揮棒姿勢的介面
interface SwingPosture
{
void Swing();
};
//實作揮棒姿勢 這是正常的揮棒姿勢
class NormalPosture:SwingPosture
{
#region SwingPosture 成員
public void Swing()
{
Console.WriteLine("我用正常姿勢揮棒");
}
#endregion
}
// 這是明星的揮棒姿勢
class StarPosture:SwingPosture
{
#region SwingPosture 成員
public void Swing()
{
Console.WriteLine("我用明星姿勢揮棒");
}
#endregion
}
}
星期一, 2月 27, 2006
C# 學習筆記
最近開始研究c#.net 以及MDX 把一些心得寫下來以免忘記‧‧‧
1. 回傳值可以是陣列參考
2. 陣列本質是指標(c#稱為參考) 與java同
3. 比較兩陣列時"==" 實際是比較是否為同一位址
4. 比較兩字串時 並非比較兩個位置 而是字串內容 跟java不同
5. 由於陣列實際是指標在運作 所以可以用多維不定數的陣列
規則是用 [x,y]
不規則是用 [x][y]
6. 改成unsafe就可以自由操作指標 預設是託管
7. GB可自由選擇是否要自己釋放動態記憶體 以免需要高效的程式因此delay
8. foreach用法
規則不管幾維
int [,]array=new int[7,12];
foreach(int temp in array)
{System.Console.WriteLine(temp); }
不規則多維
int [][][]array=new int[7][12][22];
foreach(int [][] out in array)
foreach(int [] mid in out)
foreach(int inner in mid)
{System.Console.WriteLine(inner); }
9.類別宣告裡可直接設值 同java
10.const 本身就是static
11.swap(ref int a,ref int b)等同於c++的 swap(int &a,int &b) 但是呼叫時也要加ref
xxx.swap(ref val1,ref val2);
12.out同ref 但他可以接受為設值的參數
13.參數params可作為任意數量的參數預設值 如int sum(params int [] nums)
如此可用sum(a,b) sum(a,b,c,).....
13.readonly關鍵字類似const 但是不用在宣告時設值 且預設非static
14.c#的解構子與c++不同 是由GB去喚醒
15.c#有property的觀念 也就是屬性 一個屬性可用get 與 set去操作 如此一來 在client端就可以
直接寫 xx=value; 不用再object.setXX(value);
16.c#提供內部定義陣列索引 例如
public int [] abc=new int[4];
public int this[int index]
{
set
{
abc[index]=value;
}
}
value 為隱含式的值
17.c#沒有template 跟java一樣
18.使用using XXXXXX= aaaa.bbb.ccc.ddd 可以簡化 namespace長度
這樣就可以使用 XXXXX.method();
19.c#使用namespace 來封裝類別 類似java的package
20.class前面加一個sealed關鍵字代表這個類別不能被繼承 通常用於此類別都是static時
21.internal關鍵字 代表部件內的成員都可以存取
22.base()可使繼承類別呼叫基礎類別的建構子
23.virtual代表可以被override override代表覆寫
24.在override函式裡面 可以用base.XXX()來呼叫原始的基底函式
25.abstract 表示該method 或是property或 arrayindex 只能在子類別被實作 且不能創建實體物件
但可以擁有實作的method
26.is關鍵字可以測試該物件是否為某類別 例如 if (object is XXClass)
27.as關鍵字可以簡化(26)所用的語句 如
myXX=aaa as XX;
if (myXX!=NULL)
do_some_thing;
會等於
if (aaa is XX)
{myXX=(XX)aaa;}
28.創建的類別如果沒有指定基礎類別 就預設是繼承自System.Object
29. 衍生類別method前面若加上new 則代表此物件是要隱藏父類別的同一method 也就是c++
的父類別不加virtual 的結果 c#假設前面不寫virtual 預設就是new 也就是不會動態聯繫
30.c#不支援多重繼承 用interface來代替
31.interface類似c++的pure virtual class 且不能擁有member
32.interface method不用加上存取修飾子 實作它的子類別可以加上父類別名來區別
例如 void IXXable.DrawYY();
33.上述為顯示介面函數 如果要呼叫他 必須這樣寫
Ixxable aaa=new implimentClass();
aaa.DrawYY;
不能寫
implimentClass aaa=new implimentClass();
aaa.DrawYY;
用這樣來達到多型的效果
34.用interface可以達到template的效果
35.struct與class同 但不支援繼承 且不包含解構式
36.delegate關鍵字 類似c++的函式指標 主要用於封裝方法 如
public delegate double XXX(int x,int y);
public double Sum(int x,int y){}; //參數與返回值型態都要匹配
XXX myXXX=new XXX(Sum);
double result=myXXX(10,20);
37.多重委託返回型態一定要是void
38.event是用多重委託來達成
public delegate double XXX(int x,int y);
public event XXX myXXX;
1. 回傳值可以是陣列參考
2. 陣列本質是指標(c#稱為參考) 與java同
3. 比較兩陣列時"==" 實際是比較是否為同一位址
4. 比較兩字串時 並非比較兩個位置 而是字串內容 跟java不同
5. 由於陣列實際是指標在運作 所以可以用多維不定數的陣列
規則是用 [x,y]
不規則是用 [x][y]
6. 改成unsafe就可以自由操作指標 預設是託管
7. GB可自由選擇是否要自己釋放動態記憶體 以免需要高效的程式因此delay
8. foreach用法
規則不管幾維
int [,]array=new int[7,12];
foreach(int temp in array)
{System.Console.WriteLine(temp); }
不規則多維
int [][][]array=new int[7][12][22];
foreach(int [][] out in array)
foreach(int [] mid in out)
foreach(int inner in mid)
{System.Console.WriteLine(inner); }
9.類別宣告裡可直接設值 同java
10.const 本身就是static
11.swap(ref int a,ref int b)等同於c++的 swap(int &a,int &b) 但是呼叫時也要加ref
xxx.swap(ref val1,ref val2);
12.out同ref 但他可以接受為設值的參數
13.參數params可作為任意數量的參數預設值 如int sum(params int [] nums)
如此可用sum(a,b) sum(a,b,c,).....
13.readonly關鍵字類似const 但是不用在宣告時設值 且預設非static
14.c#的解構子與c++不同 是由GB去喚醒
15.c#有property的觀念 也就是屬性 一個屬性可用get 與 set去操作 如此一來 在client端就可以
直接寫 xx=value; 不用再object.setXX(value);
16.c#提供內部定義陣列索引 例如
public int [] abc=new int[4];
public int this[int index]
{
set
{
abc[index]=value;
}
}
value 為隱含式的值
17.c#沒有template 跟java一樣
18.使用using XXXXXX= aaaa.bbb.ccc.ddd 可以簡化 namespace長度
這樣就可以使用 XXXXX.method();
19.c#使用namespace 來封裝類別 類似java的package
20.class前面加一個sealed關鍵字代表這個類別不能被繼承 通常用於此類別都是static時
21.internal關鍵字 代表部件內的成員都可以存取
22.base()可使繼承類別呼叫基礎類別的建構子
23.virtual代表可以被override override代表覆寫
24.在override函式裡面 可以用base.XXX()來呼叫原始的基底函式
25.abstract 表示該method 或是property或 arrayindex 只能在子類別被實作 且不能創建實體物件
但可以擁有實作的method
26.is關鍵字可以測試該物件是否為某類別 例如 if (object is XXClass)
27.as關鍵字可以簡化(26)所用的語句 如
myXX=aaa as XX;
if (myXX!=NULL)
do_some_thing;
會等於
if (aaa is XX)
{myXX=(XX)aaa;}
28.創建的類別如果沒有指定基礎類別 就預設是繼承自System.Object
29. 衍生類別method前面若加上new 則代表此物件是要隱藏父類別的同一method 也就是c++
的父類別不加virtual 的結果 c#假設前面不寫virtual 預設就是new 也就是不會動態聯繫
30.c#不支援多重繼承 用interface來代替
31.interface類似c++的pure virtual class 且不能擁有member
32.interface method不用加上存取修飾子 實作它的子類別可以加上父類別名來區別
例如 void IXXable.DrawYY();
33.上述為顯示介面函數 如果要呼叫他 必須這樣寫
Ixxable aaa=new implimentClass();
aaa.DrawYY;
不能寫
implimentClass aaa=new implimentClass();
aaa.DrawYY;
用這樣來達到多型的效果
34.用interface可以達到template的效果
35.struct與class同 但不支援繼承 且不包含解構式
36.delegate關鍵字 類似c++的函式指標 主要用於封裝方法 如
public delegate double XXX(int x,int y);
public double Sum(int x,int y){}; //參數與返回值型態都要匹配
XXX myXXX=new XXX(Sum);
double result=myXXX(10,20);
37.多重委託返回型態一定要是void
38.event是用多重委託來達成
public delegate double XXX(int x,int y);
public event XXX myXXX;
星期五, 9月 23, 2005
[遊戲設計][邁向遊戲程式人生八部曲] 貳部曲-用鐵還是刀
當下定決心要寫遊戲的之後,就需了解要用什麼寫遊戲?這個答案只有一個,那就是什麼都可以寫。一切都要看自己的需求,以下我會分析各種製作遊戲的常見工具,你可以視需求來選擇。
(1)Flash:非常普遍的多媒體開發工具,最大的優點是開發時程短,上手容易,可在web上執行。Action Script2.0之後使Flash變得更為強大。缺點是只支援向量圖形,難以做到3D材質貼圖,對於伺服器架構支援還不完善。
(2)Director:功能比flash更為強大,不過也因此更為複雜,對於商業遊戲而言,效率以及不夠低階的缺點,使它無法成為主流。
(3)Virtools:一個法國的3D成像引擎,也是參賽學生的最愛 XD,原因在於開發時程短,圖形化介面具親和力,顯現的視覺效果不錯,且可在網頁上執行,3.0以後更支援shader model。很可惜的是它並不是為了遊戲開發而設計的引擎,效能、可控性都不高。如果要商業化需要獲得授權,如果全部模組都要授權,所費不貲。
(4)遊戲製作大師系列:專門為製作遊戲而作的軟體,視覺化的介面讓你很快能夠上手,還有許多遊戲資源讓你不用為找不到素材而煩惱。
以上都是屬於應用層的工具,也就是技術掌握在他人手上,在該公司開發的工具平台上來製作。
如果你想要製作網頁遊戲,或是寫一些小遊戲玩玩,建議你選擇flash或是director。如果你想要作遊戲參賽或是交專題,virtools或是很好的選擇,因為評審通常只看外表,且你能在最短的時間完成專案。如果你愛好日本式的rpg遊戲,遊戲製作大師是很好的選擇。
以上的工具是已經可以用的刀,可殺人可殺雞,但很可惜它不能成為大砲,如果這些工具可以解決你的需求,你可以在市面上買相關的書,相信很快就能夠上手,你也不需要再看下面的系列文章。但如果你有更大的野心,想要了解主流遊戲程式底層的豪情壯志,我會告訴你如何擁有鐵。
(1)Flash:非常普遍的多媒體開發工具,最大的優點是開發時程短,上手容易,可在web上執行。Action Script2.0之後使Flash變得更為強大。缺點是只支援向量圖形,難以做到3D材質貼圖,對於伺服器架構支援還不完善。
(2)Director:功能比flash更為強大,不過也因此更為複雜,對於商業遊戲而言,效率以及不夠低階的缺點,使它無法成為主流。
(3)Virtools:一個法國的3D成像引擎,也是參賽學生的最愛 XD,原因在於開發時程短,圖形化介面具親和力,顯現的視覺效果不錯,且可在網頁上執行,3.0以後更支援shader model。很可惜的是它並不是為了遊戲開發而設計的引擎,效能、可控性都不高。如果要商業化需要獲得授權,如果全部模組都要授權,所費不貲。
(4)遊戲製作大師系列:專門為製作遊戲而作的軟體,視覺化的介面讓你很快能夠上手,還有許多遊戲資源讓你不用為找不到素材而煩惱。
以上都是屬於應用層的工具,也就是技術掌握在他人手上,在該公司開發的工具平台上來製作。
如果你想要製作網頁遊戲,或是寫一些小遊戲玩玩,建議你選擇flash或是director。如果你想要作遊戲參賽或是交專題,virtools或是很好的選擇,因為評審通常只看外表,且你能在最短的時間完成專案。如果你愛好日本式的rpg遊戲,遊戲製作大師是很好的選擇。
以上的工具是已經可以用的刀,可殺人可殺雞,但很可惜它不能成為大砲,如果這些工具可以解決你的需求,你可以在市面上買相關的書,相信很快就能夠上手,你也不需要再看下面的系列文章。但如果你有更大的野心,想要了解主流遊戲程式底層的豪情壯志,我會告訴你如何擁有鐵。
星期二, 6月 07, 2005
[遊戲設計][邁向遊戲程式人生八部曲] 首部曲-何苦作遊戲
懷抱著一顆熱誠的心,想一頭栽進遊戲圈子的熱血青年不少。但在踏進這個領域之前,有許多事是需要好好思考;首先,玩遊戲與作遊戲是截然不同的東西,會想作遊戲的人,一定喜歡玩遊戲,但是真正作遊戲之後,常常會失去玩遊戲的樂趣。很簡單的道理,當你理解魔術的原理之後,你就不會認為那是個魔術,而只是個技法。隨著你的理解增加,就會犯了玩遊戲的大忌-回到現實;不能融入遊戲當中,自然也就玩得不盡興。
再來則是縱使你有天馬行空的創意,如果程式無法實行,企劃的再多也是枉然,要知道遊戲這個專業領域,企劃與程式是細分開來的,也許早期的遊戲可以一人一手包辦,但目前的遊戲架構越來越大,沒有專業分工是很難達到高品質的製程,既然你選擇了當一個程式,請把你的創意精力放在程式的靈活表現上,程式人員是遊戲製作最重要的角色,也可以說掌管了一個遊戲的生死,請將目標定立成為一個好的程式設計師,而不是當個程式工人。
最後就是如果你想將這行當做吃飯的行業,就需要有一個認知,台灣的遊戲環境無法與國外相比,普遍的薪資比其他軟體人員來的低,所以想要在這行賺大錢,不是不可能,但請不要以這個為目標,否則通常會得到非常大的失落感。如果興趣與收入要能夠兼顧,完全取決於你的實力。作遊戲是幸福的,這才是遊戲人的真諦。
在我踏入這個圈子之前,也不吃了少苦頭,寫這些文章希望縮短初新者入門的曲線,把一點心得分享給大家,這系列並不會有太深的技術成份,而是對於門外漢想一窺遊戲設計殿堂所寫,如果已經有基礎的朋友可以參考,高手就可以略過。初學者看完以上幾點仍然有堅定的意志想作遊戲的話,那就請接下去看二部曲。
再來則是縱使你有天馬行空的創意,如果程式無法實行,企劃的再多也是枉然,要知道遊戲這個專業領域,企劃與程式是細分開來的,也許早期的遊戲可以一人一手包辦,但目前的遊戲架構越來越大,沒有專業分工是很難達到高品質的製程,既然你選擇了當一個程式,請把你的創意精力放在程式的靈活表現上,程式人員是遊戲製作最重要的角色,也可以說掌管了一個遊戲的生死,請將目標定立成為一個好的程式設計師,而不是當個程式工人。
最後就是如果你想將這行當做吃飯的行業,就需要有一個認知,台灣的遊戲環境無法與國外相比,普遍的薪資比其他軟體人員來的低,所以想要在這行賺大錢,不是不可能,但請不要以這個為目標,否則通常會得到非常大的失落感。如果興趣與收入要能夠兼顧,完全取決於你的實力。作遊戲是幸福的,這才是遊戲人的真諦。
在我踏入這個圈子之前,也不吃了少苦頭,寫這些文章希望縮短初新者入門的曲線,把一點心得分享給大家,這系列並不會有太深的技術成份,而是對於門外漢想一窺遊戲設計殿堂所寫,如果已經有基礎的朋友可以參考,高手就可以略過。初學者看完以上幾點仍然有堅定的意志想作遊戲的話,那就請接下去看二部曲。
星期三, 6月 01, 2005
星期二, 5月 10, 2005
[個人日誌]3D圖形搜尋引擎
訂閱:
文章 (Atom)