我目前正在使用 Swift 在iOS中创建一个Hangman游戏应用程序。

我已经完成了所有的游戏机制,并希望使用Core Graphics来绘制绞刑罚和绞刑架。我可以使用UIBezierPath绘制绞刑架和绞刑架,并将视图各部分(绞刑架,头部,身体,左臂等)的绘制分解为多个单独的函数,以创建整个图像。所有这些都在自定义UIView类中。

我似乎无法弄清楚的是,当用户做出错误的猜测时,如何添加Hangman图像的连续部分。我正在尝试避免在一系列图像之间循环。相反,我想使用相同的自定义视图通过Core Graphics逐段绘制简笔画。

如何实现绘制图的每个连续部分的功能?

诸如“self.customView.updateDrawing()”之类的东西,其中customView中的updateDrawing方法将从模型中获取有关不正确猜测数量的信息,并调用适当的方法来绘制简笔画的所需部分。

更新

这是我尝试将https://codereview.stackexchange.com/questions/97424/hangman-in-swift帖子中的视图实现到我自己的子手游戏中。它们非常适合绘制绞刑架,但实际上我无法让图像进行自我更新并绘制连续的身体部位以添加绞刑man。到目前为止,这是我的代码:

GameViewTwo:这是上面发布的GameView,我试图将其拆分并添加不同的部分作为视图的层。

 import UIKit

enum BodyPart: Int {
    case Head = 1
    case Body = 2
    case LeftArm = 5
    case RightArm = 6
    case LeftLeg = 3
    case RightLeg = 4
    case LeftEye = 7
    case RightEye = 8
    case Mouth = 9
    case Unknown = 10
}


class GameViewTwo: UIView {

    var path = UIBezierPath()
    var newPartLayer = CAShapeLayer()

    private var bodyStart: CGPoint = CGPoint.zero
    private var bodyEnd: CGPoint = CGPoint.zero
    private var headMiddle: CGPoint = CGPoint.zero

    struct DrawingConstants {
        static let gallowBaseStartScale: CGFloat = 0.15
        static let gallowBaseEndScale: CGFloat = 0.85
        static let gallowBaseHeight: CGFloat = 10
        static let gallowHeight: CGFloat = 0.05        //static let gallowHeight: CGFloat = 0.15
        static let gallowHeightStart: CGFloat = 0.175
        static let gallowHeightWidth: CGFloat = 10
        static let gallowAcrossScale: CGFloat = 0.5
        static let gallowTipHeight: CGFloat = 17.5
        static let headRadius: CGFloat = 16
        static let bodyLength: CGFloat = 25
        static let bodyHeight: CGFloat = 25
        static let legLength: CGFloat = 50
        static let grassHeightScale: CGFloat = 0.68
        static let armBack: CGFloat = 5
    }

    struct ScaleConstants {
        static let bodyLength: CGFloat = 50
        static let limbLength: CGFloat = 25
        static let handHeightScale: CGFloat = 0.4
        static let headRadius: CGFloat = 20
        static let eyeRadius = CGFloat(0.15 * ScaleConstants.headRadius)
        static let eyeOffset = CGFloat(0.3 * ScaleConstants.headRadius)
        static let mouthOffSet = CGFloat(0.3 * ScaleConstants.headRadius)
        static let mouthRadius = CGFloat(0.25 * ScaleConstants.headRadius)
    }

    var part : BodyPart?

    func setPart(part: BodyPart){
        self.part = part
    }


