Skip to content

Commit

Permalink
beginning of explosion effect
Browse files Browse the repository at this point in the history
  • Loading branch information
artur-ios-dev committed Apr 22, 2018
1 parent eb2570b commit a7a7667
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 13 deletions.
26 changes: 21 additions & 5 deletions Demo/Demo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
0BBBF5F72088A4DC001F0C00 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0BBBF5F62088A4DC001F0C00 /* Assets.xcassets */; };
0BBBF5FA2088A4DC001F0C00 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0BBBF5F82088A4DC001F0C00 /* LaunchScreen.storyboard */; };
0BDA574F2089DFF40037BD2C /* GlassBreakAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BDA57492089DFF40037BD2C /* GlassBreakAnimation.swift */; };
0BDA57502089DFF40037BD2C /* Piece.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BDA574B2089DFF40037BD2C /* Piece.swift */; };
0BDA57502089DFF40037BD2C /* GlassPiece.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BDA574B2089DFF40037BD2C /* GlassPiece.swift */; };
0BDA57512089DFF40037BD2C /* GridSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BDA574C2089DFF40037BD2C /* GridSize.swift */; };
0BDA57522089DFF40037BD2C /* UIViewExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BDA574D2089DFF40037BD2C /* UIViewExtensions.swift */; };
0BDA57532089DFF40037BD2C /* ClosedRangeExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BDA574E2089DFF40037BD2C /* ClosedRangeExtension.swift */; };
14A6616B208BE2BB0081091A /* ExplosionAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14A6616A208BE2BB0081091A /* ExplosionAnimation.swift */; };
14A6616D208BE3160081091A /* ExplosionPiece.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14A6616C208BE3160081091A /* ExplosionPiece.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -28,10 +30,12 @@
0BBBF5F92088A4DC001F0C00 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
0BBBF5FB2088A4DC001F0C00 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
0BDA57492089DFF40037BD2C /* GlassBreakAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlassBreakAnimation.swift; sourceTree = "<group>"; };
0BDA574B2089DFF40037BD2C /* Piece.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Piece.swift; sourceTree = "<group>"; };
0BDA574B2089DFF40037BD2C /* GlassPiece.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlassPiece.swift; sourceTree = "<group>"; };
0BDA574C2089DFF40037BD2C /* GridSize.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GridSize.swift; sourceTree = "<group>"; };
0BDA574D2089DFF40037BD2C /* UIViewExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewExtensions.swift; sourceTree = "<group>"; };
0BDA574E2089DFF40037BD2C /* ClosedRangeExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClosedRangeExtension.swift; sourceTree = "<group>"; };
14A6616A208BE2BB0081091A /* ExplosionAnimation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExplosionAnimation.swift; sourceTree = "<group>"; };
14A6616C208BE3160081091A /* ExplosionPiece.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExplosionPiece.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -78,7 +82,9 @@
0BDA57482089DFF40037BD2C /* Source */ = {
isa = PBXGroup;
children = (
14A66169208BE2AA0081091A /* Explosion */,
0BDA574A2089DFF40037BD2C /* GlassBreak */,
0BDA574C2089DFF40037BD2C /* GridSize.swift */,
0BDA574D2089DFF40037BD2C /* UIViewExtensions.swift */,
0BDA574E2089DFF40037BD2C /* ClosedRangeExtension.swift */,
);
Expand All @@ -90,12 +96,20 @@
isa = PBXGroup;
children = (
0BDA57492089DFF40037BD2C /* GlassBreakAnimation.swift */,
0BDA574B2089DFF40037BD2C /* Piece.swift */,
0BDA574C2089DFF40037BD2C /* GridSize.swift */,
0BDA574B2089DFF40037BD2C /* GlassPiece.swift */,
);
path = GlassBreak;
sourceTree = "<group>";
};
14A66169208BE2AA0081091A /* Explosion */ = {
isa = PBXGroup;
children = (
14A6616A208BE2BB0081091A /* ExplosionAnimation.swift */,
14A6616C208BE3160081091A /* ExplosionPiece.swift */,
);
path = Explosion;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -169,8 +183,10 @@
files = (
0BDA57532089DFF40037BD2C /* ClosedRangeExtension.swift in Sources */,
0BDA57512089DFF40037BD2C /* GridSize.swift in Sources */,
0BDA57502089DFF40037BD2C /* Piece.swift in Sources */,
14A6616D208BE3160081091A /* ExplosionPiece.swift in Sources */,
0BDA57502089DFF40037BD2C /* GlassPiece.swift in Sources */,
0BBBF5F22088A4DB001F0C00 /* ViewController.swift in Sources */,
14A6616B208BE2BB0081091A /* ExplosionAnimation.swift in Sources */,
0BBBF5F02088A4DB001F0C00 /* AppDelegate.swift in Sources */,
0BDA57522089DFF40037BD2C /* UIViewExtensions.swift in Sources */,
0BDA574F2089DFF40037BD2C /* GlassBreakAnimation.swift in Sources */,
Expand Down
80 changes: 80 additions & 0 deletions Source/Explosion/ExplosionAnimation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//
// ExplosionAnimation.swift
// Demo
//
// Created by Artur Rymarz on 21.04.2018.
// Copyright © 2018 Artrmz. All rights reserved.
//

import UIKit

public extension UIView {
public func explode(size: GridSize = GridSize(columns: 10, rows: 10)) {
guard let screenshot = self.screenshot, !isHidden else {
return
}

let pieces = calculatePieces(for: screenshot, size: size)
explodeAnimation(with: pieces)
}


// TODO: extract some methods between both animations (break glass and explosion)
private func explodeAnimation(with pieces: [ExplosionPiece]) {
let animationView = UIView()
animationView.clipsToBounds = true
animationView.frame = self.frame
guard let superview = self.superview else {
return
}

self.isHidden = true
superview.addSubview(animationView)

let pieceLayers = showJointPieces(pieces, animationView: animationView)
}

// TODO: extract for both animations
private func showJointPieces(_ pieces: [ExplosionPiece], animationView: UIView) -> [CALayer] {
var allPieceLayers = [CALayer]()
for index in 0..<pieces.count {
let piece = pieces[index]
let pieceLayer = CALayer()
pieceLayer.contents = piece.image.cgImage
pieceLayer.frame = CGRect(x: piece.position.x, y: piece.position.y, width: piece.image.size.width, height: piece.image.size.height)
animationView.layer.addSublayer(pieceLayer)
allPieceLayers.append(pieceLayer)
}

return allPieceLayers
}

private func calculatePieces(for image: UIImage, size: GridSize) -> [ExplosionPiece] {
var pieces = [ExplosionPiece]()
let columns = size.columns
let rows = size.rows

let singlePieceSize = CGSize(width: image.size.width / CGFloat(columns), height: image.size.height / CGFloat(rows))

for row in 0..<rows {
for column in 0..<columns {
// TODO: wrong scale?
let position = CGPoint(x: CGFloat(column) * singlePieceSize.width, y: CGFloat(row) * singlePieceSize.height)

let cropRect = CGRect(origin: position, size: singlePieceSize)
guard
let cgImage = image.cgImage,
let pieceCgImage = cgImage.cropping(to: cropRect)
else {
continue
}

let pieceImage = UIImage(cgImage: pieceCgImage)
let piece = ExplosionPiece(position: position, image: pieceImage)
pieces.append(piece)
}
}

return pieces
}
}
14 changes: 14 additions & 0 deletions Source/Explosion/ExplosionPiece.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// ExplosionPiece.swift
// Demo
//
// Created by Artur Rymarz on 21.04.2018.
// Copyright © 2018 Artrmz. All rights reserved.
//

import UIKit

struct ExplosionPiece {
let position: CGPoint
let image: UIImage
}
13 changes: 7 additions & 6 deletions Source/GlassBreak/GlassBreakAnimation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public extension UIView {
breakAnimation(with: pieces, columns: size.columns, removeAfterCompletion: removeAfterCompletion, completion: completion)
}

private func breakAnimation(with pieces: [[Piece]], columns: Int, removeAfterCompletion: Bool, completion: (() -> Void)?) {
private func breakAnimation(with pieces: [[GlassPiece]], columns: Int, removeAfterCompletion: Bool, completion: (() -> Void)?) {
let animationView = UIView()
animationView.clipsToBounds = true
animationView.frame = self.frame
Expand All @@ -39,7 +39,8 @@ public extension UIView {
animateFalling(allPieceLayers: pieceLayers, columns: CGFloat(columns), animationView: animationView, removeAfterCompletion: removeAfterCompletion, completion: completion)
}

private func showJointPieces(_ pieces: [[Piece]], animationView: UIView) -> [CALayer] {
// TODO: create protocol and extract for both animations
private func showJointPieces(_ pieces: [[GlassPiece]], animationView: UIView) -> [CALayer] {
var allPieceLayers = [CALayer]()
for row in 0..<pieces.count {
for column in 0..<pieces[row].count {
Expand Down Expand Up @@ -108,16 +109,16 @@ public extension UIView {
return corners
}

private func calculatePieces(for image: UIImage, size: GridSize) -> [[Piece]] {
var pieces = [[Piece]]()
private func calculatePieces(for image: UIImage, size: GridSize) -> [[GlassPiece]] {
var pieces = [[GlassPiece]]()
let columns = size.columns
let rows = size.rows

let singlePieceSize = CGSize(width: image.size.width / CGFloat(columns), height: image.size.height / CGFloat(rows))
let corners = calculateCorners(for: singlePieceSize, gridSize: size)

for row in 0..<rows {
var rowPieces = [Piece]()
var rowPieces = [GlassPiece]()
for column in 0..<columns {
let lt = corners[row][column]
let rt = corners[row][column + 1]
Expand All @@ -135,7 +136,7 @@ public extension UIView {
continue
}

let piece = Piece(position: block.origin, corners: [lt, rt, rb, lb], image: pieceImage)
let piece = GlassPiece(position: block.origin, corners: [lt, rt, rb, lb], image: pieceImage)
rowPieces.append(piece)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Piece.swift
// GlassPiece.swift
// Demo
//
// Created by Artur Rymarz on 20.04.2018.
Expand All @@ -8,7 +8,7 @@

import UIKit

struct Piece {
struct GlassPiece {
let position: CGPoint
let corners: [CGPoint]
let image: UIImage
Expand Down
File renamed without changes.

0 comments on commit a7a7667

Please sign in to comment.