搜尋此網誌

2010年1月20日 星期三

Silverlight & Game:Puzzlies - Part 1

寫個Puzzlies小遊戲吧!
遊戲內容非常單純,移動3 x 3或 N x N的圖片區塊,恢復為完整的圖即成功。

本篇內容,先建立Puzzles的骨架及基本動作,其中我們一共會建立兩個 .xaml檔及一個.cs檔,另外需匯入一張圖片,檔案名稱如下:
 a. MainPage.xaml
 b. imageBox.xaml
 c. myRecorder.cs
 d. 圖片:imgs/Orz.png
(置於 imgs 資料夾之下)

1.建立一個新的Silverlight Applciation專案,在這裡我將專案名稱命為「ImageClip_Puzzlies」,以下為完整MainPage.xaml內容:

<UserControl x:Class="ImageClip_Puzzles.MainPage"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480" Loaded="loadImg">
 <Grid  Background="Gray" Width="500" Height="500"
    VerticalAlignment="Center" HorizontalAlignment="Center" >
  <Grid x:Name="PuzzlesTop" >
   <Grid.ColumnDefinitions>
    <ColumnDefinition Width="10"/>
    <ColumnDefinition Width="*"/>
    <ColumnDefinition Width="10"/>
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
   <RowDefinition Height="10"/>
   <RowDefinition Height="*"/>
   <RowDefinition Height="10"/>
  </Grid.RowDefinitions>
   <Grid Grid.Column="1" Grid.Row="1">
    <Rectangle Fill="Black"/>
   </Grid>
  </Grid>
  <TextBlock Text="sys" x:Name="sysMsg" FontSize="12"
      VerticalAlignment="Top" HorizontalAlignment="Center">
   <TextBlock.RenderTransform>
    <TranslateTransform X="0" Y="-20"/>
   </TextBlock.RenderTransform>
  </TextBlock>
 </Grid>    
</UserControl>

2.接著是imageBox.xaml的內容:

<UserControl x:Class="ImageClip_Puzzles.imageBox"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

 Width="Auto" Height="Auto" x:Name="imageTop"  >    
 <Canvas Height="600" Width="600" x:Name="imageCanvas">
  <Canvas.Resources>
   <Storyboard x:Name="moveImage_Direct_Up" SpeedRatio="5">
    <DoubleAnimation x:Name="UpAnima"
     Storyboard.TargetName="imageGrid"
     Storyboard.TargetProperty="(Canvas.Top)"
     From="0" To="0" Duration="0:0:1"  AutoReverse="False"/>
    <DoubleAnimation x:Name="borderAnima_Up"
     Storyboard.TargetName="imageBorder"
     Storyboard.TargetProperty="(Border.RenderTransform).Y"
     From="0" To="0" Duration="0:0:1" AutoReverse="False"/>
   </Storyboard>
   <Storyboard x:Name="moveImage_Direct_Left" SpeedRatio="5">
    <DoubleAnimation x:Name="LeftAnima"
     Storyboard.TargetName="imageGrid"
     Storyboard.TargetProperty="(Canvas.Left)"
     From="0" To="0" Duration="0:0:1"  AutoReverse="False"/>

    <DoubleAnimation x:Name="borderAnima_Left"
     Storyboard.TargetName="imageBorder"
     Storyboard.TargetProperty="(Border.RenderTransform).X"
     From="0" To="0" Duration="0:0:1" AutoReverse="False"/>
   </Storyboard>
  </Canvas.Resources>
  <Grid Canvas.Top="0" Canvas.Left="0"
   Width="480" Height="480" x:Name="imageGrid" >
   <Image Source="imgs/Orz.png" Stretch="Fill" x:Name="imageContent">
    <Image.Clip>
     <RectangleGeometry Rect="0,0,160,160 " >
     <RectangleGeometry.Transform>
      <TranslateTransform X="0" Y="0" x:Name="ImageAreaTransform"/>
     </RectangleGeometry.Transform>
     </RectangleGeometry>
    </Image.Clip>
   </Image>
  </Grid>
  <Border BorderBrush="#FF666666" BorderThickness="5" x:Name="imageBorder">
   <Border.RenderTransform>
    <TranslateTransform X="0" Y="0" x:Name="boardPosition"/>
   </Border.RenderTransform>
   <Rectangle x:Name="imageColor"
    Width="155" Height="155" Fill="Red" Opacity="0.01"/>
  </Border>
  <Grid Visibility="Visible">
   <Grid.RenderTransform>
    <TranslateTransform X="5" Y="10" x:Name="msgPos"/>
   </Grid.RenderTransform>
   <Grid.RowDefinitions>

    <RowDefinition Height="14"/>
    <RowDefinition Height="14"/>
    <RowDefinition Height="14"/>
    <RowDefinition Height="14"/>
    <RowDefinition Height="14"/>
   </Grid.RowDefinitions>
   <TextBlock x:Name="imgSysMsg1" Text="" FontSize="12" Grid.Row="0"/>
   <TextBlock x:Name="imgSysMsg2" Text="" FontSize="12" Grid.Row="1"/>
   <TextBlock x:Name="imgSysMsg3" Text="" FontSize="12" Grid.Row="2"/>
   <TextBlock x:Name="imgSysMsg4" Text="" FontSize="12" Grid.Row="3"/>
   <TextBlock x:Name="imgSysMsg5" Text="" FontSize="12" Grid.Row="4"/>
  </Grid>
 </Canvas>
