Skip to content

Commit

Permalink
prepare a release
Browse files Browse the repository at this point in the history
  • Loading branch information
potato04 committed May 5, 2019
1 parent f9deb9e commit 23bb1c5
Show file tree
Hide file tree
Showing 20 changed files with 553 additions and 23 deletions.
32 changes: 16 additions & 16 deletions ThanosSnap/ThanosSnap.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
/* Begin PBXBuildFile section */
4BA017A122760D68005B59D3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BA017A022760D68005B59D3 /* AppDelegate.swift */; };
4BA017A322760D68005B59D3 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BA017A222760D68005B59D3 /* ViewController.swift */; };
4BA017A622760D68005B59D3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4BA017A422760D68005B59D3 /* Main.storyboard */; };
4BA017A822760D6B005B59D3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4BA017A722760D6B005B59D3 /* Assets.xcassets */; };
4BA017AB22760D6B005B59D3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4BA017A922760D6B005B59D3 /* LaunchScreen.storyboard */; };
4BA017BC22760E7A005B59D3 /* thanos_dust_5.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 4BA017B422760E79005B59D3 /* thanos_dust_5.mp3 */; };
4BA017BD22760E7A005B59D3 /* thanos_reverse_sound.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 4BA017B522760E79005B59D3 /* thanos_reverse_sound.mp3 */; };
Expand All @@ -20,14 +18,16 @@
4BA017C122760E7A005B59D3 /* thanos_dust_1.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 4BA017B922760E79005B59D3 /* thanos_dust_1.mp3 */; };
4BA017C222760E7A005B59D3 /* thanos_dust_6.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 4BA017BA22760E79005B59D3 /* thanos_dust_6.mp3 */; };
4BA017C322760E7A005B59D3 /* thanos_snap_sound.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 4BA017BB22760E7A005B59D3 /* thanos_snap_sound.mp3 */; };
4BA017C522760F1D005B59D3 /* AnimatableSpriteLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BA017C422760F1D005B59D3 /* AnimatableSpriteLayer.swift */; };
4BA017C72277108C005B59D3 /* ThanosGauntlet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BA017C62277108C005B59D3 /* ThanosGauntlet.swift */; };
4BA017D3227A10B8005B59D3 /* DustEffectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BA017D2227A10B8005B59D3 /* DustEffectView.swift */; };
4BA017D7227A1110005B59D3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4BA017D6227A1110005B59D3 /* Assets.xcassets */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
4BA0179D22760D68005B59D3 /* ThanosSnap.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ThanosSnap.app; sourceTree = BUILT_PRODUCTS_DIR; };
4BA017A022760D68005B59D3 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
4BA017A222760D68005B59D3 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
4BA017A522760D68005B59D3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
4BA017A722760D6B005B59D3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
4BA017AA22760D6B005B59D3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
4BA017AC22760D6B005B59D3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
4BA017B422760E79005B59D3 /* thanos_dust_5.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = thanos_dust_5.mp3; sourceTree = "<group>"; };
Expand All @@ -38,6 +38,10 @@
4BA017B922760E79005B59D3 /* thanos_dust_1.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = thanos_dust_1.mp3; sourceTree = "<group>"; };
4BA017BA22760E79005B59D3 /* thanos_dust_6.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = thanos_dust_6.mp3; sourceTree = "<group>"; };
4BA017BB22760E7A005B59D3 /* thanos_snap_sound.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = thanos_snap_sound.mp3; sourceTree = "<group>"; };
4BA017C422760F1D005B59D3 /* AnimatableSpriteLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimatableSpriteLayer.swift; sourceTree = "<group>"; };
4BA017C62277108C005B59D3 /* ThanosGauntlet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThanosGauntlet.swift; sourceTree = "<group>"; };
4BA017D2227A10B8005B59D3 /* DustEffectView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DustEffectView.swift; sourceTree = "<group>"; };
4BA017D6227A1110005B59D3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -74,15 +78,17 @@
4BA017B322760E3E005B59D3 /* Sounds */,
4BA017A022760D68005B59D3 /* AppDelegate.swift */,
4BA017A222760D68005B59D3 /* ViewController.swift */,
4BA017A422760D68005B59D3 /* Main.storyboard */,
4BA017D2227A10B8005B59D3 /* DustEffectView.swift */,
4BA017C422760F1D005B59D3 /* AnimatableSpriteLayer.swift */,
4BA017C62277108C005B59D3 /* ThanosGauntlet.swift */,
);
path = ThanosSnap;
sourceTree = "<group>";
};
4BA017B222760DA2005B59D3 /* Supporting Files */ = {
isa = PBXGroup;
children = (
4BA017A722760D6B005B59D3 /* Assets.xcassets */,
4BA017D6227A1110005B59D3 /* Assets.xcassets */,
4BA017A922760D6B005B59D3 /* LaunchScreen.storyboard */,
4BA017AC22760D6B005B59D3 /* Info.plist */,
);
Expand Down Expand Up @@ -164,8 +170,7 @@
files = (
4BA017BD22760E7A005B59D3 /* thanos_reverse_sound.mp3 in Resources */,
4BA017AB22760D6B005B59D3 /* LaunchScreen.storyboard in Resources */,
4BA017A822760D6B005B59D3 /* Assets.xcassets in Resources */,
4BA017A622760D68005B59D3 /* Main.storyboard in Resources */,
4BA017D7227A1110005B59D3 /* Assets.xcassets in Resources */,
4BA017C222760E7A005B59D3 /* thanos_dust_6.mp3 in Resources */,
4BA017C122760E7A005B59D3 /* thanos_dust_1.mp3 in Resources */,
4BA017BF22760E7A005B59D3 /* thanos_dust_4.mp3 in Resources */,
Expand All @@ -183,6 +188,9 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4BA017D3227A10B8005B59D3 /* DustEffectView.swift in Sources */,
4BA017C72277108C005B59D3 /* ThanosGauntlet.swift in Sources */,
4BA017C522760F1D005B59D3 /* AnimatableSpriteLayer.swift in Sources */,
4BA017A322760D68005B59D3 /* ViewController.swift in Sources */,
4BA017A122760D68005B59D3 /* AppDelegate.swift in Sources */,
);
Expand All @@ -191,14 +199,6 @@
/* End PBXSourcesBuildPhase section */

/* Begin PBXVariantGroup section */
4BA017A422760D68005B59D3 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
4BA017A522760D68005B59D3 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
4BA017A922760D6B005B59D3 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
Expand Down
36 changes: 36 additions & 0 deletions ThanosSnap/ThanosSnap/AnimatableSpriteLayer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// AnimatableSpriteLayer.swift
// ThanosSnap
//
// Inspired by https://www.calayer.com/core-animation/2018/01/05/creating-a-simple-animatable-sprite-layer.html
//

import UIKit

class AnimatableSpriteLayer: CALayer {

private var animationValues = [CGFloat]()

convenience init(spriteSheetImage: UIImage, spriteFrameSize: CGSize ) {
self.init()

masksToBounds = true
contentsGravity = CALayerContentsGravity.left
contents = spriteSheetImage.cgImage
bounds.size = spriteFrameSize

let frameCount = Int(spriteSheetImage.size.width / spriteFrameSize.width)
for frameIndex in 0..<frameCount {
animationValues.append(CGFloat(frameIndex) / CGFloat(frameCount))
}
}

func play() {
let spriteKeyframeAnimation = CAKeyframeAnimation(keyPath: "contentsRect.origin.x")
spriteKeyframeAnimation.values = animationValues
spriteKeyframeAnimation.duration = 2.0
spriteKeyframeAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
spriteKeyframeAnimation.calculationMode = CAAnimationCalculationMode.discrete
add(spriteKeyframeAnimation, forKey: nil)
}
}
6 changes: 6 additions & 0 deletions ThanosSnap/ThanosSnap/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.

self.window = UIWindow(frame: UIScreen.main.bounds)
let controller = ViewController()
self.window?.rootViewController = controller
self.window?.makeKeyAndVisible()

return true
}

