Skip to content

Commit

Permalink
Added new turtle playground files for Xcode 7 with multiple pages and…
Browse files Browse the repository at this point in the history
… a target.
  • Loading branch information
dimsumthinking committed Aug 12, 2015
1 parent 5cbebe5 commit b4bb371
Show file tree
Hide file tree
Showing 66 changed files with 1,649 additions and 2 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ A few preliminary notes:

* This playground requires the new playground format and features released in Xcode 7 and Swift 2. This version requires Yosemite.
* From time to time playgrounds can crash or seem to disappear from time to time. The current fix suggested by Apple is to show the package contents of the playground and delete the workspace.
* Type "turtle" in the playground. You should see "Turtle_Sources.Turtle" on the right. Mouse over it and you will see the quick look icon and the show value icon. Click on the show value icon. You should see a rectangle with a turtle in the middle. Enlarge the box if you like.
* Make the turtle move by typing in "forward()". Make the turtle turn by typing in "right()".
* Type "turtle" in the Linear Turtle playground page. You should see "Linear_Turtle_with_Target_PageSources.Turtle" on the right. Mouse over it and you will see the quick look icon and the show value icon. Click on the show value icon. You should see a rectangle with a turtle in the middle. Enlarge the box if you like.
* Make the turtle move by typing in "forward() or back()". Stop when you've hit your target'.
* In the next page add the functions right() and left().
* In the next page the four functions can take arguments specifying how much to move forward() or back() and how much to turn right() or left().
* In the next page you can change colors using penColor() or nextColor().
* In the final page you can show() and hide() the icon or control the pen using penUp() or penDown().
* Create routines and your own functions.

I am working on a book that will serve as a tutorial using this playground. It will be available soon.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*:
### Before We Begin
[TOC](Contents) | Previous | [Next](@next)

---
We need to save the position of our target or it will constantly be moving around.

* Find your `Documents` director.
* Add a new folder named `Shared Playground Data` making sure that there's a space between each word.

Enjoy!

---

[TOC](TOC) | Previous | [Next](@next) */
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*:
### The Turtle Playground
* [Before We Begin](Before%20We%20Begin)
* [Linear Turtle with Target](Linear%20Turtle%20with%20Target)
* [Turtle with Target](Turtle%20with%20Target)
* [Turtle with Parameters and Target](Turtle%20with%20Parameters%20and%20Target)
* [Cosmic Turtle and Target](Cosmic%20Turtle%20and%20Target)
* [Turtle](Turtle)
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*:
### Cosmic Turtle and Target Hints

[Back](Cosmic%20Turtle%20and%20Target)

---
* The `penColor()` and `nextColor()` functions are used to set the pen's color or to cycle through them.
* The colors included are Red, Orange, Yellow, PeaGreen, Green, BlueGreen, Cyan, Cerullian, Blue, Purple, Magenta, Pink
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*:
### Cosmic Turtle and Target ([Hint](Cosmic%20Turtle%20and%20Target%20Hint))

[TOC](Contents) | [Previous](@previous) | [Next](@next)

---
*/

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import UIKit

