Triangle UIView - Swift

前端 未结 5 1570
长情又很酷
长情又很酷 2020-12-05 06:43

So I\'m making a game in which I am dropping objects which have to be destroyed by a spike(triangle) at the bottom of the screen by a user.

I cannot work out how to

相关标签:
5条回答
  • 2020-12-05 07:11

    I have tried a PNG triangle but it detects the collision as the border of the image not the start of the triangle.

    There is nothing you can do about that if you're going to use simple-minded collisions (e.g. the built-in UIKit Dynamics - it does only rectangular view collisions). If you want advanced shape collisions, either you must implement them yourself or you must use Sprites.

    and for the user to move it

    That is much easier to deal with: simply override hitTest for this view and return nil if the place the user touches is outside the borders of the triangle image.

    0 讨论(0)
  • 2020-12-05 07:13

    Updated for Swift 3:

    class TriangleView : UIView {
    
        override init(frame: CGRect) {
            super.init(frame: frame)
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    
        override func draw(_ rect: CGRect) {
    
            guard let context = UIGraphicsGetCurrentContext() else { return }
    
            context.beginPath()
            context.move(to: CGPoint(x: rect.minX, y: rect.maxY))
            context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
            context.addLine(to: CGPoint(x: (rect.maxX / 2.0), y: rect.minY))
            context.closePath()
    
            context.setFillColor(red: 1.0, green: 0.5, blue: 0.0, alpha: 0.60)
            context.fillPath()
        }
    }
    


    Swift 2:

    import UIKit
    
    class TriangleView : UIView {
    
        override init(frame: CGRect) {
            super.init(frame: frame)
        }
    
        required init(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    
        override func drawRect(rect: CGRect) {
    
            var ctx : CGContextRef = UIGraphicsGetCurrentContext()
    
            CGContextBeginPath(ctx)
            CGContextMoveToPoint(ctx, CGRectGetMinX(rect), CGRectGetMaxY(rect))
            CGContextAddLineToPoint(ctx, CGRectGetMaxX(rect), CGRectGetMaxY(rect))
            CGContextAddLineToPoint(ctx, (CGRectGetMaxX(rect)/2.0), CGRectGetMinY(rect))
            CGContextClosePath(ctx)
    
            CGContextSetRGBFillColor(ctx, 1.0, 0.5, 0.0, 0.60);
            CGContextFillPath(ctx);
           }
     } 
    

    This will start from MinX, MaxY;
    Draw a line from the start to MaxX, MaxY;
    Draw a line from MaxX,MaxY to MaxX/2, MinY;
    Then close the path to the start location.

    The next part sets the color you want to use. In this example 255,127,0, Alpha 0.6 Then will fill the path you just drew above with the set color.

    Then in your View Controller

    Swift 3:

    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let triangle = TriangleView(frame: CGRect(x: 10, y: 20, width: 25 , height: 30))
            triangle.backgroundColor = .white
            view.addSubview(triangle)
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    }
    


    Swift 2:

    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
    
            let triangle = TriangleView(frame: CGRectMake(10, 20, 25, 30))
            triangle.backgroundColor = .whiteColor()
            view.addSubview(triangle)
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    }
    

    However, this is going to cause the same problem as the frame of this view is still going to be a rectangle. UIKit works with rectangles, you would have to use another framework, like Sprite Kit.

    0 讨论(0)
  • 2020-12-05 07:13

    I've modified the previous code a bit to add margin and fill color as inspectable and it works well with Swift4:

    import UIKit
    
    @IBDesignable
    class TriangleView : UIView {
        var _color: UIColor! = UIColor.blue
        var _margin: CGFloat! = 0
    
        @IBInspectable var margin: Double {
            get { return Double(_margin)}
            set { _margin = CGFloat(newValue)}
        }
    
    
        @IBInspectable var fillColor: UIColor? {
            get { return _color }
            set{ _color = newValue }
        }
    
        override init(frame: CGRect) {
            super.init(frame: frame)
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    
        override func draw(_ rect: CGRect) {
    
            guard let context = UIGraphicsGetCurrentContext() else { return }
    
            context.beginPath()
            context.move(to: CGPoint(x: rect.minX + _margin, y: rect.maxY - _margin))
            context.addLine(to: CGPoint(x: rect.maxX - _margin, y: rect.maxY - _margin))
            context.addLine(to: CGPoint(x: (rect.maxX / 2.0), y: rect.minY + _margin))
            context.closePath()
    
            context.setFillColor(_color.cgColor)
            context.fillPath()
        }
    }
    
    0 讨论(0)
  • 2020-12-05 07:21

    CAShapeLayer it can change the shape of layers.

        var mask = CAShapeLayer()
        mask.frame = self.layer.bounds
    
        let width = self.layer.frame.size.width
        let height = self.layer.frame.size.height
    
        var path = CGPathCreateMutable()
    
        CGPathMoveToPoint(path, nil, 30, 0)
        CGPathAddLineToPoint(path, nil, width, 0)
        CGPathAddLineToPoint(path, nil, width, height)
        CGPathAddLineToPoint(path, nil, 0, height)
        CGPathAddLineToPoint(path, nil, 30, 0)
    
        mask.path = path
    
        // CGPathRelease(path); - not needed
    
        self.layer.mask = mask
    
        var shape = CAShapeLayer()
        shape.frame = self.bounds
        shape.path = path
        shape.lineWidth = 3.0
        shape.strokeColor = UIColor.whiteColor().CGColor
        shape.fillColor = UIColor.clearColor().CGColor
    
        self.layer.insertSublayer(shape, atIndex: 0)
    
    0 讨论(0)
  • 2020-12-05 07:23

    Swift 5:

    This code worked for me for different sides. for UIView using CGMutablePath() and CAShapeLayer()

    *Assuming your view's height and width are same.

    *Set your views's background color as clearColor.

    A) Right Side

     @IBOutlet weak var triangleView: UIView!
    
     override func viewDidLoad() {
            super.viewDidLoad()
            self.setRightTriangle()   
        }
    
     func setRightTriangle(){
            let heightWidth = triangleView.frame.size.width //you can use triangleView.frame.size.height
            let path = CGMutablePath()
    
            path.move(to: CGPoint(x: heightWidth/2, y: 0))
            path.addLine(to: CGPoint(x:heightWidth, y: heightWidth/2))
            path.addLine(to: CGPoint(x:heightWidth/2, y:heightWidth))
            path.addLine(to: CGPoint(x:heightWidth/2, y:0))
    
            let shape = CAShapeLayer()
            shape.path = path
            shape.fillColor = UIColor.blue.cgColor
    
            triangleView.layer.insertSublayer(shape, at: 0)
        }
    


    B) Left Side

     func setLeftTriangle(){
            let heightWidth = triangleView.frame.size.width
            let path = CGMutablePath()
    
            path.move(to: CGPoint(x: heightWidth/2, y: 0))
            path.addLine(to: CGPoint(x:0, y: heightWidth/2))
            path.addLine(to: CGPoint(x:heightWidth/2, y:heightWidth))
            path.addLine(to: CGPoint(x:heightWidth/2, y:0))
    
            let shape = CAShapeLayer()
            shape.path = path
            shape.fillColor = UIColor.blue.cgColor
    
            triangleView.layer.insertSublayer(shape, at: 0)
        }
    


    C) Up Side

      func setUpTriangle(){
            let heightWidth = triangleView.frame.size.width
               let path = CGMutablePath()
    
               path.move(to: CGPoint(x: 0, y: heightWidth))
               path.addLine(to: CGPoint(x:heightWidth/2, y: heightWidth/2))
               path.addLine(to: CGPoint(x:heightWidth, y:heightWidth))
               path.addLine(to: CGPoint(x:0, y:heightWidth))
    
               let shape = CAShapeLayer()
               shape.path = path
               shape.fillColor = UIColor.blue.cgColor
    
               triangleView.layer.insertSublayer(shape, at: 0)
           }
    


    D) Down Side

      func setDownTriangle(){
            let heightWidth = triangleView.frame.size.width
            let path = CGMutablePath()
    
            path.move(to: CGPoint(x: 0, y: 0))
            path.addLine(to: CGPoint(x:heightWidth/2, y: heightWidth/2))
            path.addLine(to: CGPoint(x:heightWidth, y:0))
            path.addLine(to: CGPoint(x:0, y:0))
    
            let shape = CAShapeLayer()
            shape.path = path
            shape.fillColor = UIColor.blue.cgColor
    
            triangleView.layer.insertSublayer(shape, at: 0)
        }
    

    *Change X any Y values according to your requirement.

    0 讨论(0)
提交回复
热议问题