Expand Down
12 changes: 8 additions & 4 deletions ThanosSnap/ThanosSnap/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina6_1" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="ThanosSnap" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
Expand Down
160 changes: 160 additions & 0 deletions ThanosSnap/ThanosSnap/DustEffectView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
//
// DustEffectView.swift
// ThanosSnap
//
// Created by potato04 on 2019/5/1.
// Copyright © 2019 potato04. All rights reserved.
//

import UIKit
import AVFoundation

protocol DustEffectViewDelegate: class {
func DustEffectDidCompleted()
}

class DustEffectView: UIView, CAAnimationDelegate {

weak var delegate: DustEffectViewDelegate?

var soundPlayer: AVAudioPlayer?

var image: UIImage? {
didSet {
if let image = image {
let images = createDustImages(image: image)
let imagesCount = images.count
for (i, image) in images.enumerated() {
// create layer
let layer = CALayer()
layer.frame = bounds
layer.contents = image.cgImage
self.layer.addSublayer(layer)


let centerX = Double(layer.position.x)
let centerY = Double(layer.position.y)

// attach animation
let radian1 = Double.pi / 12 * Double.random(in: -0.5..<0.5)
let radian2 = Double.pi / 12 * Double.random(in: -0.5..<0.5)

let random = Double.pi * 2 * Double.random(in: -0.5..<0.5)
let transX = 30 * cos(random)
let transY = 15 * sin(random)

//x' = x*cos(a) - y*sin(a)
//y' = y*cos(a) + x*sin(a)
let realTransX = transX * cos(radian1) - transY * sin(radian1)
let realTransY = transY * cos(radian1) + transX * sin(radian1)
let realEndPoint = CGPoint(x: centerX + realTransX, y: centerY + realTransY)
let controlPoint = CGPoint(x: centerX + transX, y: centerY + transY)

let movePath = UIBezierPath()
movePath.move(to: layer.position)
movePath.addQuadCurve(to: realEndPoint, controlPoint: controlPoint)

let moveAnimation = CAKeyframeAnimation(keyPath: "position")
moveAnimation.path = movePath.cgPath
moveAnimation.calculationMode = .paced

let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotateAnimation.toValue = radian1 + radian2

let fadeOutAnimation = CABasicAnimation(keyPath: "opacity")
fadeOutAnimation.toValue = 0.0

let animationGroup = CAAnimationGroup()
animationGroup.animations = [moveAnimation, rotateAnimation, fadeOutAnimation]
animationGroup.duration = 1
animationGroup.beginTime = CACurrentMediaTime() + 1.35 * Double(i) / Double(imagesCount)
animationGroup.isRemovedOnCompletion = false
animationGroup.fillMode = .forwards

if i == images.count - 1 {
animationGroup.delegate = self
}
layer.add(animationGroup, forKey: nil)
}

soundPlayer = try? AVAudioPlayer(contentsOf: URL(fileURLWithPath: Bundle.main.path(forResource: "thanos_dust_\(Int.random(in: 1...6))", ofType: "mp3")!))
if soundPlayer != nil {
soundPlayer!.prepareToPlay()
soundPlayer!.play()
}
}

}
}

override init(frame: CGRect) {
super.init(frame: frame)
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}

private func removeAllSublayers() {
if let sublayers = layer.sublayers {
for layer in sublayers {
layer.removeFromSuperlayer()
}
}
}

func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
if flag {
removeAllSublayers()
delegate?.DustEffectDidCompleted()
}
}