    // Only override draw() if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func draw(_ rect: CGRect) {
        // Drawing code
        drawGallow()

    }


    func add(part: BodyPart){

        let partPath = path(forPart: part)
        newPartLayer.frame = bounds
        newPartLayer.path = partPath.cgPath
        newPartLayer.strokeColor = UIColor.black.cgColor
        let strokeAnim = CABasicAnimation(keyPath: "strokeEnd")
        strokeAnim.fromValue = 0
        strokeAnim.toValue = 1
        strokeAnim.duration = 1
        layer.addSublayer(newPartLayer)
        newPartLayer.add(strokeAnim, forKey: "path")

    }

    func path(forPart: BodyPart)-> UIBezierPath {

        switch forPart {

        case BodyPart.Head :
            let centerX = CGFloat(bounds.size.width * DrawingConstants.gallowAcrossScale - (DrawingConstants.gallowHeightWidth / 2))
            let centerY = CGFloat(bounds.size.height * DrawingConstants.gallowHeight + DrawingConstants.gallowBaseHeight + DrawingConstants.gallowTipHeight + ScaleConstants.headRadius)
            let center = CGPoint(x: centerX, y: centerY)
            headMiddle = center
            path = UIBezierPath(arcCenter: center, radius: ScaleConstants.headRadius, startAngle: CGFloat(0), endAngle: CGFloat(2 * M_PI), clockwise: true)
            path.lineWidth = CGFloat(2)

            return path

        case BodyPart.Body :
            let add = CGFloat(DrawingConstants.gallowBaseHeight + DrawingConstants.gallowTipHeight + 2 * ScaleConstants.headRadius)
            let startPointY = CGFloat(bounds.size.height * DrawingConstants.gallowHeight + add)
            let startPointX = CGFloat(bounds.size.width * DrawingConstants.gallowAcrossScale - (DrawingConstants.gallowHeightWidth / 2))
            let startPoint = CGPoint(x: startPointX, y: startPointY)
            let endPoint = CGPoint(x: startPoint.x, y: startPoint.y + ScaleConstants.bodyLength)
            bodyStart = startPoint
            bodyEnd = endPoint
            path.lineWidth = CGFloat(2)
            path.move(to: startPoint)
            path.addLine(to: endPoint)
            return path

        case BodyPart.LeftLeg :
            let startPoint = CGPoint(x: bodyEnd.x, y: bodyEnd.y)
            let endPoint = CGPoint(x: startPoint.x - ScaleConstants.limbLength, y: startPoint.y + ScaleConstants.limbLength)
            path.lineWidth = CGFloat(2)
            path.move(to: startPoint)
            path.addLine(to: endPoint)
            return path

        case BodyPart.RightLeg :
            let startPoint = CGPoint(x: bodyEnd.x, y: bodyEnd.y)
            let endPoint = CGPoint(x: startPoint.x + ScaleConstants.limbLength, y: startPoint.y + ScaleConstants.limbLength)
            path.lineWidth = CGFloat(2)
            path.move(to: startPoint)
            path.addLine(to: endPoint)
            return path

        case BodyPart.LeftArm :
            let startPoint = CGPoint(x: bodyStart.x, y: bodyStart.y + ScaleConstants.handHeightScale * ScaleConstants.bodyLength)
            let endPoint = CGPoint(x: startPoint.x - ScaleConstants.limbLength, y: startPoint.y - ScaleConstants.limbLength * ScaleConstants.handHeightScale)
            path.lineWidth = CGFloat(2)
            path.move(to: startPoint)
            path.addLine(to: endPoint)
            return path

        case BodyPart.RightArm :
            let startPoint = CGPoint(x: bodyStart.x, y: bodyStart.y + ScaleConstants.handHeightScale * ScaleConstants.bodyLength)
            let endPoint = CGPoint(x: startPoint.x + ScaleConstants.limbLength, y: startPoint.y - ScaleConstants.limbLength * ScaleConstants.handHeightScale)
            path.lineWidth = CGFloat(2)
            path.move(to: startPoint)
            path.addLine(to: endPoint)
            return path

        case BodyPart.LeftEye :
            UIColor.black.set()
            let eyeMiddle = CGPoint(x: headMiddle.x - ScaleConstants.eyeOffset, y: headMiddle.y - ScaleConstants.eyeOffset)

            let path = UIBezierPath(arcCenter: eyeMiddle, radius: ScaleConstants.eyeRadius, startAngle: 0, endAngle: CGFloat(2 * M_PI), clockwise: true)
            path.lineWidth = CGFloat(1)
            return path

        case BodyPart.RightEye :
            UIColor.black.set()
            let eyeMiddle = CGPoint(x: headMiddle.x + ScaleConstants.eyeOffset, y: headMiddle.y - ScaleConstants.eyeOffset)

            let path = UIBezierPath(arcCenter: eyeMiddle, radius: ScaleConstants.eyeRadius, startAngle: 0, endAngle: CGFloat(2 * M_PI), clockwise: true)
            path.lineWidth = CGFloat(1)
            return path

        default:
            return path
        }
    }

    /******************************************************************************************/

    func connectPoints(bottomLeftPoint: CGPoint, bottomRightPoint: CGPoint, topLeftPoint: CGPoint, topRightPoint: CGPoint, color: UIColor) {
        color.set()

        let path = UIBezierPath()
        path.move(to: bottomLeftPoint)
        path.addLine(to: topLeftPoint)
        path.addLine(to: topRightPoint)
        path.addLine(to: bottomRightPoint)
        path.close()
        path.fill()
        path.stroke()

    }

    func calculateMidPoint(point1: CGPoint, point2: CGPoint) -> CGPoint {
        return CGPoint(x: (point1.x + point2.x) / 2, y: (point1.y + point2.y) / 2)

    }

    /*****************************************************************************************/

    func drawGrass() {
        let topStartPoint = CGPoint(x: CGFloat(0), y: CGFloat(bounds.size.height * DrawingConstants.grassHeightScale))
        let topRightPoint = CGPoint(x: CGFloat(bounds.size.width), y: topStartPoint.y)
        let bottomRightPoint = CGPoint(x: topRightPoint.x, y: CGFloat(bounds.size.height))
        let bottomLeftPoint = CGPoint(x: CGFloat(0), y: bottomRightPoint.y)

        connectPoints(bottomLeftPoint: bottomLeftPoint, bottomRightPoint: bottomRightPoint, topLeftPoint: topStartPoint, topRightPoint: topRightPoint, color: UIColor.green)
    }

    func drawSky() {
        let bottomLeftPoint = CGPoint(x: CGFloat(0), y: CGFloat(bounds.size.height * DrawingConstants.grassHeightScale))
        let topLeftPoint = CGPoint(x: CGFloat(0), y: CGFloat(0))
        let topRightPoint = CGPoint(x: CGFloat(bounds.size.width), y: CGFloat(0))
        let bottomRightPoint = CGPoint(x: CGFloat(bounds.size.width), y: CGFloat(bounds.size.height * DrawingConstants.grassHeightScale))

        connectPoints(bottomLeftPoint: bottomLeftPoint, bottomRightPoint: bottomRightPoint, topLeftPoint: topLeftPoint, topRightPoint: topRightPoint, color: UIColor.cyan)
    }

    func drawGallow() {
        drawGallowBase()
        drawGallowHeight()
        drawGallowAcross()
        drawGallowTip()
    }

    func drawGallowBase() {
        let bottomLeftPoint = CGPoint(x: CGFloat(bounds.size.width * DrawingConstants.gallowBaseStartScale), y: CGFloat(bounds.size.height * DrawingConstants.grassHeightScale))
        let topLeftPoint = CGPoint(x: bottomLeftPoint.x, y: bottomLeftPoint.y - DrawingConstants.gallowBaseHeight)
        let topRightPoint = CGPoint(x: CGFloat(bounds.size.width * DrawingConstants.gallowBaseEndScale), y: topLeftPoint.y)
        let bottomRightPoint = CGPoint(x: topRightPoint.x, y: bottomLeftPoint.y)

        connectPoints(bottomLeftPoint: bottomLeftPoint, bottomRightPoint: bottomRightPoint, topLeftPoint: topLeftPoint, topRightPoint: topRightPoint, color: UIColor.brown)
    }

    func drawGallowHeight() {
        let bottomLeftPoint = CGPoint(x: CGFloat(bounds.size.width * DrawingConstants.gallowHeightStart), y: CGFloat(bounds.size.height * DrawingConstants.grassHeightScale - DrawingConstants.gallowBaseHeight))
        let bottomRightPoint = CGPoint(x: bottomLeftPoint.x + DrawingConstants.gallowHeightWidth, y: bottomLeftPoint.y)
        let topLeftPoint = CGPoint(x: bottomLeftPoint.x, y: bounds.size.height * DrawingConstants.gallowHeight)
        let topRightPoint = CGPoint(x: bottomRightPoint.x, y: topLeftPoint.y)

        connectPoints(bottomLeftPoint: bottomLeftPoint, bottomRightPoint: bottomRightPoint, topLeftPoint: topLeftPoint, topRightPoint: topRightPoint, color: UIColor.brown)
    }

    func drawGallowAcross() {
        let bottomLeftPoint = CGPoint(x: CGFloat(bounds.size.width * DrawingConstants.gallowHeightStart) + DrawingConstants.gallowHeightWidth, y: CGFloat(bounds.size.height * DrawingConstants.gallowHeight + DrawingConstants.gallowBaseHeight))
        let bottomRightPoint = CGPoint(x: CGFloat(bounds.size.width * DrawingConstants.gallowAcrossScale), y: bottomLeftPoint.y)
        let topLeftPoint = CGPoint(x: bottomLeftPoint.x, y: CGFloat(bounds.size.height * DrawingConstants.gallowHeight))
        let topRightPoint = CGPoint(x: CGFloat(bottomRightPoint.x), y: topLeftPoint.y)
        connectPoints(bottomLeftPoint: bottomLeftPoint, bottomRightPoint: bottomRightPoint, topLeftPoint: topLeftPoint, topRightPoint: topRightPoint, color: UIColor.brown)
    }

    func drawGallowTip() {
        let topLeftPoint = CGPoint(x: CGFloat(bounds.size.width * DrawingConstants.gallowAcrossScale - DrawingConstants.gallowHeightWidth), y: CGFloat(bounds.size.height * DrawingConstants.gallowHeight + DrawingConstants.gallowBaseHeight))
        let topRightPoint = CGPoint(x: CGFloat(bounds.size.width * DrawingConstants.gallowAcrossScale), y: topLeftPoint.y)
        let bottomLeftPoint = CGPoint(x: topLeftPoint.x, y: topLeftPoint.y + DrawingConstants.gallowTipHeight)
        let bottomRightPoint = CGPoint(x: topRightPoint.x, y: bottomLeftPoint.y)

        connectPoints(bottomLeftPoint: bottomLeftPoint, bottomRightPoint: bottomRightPoint, topLeftPoint: topLeftPoint, topRightPoint: topRightPoint, color: UIColor.brown)
    }

    /*******************************************************************************************/




}

