2016-12-02 4 views
1

В настоящее время я создаю приложение для игры в висельник в iOS, используя Swift.iOS Animation with Core Graphics

У меня есть все механики игры, и я хотел использовать Core Graphics для рисования палача и виселицы. Я могу нарисовать виселицу и палач с помощью UIBezierPath и сломал рисунок каждой части вида (виселицы, голова, тело, левая рука, ...) в отдельные функции, которые вызывают для создания всего изображения. Все это внутри пользовательского класса UIView.

То, что я не могу понять, заключается в том, как добавить последовательные части изображения Hangman, поскольку пользователь делает неправильные догадки. Я пытаюсь избежать серии изображений, которые я цикла между ними. Вместо этого я хочу использовать тот же пользовательский вид, чтобы рисовать фигурку палочки по частям с помощью Core Graphics.

Как я могу реализовать функцию, которая будет рисовать каждую последующую часть фигуры?

Что-то вроде «self.customView.updateDrawing()», где метод updateDrawing в customView будет получать информацию от модели о количестве неправильных догадок и вызывать соответствующие методы для рисования необходимых частей фигуры палки.

UPDATE

Вот моя попытка реализации вид с этого поста https://codereview.stackexchange.com/questions/97424/hangman-in-swift в мою собственную игру палач. Они отлично подходят для рисования виселицы, но я не могу получить изображение, чтобы обновить его и нарисовать последовательные части тела, чтобы добавить палача. Вот мой код:

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 является GameViewTwo

+0

быть в курсе вашей проблемы. dont быть настолько описательным – Saranjith

ответ

2

Создайте список для каждой части тела. Сделайте его целым числом, чтобы вы могли создать его с количеством неправильных ответов.

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: «путь») или поглаживание пути в любом направлении. Это будет хорошо. Вы можете даже перемещать части вокруг самостоятельно или делать с ними другие забавные вещи, если вы сохранили ссылку на все частичные слои. Таким образом, вы как бы придерживаетесь парадигмы модели-представления-контроллера. Вы сохраняете состояние игры вдали от своего вида, все ваше представление добавляет его на части тела, а ваш контроллер предоставляет части для этого. Это не огромное дело с простыми вещами, но хорошо иметь в виду, когда вы поправляетесь, и все усложняется.

Быстрое редактирование: вы можете попробовать keyPath: «путь», дать ему путь к началу пути (возможно, путь к телу) и конечный путь, это будет выглядеть так, как часть вырастает из тела. Удачи!

*** Отредактированный ответ.

Я очистил ваш код здесь. Я не совсем уверен, почему у вас есть определенные переменные или небольшая приватная структура класса, но это нормально, я оставил их. Я переместил некоторые вещи вокруг, но в основном сохранил их, кроме тех случаев, когда было ясно, что вы рисуете прямоугольник вместо какой-то другой формы. Я не пытался запустить его. Лемм знает, как это происходит.

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 
} 
} 
+0

Да, я узнаю, что мои рисунки с UIBezierPath должны быть слоями, которые можно добавить. Я продолжаю получать контекстные ошибки, поэтому я читал документацию для контекстов. Я работаю над тем, чтобы изменить существующий пользовательский класс представления на слои, добавленные в представление, поскольку у меня уже есть версии моих методов рисования, которые являются автономными или частью цепочки функций, которые вызываются с параметром Int, который определяет, как большая часть палача нарисована. Я основал его на этом http://codereview.stackexchange.com/questions/97424/hangman-in-swift – TheTotalJim

+0

Я отправляю свой код, когда могу его очистить, спасибо за предложения. – TheTotalJim

+1

Включение пути безье в новый CAShapeLayer очень просто. Просто сделайте то, что я показал выше, назначьте путь следующим образом: newShapeLayer.path = myBezierPath.cgPath, и все готово. Одна вещь, хотя, когда вы находите ответ полезным, дайте ему преимущество. Когда ответ решает вашу проблему, поставьте галочку. Добро пожаловать в SO! –

1

подход, как это будет работать. Имейте свойство вашего собственного класса HangmanView под названием incorrectGuesses. Изменение этого свойства вызовет перерисовку представления, вызвав setNeedsDisplay на себя.

Использование инструкции switch и fallthough позволит увеличить размер чертежа при увеличении incorrectGuesses.

class HangmanView: UIView { 
    var incorrectGuesses = 0 { 
     didSet { 
      self.setNeedsDisplay() 
     } 
    } 

    override func draw(_ rect: CGRect) { 
     switch incorrectGuesses { 
     case let x where x > 5: 
      drawRightLeg() 
      fallthrough 
     case 5: 
      drawLeftLeg() 
      fallthrough 
     case 4: 
      drawRightArm() 
      fallthrough 
     case 3: 
      drawLeftArm() 
      fallthrough 
     case 2: 
      drawBody() 
      fallthrough 
     case 1: 
      drawHead() 
      fallthrough 
     case 0: 
      drawGallows() 
     default: 
      break 
     } 
    } 

    func drawGallows() { 
     // code to draw gallows 
    } 

    func drawHead() { 
     // code to draw head 
    } 

    func drawBody() { 
     // code to draw body 
    } 

    func drawLeftArm() { 
     // code to draw left arm 
    } 

    func drawRightArm() { 
     // code to draw right arm 
    } 

    func drawLeftLeg() { 
     // code to draw left leg 
    } 

    func drawRightLeg() { 
     // code to draw right leg 
    } 

} 

Чтобы использовать его, вы могли бы иметь выход для HangmanView в вашем ViewController, и вы бы просто установить incorrectGuesses обновить вид:

class ViewController: UIViewController { 
    @IBOutlet weak var hangmanView: HangManView! 
    var incorrectGuesses = 0 

    func gameplay() { 
     ... 

     if letter not in word { 
      incorrectGuesses += 1 

      // Update the HangmanView 
      hangmanView.incorrectGuesses = incorrectGuesses 
     } 
    } 
} 

В раскадровку, добавить UIView и установите Класс на номер HangmanView в Идентификационный инспектор, а затем подключите его к розетке.


Если вы хотите, чтобы оживить рисунок HangmanView, вы можете добавить animationCount свойство в HangmanView. Если для этого параметра установлено значение, например 3, он будет анимировать чертеж по битам каждые 0.5 секунд. Чтобы использовать его, вы должны установить hangmanView.animationCount = 3.

var animationCount = 0 { 
    didSet { 
     incorrectGuesses = 0 
     if animationCount > incorrectGuesses { 
      _ = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in 
       self.incorrectGuesses += 1 
       if self.incorrectGuesses >= self.animationCount { 
        timer.invalidate() 
       } 
      } 
     } 
    } 
} 
+0

Итак, тогда в ViewController я мог бы просто изменить файл hangmanView .incorrectGuesses var? Затем .setNeedsDisplay() вызовет draw (_rect: CGRect), который будет вызываться, и представление обновит, какие части были нарисованы. Думаю, я правильно вас понимаю, это, безусловно, стоит попробовать. Спасибо за предложение. – TheTotalJim

+0

Это правильно. Добро пожаловать. – vacawama