private func createDustImages(image: UIImage) -> [UIImage] {
var result = [UIImage]()
guard let inputCGImage = image.cgImage else {
return result
}
let colorSpace = CGColorSpaceCreateDeviceRGB()
let width = inputCGImage.width
let height = inputCGImage.height
let bytesPerPixel = 4
let bitsPerComponent = 8
let bytesPerRow = bytesPerPixel * width
let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Little.rawValue

guard let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo) else {
return result
}
context.draw(inputCGImage, in: CGRect(x: 0, y: 0, width: width, height: height))
guard let buffer = context.data else {
return result
}

let pixelBuffer = buffer.bindMemory(to: UInt32.self, capacity: width * height)

//尝试提高这个沙化图片数量,效果也会越好
let imagesCount = 32
var framePixels = Array(repeating: Array(repeating: UInt32(0), count: width * height), count: imagesCount)

for column in 0..<width {
for row in 0..<height {
let offset = row * width + column
for _ in 0...1 {
let temp = Double.random(in: 0..<1) + 2 * (Double(column)/Double(width))
let index = Int(floor(Double(imagesCount) * ( temp / 3)))
framePixels[index][offset] = pixelBuffer[offset]
}
}
}
for frame in framePixels {
let data = UnsafeMutablePointer(mutating: frame)
guard let context = CGContext(data: data, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo) else {
continue
}
result.append(UIImage(cgImage: context.makeImage()!, scale: image.scale, orientation: image.imageOrientation))
}
return result
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "baidu@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "baidu@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
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,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "google@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "google@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
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

0 comments on commit 23bb1c5

Please sign in to comment.