struct Avatar {
private(set) var view = UIImageView()
private(set) var headingInRadians = 0.0
private let image: UIImage

// MARK: - Initializers

init(){
image = UIImage(named: "Turtle.png")!
view = UIImageView(image: colorAvatar(initialPenColor))
}

private init(view: UIImageView, image: UIImage, headingInRadians: Double) {
self.view = view
self.headingInRadians = headingInRadians
self.image = image
}

// MARK: - Direction

func increaseHeadingBy(degrees: Double) -> Avatar {
return Avatar(view: view, image: image, headingInRadians: headingInRadians + degrees/180 * M_PI )
}


// MARK: - Position

func positionTransform(currentPoint: CGPoint) -> CGAffineTransform {
let rotateByRadians = CGAffineTransformMakeRotation(CGFloat(headingInRadians))
let centerOfTurtleX = currentPoint.x - view.center.x
let centerOfTurtleY = currentPoint.y - view.center.y
let moveTurtle = CGAffineTransformMakeTranslation(centerOfTurtleX, centerOfTurtleY)
let turtleTransform = CGAffineTransformConcat(rotateByRadians, moveTurtle)
return turtleTransform
}

// MARK: - Color

func penColor(penColor: PenColor) -> Avatar {
view.image = colorAvatar(penColor)
return Avatar(view: view, image: image, headingInRadians: headingInRadians)
}

private func colorAvatar(penColor: PenColor) -> UIImage {
let angle = penColor.hue * M_PI * 2.0
guard let inputImage = CIImage(image: image),
let hueAdjuster = CIFilter(name: "CIHueAdjust", withInputParameters: [kCIInputImageKey : inputImage ,
kCIInputAngleKey : NSNumber(double: angle)]) else {
return image
}
return UIImage(CIImage: hueAdjuster.outputImage!)
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import UIKit

let centerX = 300
let centerY = 300
let width = 2 * centerX
let height = 2 * centerY
let terrarium = CGRect(x: 0, y: 0, width: width, height: height)

let lineWidth: CGFloat = 4.0

private let targetOffset = 25
let targetHorizontalOffset = targetOffset
let targetVerticalOffset = targetOffset
let targetSteps = 11

let targetWidth = 2 * targetHorizontalOffset
let targetHeight = 2 * targetVerticalOffset

let standardForwardDistance = 2 * targetOffset
let rightAngle = 90

let environmentColor = UIColor.blackColor()
let initialPenColor = PenColor.Green
let victoryColor = UIColor.lightGrayColor()
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import UIKit

struct Path {
var bezierPath = UIBezierPath()
var currentPoint: CGPoint {
return bezierPath.currentPoint
}
let penColor: PenColor

// MARK: - Initializers

init(startingPoint: CGPoint, penColor: PenColor = initialPenColor) {
bezierPath.moveToPoint(startingPoint)
bezierPath.lineWidth = lineWidth
self.penColor = penColor
}

private init(bezierPath: UIBezierPath, penColor: PenColor) {
self.bezierPath = bezierPath
self.penColor = penColor
}

// MARK: - Position

func moveTo(x x:Double, y: Double) -> Path {
bezierPath.addLineToPoint(CGPoint(x: x, y: y))
return Path(bezierPath: bezierPath, penColor: penColor)
}

func forward(distance: Double, inDirection headingInRadians: Double) -> Path {
let dx = distance * cos(headingInRadians)
let dy = distance * sin(headingInRadians)
let currentX = Double(bezierPath.currentPoint.x)
let currentY = Double(bezierPath.currentPoint.y)
return moveTo(x: currentX + dx, y: currentY + dy)
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import UIKit

public enum PenColor: Int {
case Red
case Orange
case Yellow
case PeaGreen, Green, BlueGreen
case Cyan, Cerullian, Blue
case Purple, Magenta, Pink


var color: UIColor {
return UIColor(hue: CGFloat(hue), saturation: 1, brightness: 1, alpha: 1)
}

func next() -> PenColor {
let numberOfNextColor = (rawValue + 7) % PenColor.Pink.rawValue
return PenColor(rawValue: numberOfNextColor)!
}

var hue: Double {
return Double(rawValue)/12.0
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import UIKit
import XCPlayground
import GameKit

struct Target {
static private let path = (XCPSharedDataDirectoryPath as NSString).stringByAppendingPathComponent("Target.plist")
let targetView = UIImageView(image: UIImage(named: "Target.png"))
let startingMarkerView = UIImageView(image: UIImage(named: "RightArrow.png"))
let targetCoordinateX: Int
let targetCoordinateY: Int

init() {
(targetCoordinateX, targetCoordinateY) = Target.readFromFile()
positionTargetAndStartingView()
}
private init(targetCoordinateX: Int, targetCoordinateY: Int) {
self.targetCoordinateX = targetCoordinateX
self.targetCoordinateY = targetCoordinateY
positionTargetAndStartingView()
}

func positionTargetAndStartingView() {
targetView.frame = CGRect(x: targetCoordinateX - targetHorizontalOffset, y: targetCoordinateY - targetVerticalOffset, width: targetWidth, height: targetHeight)
startingMarkerView.frame = CGRect(x: centerX - targetHorizontalOffset, y: centerY - targetVerticalOffset, width: targetWidth, height: targetHeight)
}

func containsPoint(x: CGFloat, y: CGFloat) -> Bool {
return abs(Int(x) - targetCoordinateX) < targetHorizontalOffset && abs(Int(y) - targetCoordinateY) < targetHorizontalOffset
}



static func readFromFile() -> (Int, Int) {
guard let dictionary = NSDictionary(contentsOfFile: path), x = dictionary["x"] as? NSNumber, y = dictionary["y"] as? NSNumber else {
Target.writeToFile(x: 8 * targetWidth, y: 3 * targetHeight)
return (8 * targetWidth, 3 * targetHeight)
}
return (x.integerValue, y.integerValue)

}

static func writeToFile(x x: Int, y: Int) {
let dictionary = ["x" : x, "y" : y] as NSDictionary
dictionary.writeToFile(Target.path, atomically: true)
}


func resetTarget() -> Target {
let source = GKARC4RandomSource()
source.dropValuesWithCount(1000)
let distribution = GKShuffledDistribution(lowestValue: 1, highestValue: 11)
let x = distribution.nextInt() * targetWidth
let y = distribution.nextInt() * targetHeight
Target.writeToFile(x: x, y: y)
return Target(targetCoordinateX: x, targetCoordinateY: y)
}




}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import UIKit

public private(set) var turtle = Turtle()


public struct Turtle {

private var currentPath: Path
public let view: TurtleView
private var avatar: Avatar
private let target: Target

// MARK: - Initializers

public init() {
let terrariumFrame = CGRect(x: 0, y: 0, width: width, height: height)
avatar = Avatar()
view = TurtleView(frame: terrariumFrame, avatarView: avatar.view)
currentPath = Path(startingPoint: CGPoint(x: centerX , y: centerY))
target = Target()
view.addPath(currentPath)
view.addSubview(target.targetView)
view.addSubview(target.startingMarkerView)
updateAvatar()
}
private init(currentPath: Path, view: TurtleView, avatar: Avatar, target: Target){
self.currentPath = currentPath
self.view = view
self.avatar = avatar
self.target = target
updateAvatar()
}

// MARK: - Position

func forward(distance: Double) {
let path = currentPath.forward(distance, inDirection: avatar.headingInRadians)
turtle = Turtle(currentPath: path, view: view, avatar: avatar, target: target)
if target.containsPoint(path.currentPoint.x, y: path.currentPoint.y) {
view.backgroundColor = victoryColor
} else {
view.backgroundColor = environmentColor
}
}

// MARK: - Colors

func penColor(penColor: PenColor) {
let path = Path(startingPoint:currentPath.currentPoint, penColor: penColor )
view.addPath(path)
turtle = Turtle(currentPath: path, view: view, avatar: avatar.penColor(penColor), target: target)

}
func nextColor() {
penColor(currentPath.penColor.next())
}

// MARK: - Direction

func increaseHeadingBy(degrees: Double) {
turtle = Turtle(currentPath: currentPath, view: view, avatar: avatar.increaseHeadingBy(degrees), target: target)

}


// MARK: Utility

private func updateAvatar() {
view.updateAvatarTransform(avatar.positionTransform(currentPath.currentPoint))
}
func resetTarget() {
turtle = Turtle(currentPath: currentPath, view: view, avatar: avatar, target: target.resetTarget())
}
}

extension Turtle: CustomPlaygroundQuickLookable {
public func customPlaygroundQuickLook() -> PlaygroundQuickLook {

return PlaygroundQuickLook(reflecting: view)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import UIKit
import CoreGraphics


public class TurtleView: UIView {
private var paths = [Path]()
private var avatarView = UIImageView()


// MARK: Initializers
init(frame: CGRect, avatarView: UIImageView) {
super.init(frame: frame)
self.avatarView = avatarView
backgroundColor = environmentColor
addSubview(avatarView)
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder:aDecoder)
}

// MARK: Draw Methods
override public func drawRect(rect: CGRect) {
for path in paths {
path.penColor.color.setStroke()
path.bezierPath.stroke()
}
}
func addPath(path:Path) {
paths.append(path)
}
func updateAvatarTransform(transform: CGAffineTransform) {
avatarView.transform = transform
}
}
Loading

0 comments on commit b4bb371

Please sign in to comment.