Skip to content

Instantly share code, notes, and snippets.

@eviathan
Last active May 18, 2019 18:13
Show Gist options
  • Save eviathan/69a53b9be57c05d1065c774c407cee9e to your computer and use it in GitHub Desktop.
Save eviathan/69a53b9be57c05d1065c774c407cee9e to your computer and use it in GitHub Desktop.
//
// ConnectFourBoardView.swift
// TestForMeitar
//
// Created by Brian on 18/05/2019.
// Copyright © 2019 Eviathan. All rights reserved.
//
import Foundation
import UIKit
@IBDesignable
class ConnectFourBoardView: UIView {
var counter: CGFloat = 5.0
var coinLayer = CALayer()
var foregroundLayer = CALayer()
var spacing: CGFloat = 12.0
var gridSize: CGPoint = CGPoint(x: 7, y: 6)
var circleSize: CGFloat {
get {
return (bounds.width - (spacing * (gridSize.x-1))) / gridSize.x
}
}
var board: [Int] = [Int]()
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
setupView()
}
override func layoutSublayers(of layer: CALayer) {
if layer == self.layer
{
coinLayer.frame = bounds
coinLayer.bounds = bounds
foregroundLayer.frame = bounds
foregroundLayer.bounds = bounds
}
foregroundLayer.mask = getGridMask()
super.layoutSublayers(of: layer)
}
func setupView() {
// Initialise view
backgroundColor = UIColor(hue: 0, saturation: 0, brightness: 0.3, alpha: 1.0)
// Initialise Coin Layer
layer.addSublayer(coinLayer)
// Initialise Foreground (grid mask)
foregroundLayer.backgroundColor = UIColor.black.cgColor
layer.addSublayer(foregroundLayer)
// Initialise Test Data
isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
addGestureRecognizer(tap)
}
var tapCounter = 0
@objc func handleTap(_ sender: UITapGestureRecognizer) {
let tap = sender.location(in: self)
let posIndexX = ((tap.x / frame.width) * gridSize.x).rounded(.down)
coinLayer.addSublayer(createCoin(x: posIndexX, y: (gridSize.y-1) - CGFloat(board[Int(posIndexX)]), color: tapCounter % 2 == 0 ? UIColor.red : UIColor.green))
board[Int(posIndexX)] = board[Int(posIndexX)] + 1
tapCounter+=1
}
// Gets the circle path for a given position
func getCirclePathAt(x: CGFloat, y: CGFloat) -> UIBezierPath {
return UIBezierPath(ovalIn: CGRect(x: CGFloat(x) * (circleSize + spacing),
y: CGFloat(y) * (circleSize + spacing),
width: circleSize,
height: circleSize))
}
// Creates a coin at given position
func createCoin(x: CGFloat, y: CGFloat, color: UIColor) -> CAShapeLayer {
let coin = CAShapeLayer()
coin.fillColor = color.cgColor
coin.path = getCirclePathAt(x: x, y: y).cgPath
let animation = CABasicAnimation(keyPath: "path")
animation.fromValue = getCirclePathAt(x: x, y: 0).cgPath
animation.toValue = coin.path
animation.duration = Double(y) * 0.075
coin.add(animation, forKey: "animatePath")
return coin
}
// Creates the grid mask layer
func getGridMask() -> CALayer {
let mask = CAShapeLayer(layer: layer)
mask.frame = bounds
let path = UIBezierPath(rect: frame(forAlignmentRect: bounds))
let gridWidth: Int = Int(gridSize.x)
let gridHeight: Int = Int(gridSize.y)
for x in 0..<gridWidth {
board.append(0)
for y in 0..<gridHeight {
path.append(getCirclePathAt(x: CGFloat(x), y: CGFloat(y)).reversing())
}
}
mask.path = path.cgPath
return mask
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment