见缝插针游戏的实现

作者 : 开心源码 本文共3567个字,预计阅读时间需要9分钟 发布时间: 2022-05-12 共127人阅读

游戏的背景:

前言:这个游戏是2015年出来的,刚开始当时aa(见缝插针)游戏很火,我也是玩了好大半天,深深地求虐感屡试不爽。那个时候我还是一个iOS小兵一枚,当时就感觉这游戏如此简单到炸裂,于是就想着尝试实现它,但是…(此处省略100字)。
时间过得真快,过去了两年,偶然翻看博客,发现有人也有类似的实现和想法,并且提供了很好的思路。于是乎,我又下定决心研究一翻,这才有了今天的实现。

游戏的逻辑:

每一关你都有不同数量的“针”,中心的圆盘上初始状态可能就会有“针”已经插入就绪,不过这是为添加游戏难度而设计的。你的任务就是将你所在关卡中所持有的所有“针”插入到中心转动的圆盘上去(插入点是相对固定的),前提是不能与其余“针”相互接触,否则游戏宣告失败。为了不让你很快通关,后面的关卡天经地义难度会越来越大,比方圆盘转速添加、初始就绪“针”数和持有针数添加、顺逆时针变速转动等。

实现思路:

中心的圆盘是一个CAShapeLayer,点击屏幕就去扩展CAShapeLayer的path,达到针插在圆盘上的效果。对于“针”的动态移动过程, 即可以创立一个过渡的“针”视图来等效代替。那么核心的问题就来了:我在扩展图层的路径时,怎样确定绘制的起始点和终点呢?由于在中心圆盘的旋转过程中,其上的个点也会随之一起做仿射变换。假如你在图层旋转时还是以圆盘静止时硬编码取到的起点和终点来确认绘制“针”的话,那么新绘制的“针”就会和之前“插上”的“针”重合在一起,导致的结果就是:无论你怎样“插针”,圆盘上看到的就只有一根“针”,尽管实际上它是很多“针”重叠在一起而体现出来的结果。

CAShapeLayer属于QuartzCore框架,继承自CALayer。CAShapeLayer是在坐标系内绘制贝塞尔曲线的,通过绘制贝塞尔曲线,设置shape(形状)的path(路径),从而绘制各种各样的图形以及不规则图形。因而,用CAShapeLayer需要与UIBezierPath一起用。
UIBezierPath类允许你在自己设置的 View 中绘制和渲染由直线和曲线组成的路径。你可以在初始化的时候直接为你的UIBezierPath指定一个几何图形。
浅显点就是UIBezierPath使用来指定绘制图形路径,而CAShapeLayer就是根据路径来绘图的。

仿射:无论变换矩阵使用什么值,图层中平行的两条线在变换之后依然保持平行。(平移,缩放,旋转等)

1、那么首要问题就是如何得到当前“针”的绘制起点和终点?

值得庆幸的是中心转轴是圆形的(故称之为圆盘),而且也只能是在圆形的情况下才能设计出aa这样的游戏效果。由于插针的起点和终点的计算依赖于圆形的中心到边界各点的距离相等这一性质,具体可以使用如下两张图来表示坐标点的换算过程:

顺时针逆时针

其中的基准点为在静止时“针”的插入点(对应于绘制“针”的起点),而终点可以通过相同的方法来实现换算,只不过半径r的值需要做出相应的调整。
基准点(x’,y’),实际为了计算方便我们取(r,2r)

顺时针旋转诱导公式:
x = x’ + r * sinθ
y = y’ – r + r * cosθ

逆时针旋转诱导公式:
x = x’ – r * sinθ
y = y’ – r + r * cosθ

终点计算,只需把对应的r,换成实际的r就可。
根据公式,我们看出,要想求出针的起点和终点,我们必需知道图层旋转的角度。于是,第二个问题就出来了:

2、如何获得在旋转过程中图层的旋转角度?

我们都知道的是要是涉及到动画的话,图层会将动画的过程交给presentationLayer(体现层)来完成。至于动画的初值和终值之间的中间值则由系统不断计算,并通过体现层来展现。
既然我们选使用的是图层,我们就需要知道它的transform属性是一个名为CATransform3D的结构体变量,而XXView的transform属性是一个名为CGAffineTransform的结构体变量。前者就自然没有a、b这样的成员变量,而是这样的一个矩阵结构:

struct CATransform3D{  CGFloat m11, m12, m13, m14;             CGFloat m21, m22, m23, m24;  CGFloat m31, m32, m33, m34;  CGFloat m41, m42, m43, m44;};通过矩阵控制坐标变换struct CATransform3D{  CGFloat m11(x缩放), m12(y切变), m13(旋转), m14();  CGFloat m21(x切变), m22(y缩放), m23(和m32一起决定x轴的旋转), m24();  CGFloat m31(和m13一起决定y轴的旋转),m32(和m23一起决定x轴的旋转), m33(z缩放), m34(透视效果,要操作的这个对象要有旋转的角度,否则没有效果。正直/负值都有意义);  CGFloat m41(x平移), m42(y平移), m43(z平移), m44(初始为1);};

其中的m14、m24、m34、m44只是作为矩阵的占位符,通常会将m14、m24、m34设置为0,m44设为1。
常见的变化矩阵:

常见的变换矩阵

举例:图层绕Z轴顺时针旋转推导过程

图层绕Z轴旋转推导

矩阵变换:

矩阵变换

    x' = m11 * x + m21 * y + m31 * z + m41    y' = m12 * x + m22 * y + m32 * z + m42    z' = m13 * x + m23 * y + m33 * z + m43    x1 = cosB * x0 - sinB * y0    y1 = sinB * x0 + cosB * y0        cosB   sinB    0    0   -sinB   cosB    0    0      0     0      1    0      0     0      0    1

aa中我们是围绕z轴旋转的,我们即可以用反正切变换函数参入实际参数m21、m22的值即可以实时地知道图层的当前旋转角度了:
三角函数:
tanθ = {sinθ\over cosθ}

θ = atan({sinθ\over cosθ})

θ = atan2({sinθ,cosθ})

  func transformRotationAngle() -> CGFloat {        var degreeAngle:CGFloat = -CGFloat(atan2f(Float(self.presentation()!.transform.m21), Float(self.presentation()!.transform.m22)))        if (degreeAngle < 0.0) {            degreeAngle = degreeAngle + (CGFloat)(2.0 * Double.pi)        }        return degreeAngle;    }

借助于数学诱导公式,坐标的变换计算公式可以统一为如下形式:

 func convertPointWhenRotatingWithBenchmarkPoint(point:CGPoint,radius:CGFloat) -> CGPoint {        let rotationAngle:CGFloat = (self.presentation()?.transformRotationAngle())!        return CGPoint.init(x: point.x + CGFloat(sinf(Float(rotationAngle))) * radius, y: point.y - radius + CGFloat(cosf(Float(rotationAngle))) * radius)    }

在图层的旋转过程中,针的起点和终点都通过以上计算出来了,接着,生成一个贝塞尔曲线,而后追加到整体的贝塞尔曲线中,再赋值给CAShapeLayer(圆盘)的path,这样就达到了针的生成效果。

let strokeBezier = UIBezierPath()strokeBezier.move(to: strokeStartPoint)strokeBezier.addLine(to: strokeEndPoint)strokeBezier.move(to: strokeEndPoint) strokeBezier.addArc(withCenter: strokeEndPoint, radius: kTopRoundRadius, startAngle: 0, endAngle: CGFloat(Double.pi * 2.0), clockwise: true)self.arrowStrokePath.append(strokeBezier)self.centralAxisLayer.path = self.arrowStrokePath.cgPath;

游戏效果:

游戏界面
Github:
SpringAndSummer/Game
参考资料:
https://blog.csdn.net/u013282174/article/details/50388546
https://blog.csdn.net/zmmzxxx/article/details/74276077

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 见缝插针游戏的实现

发表回复