WP7 - Silverlight and XNA Application or 3D Graphics Application

WP7–Silverlight and XNA Application or 3D Graphics Application

要開發Windows phone的程式有兩種選擇,

想要開發遊戲的話用XNA,開發一般應用程式的話用Silverlight,當然反過來也可以,只是比較麻煩!

不過現在,終於可以混在一起做瀨尿牛丸了!!!

 

在windows phone OS 7.1 裡新出現了幾個不一樣的專案,

其中一個在Silverlight for Windows Phone裡的就是Windows Phone 3D Griphics Application專案,

他和XNA Game Studio 4.0 裡面的Windows Phone Silverlight and XNA Application專案是一樣的東西。

這兩個專案的目的就是讓XNA和Silverlight結合起來,

如此一來開發遊戲也可以用Silverlight的介面,Silverlight也可以用XNA的3D等功能,

真是好吃新奇又好玩啊!

 

首先,開啟Windows Phone 3D Griphics Application專案

這已經是一個可以執行的專案了,直接按F5試試看

一開始是一個很平常的Silverlight頁面,

image

點選Play之後會換到類似遊戲的頁面,會有一個方塊不斷的移動

image

整個專案的架構如下

image

TestGraphicsApp1是Silverlight的專案型態,裡面有兩個頁面,MainPage 和 GamePage。

TestGraphicsApp1LibraryContent是放置資源用的,和XNA的Content專案是一樣功能的

而中間的TestGraphicsApp1Library可以當成之前寫XNA用的主專案,

不同的地方是以前XNA專案裡的game.cs移到Silverlight專案裡的GamePage

 

MainPage的內容非常簡單,就是一個按鈕,按下去會轉到GamePage

GamePage的xaml檔也很簡單,空空的,主要的程式碼都在GamePage.cs檔裡

由建構子開始看

   1:  public GamePage() {
   2:      InitializeComponent();
   3:  
   4:      // Get the application's ContentManager
   5:      content = (Application.Current as App).Content;
   6:  
   7:      // Create a timer for this page
   8:      timer = new GameTimer();
   9:      timer.UpdateInterval = TimeSpan.FromTicks(333333);
  10:      timer.Update += OnUpdate;
  11:      timer.Draw += OnDraw;
  12:  }

很明顯的他實體化一個GameTimer,並由他來控制Update以及Draw,並且每秒呼叫30次。

接著看看進入頁面和離開頁面的程式

   1:  protected override void OnNavigatedTo(NavigationEventArgs e) {
   2:  
   3:      // Set the sharing mode of the graphics device to turn on XNA rendering
   4:      SharedGraphicsDeviceManager.Current.GraphicsDevice.SetSharingMode(true);
   5:      
   6:      spriteBatch = new SpriteBatch(SharedGraphicsDeviceManager.Current.GraphicsDevice);
   7:  
   8:      // TODO: use this.content to load your game content here
   9:      texture = content.Load<Texture2D>("redRect");
  10:  
  11:      spritePosition.X = 0;
  12:      spritePosition.Y = 0;
  13:  
  14:      spriteHeight = texture.Height;
  15:      spriteWidth = texture.Width;
  16:  
  17:  
  18:      // Start the timer
  19:      timer.Start();
  20:  
  21:      base.OnNavigatedTo(e);
  22:  }
  23:  
  24:  protected override void OnNavigatedFrom(NavigationEventArgs e) {
  25:      // Stop the timer
  26:      timer.Stop();
  27:  
  28:      // Set the sharing mode of the graphics device to turn off XNA rendering
  29:      SharedGraphicsDeviceManager.Current.GraphicsDevice.SetSharingMode(false);
  30:  
  31:      base.OnNavigatedFrom(e);
  32:  }

這裡有兩個很重要的地方,分別是第4行和第29行

他用來設定顯示裝置是否要分享給XNA使用,所以一進入畫面要先設定成true,如此Silverlight和XNA都可以使用顯示裝置

再來是 OnUpdate 和 OnDraw 函式,就和XNA的 Update 和 Draw 一樣功能,這裡就不多說。

 

而既然專案合併了,那我當然想在執行XNA的時候使用Silverlight的控制項囉。

由於GamePage.xaml沒有容器,所以先拉個Grid到裡面

在拉幾個基本的控制項,如Button,TextBox到Grid內,

image

再讓Button做些事情

   1:  private void button1_Click(object sender, RoutedEventArgs e) {
   2:      purse = !purse;
   3:      if (purse == true) MSG.Text = "暫停";
   4:      else MSG.Text = "開始";
   5:  }

其中MSG就是中間那個TextBlock的名字。

 

然後按F5,執行看看!

恩恩,啥都沒有,和之前一樣! 世間果然並非如此美好!!

不過按一下最上方,竟然有虛擬鍵盤出現,看來控制項的確存在,只是看不到罷了

要讓控制項出現就要先宣到一個UIElementRenderer,

此類別只有在Windows phone裡才有用,是把Silverlight 的 UIElement畫到Texture用的,

 

   1:  UIElementRenderer elementRenderer;
   2:  
   3:  public GamePage() {
   4:      InitializeComponent();
   5:  
   6:      // Get the application's ContentManager
   7:      content = (Application.Current as App).Content;
   8:  
   9:      // Create a timer for this page
  10:      timer = new GameTimer();
  11:      timer.UpdateInterval = TimeSpan.FromTicks(333333);
  12:      timer.Update += OnUpdate;
  13:      timer.Draw += OnDraw;
  14:  
  15:      LayoutUpdated += new EventHandler(GamePage_LayoutUpdated);
  16:  
  17:  }
  18:  
  19:  private void GamePage_LayoutUpdated(object sender, EventArgs e) {
  20:  
  21:      if (null == elementRenderer) {
  22:          elementRenderer = new UIElementRenderer(this, (int)ActualWidth, (int)ActualHeight);
  23:      }
  24:  
  25:  }
  26:  
  27:  private void OnDraw(object sender, GameTimerEventArgs e) {
  28:      SharedGraphicsDeviceManager.Current.GraphicsDevice.Clear(Color.CornflowerBlue);
  29:  
  30:      // TODO: Add your drawing code here
  31:      elementRenderer.Render();
  32:      // Draw the sprite
  33:      spriteBatch.Begin();
  34:      spriteBatch.Draw(texture, spritePosition, Color.White);
  35:      spriteBatch.Draw(elementRenderer.Texture, Vector2.Zero, Color.White);
  36:      spriteBatch.End();
  37:      
  38:  }

 

第一行先宣告UIElementRenderer,然後在LayoutUpdated的時候產生實體,定設定要畫的範圍,

然後第31行在OnDraw函式內呼叫Render,UIElementRenderer就會將畫面畫在自己的Texture屬性裡,

接著第35行把silverlight的控制項畫出來。

 

再來看看結果

image

也會出現輸入法

image

甚至顯示中文也沒問題,這個大幅簡化XNA的中文顯示問題呢!

image

 

XNA和Silverlight混在一起做瀨尿牛丸是不是很威啊!!

這個也是Silverlight 5 會出現的功能喔!~~希望到時候可以用XNA寫網頁遊戲!!