然后像这样从我的GameViewController中调用它
let newPart = BodyPart(rawValue: (model?.attempts)!)

            self.hangmanView.add(part: newPart!)

hangmanView是GameView2

最佳答案

为每个身体部位创建一个枚举。使其为整数,以便可以使用错误答案的数量实例化它。

enum BodyPart: Int {
    case head = 0
    case leftArm
    case rightArm
...
}

使身体焕然一新
let newPart = BodyPart(rawValue: incorrectGuesses - 1)

为您的视图提供一些功能...
func add(part: BodyPart){
    // first get a drawing path according to that part
    let partPath = path(for: part)

    // lets add a new layer so we can animate it seperately
    let newPartLayer = CAShapeLayer()
    newPartLayer.frame = bounds
    newPartLayer.path = partPath
    // linewidth, linecap you might want to play with

   let strokeAnim = CABasicAnimation(keyPath: "strokeEnd")
   strokeAnim.fromValue = 0
   strokeAnim.toValue = 1
   strokeAnim.duration = 0.5 // play with it, see what you like

   layer.addSublayer(layer: newPartLayer)
   newPartLayer.add(anim: strokeAnim)
}


func path(for: BodyPart) -> CGPath {

    // draw your part path, return it as a CGPath
}

然后从您的控制器中实例化一个新零件并将其添加到hangmanview中,它将在您在绘图代码中绘制该图层时对其进行绘制。 UIBezierPath具有.cgPath变量,可以将其转换为核心图形路径。
let newPart = BodyPart(rawValue: incorrectGuesses - 1)
hangmanView.add(part: newPart)

