遊戲內容非常單純,移動3 x 3或 N x N的圖片區塊,恢復為完整的圖即成功。
本篇內容,先建立Puzzles的骨架及基本動作,其中我們一共會建立兩個 .xaml檔及一個.cs檔,另外需匯入一張圖片,檔案名稱如下:
a. MainPage.xaml
b. imageBox.xaml
c. myRecorder.cs
d. 圖片:imgs/Orz.png
1.建立一個新的Silverlight Applciation專案,在這裡我將專案名稱命為
<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.接著是
<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.別忘了
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());
    }
  }
} 
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.最後是
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,執行時我們能夠簡單看到目前圖片位置的屬性值。
執行結果
 

沒有留言:
張貼留言