溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

WPF+SkiaSharp怎么實(shí)現(xiàn)自繪投籃小游戲

發(fā)布時(shí)間:2022-08-05 14:14:40 來源:億速云 閱讀:148 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹了WPF+SkiaSharp怎么實(shí)現(xiàn)自繪投籃小游戲的相關(guān)知識,內(nèi)容詳細(xì)易懂,操作簡單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇WPF+SkiaSharp怎么實(shí)現(xiàn)自繪投籃小游戲文章都會有所收獲,下面我們一起來看看吧。

    投籃小游戲

    規(guī)則,點(diǎn)擊投籃目標(biāo)點(diǎn),就會有一個(gè)球沿著相關(guān)拋物線,然后,判斷是否進(jìn)入籃子里,其實(shí)就是一個(gè)矩形,直接是按照碰撞檢測來的,碰到就算進(jìn)去了,對其增加了一個(gè)分?jǐn)?shù)統(tǒng)計(jì)等功能。

    Wpf 和 SkiaSharp

    新建一個(gè) WPF 項(xiàng)目,然后,Nuget 包即可

    要添加 Nuget 包

    Install-Package SkiaSharp.Views.WPF -Version 2.88.0

    其中核心邏輯是這部分,會以我設(shè)置的 60FPS 來刷新當(dāng)前的畫板。

    skContainer.PaintSurface += SkContainer_PaintSurface;
    _ = Task.Run(() =>
    {
        while (true)
        {
            try
            {
                Dispatcher.Invoke(() =>
                {
                    skContainer.InvalidateVisual();
                });
                _ = SpinWait.SpinUntil(() => false, 1000 / 60);//每秒60幀
            }
            catch
            {
                break;
            }
        }
    });

    彈球?qū)嶓w代碼 (Ball.cs)

    public class Ball
    {
        public double X { get; set; }
        public double Y { get; set; }
        public double VX { get; set; }
        public double VY { get; set; }
        public int Radius { get; set; }
    }

    粒子花園核心類 (ParticleGarden.cs)

    /// <summary>
    /// 光線投影法碰撞檢測
    /// 投籃小游戲
    /// </summary>
    public class RayProjection
    {
        public SKPoint centerPoint;
        public double G = 0.3;
        public double F = 0.98;
        public double Easing = 0.03;
        public bool IsMoving = false;
        public SKPoint CurrentMousePoint = SKPoint.Empty;
        public SKPoint lastPoint = SKPoint.Empty;
        public Rect Box;
        public Ball Ball;
        public SKCanvas canvas;
        public int ALLCount = 10;
        public List<bool> bools = new List<bool>();
        public bool IsOver = false;
        /// <summary>
        /// 渲染
        /// </summary>
        public void Render(SKCanvas canvas, SKTypeface Font, int Width, int Height)
        {
            canvas.Clear(SKColors.White);
            this.canvas = canvas;
            centerPoint = new SKPoint(Width / 2, Height / 2);
            //球
            if (Ball == null)
            {
                Ball = new Ball()
                {
                    X = 50,
                    Y = Height - 50,
                    Radius = 30
                };
            }
            //箱子
            var boxX = Width - 170;
            var boxY = Height - 80;
            if (Box.X == 0)
            {
                Box = new Rect(boxX, boxY, 120, 70);
            }
            else
            {
                if (Box.X != boxX && Box.Y != boxY)
                {
                    Box.X = boxX;
                    Box.Y = boxY;
                }
            }
    
            if (bools.Count >= ALLCount)
            {
                IsOver = true;
            }
    
            if (!IsOver)
            {
                if (IsMoving)
                {
                    BallMove(Width, Height);
                }
                else
                {
                    DrawLine();
                }
    
                //彈球
                DrawCircle(canvas, Ball);
                //矩形
                DrawRect(canvas, Box);
    
                //計(jì)分
                using var paint1 = new SKPaint
                {
                    Color = SKColors.Blue,
                    IsAntialias = true,
                    Typeface = Font,
                    TextSize = 24
                };
                string count = $"總次數(shù):{ALLCount} 剩余次數(shù):{ALLCount - bools.Count} 投中次數(shù):{bools.Count(t => t)}";
                canvas.DrawText(count, 100, 20, paint1);
            }
            else
            {
                SKColor sKColor = SKColors.Blue;
                //計(jì)分
                var SuccessCount = bools.Count(t => t);
                string count = "";
                switch (SuccessCount)
                {
                    case 0:
                        {
                            count = $"太糗了吧,一個(gè)都沒投中!";
                            sKColor = SKColors.Black;
                        }
                        break;
                    case 1:
                    case 2:
                    case 3:
                    case 4:
                    case 5:
                        {
                            count = $"你才投中:{SuccessCount}次,繼續(xù)努力!";
                            sKColor = SKColors.Blue;
                        }
                        break;
                    case 6:
                    case 7:
                    case 8:
                    case 9:
                        {
                            count = $"恭喜 投中:{SuccessCount}次!!!";
                            sKColor = SKColors.YellowGreen;
                        }
                        break;
                    case 10: { count = $"全部投中,你太厲害了!";
                            sKColor = SKColors.Red;
                        } break;
                }
                using var paint1 = new SKPaint
                {
                    Color = sKColor,
                    IsAntialias = true,
                    Typeface = Font,
                    TextSize = 48
                };
                var fontCenter = paint1.MeasureText(count);
                canvas.DrawText(count, centerPoint.X - fontCenter / 2, centerPoint.Y, paint1);
            }
            using var paint = new SKPaint
            {
                Color = SKColors.Blue,
                IsAntialias = true,
                Typeface = Font,
                TextSize = 24
            };
            string by = $"by 藍(lán)創(chuàng)精英團(tuán)隊(duì)";
            canvas.DrawText(by, 600, 20, paint);
        }
        /// <summary>
        /// 畫一個(gè)圓
        /// </summary>
        public void DrawCircle(SKCanvas canvas, Ball ball)
        {
            using var paint = new SKPaint
            {
                Color = SKColors.Blue,
                Style = SKPaintStyle.Fill,
                IsAntialias = true,
                StrokeWidth = 2
            };
            canvas.DrawCircle((float)ball.X, (float)ball.Y, ball.Radius, paint);
        }
        /// <summary>
        /// 畫一個(gè)矩形
        /// </summary>
        public void DrawRect(SKCanvas canvas, Rect box)
        {
            using var paint = new SKPaint
            {
                Color = SKColors.Green,
                Style = SKPaintStyle.Fill,
                IsAntialias = true,
                StrokeWidth = 2
            };
            canvas.DrawRect((float)box.X, (float)box.Y, (float)box.Width, (float)box.Height, paint);
        }
        /// <summary>
        /// 劃線
        /// </summary>
        public void DrawLine()
        {
            //劃線
            using var LinePaint = new SKPaint
            {
                Color = SKColors.Red,
                Style = SKPaintStyle.Fill,
                StrokeWidth = 2,
                IsStroke = true,
                StrokeCap = SKStrokeCap.Round,
                IsAntialias = true
            };
            var path = new SKPath();
            path.MoveTo((float)CurrentMousePoint.X, (float)CurrentMousePoint.Y);
            path.LineTo((float)Ball.X, (float)Ball.Y);
            path.Close();
            canvas.DrawPath(path, LinePaint);
        }
        public void BallMove(int Width, int Height)
        {
            Ball.VX *= F;
            Ball.VY *= F;
            Ball.VY += G;
    
            Ball.X += Ball.VX;
            Ball.Y += Ball.VY;
    
            var hit = CheckHit();
            // 邊界處理和碰撞檢測
            if (hit || Ball.X - Ball.Radius > Width || Ball.X + Ball.Radius < 0 || Ball.Y - Ball.Radius > Height || Ball.Y + Ball.Radius < 0)
            {
                bools.Add(hit);
                IsMoving = false;
                Ball.X = 50;
                Ball.Y = Height - 50;
            }
    
            lastPoint.X = (float)Ball.X;
            lastPoint.Y = (float)Ball.Y;
        }
        public bool CheckHit()
        {
            var k1 = (Ball.Y - lastPoint.Y) / (Ball.X - lastPoint.X);
            var b1 = lastPoint.Y - k1 * lastPoint.X;
            var k2 = 0;
            var b2 = Ball.Y;
            var cx = (b2 - b1) / (k1 - k2);
            var cy = k1 * cx + b1;
            if (cx - Ball.Radius / 2 > Box.X && cx + Ball.Radius / 2 < Box.X + Box.Width && Ball.Y - Ball.Radius > Box.Y)
            {
                return true;
            }
            return false;
        }
        public void MouseMove(SKPoint sKPoint)
        {
            CurrentMousePoint = sKPoint;
        }
        public void MouseDown(SKPoint sKPoint)
        {
            CurrentMousePoint = sKPoint;
        }
        public void MouseUp(SKPoint sKPoint)
        {
            if (bools.Count < ALLCount)
            {
                IsMoving = true;
                Ball.VX = (sKPoint.X - Ball.X) * Easing;
                Ball.VY = (sKPoint.Y - Ball.Y) * Easing;
                lastPoint.X = (float)Ball.X;
                lastPoint.Y = (float)Ball.Y;
            }
        }
    }

    效果如下

    WPF+SkiaSharp怎么實(shí)現(xiàn)自繪投籃小游戲

    關(guān)于“WPF+SkiaSharp怎么實(shí)現(xiàn)自繪投籃小游戲”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“WPF+SkiaSharp怎么實(shí)現(xiàn)自繪投籃小游戲”知識都有一定的了解,大家如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道。

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI