/// <summary> /// 渲染拼图碎片。 /// </summary> protected override void Render() { int idx = CurrentPieces.Count - 1; for (; idx >= 0; idx--) { JigsawPiece piece = CurrentPieces[idx]; if (!piece.Visible) { continue; } brush.Transform = piece.TransformMatrix; this.RenderTarget.FillGeometry(piece.Path, brush); Brush lineBrush = normalBrush; if ((piece.State & JigsawPieceState.Selected) == JigsawPieceState.Selected) { lineBrush = selectedBrush; } else if ((piece.State & JigsawPieceState.Highlight) == JigsawPieceState.Highlight) { lineBrush = highlightBrush; } this.RenderTarget.DrawGeometry(piece.Path, lineBrush, 1); } }
/// <summary> /// 检查当前拼图碎片能否与其它拼图碎片合并。 /// </summary> private void CheckAnchor() { int finished = this.FinishedPercent; lastPiece = pieces.Merge(lastPiece, gameInfo.AnchorRadius); // 移除被合并的拼图碎片。 this.selectedPieces.IntersectWith(pieces); // 吸附到正确的位置。 if (gameInfo.AnchorToBackground && lastPiece.Rotate == 0) { float tx = lastPiece.Offset.X; float ty = lastPiece.Offset.Y; if ((tx * tx + ty * ty) <= gameInfo.AnchorRadius * gameInfo.AnchorRadius) { lastPiece.Frozen = true; lastPiece.Offset = new Vector2(); pieces.BringToBack(lastPiece); } } pieces.CollectInRectangle(renderPanel.JigsawRegion, this.selectedPieces); if (selectedPieces.SingleSelected) { selectedPieces.Clear(); } renderPanel.AutoMouseScroll = false; gameChanged = true; if (this.FinishedPercent != finished) { UpdateFinishedPercent(); } }
/// <summary> /// 鼠标移动。 /// </summary> private void renderPanel_MouseMove(object sender, MouseEventArgs e) { Vector2 loc = renderPanel.PointToJigsaw(e.Location); if (isDraging) { // 拖动被选中的拼图碎片 Drag(loc); lastMousePoint = loc; } else if (isSelecting) { // 选择图片。 if (lastMousePoint.X < loc.X) { selectRect.Left = lastMousePoint.X; selectRect.Right = loc.X; } else { selectRect.Left = loc.X; selectRect.Right = lastMousePoint.X; } if (lastMousePoint.Y < loc.Y) { selectRect.Top = lastMousePoint.Y; selectRect.Bottom = loc.Y; } else { selectRect.Top = loc.Y; selectRect.Bottom = lastMousePoint.Y; } selectedPieces.Clear(); selectedPieces.AddRange(pieces.GetPiece(selectRect)); } else { // 鼠标经过时高亮拼图碎片 if (lastPiece != null) { lastPiece.State &= ~JigsawPieceState.Highlight; } lastPiece = pieces.GetPiece(loc); if (lastPiece != null && !lastPiece.Frozen) { lastPiece.State |= JigsawPieceState.Highlight; } } InvalidateAll(); }
/// <summary> /// 鼠标弹起。 /// </summary> private void renderPanel_MouseUp(object sender, MouseEventArgs e) { renderPanel.Cursor = Cursors.Default; if (e.Button == MouseButtons.Left) { if (isDraging) { // 鼠标弹起,放下拼图碎片。 StopDrag(); CheckAnchor(); } else if (isSelecting) { isSelecting = false; } // 把拼图碎片放到最底层。 if (Control.ModifierKeys == Keys.Control) { if (lastPiece != null) { pieces.BringToBack(lastPiece); } } } else if (e.Button == MouseButtons.Right && gameInfo.Rotatable) { // 右键旋转 Vector2 loc = renderPanel.PointToJigsaw(e.Location); lastPiece = pieces.GetPiece(loc); if (lastPiece != null && !lastPiece.Frozen) { pieces.BringToFront(lastPiece); if (Control.ModifierKeys == Keys.Control) { lastPiece.Rotate = (lastPiece.Rotate + 270) % 360; } else { lastPiece.Rotate = (lastPiece.Rotate + 90) % 360; } CheckAnchor(); } } InvalidateAll(); }
/// <summary> /// 返回指定拼图碎片的阴影位图。 /// </summary> /// <param name="piece">要获取阴影位图的拼图碎片。</param> /// <returns>指定拼图碎片的阴影位图。</returns> private Tuple <Bitmap, Vector2> GetShadow(JigsawPiece piece) { Tuple <Bitmap, Vector2> tuple; if (!shadowCache.TryGetValue(piece.OriginalPath, out tuple)) { // 移除已被释放的拼图碎片。 Geometry disposedGeom = null; if ((disposedGeom = shadowCache.Keys.FirstOrDefault(g => g.IsDisposed)) != null) { shadowCache.Remove(disposedGeom); } RectangleF bounds = piece.OriginalPath.GetBounds(); Size2 size = new Size2((int)bounds.Width + ShadowPadding * 2, (int)bounds.Height + ShadowPadding * 2); using (Bitmap1 source = DeviceManager.CreateBitmap(size)) { Bitmap1 target = DeviceManager.CreateBitmap(size); // 设置特效的输入。 shadowEffect.SetInput(0, source, true); // 阴影的偏移。 Vector2 offset = new Vector2(bounds.Left - ShadowPadding, bounds.Top - ShadowPadding); using (TransformedGeometry tGeom = new TransformedGeometry(this.DeviceContext.Factory, piece.OriginalPath, Matrix3x2.Translation(-offset.X, -offset.Y))) { // 将拼图碎片绘制到位图上。 this.DeviceContext.Target = source; this.DeviceContext.BeginDraw(); this.DeviceContext.Clear(Color.Transparent); this.DeviceContext.FillGeometry(tGeom, blackBrush); this.DeviceContext.EndDraw(); // 将添加特效后的拼图碎片绘制到位图上。 this.DeviceContext.Target = target; this.DeviceContext.BeginDraw(); this.DeviceContext.DrawImage(shadowEffect); this.DeviceContext.EndDraw(); tuple = new Tuple <Bitmap, Vector2>(target, offset); shadowCache.Add(piece.OriginalPath, tuple); } } } return(tuple); }
/// <summary> /// 渲染拼图碎片。 /// </summary> protected override void Render() { int idx = CurrentPieces.Count - 1; bool drawShadow = true; for (; idx >= 0; idx--) { JigsawPiece piece = CurrentPieces[idx]; if (!piece.Visible) { continue; } if ((piece.State & JigsawPieceState.Draging) == JigsawPieceState.Draging && drawShadow) { // 之后的拼图碎片都是拖动状态,绘制阴影。 drawShadow = false; for (int i = idx; i >= 0; i--) { Tuple <Bitmap, Vector2> shadow = GetShadow(CurrentPieces[i]); brush.Bitmap = shadow.Item1; brush.Transform = Matrix3x2.Translation(shadow.Item2) * CurrentPieces[i].TransformMatrix * Matrix3x2.Translation(shadowOffset); RectangleF bounds = CurrentPieces[i].Bounds; this.RenderTarget.FillRectangle(new RectangleF(bounds.X - ShadowPadding, bounds.Y - ShadowPadding, bounds.Width + ShadowPadding * 2, bounds.Height + ShadowPadding * 2), brush); } } this.brush.Bitmap = images[piece.Rotate / 90]; brush.Transform = piece.TransformMatrix; this.RenderTarget.FillGeometry(piece.Path, brush); // 叠加被选择的颜色,仅当没有被拖动时才叠加。 if ((piece.State & JigsawPieceState.Selected) == JigsawPieceState.Selected && (piece.State & JigsawPieceState.Draging) == JigsawPieceState.None) { this.RenderTarget.FillGeometry(piece.Path, selectedBrush); } } }
/// <summary> /// Randomizes the jigsaw pieces. /// </summary> private void RandomizeJigsawPieces() { System.Random rand = new System.Random(); int tileCount = 0; for (int col = 1; col >= -1; col--) { for (int row = -1; row <= 1; row++) { Vector3 origPos = new Vector3(row, col, 0f); int ranPosID = rand.Next(0, _tilePositionList.Count - 1); Vector3 ranPos = _tilePositionList[ranPosID]; JigsawPiece tile = Instantiate(tilePrefab, ranPos, Quaternion.identity); tile.SetSprite(tileSprites[tileSetID].spriteRow[tileCount]); tile.TilePos = new Vector3(row, col, 0f); _tilePositionList.RemoveAt(ranPosID); _tileList.Add(tile); tileCount++; } } }
void OnDrawGizmos() { Gizmos.matrix = transform.localToWorldMatrix; if (generate) { float pieceWidth = width / columns; float pieceHeight = height / rows; JigsawPiece jigBiz = JigsawPiece.GenerateRandom(pieceWidth, pieceHeight, seed); totalVerts = jigBiz.Evaluate(bezierSmoothness * 4).Select(point => point.ToXZVector3()); } if (totalVerts != null) { int drawCount = Mathf.FloorToInt((totalVerts.Count() + 1) * percentDrawn); for (int i = 1; i < drawCount; i++) { Gizmos.color = new Color(0, ((float)i) / (totalVerts.Count() - 1), 0); var prevIndex = (i - 1) % totalVerts.Count(); var currentIndex = i % totalVerts.Count(); var start = totalVerts.ElementAt(prevIndex); var end = totalVerts.ElementAt(currentIndex); Gizmos.DrawLine(start, end); } } }
/// <summary> /// 鼠标按下。 /// </summary> private void renderPanel_MouseDown(object sender, MouseEventArgs e) { isSelecting = false; if (e.Button == MouseButtons.Left) { lastMousePoint = renderPanel.PointToJigsaw(e.Location); lastPiece = pieces.GetPiece(lastMousePoint); if (lastPiece != null && lastPiece.Frozen) { lastPiece = null; } if (lastPiece == null) { selectedPieces.Clear(); isSelecting = true; selectRect = new RectangleF(lastMousePoint.X, lastMousePoint.Y, 0f, 0f); } else { renderPanel.Cursor = Cursors.Hand; if (!selectedPieces.Contains(lastPiece)) { // 拖动单个拼图碎片 selectedPieces.Clear(); selectedPieces.Add(lastPiece); } StartDrag(); renderPanel.AutoMouseScroll = true; } } else { selectedPieces.Clear(); } InvalidateAll(); }