当您需要新游戏时,只需从hangmanView中删除所有子图层即可。 CAShapeLayers对于仅很小的形状确实非常有用,并且您可以为更改路径(keyPath:“path”)或沿任一方向抚摸路径设置动画。看起来不错如果保留对所有零件层的引用,您甚至可以独立移动零件或与它们一起做其他有趣的事情。这样,您就可以遵守模型视图控制器范例。您可以使游戏状态远离您的视图,所有视图都将其添加到身体部位上,而您的控制器则提供了执行此动作的部位。处理简单的事情并不是什么大问题,但是当您变得更好并且事情变得更加复杂时,最好记住一点。

快速编辑:您可能想尝试keyPath:“path”,给它一个开始路径(也许是身体路径)和一个结束路径,它看起来像零件从身体中长出来。祝好运!

***编辑答案。

我在这里清理了您的代码。我不太确定为什么在其中或某些小类的 private 结构中有某些变量,但是没关系,我把它们留在里面了。我四处移动了一些东西,但基本上保持不变,除了很明显你在画矩形而不是其他形状。我没有尝试运行它。莱姆知道情况如何。
enum BodyPart: Int {
case noose = 0
case head
case body
case leftLeg
case rightLeg
case leftArm
case rightArm
case leftEye
case rightEye
case mouth
case unknown
}