</UserControl>


3.別忘了 mainPage.xamlimageBox.xaml的 .cs內容:

mainPage.xaml

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace ImageClip_Puzzles
{
 public partial class MainPage : UserControl
 {
  private void SysMsg(string msg)
  {
   sysMsg.Text = msg;
  }
  int gridNum = 3;
  int imageSize = 160;
  Point[,] imagePos;
  imageBox[] IBArray;

  public MainPage()
  {
   InitializeComponent();
  }
  private void loadImg(object sender, RoutedEventArgs e)
  {
   imagePos = new Point[gridNum, gridNum];
   IBArray = new imageBox[gridNum * gridNum];
   for (int i = 0; i < gridNum; i++)
   {
    for (int j = 0; j < gridNum; j++)
    {
     imageBox ib = new imageBox();
     int indexOfAll = i * gridNum + j;
     IBArray[indexOfAll] = ib;

     ib.MouseLeftButtonDown += onImageClick;
     ib.moveImage_Direct_Up.Completed += moveIsFinish;
     ib.moveImage_Direct_Left.Completed += moveIsFinish;

     ib.setInfo(indexOfAll,i, j, gridNum, imageSize);
     PuzzlesTop.Children.Add(ib);
     ib.setGridPosition(1, 1);
     imagePos[i, j] =
      new Point(j * imageSize, i * imageSize);
}
}
BArray[0].setImageColor(0xFF, 0x00, 0x00);
}
bool imgIsMoving = false;
private void onImageClick(object sender, MouseButtonEventArgs e)
{
SysMsg("imgIsMoving : " + imgIsMoving.ToString());
if (imgIsMoving) return;
imgIsMoving = true;
imageBox uc = sender as imageBox;
string dir = getPic1(IBArray[uc.indexOfAllIBArray].rowIndex,
IBArray[uc.indexOfAllIBArray].colIndex);
uc.moveImageTo(dir);
switch (dir)
{
case "up":
IBArray[0].moveImageTo("down");
break;
case "down":
IBArray[0].moveImageTo("up");
break;
case "left":
IBArray[0].moveImageTo("right");
break;
case "right":
IBArray[0].moveImageTo("left");
break;
default:
imgIsMoving = false;
break;
}
}
private void moveIsFinish(object sender, EventArgs e)
{
Storyboard sb = (Storyboard)sender;
imageBox tmpImageBox =
(imageBox) sb.GetValue(myRecorder.record_ImageBox);
if (tmpImageBox.indexOfAllIBArray == 0) return;
int tmpRIndex = tmpImageBox.rowIndex;
int tmpCIndex = tmpImageBox.colIndex;

tmpImageBox.resetCurrentPosition(IBArray[0].rowIndex,
IBArray[0].colIndex);
IBArray[0].resetCurrentPosition(tmpRIndex, tmpCIndex);

imgIsMoving = false;
}
private string getPic1(int r, int c)
{
if (((r - 1) == IBArray[0].rowIndex)
&& (c == IBArray[0].colIndex))
// at down of Pic0 - - -> (r-1,c) then the imagemove 'up'
{
return "up";
}
else if (((r + 1) == IBArray[0].rowIndex)
&& (c == IBArray[0].colIndex))
//at top of Pic0 - - -> (r+1,c) then the image move 'down'
{
return "down";
}
else if ((r == IBArray[0].rowIndex)
&& ((c-1) == IBArray[0].colIndex))
//at right of Pic0 - - -> (r,c-1) then the image move 'left'
{
return "left";
}
else if ((r == IBArray[0].rowIndex)
&& ((c + 1) == IBArray[0].colIndex))
{
return "right";
}
else
{
return "stay";
}
}
private void showImageBoxMsg(imageBox ib)
{
ib.SysMsg("ib name : " + ib.Name,
    ", indexOfArrlyIBArray : " + ib.indexOfAllIBArray.ToString(),
    ", IBArray postion on " + ib.indexOfAllIBArray.ToString(),
    ", rowIndex : " + IBArray[ib.indexOfAllIBArray].rowIndex.ToString(),
    ", cowIndex : " + IBArray[ib.indexOfAllIBArray].colIndex.ToString());
}
}
} 


