2016-12-02 3 views
1

現在、Swiftを使用して、iOSでハングマンゲームアプリケーションを作成しています。コアグラフィックスを使用したiOSアニメーション

私はすべてのゲームの仕組みを完了しており、ハングマンと教授を描くためにCore Graphicsを使用したかったのです。私はUIBezierPathを使ってガウとハンベマンを描くことができ、ビューの各部分(ガウ、頭、体、左腕など)の描画を、イメージ全体を作成するために呼び出される別々の関数に分割しました。これらはすべてカスタムUIViewクラスの内部にあります。

私が理解できないようなことは、ユーザーが間違った推測をすると、ハングマンイメージの連続部分を追加する方法です。私は、私が繰り返す一連の画像を避けようとしています。代わりに、同じカスタムビューを使用して、Core Graphicsを使用してスティックフィギュアを1つずつ描画します。

フィギュアの連続する各部分を描画する関数を実装するにはどうすればよいですか?

「self.customView.updateDrawing()」のようなものは、customViewのupdateDrawingメソッドが、間違った推測の数についてモデルから情報を取得し、スティックフィギュアの必要な部分を描画するための適切なメソッドを呼び出します。

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) 
    } 

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




} 

し、それがhangmanViewは、このようなアプローチがうまくいくGameViewTwo

+0

問題に直接対処してください。あまり説明的ではありません – 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 
} 

をあなたのビューを与える新しいパーツをインスタンス化し、あなたにそれを追加作成しますあなたが描画コードで描画したときにレイヤーを描画します。 UIBezierPathにはコアグラフィックパスとしてキャストする.cgPath変数があります。

let newPart = BodyPart(rawValue: incorrectGuesses - 1) 
hangmanView.add(part: newPart) 

新しいゲームが必要な場合は、hangmanViewからすべてのサブレイヤを削除してください。 CAShapeLayersは、単純に小さな図形には本当に便利で、パスの変更(keyPath: "path")やパスをどちらの方向にでも描くことができます。それはよさそうだ。すべての部品レイヤーを参照していれば、部品を独立して動かすことも、他の面白いことをすることもできます。このようにして、あなたはモデルビューコントローラのパラダイムを守ります。ゲームの状態をあなたの視点から遠ざけて、あなたの視点はボディパーツに追加され、コントローラーはそのようなパーツを提供します。単純なものではそれほど大きな問題ではありませんが、あなたがより良くなり、状況がより複雑になるにつれて心に留めておくことは良いことです。

クイック編集:keyPath: "path"を試して、開始パス(本体パスかもしれない)と終了パスを指定すると、パーツがボディから大きくなったように見えます。がんばろう!

***編集回答。

ここでコードを整理しました。なぜあなたはそこに特定の変数があるのか​​、小さなクラスのprivate構造体があるのか​​は完全にはわかりませんが、大丈夫です。私はそれらを残しました。私はいくつかのものを動かしましたが、いくつかの他の形の代わりに。私はそれを実行しようとしなかった。 Lemmeはそれがどうなるか知っています。

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のようなパスを割り当てれば完了です。あなたが答えを見つけたら、それをアップヴォートにしてください。答えがあなたの問題を解決したら、それにチェックマークを付けてください。ようこそ! –

1

あるこの

let newPart = BodyPart(rawValue: (model?.attempts)!) 

      self.hangmanView.add(part: newPart!) 

ように私のGameViewControllerから呼び出されます。カスタム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 
    } 

} 

それを使用するには、あなたのViewControllerHangmanViewのための出口を持つことができ、そしてあなただけのビューを更新する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の描画をアニメーション化する場合は


は、あなたがHangmanViewanimationCountプロパティを追加することができます。値が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

関連する問題