class HangmanView: UIView {


var partLayers = [CAShapeLayer]()
private var bodyStart: CGPoint = CGPoint.zero
private var bodyEnd: CGPoint = CGPoint.zero
private var headMiddle: CGPoint = CGPoint.zero

var currentPart: BodyPart?


func clear() {

    for i in partLayers {
        i.removeFromSuperlayer()
    }

    partLayers.removeAll()
}

func add(part: BodyPart){

    currentPart = part


    let newPartLayer = CAShapeLayer()

    let partPath = path(forPart: part)
    newPartLayer.frame = bounds
    newPartLayer.path = partPath.cgPath
    newPartLayer.strokeColor = UIColor.black.cgColor
    newPartLayer.fillColor = UIColor.clear.cgColor

    newPartLayer.lineCap = kCALineCapRound
    newPartLayer.lineWidth = part == .rightEye || part == .leftEye ? 1 : 2

    let strokeAnim = CABasicAnimation(keyPath: "strokeEnd")
    strokeAnim.fromValue = 0
    strokeAnim.toValue = 1
    strokeAnim.duration = 1
    layer.addSublayer(newPartLayer)
    newPartLayer.add(strokeAnim, forKey: "path")
    partLayers.append(newPartLayer)

}

func path(forPart: BodyPart) -> UIBezierPath {

    switch forPart {
    case .noose:
        return UIBezierPath()


    case .head :
        let centerX = CGFloat(bounds.size.width * DrawingConstants.gallowAcrossScale - (DrawingConstants.gallowHeightWidth / 2))
        let centerY = CGFloat(bounds.size.height * DrawingConstants.gallowHeight + DrawingConstants.gallowBaseHeight + DrawingConstants.gallowTipHeight + ScaleConstants.headRadius)
        let center = CGPoint(x: centerX, y: centerY)
        headMiddle = center
        let path = UIBezierPath(arcCenter: center, radius: ScaleConstants.headRadius, startAngle: CGFloat(0), endAngle: CGFloat(2 * M_PI), clockwise: true)

        return path

    case .body :
        let add = CGFloat(DrawingConstants.gallowBaseHeight + DrawingConstants.gallowTipHeight + 2 * ScaleConstants.headRadius)
        let startPointY = CGFloat(bounds.size.height * DrawingConstants.gallowHeight + add)
        let startPointX = CGFloat(bounds.size.width * DrawingConstants.gallowAcrossScale - (DrawingConstants.gallowHeightWidth / 2))
        let startPoint = CGPoint(x: startPointX, y: startPointY)
        let endPoint = CGPoint(x: startPoint.x, y: startPoint.y + ScaleConstants.bodyLength)
        bodyStart = startPoint
        bodyEnd = endPoint
        let path = UIBezierPath()
        path.move(to: startPoint)
        path.addLine(to: endPoint)
        return path

    case .leftLeg :
        let startPoint = CGPoint(x: bodyEnd.x, y: bodyEnd.y)
        let endPoint = CGPoint(x: startPoint.x - ScaleConstants.limbLength, y: startPoint.y + ScaleConstants.limbLength)
        let path = UIBezierPath()
        path.move(to: startPoint)
        path.addLine(to: endPoint)
        return path

    case .rightLeg :
        let startPoint = CGPoint(x: bodyEnd.x, y: bodyEnd.y)
        let endPoint = CGPoint(x: startPoint.x + ScaleConstants.limbLength, y: startPoint.y + ScaleConstants.limbLength)
        let path = UIBezierPath()
        path.move(to: startPoint)
        path.addLine(to: endPoint)
        return path

    case .leftArm :
        let startPoint = CGPoint(x: bodyStart.x, y: bodyStart.y + ScaleConstants.handHeightScale * ScaleConstants.bodyLength)
        let endPoint = CGPoint(x: startPoint.x - ScaleConstants.limbLength, y: startPoint.y - ScaleConstants.limbLength * ScaleConstants.handHeightScale)
        let path = UIBezierPath()
        path.move(to: startPoint)
        path.addLine(to: endPoint)
        return path

    case .rightArm :
        let startPoint = CGPoint(x: bodyStart.x, y: bodyStart.y + ScaleConstants.handHeightScale * ScaleConstants.bodyLength)
        let endPoint = CGPoint(x: startPoint.x + ScaleConstants.limbLength, y: startPoint.y - ScaleConstants.limbLength * ScaleConstants.handHeightScale)
        let path = UIBezierPath()
        path.move(to: startPoint)
        path.addLine(to: endPoint)
        return path

    case .leftEye :
        let eyeMiddle = CGPoint(x: headMiddle.x - ScaleConstants.eyeOffset, y: headMiddle.y - ScaleConstants.eyeOffset)

        let path = UIBezierPath(arcCenter: eyeMiddle, radius: ScaleConstants.eyeRadius, startAngle: 0, endAngle: CGFloat(2 * M_PI), clockwise: true)
        path.lineWidth = CGFloat(1)
        return path

    case .rightEye :
        let eyeMiddle = CGPoint(x: headMiddle.x + ScaleConstants.eyeOffset, y: headMiddle.y - ScaleConstants.eyeOffset)

        let path = UIBezierPath(arcCenter: eyeMiddle, radius: ScaleConstants.eyeRadius, startAngle: 0, endAngle: CGFloat(2 * M_PI), clockwise: true)
        path.lineWidth = CGFloat(1)
        return path

    default:
        return UIBezierPath()
    }
}




override func draw(_ rect: CGRect) {

    guard let context = UIGraphicsGetCurrentContext() else { return }
    // get the drawing context and save the ground state
    context.saveGState()

    // add sky and grass, now they are just rectangles
    context.setFillColor(UIColor.cyan.cgColor)
    context.fill(sky(rect))

    context.setFillColor(UIColor.green.cgColor)
    context.fill(grass(rect))

    context.setFillColor(UIColor.brown.cgColor)

    context.addPath(gallowBase(rect))
    context.addPath(gallowHeight(rect))
    context.addPath(gallowAcross(rect))
    context.addPath(gallowTip(rect))

    context.fillPath()
    context.restoreGState()

}



func gallowBase(_ rect: CGRect) -> CGPath {

    let bottomLeftPoint = CGPoint(x: CGFloat(rect.width * DrawingConstants.gallowBaseStartScale), y: CGFloat(rect.height * DrawingConstants.grassHeightScale))
    let topLeftPoint = CGPoint(x: bottomLeftPoint.x, y: bottomLeftPoint.y - DrawingConstants.gallowBaseHeight)
    let topRightPoint = CGPoint(x: CGFloat(rect.width * DrawingConstants.gallowBaseEndScale), y: topLeftPoint.y)
    let bottomRightPoint = CGPoint(x: topRightPoint.x, y: bottomLeftPoint.y)

    let path = CGMutablePath()
    path.addLines(between: [bottomLeftPoint,topLeftPoint, topRightPoint,bottomRightPoint])
    path.closeSubpath()
    return path
}

func gallowHeight(_ rect: CGRect)  -> CGPath {
    let bottomLeftPoint = CGPoint(x: CGFloat(rect.width * DrawingConstants.gallowHeightStart), y: CGFloat(rect.height * DrawingConstants.grassHeightScale - DrawingConstants.gallowBaseHeight))
    let bottomRightPoint = CGPoint(x: bottomLeftPoint.x + DrawingConstants.gallowHeightWidth, y: bottomLeftPoint.y)
    let topLeftPoint = CGPoint(x: bottomLeftPoint.x, y: rect.height * DrawingConstants.gallowHeight)
    let topRightPoint = CGPoint(x: bottomRightPoint.x, y: topLeftPoint.y)

    let path = CGMutablePath()
    path.addLines(between: [bottomLeftPoint,topLeftPoint, topRightPoint,bottomRightPoint])
    path.closeSubpath()
    return path
}

func gallowAcross(_ rect: CGRect)  -> CGPath {
    let bottomLeftPoint = CGPoint(x: CGFloat(rect.width * DrawingConstants.gallowHeightStart) + DrawingConstants.gallowHeightWidth, y: CGFloat(rect.height * DrawingConstants.gallowHeight + DrawingConstants.gallowBaseHeight))


    let bottomRightPoint = CGPoint(x: CGFloat(rect.width * DrawingConstants.gallowAcrossScale), y: bottomLeftPoint.y)
    let topLeftPoint = CGPoint(x: bottomLeftPoint.x, y: CGFloat(rect.height * DrawingConstants.gallowHeight))
    let topRightPoint = CGPoint(x: CGFloat(bottomRightPoint.x), y: topLeftPoint.y)

    let path = CGMutablePath()
    path.addLines(between: [bottomLeftPoint,topLeftPoint, topRightPoint,bottomRightPoint])
    path.closeSubpath()
    return path
}

func gallowTip(_ rect: CGRect)  -> CGPath {
    let topLeftPoint = CGPoint(x: CGFloat(rect.width * DrawingConstants.gallowAcrossScale - DrawingConstants.gallowHeightWidth), y: CGFloat(rect.height * DrawingConstants.gallowHeight + DrawingConstants.gallowBaseHeight))
    let topRightPoint = CGPoint(x: CGFloat(rect.width * DrawingConstants.gallowAcrossScale), y: topLeftPoint.y)
    let bottomLeftPoint = CGPoint(x: topLeftPoint.x, y: topLeftPoint.y + DrawingConstants.gallowTipHeight)
    let bottomRightPoint = CGPoint(x: topRightPoint.x, y: bottomLeftPoint.y)

    let path = CGMutablePath()
    path.addLines(between: [bottomLeftPoint,topLeftPoint, topRightPoint,bottomRightPoint])
    path.closeSubpath()
    return path
}



func grass(_ rect: CGRect)  -> CGRect {


    let grassRect = CGRect(x: 0, y: rect.height * DrawingConstants.grassHeightScale, width: rect.width, height: (1 - DrawingConstants.grassHeightScale) * rect.height)

    return grassRect
}

func sky(_ rect: CGRect)  -> CGRect {

    let skyRect = CGRect(x: 0, y: 0, width: rect.width, height: DrawingConstants.grassHeightScale * rect.height)

    return skyRect

}


func calculateMidPoint(point1: CGPoint, point2: CGPoint) -> CGPoint {
    return CGPoint(x: (point1.x + point2.x) / 2, y: (point1.y + point2.y) / 2)

}


struct DrawingConstants {
    static let gallowBaseStartScale: CGFloat = 0.15
    static let gallowBaseEndScale: CGFloat = 0.85
    static let gallowBaseHeight: CGFloat = 10
    static let gallowHeight: CGFloat = 0.05        //static let gallowHeight: CGFloat = 0.15
    static let gallowHeightStart: CGFloat = 0.175
    static let gallowHeightWidth: CGFloat = 10
    static let gallowAcrossScale: CGFloat = 0.5
    static let gallowTipHeight: CGFloat = 17.5
    static let headRadius: CGFloat = 16
    static let bodyLength: CGFloat = 25
    static let bodyHeight: CGFloat = 25
    static let legLength: CGFloat = 50
    static let grassHeightScale: CGFloat = 0.68
    static let armBack: CGFloat = 5
}

struct ScaleConstants {
    static let bodyLength: CGFloat = 50
    static let limbLength: CGFloat = 25
    static let handHeightScale: CGFloat = 0.4
    static let headRadius: CGFloat = 20
    static let eyeRadius = 0.15 * headRadius
    static let eyeOffset = 0.3 * headRadius
    static let mouthOffSet = 0.3 * headRadius
    static let mouthRadius = 0.25 * headRadius
}
}

08-19 11:57