WPF+SkiaSharp实现自绘投篮小游戏
作者:蓝创精英团队 时间:2023-09-06 22:59:51
投篮小游戏
规则,点击投篮目标点,就会有一个球沿着相关抛物线,然后,判断是否进入篮子里,其实就是一个矩形,直接是按照碰撞检测来的,碰到就算进去了,对其增加了一个分数统计等功能。
Wpf 和 SkiaSharp
新建一个 WPF 项目,然后,Nuget 包即可
要添加 Nuget 包
Install-Package SkiaSharp.Views.WPF -Version 2.88.0
其中核心逻辑是这部分,会以我设置的 60FPS 来刷新当前的画板。
skContainer.PaintSurface += SkContainer_PaintSurface;
_ = Task.Run(() =>
{
while (true)
{
try
{
Dispatcher.Invoke(() =>
{
skContainer.InvalidateVisual();
});
_ = SpinWait.SpinUntil(() => false, 1000 / 60);//每秒60帧
}
catch
{
break;
}
}
});
弹球实体代码 (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);
//计分
using var paint1 = new SKPaint
{
Color = SKColors.Blue,
IsAntialias = true,
Typeface = Font,
TextSize = 24
};
string count = $"总次数:{ALLCount} 剩余次数:{ALLCount - bools.Count} 投中次数:{bools.Count(t => t)}";
canvas.DrawText(count, 100, 20, paint1);
}
else
{
SKColor sKColor = SKColors.Blue;
//计分
var SuccessCount = bools.Count(t => t);
string count = "";
switch (SuccessCount)
{
case 0:
{
count = $"太糗了吧,一个都没投中!";
sKColor = SKColors.Black;
}
break;
case 1:
case 2:
case 3:
case 4:
case 5:
{
count = $"你才投中:{SuccessCount}次,继续努力!";
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 蓝创精英团队";
canvas.DrawText(by, 600, 20, paint);
}
/// <summary>
/// 画一个圆
/// </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>
/// 画一个矩形
/// </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;
}
}
}
效果如下
还不错,得了7分,当然,我也可以得10分的,不过,还好了。
来源:https://www.cnblogs.com/kesshei/p/16552463.html
标签:WPF,SkiaSharp,投篮,游戏
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
分享一个Android设置圆形图片的特别方法
2022-06-27 23:17:27
![](https://img.aspxhome.com/file/2023/7/111687_0s.png)
mybatis中<choose>标签的用法说明
2023-07-22 19:37:27
![](https://img.aspxhome.com/file/2023/5/132185_0s.png)
快速了解Java中NIO核心组件
2023-01-01 12:21:13
![](https://img.aspxhome.com/file/2023/8/91538_0s.jpg)
OpenHarmony实现屏幕亮度动态调节方法详解
2022-01-13 18:24:08
Java中Excel高效解析工具EasyExcel的实践
2023-05-28 13:36:38
![](https://img.aspxhome.com/file/2023/9/86059_0s.webp)
Java生成二维码可添加logo和文字功能
2021-06-23 22:24:35
Android之利用EventBus发送消息传递示例
2022-11-02 08:25:21
![](https://img.aspxhome.com/file/2023/0/129040_0s.gif)
C#实现简单记事本程序
2022-07-20 23:52:37
![](https://img.aspxhome.com/file/2023/7/83237_0s.jpg)
Android之在linux终端执行shell脚本直接打印当前运行app的日志的实现方法
2021-06-12 23:41:08
java实现电话本管理系统
2023-10-11 14:51:19
![](https://img.aspxhome.com/file/2023/1/84301_0s.png)
Android开发新手常见的10个误区
2021-07-30 02:14:10
SpringBoot整合Web开发之Json数据返回的实现
2023-04-27 05:06:51
![](https://img.aspxhome.com/file/2023/9/61639_0s.png)
Unity3D应用之时钟与钟表小组件的使用教程
2023-05-15 04:43:35
![](https://img.aspxhome.com/file/2023/1/91361_0s.png)
深入理解Java虚拟机体系结构
2021-09-15 19:46:53
![](https://img.aspxhome.com/file/2023/6/62366_0s.png)
完美解决springboot中使用mybatis字段不能进行自动映射的问题
2023-07-27 00:41:35
![](https://img.aspxhome.com/file/2023/7/61157_0s.png)
Gradle的使用教程详解
2022-08-12 05:02:11
![](https://img.aspxhome.com/file/2023/0/84220_0s.png)
Android WebView如何判定网页加载的错误
2023-09-22 14:33:20
![](https://img.aspxhome.com/file/2023/1/103911_0s.png)
java如何获得redis所有的key-value
2022-03-13 12:22:14
![](https://img.aspxhome.com/file/2023/3/60823_0s.jpg)
Android中AsyncTask与handler用法实例分析
2023-12-04 00:01:52
![](https://img.aspxhome.com/file/2023/8/88128_0s.png)
C#实现读写ini文件类实例
2023-09-06 18:47:00