imageBox.xaml

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace ImageClip_Puzzles
{
public partial class imageBox : UserControl
{
 int separaNum = 3;
 int imgSize = 160;
 public int rowIndex = 0;
 public int colIndex = 0;
 public int orgiRowIndex = 0;
 public int orgiColIndex = 0;
 public int indexOfAllIBArray = 99;

 Point currentBorderPosition = new Point();
 public imageBox()
 {
  InitializeComponent();
 }
 public void setInfo(int indexOfArray,int rIndex,
      int cIndex,int separateNum,int imageSize)
 {
  indexOfAllIBArray = indexOfArray;
  separaNum = separateNum;
  imgSize = imageSize;
  imageUV(rIndex, cIndex);
  this.Name =
   "R(" + rIndex.ToString() + ")C(" + cIndex.ToString() + ")";
  rowIndex = rIndex;
  colIndex = cIndex;
  orgiRowIndex = rIndex;
  orgiColIndex = cIndex;
  animaRecordInfo(indexOfArray);
 }
 private void animaRecordInfo(int index)//, string name)
 {
  moveImage_Direct_Up.SetValue(myRecorder.record_ImageBox, this);
  moveImage_Direct_Left.SetValue(myRecorder.record_ImageBox, this);
 }
 private void imageUV(int indexU,int indexV)
 {
  ImageAreaTransform.X = indexV * 160;
  ImageAreaTransform.Y = indexU * 160;
  this.boardPosition.X = ImageAreaTransform.X;
  this.boardPosition.Y = ImageAreaTransform.Y;
  currentBorderPosition =
     new Point(ImageAreaTransform.X,ImageAreaTransform.Y);
  msgPos.X = ImageAreaTransform.X;
  msgPos.Y = ImageAreaTransform.Y;
 }
 public void setGridPosition(int rowIndex, int colIndex)
 {
  this.SetValue(Grid.RowProperty, rowIndex);
  this.SetValue(Grid.ColumnProperty, colIndex);
 }
 public void setImageColor(byte r, byte g, byte b)
 {
  Color c = Color.FromArgb(255, r, g, b);
  imageColor.Fill = new SolidColorBrush(c);
  imageColor.Opacity = 0.7;
 }
 public void SysMsg(string msg)
 {
  imgSysMsg1.Text = msg;
 }
 public void SysMsg(string msg1, string msg2)
 {
  imgSysMsg1.Text = msg1;
  imgSysMsg2.Text = msg2;
 }
 public void SysMsg(string msg1, string msg2, string msg3)
 {
  imgSysMsg1.Text = msg1;
  imgSysMsg2.Text = msg2;
  imgSysMsg3.Text = msg3;
 }
 public void SysMsg(string msg1, string msg2,
           string msg3, string msg4)
 {
  imgSysMsg1.Text = msg1;
  imgSysMsg2.Text = msg2;
  imgSysMsg3.Text = msg3;
  imgSysMsg4.Text = msg4;
 }
 public void SysMsg(string msg1, string msg2,
           string msg3, string msg4, string msg5)
 {
  imgSysMsg1.Text = msg1;
  imgSysMsg2.Text = msg2;
  imgSysMsg3.Text = msg3;
  imgSysMsg4.Text = msg4;
  imgSysMsg5.Text = msg5;
 }
 public void moveImageTo(string dir)
 {
  SysMsg("");
  switch (dir)
  {
   case "up":
    this.UpAnima.From =
     Convert.ToDouble( imageGrid.GetValue(Canvas.TopProperty));
    this.UpAnima.To = this.UpAnima.From - imgSize;
    this.borderAnima_Up.From = this.boardPosition.Y;
    this.currentBorderPosition.Y -= imgSize;
    this.borderAnima_Up.To = this.currentBorderPosition.Y;
    this.moveImage_Direct_Up.Begin();
    break;
   case "down":
    this.UpAnima.From =
     Convert.ToDouble(imageGrid.GetValue(Canvas.TopProperty));
    this.UpAnima.To = this.UpAnima.From + imgSize;
    this.borderAnima_Up.From = this.currentBorderPosition.Y;
    this.currentBorderPosition.Y += imgSize;
    this.borderAnima_Up.To = this.currentBorderPosition.Y;
    this.moveImage_Direct_Up.Begin();
    break;
   case "left":
    this.LeftAnima.From =
     Convert.ToDouble(imageGrid.GetValue(Canvas.LeftProperty));
    this.LeftAnima.To = this.LeftAnima.From - imgSize;
    this.borderAnima_Left.From = this.currentBorderPosition.X;
    this.currentBorderPosition.X -= imgSize;
    this.borderAnima_Left.To = this.currentBorderPosition.X;
    this.moveImage_Direct_Left.Begin();
    break;
   case "right":
    this.LeftAnima.From = Convert.ToDouble(imageGrid.GetValue(Canvas.LeftProperty));
    this.LeftAnima.To = this.LeftAnima.From + 160;
    this.borderAnima_Left.From =
      this.currentBorderPosition.X;
    this.currentBorderPosition.X += imgSize;
    this.borderAnima_Left.To =
      this.currentBorderPosition.X;
    this.moveImage_Direct_Left.Begin();
    break;
   default:
    SysMsg("default in dir");
    break;
  }
  msgPos.X = this.currentBorderPosition.X + 5;
  msgPos.Y = this.currentBorderPosition.Y + 10;


 }
 public void resetCurrentPosition(int r,int c)
 {
  this.rowIndex = r;
  this.colIndex = c;
 showInfo();
 }
 public void showInfo()
 {
  SysMsg("boardPosition(X,Y): (" + this.boardPosition.X.ToString() +
    ","+ this.boardPosition.Y.ToString() +")",
   "TopLeft: (" + imageGrid.GetValue(Canvas.TopProperty).ToString() +
   "," + imageGrid.GetValue(Canvas.LeftProperty).ToString() ,
   "RowIndex : " + this.rowIndex.ToString(),
   "ColIndex : " + this.colIndex.ToString(),
   "name : "+this.Name);
 }
}
}


4.最後是 myRecorder.cs 的內容:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace ImageClip_Puzzles
{
 public class myRecorder
 {
  public static readonly DependencyProperty record_ImageBox =
   DependencyProperty.RegisterAttached(
    "recordImageBox",
    typeof(imageBox),
    typeof(myRecorder),
    null);
  public static void recordImageBox(DependencyObject obj,
                   imageBox ib)
  {
   obj.SetValue(record_ImageBox, ib);
  }
  public static imageBox readImageBox(DependencyObject obj)
  {
   return (imageBox)obj.GetValue(record_ImageBox);
  }
 }
}


先前已有介紹如何在Silverlight元件裡額外加入一個屬性,「myRecorder.cs」的內容即新增的屬性的Class。

就本篇內容來說,遊戲時「圖片區塊的移動」的動作已寫好。此外為了除蟲方便,程式中加入了「SysMsg」Function,執行時我們能夠簡單看到目前圖片位置的屬性值。



執行結果

沒有留言:

張貼留言