WPF特效-拼圖遊戲
此文主要描述我實現碎片化的便捷過程。
步驟1:
? ?選取參考圖如下(百度圖庫搜的):
步驟2:
? ?根據效果圖或者模型構建貝塞爾曲線,為了方便查看效果,可以設置控制點,Console.WriteLine或直接UI上顯示的方式記錄最終坐標,效果圖如:
?
?上圖中的紅線,為兩條貝塞爾曲線,左側的位置我已經通過控制點的方式調好。 上圖Gif為我調整上方第二條貝塞爾的示意。
步驟3:
?當上方右側的第二條貝塞爾曲線也調整好後,就已經相當於調整好了所有的四條邊。
? 具體原理為:最上方的一條線繞著最右邊的頂點逆時針旋轉90度即可得到右側的線。右側的線以最下方的點逆時針旋轉90度就是下方的線。左側的線也通過旋轉下方的線得到。唯一需要做的就是抽一個某個點圍繞中心點逆時針旋轉90度後得到新點的函數。
如我的示例代碼,我通過步驟1得到了 上方線的兩條Bezier線的值,直接寫入xaml中。(註:我提前根據步驟一的示例圖,給出了每條Bezier的終點,即Point3)<Canvas Width="448" Height="448" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="160" x:Name="CvMainZm" Background="Transparent"> <Path Stroke="Red" StrokeThickness="1" Fill="Blue" x:Name="Path1Zm"> <Path.Data> <PathGeometry> <PathGeometry.Figures> <PathFigureCollection> <PathFigure StartPoint="96, 96"> <PathFigure.Segments> <PathSegmentCollection> <BezierSegment x:Name="Bezier1Zm" Point1="286 62" Point2="96 176" Point3="224 192"/> <BezierSegment x:Name="Bezier2Zm" Point1="352 176" Point2="162 62" Point3="352 96"/> <BezierSegment x:Name="Bezier3Zm" Point3="448 224"/> <BezierSegment x:Name="Bezier4Zm" Point3="352 352"/> <BezierSegment x:Name="Bezier5Zm" Point3="224 266"/> <BezierSegment x:Name="Bezier6Zm" Point3="96 352"/> <BezierSegment x:Name="Bezier7Zm" Point3="0 224"/> <BezierSegment x:Name="Bezier8Zm" Point3="96 96"/> </PathSegmentCollection> </PathFigure.Segments> </PathFigure> </PathFigureCollection> </PathGeometry.Figures> </PathGeometry> </Path.Data> </Path> </Canvas>
<BezierSegment x:Name="Bezier1Zm" Point1="286 62" Point2="96 176" Point3="224 192"/>
<BezierSegment x:Name="Bezier2Zm" Point1="352 176" Point2="162 62" Point3="352 96"/>
旋轉設置右側線操作:
private void SetRightFirstBezier() { Point oPoint1 = this.Bezier2Zm.Point1; Point oPoint2 = this.Bezier2Zm.Point2; Point oOrigin = this.Bezier2Zm.Point3; Point oNew = this.CarouselPointAnticlockwise(oPoint1, oOrigin); Point oNew2 = this.CarouselPointAnticlockwise(oPoint2, oOrigin); this.Bezier3Zm.Point1 = oNew2; this.Bezier3Zm.Point2 = oNew; } private void SetRightSecondBezier() { Point oPoint1 = this.Bezier1Zm.Point1; Point oPoint2 = this.Bezier1Zm.Point2; Point oOrigin = this.Bezier2Zm.Point3; Point oNew = this.CarouselPointAnticlockwise(oPoint1, oOrigin); Point oNew2 = this.CarouselPointAnticlockwise(oPoint2, oOrigin); this.Bezier4Zm.Point1 = oNew2; this.Bezier4Zm.Point2 = oNew; }
// 繞頂點旋轉得到新點坐標
private Point CarouselPointAnticlockwise(Point oPoint, Point oOrigin)
{
? ? double dY = oOrigin.Y - oPoint.Y;
? ? double dX = oOrigin.X - oPoint.X;
? ? double dXAdd = dX - dY;
? ? double dYAdd = dX + dY;
? ? double dNewX = oPoint.X + dXAdd;
? ? double dNewY = oPoint.Y + dYAdd;
? ? return new Point(dNewX, dNewY);
}
下方和左方以此類推。 這樣通過後臺點旋轉的旋轉計算處理就可得到所有的Bezier。實現效果如下圖。步驟4:
通過步驟3得到的Path與RectangleGeometry進行組合,設置成不同碎片的Clip屬性即可得到所有用到的碎片,效果圖如下:
組合過程中,部分碎片的Clip可通過其他碎片的Clip直接翻轉或者順時針、逆時針旋轉直接得到。如:
?<CombinedGeometry x:Key="KeyPieceType4"?
? ? ? ? ? ? ? ? ? ? ? ? ? Geometry1="{StaticResource KeyPieceType1}">
? ? ? ? ? ? <CombinedGeometry.Transform>
? ? ? ? ? ? ? ? <TransformGroup>
? ? ? ? ? ? ? ? ? ? <ScaleTransform ScaleX="-1" CenterX="224" ScaleY="-1" CenterY="224" />
? ? ? ? ? ? ? ? ? ? <RotateTransform Angle="-90" CenterX="224" CenterY="224"/>
? ? ? ? ? ? ? ? </TransformGroup>
? ? ? ? ? ? </CombinedGeometry.Transform>
? ? ? ? </CombinedGeometry>
步驟5:
可以通過提前設定矩陣碎片樣式的固定模式得到所有切圖,也可以隨機生成每個碎片,每個片的形狀通過檢索左側右邊是否凹凸和上側碎片下邊是否凹凸獲得。我的碎片化效果如下圖。
WPF特效-拼圖遊戲