Initial version of Privyet, after finishing tutorial on Bloc Web site

This commit is contained in:
Amy G. Bowersox 2020-05-24 21:56:11 -06:00
commit 7731be4ccb
54 changed files with 2192 additions and 0 deletions

View File

@ -0,0 +1,647 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
E1EB2FB2247A33F200AA6A24 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EB2FB1247A33F200AA6A24 /* AppDelegate.swift */; };
E1EB2FB6247A33F200AA6A24 /* Actions.sks in Resources */ = {isa = PBXBuildFile; fileRef = E1EB2FB5247A33F200AA6A24 /* Actions.sks */; };
E1EB2FB8247A33F200AA6A24 /* GameScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EB2FB7247A33F200AA6A24 /* GameScene.swift */; };
E1EB2FBA247A33F200AA6A24 /* GameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EB2FB9247A33F200AA6A24 /* GameViewController.swift */; };
E1EB2FBD247A33F200AA6A24 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E1EB2FBB247A33F200AA6A24 /* Main.storyboard */; };
E1EB2FBF247A340600AA6A24 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E1EB2FBE247A340600AA6A24 /* Assets.xcassets */; };
E1EB2FC2247A340600AA6A24 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E1EB2FC0247A340600AA6A24 /* LaunchScreen.storyboard */; };
E1EB2FCD247A340700AA6A24 /* PrivyetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EB2FCC247A340700AA6A24 /* PrivyetTests.swift */; };
E1EB2FD8247A340700AA6A24 /* PrivyetUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EB2FD7247A340700AA6A24 /* PrivyetUITests.swift */; };
E1EB2FE6247A37EB00AA6A24 /* Sounds in Resources */ = {isa = PBXBuildFile; fileRef = E1EB2FE5247A37EB00AA6A24 /* Sounds */; };
E1EB2FE9247A3CB900AA6A24 /* Array2D.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EB2FE8247A3CB900AA6A24 /* Array2D.swift */; };
E1EB2FEB247A408800AA6A24 /* Block.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EB2FEA247A408800AA6A24 /* Block.swift */; };
E1EB2FED247A459200AA6A24 /* Shape.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EB2FEC247A459200AA6A24 /* Shape.swift */; };
E1EB2FEF247A4D6E00AA6A24 /* SquareShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EB2FEE247A4D6E00AA6A24 /* SquareShape.swift */; };
E1EB2FF1247A4F4900AA6A24 /* TShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EB2FF0247A4F4900AA6A24 /* TShape.swift */; };
E1EB2FF3247A543000AA6A24 /* LineShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EB2FF2247A543000AA6A24 /* LineShape.swift */; };
E1EB2FF5247A55CF00AA6A24 /* LShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EB2FF4247A55CF00AA6A24 /* LShape.swift */; };
E1EB2FF7247A58D900AA6A24 /* JShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EB2FF6247A58D900AA6A24 /* JShape.swift */; };
E1EB2FF9247A5C8200AA6A24 /* SShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EB2FF8247A5C8200AA6A24 /* SShape.swift */; };
E1EB2FFB247A5E4200AA6A24 /* ZShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EB2FFA247A5E4200AA6A24 /* ZShape.swift */; };
E1EB2FFD247AF6ED00AA6A24 /* Privyet.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EB2FFC247AF6ED00AA6A24 /* Privyet.swift */; };
E1EB2FFE247B2FFA00AA6A24 /* Sprites.atlas in Resources */ = {isa = PBXBuildFile; fileRef = E1EB2FE7247A380100AA6A24 /* Sprites.atlas */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
E1EB2FC9247A340700AA6A24 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = E1EB2FA6247A33F200AA6A24 /* Project object */;
proxyType = 1;
remoteGlobalIDString = E1EB2FAD247A33F200AA6A24;
remoteInfo = Privyet;
};
E1EB2FD4247A340700AA6A24 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = E1EB2FA6247A33F200AA6A24 /* Project object */;
proxyType = 1;
remoteGlobalIDString = E1EB2FAD247A33F200AA6A24;
remoteInfo = Privyet;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
E1EB2FAE247A33F200AA6A24 /* Privyet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Privyet.app; sourceTree = BUILT_PRODUCTS_DIR; };
E1EB2FB1247A33F200AA6A24 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
E1EB2FB5247A33F200AA6A24 /* Actions.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = Actions.sks; sourceTree = "<group>"; };
E1EB2FB7247A33F200AA6A24 /* GameScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameScene.swift; sourceTree = "<group>"; };
E1EB2FB9247A33F200AA6A24 /* GameViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameViewController.swift; sourceTree = "<group>"; };
E1EB2FBC247A33F200AA6A24 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
E1EB2FBE247A340600AA6A24 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
E1EB2FC1247A340600AA6A24 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
E1EB2FC3247A340600AA6A24 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
E1EB2FC8247A340700AA6A24 /* PrivyetTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PrivyetTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
E1EB2FCC247A340700AA6A24 /* PrivyetTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivyetTests.swift; sourceTree = "<group>"; };
E1EB2FCE247A340700AA6A24 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
E1EB2FD3247A340700AA6A24 /* PrivyetUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PrivyetUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
E1EB2FD7247A340700AA6A24 /* PrivyetUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivyetUITests.swift; sourceTree = "<group>"; };
E1EB2FD9247A340700AA6A24 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
E1EB2FE5247A37EB00AA6A24 /* Sounds */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Sounds; sourceTree = "<group>"; };
E1EB2FE7247A380100AA6A24 /* Sprites.atlas */ = {isa = PBXFileReference; lastKnownFileType = folder.skatlas; path = Sprites.atlas; sourceTree = "<group>"; };
E1EB2FE8247A3CB900AA6A24 /* Array2D.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Array2D.swift; sourceTree = "<group>"; };
E1EB2FEA247A408800AA6A24 /* Block.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Block.swift; sourceTree = "<group>"; };
E1EB2FEC247A459200AA6A24 /* Shape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shape.swift; sourceTree = "<group>"; };
E1EB2FEE247A4D6E00AA6A24 /* SquareShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SquareShape.swift; sourceTree = "<group>"; };
E1EB2FF0247A4F4900AA6A24 /* TShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TShape.swift; sourceTree = "<group>"; };
E1EB2FF2247A543000AA6A24 /* LineShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineShape.swift; sourceTree = "<group>"; };
E1EB2FF4247A55CF00AA6A24 /* LShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LShape.swift; sourceTree = "<group>"; };
E1EB2FF6247A58D900AA6A24 /* JShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JShape.swift; sourceTree = "<group>"; };
E1EB2FF8247A5C8200AA6A24 /* SShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SShape.swift; sourceTree = "<group>"; };
E1EB2FFA247A5E4200AA6A24 /* ZShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZShape.swift; sourceTree = "<group>"; };
E1EB2FFC247AF6ED00AA6A24 /* Privyet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Privyet.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
E1EB2FAB247A33F200AA6A24 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
E1EB2FC5247A340700AA6A24 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
E1EB2FD0247A340700AA6A24 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
E1EB2FA5247A33F200AA6A24 = {
isa = PBXGroup;
children = (
E1EB2FB0247A33F200AA6A24 /* Privyet */,
E1EB2FCB247A340700AA6A24 /* PrivyetTests */,
E1EB2FD6247A340700AA6A24 /* PrivyetUITests */,
E1EB2FAF247A33F200AA6A24 /* Products */,
);
sourceTree = "<group>";
};
E1EB2FAF247A33F200AA6A24 /* Products */ = {
isa = PBXGroup;
children = (
E1EB2FAE247A33F200AA6A24 /* Privyet.app */,
E1EB2FC8247A340700AA6A24 /* PrivyetTests.xctest */,
E1EB2FD3247A340700AA6A24 /* PrivyetUITests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
E1EB2FB0247A33F200AA6A24 /* Privyet */ = {
isa = PBXGroup;
children = (
E1EB2FB1247A33F200AA6A24 /* AppDelegate.swift */,
E1EB2FB5247A33F200AA6A24 /* Actions.sks */,
E1EB2FB7247A33F200AA6A24 /* GameScene.swift */,
E1EB2FB9247A33F200AA6A24 /* GameViewController.swift */,
E1EB2FE7247A380100AA6A24 /* Sprites.atlas */,
E1EB2FE5247A37EB00AA6A24 /* Sounds */,
E1EB2FBB247A33F200AA6A24 /* Main.storyboard */,
E1EB2FBE247A340600AA6A24 /* Assets.xcassets */,
E1EB2FC0247A340600AA6A24 /* LaunchScreen.storyboard */,
E1EB2FC3247A340600AA6A24 /* Info.plist */,
E1EB2FE8247A3CB900AA6A24 /* Array2D.swift */,
E1EB2FEA247A408800AA6A24 /* Block.swift */,
E1EB2FEC247A459200AA6A24 /* Shape.swift */,
E1EB2FEE247A4D6E00AA6A24 /* SquareShape.swift */,
E1EB2FF0247A4F4900AA6A24 /* TShape.swift */,
E1EB2FF2247A543000AA6A24 /* LineShape.swift */,
E1EB2FF4247A55CF00AA6A24 /* LShape.swift */,
E1EB2FF6247A58D900AA6A24 /* JShape.swift */,
E1EB2FF8247A5C8200AA6A24 /* SShape.swift */,
E1EB2FFA247A5E4200AA6A24 /* ZShape.swift */,
E1EB2FFC247AF6ED00AA6A24 /* Privyet.swift */,
);
path = Privyet;
sourceTree = "<group>";
};
E1EB2FCB247A340700AA6A24 /* PrivyetTests */ = {
isa = PBXGroup;
children = (
E1EB2FCC247A340700AA6A24 /* PrivyetTests.swift */,
E1EB2FCE247A340700AA6A24 /* Info.plist */,
);
path = PrivyetTests;
sourceTree = "<group>";
};
E1EB2FD6247A340700AA6A24 /* PrivyetUITests */ = {
isa = PBXGroup;
children = (
E1EB2FD7247A340700AA6A24 /* PrivyetUITests.swift */,
E1EB2FD9247A340700AA6A24 /* Info.plist */,
);
path = PrivyetUITests;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
E1EB2FAD247A33F200AA6A24 /* Privyet */ = {
isa = PBXNativeTarget;
buildConfigurationList = E1EB2FDC247A340700AA6A24 /* Build configuration list for PBXNativeTarget "Privyet" */;
buildPhases = (
E1EB2FAA247A33F200AA6A24 /* Sources */,
E1EB2FAB247A33F200AA6A24 /* Frameworks */,
E1EB2FAC247A33F200AA6A24 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = Privyet;
productName = Privyet;
productReference = E1EB2FAE247A33F200AA6A24 /* Privyet.app */;
productType = "com.apple.product-type.application";
};
E1EB2FC7247A340700AA6A24 /* PrivyetTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = E1EB2FDF247A340700AA6A24 /* Build configuration list for PBXNativeTarget "PrivyetTests" */;
buildPhases = (
E1EB2FC4247A340700AA6A24 /* Sources */,
E1EB2FC5247A340700AA6A24 /* Frameworks */,
E1EB2FC6247A340700AA6A24 /* Resources */,
);
buildRules = (
);
dependencies = (
E1EB2FCA247A340700AA6A24 /* PBXTargetDependency */,
);
name = PrivyetTests;
productName = PrivyetTests;
productReference = E1EB2FC8247A340700AA6A24 /* PrivyetTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
E1EB2FD2247A340700AA6A24 /* PrivyetUITests */ = {
isa = PBXNativeTarget;
buildConfigurationList = E1EB2FE2247A340700AA6A24 /* Build configuration list for PBXNativeTarget "PrivyetUITests" */;
buildPhases = (
E1EB2FCF247A340700AA6A24 /* Sources */,
E1EB2FD0247A340700AA6A24 /* Frameworks */,
E1EB2FD1247A340700AA6A24 /* Resources */,
);
buildRules = (
);
dependencies = (
E1EB2FD5247A340700AA6A24 /* PBXTargetDependency */,
);
name = PrivyetUITests;
productName = PrivyetUITests;
productReference = E1EB2FD3247A340700AA6A24 /* PrivyetUITests.xctest */;
productType = "com.apple.product-type.bundle.ui-testing";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
E1EB2FA6247A33F200AA6A24 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1150;
LastUpgradeCheck = 1150;
ORGANIZATIONNAME = "Erbosoft Metaverse Design Solutions";
TargetAttributes = {
E1EB2FAD247A33F200AA6A24 = {
CreatedOnToolsVersion = 11.5;
};
E1EB2FC7247A340700AA6A24 = {
CreatedOnToolsVersion = 11.5;
TestTargetID = E1EB2FAD247A33F200AA6A24;
};
E1EB2FD2247A340700AA6A24 = {
CreatedOnToolsVersion = 11.5;
TestTargetID = E1EB2FAD247A33F200AA6A24;
};
};
};
buildConfigurationList = E1EB2FA9247A33F200AA6A24 /* Build configuration list for PBXProject "Privyet" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = E1EB2FA5247A33F200AA6A24;
productRefGroup = E1EB2FAF247A33F200AA6A24 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
E1EB2FAD247A33F200AA6A24 /* Privyet */,
E1EB2FC7247A340700AA6A24 /* PrivyetTests */,
E1EB2FD2247A340700AA6A24 /* PrivyetUITests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
E1EB2FAC247A33F200AA6A24 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E1EB2FFE247B2FFA00AA6A24 /* Sprites.atlas in Resources */,
E1EB2FE6247A37EB00AA6A24 /* Sounds in Resources */,
E1EB2FBD247A33F200AA6A24 /* Main.storyboard in Resources */,
E1EB2FBF247A340600AA6A24 /* Assets.xcassets in Resources */,
E1EB2FC2247A340600AA6A24 /* LaunchScreen.storyboard in Resources */,
E1EB2FB6247A33F200AA6A24 /* Actions.sks in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E1EB2FC6247A340700AA6A24 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
E1EB2FD1247A340700AA6A24 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
E1EB2FAA247A33F200AA6A24 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E1EB2FF5247A55CF00AA6A24 /* LShape.swift in Sources */,
E1EB2FEF247A4D6E00AA6A24 /* SquareShape.swift in Sources */,
E1EB2FB8247A33F200AA6A24 /* GameScene.swift in Sources */,
E1EB2FF7247A58D900AA6A24 /* JShape.swift in Sources */,
E1EB2FED247A459200AA6A24 /* Shape.swift in Sources */,
E1EB2FE9247A3CB900AA6A24 /* Array2D.swift in Sources */,
E1EB2FF3247A543000AA6A24 /* LineShape.swift in Sources */,
E1EB2FF9247A5C8200AA6A24 /* SShape.swift in Sources */,
E1EB2FF1247A4F4900AA6A24 /* TShape.swift in Sources */,
E1EB2FFD247AF6ED00AA6A24 /* Privyet.swift in Sources */,
E1EB2FEB247A408800AA6A24 /* Block.swift in Sources */,
E1EB2FBA247A33F200AA6A24 /* GameViewController.swift in Sources */,
E1EB2FFB247A5E4200AA6A24 /* ZShape.swift in Sources */,
E1EB2FB2247A33F200AA6A24 /* AppDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E1EB2FC4247A340700AA6A24 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E1EB2FCD247A340700AA6A24 /* PrivyetTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E1EB2FCF247A340700AA6A24 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E1EB2FD8247A340700AA6A24 /* PrivyetUITests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
E1EB2FCA247A340700AA6A24 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = E1EB2FAD247A33F200AA6A24 /* Privyet */;
targetProxy = E1EB2FC9247A340700AA6A24 /* PBXContainerItemProxy */;
};
E1EB2FD5247A340700AA6A24 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = E1EB2FAD247A33F200AA6A24 /* Privyet */;
targetProxy = E1EB2FD4247A340700AA6A24 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
E1EB2FBB247A33F200AA6A24 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
E1EB2FBC247A33F200AA6A24 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
E1EB2FC0247A340600AA6A24 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
E1EB2FC1247A340600AA6A24 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
E1EB2FDA247A340700AA6A24 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
E1EB2FDB247A340700AA6A24 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
E1EB2FDD247A340700AA6A24 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
INFOPLIST_FILE = Privyet/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 0.1;
PRODUCT_BUNDLE_IDENTIFIER = com.erbosoft.Privyet;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
E1EB2FDE247A340700AA6A24 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
INFOPLIST_FILE = Privyet/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 0.1;
PRODUCT_BUNDLE_IDENTIFIER = com.erbosoft.Privyet;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
E1EB2FE0247A340700AA6A24 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
INFOPLIST_FILE = PrivyetTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.erbosoft.PrivyetTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Privyet.app/Privyet";
};
name = Debug;
};
E1EB2FE1247A340700AA6A24 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
INFOPLIST_FILE = PrivyetTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.erbosoft.PrivyetTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Privyet.app/Privyet";
};
name = Release;
};
E1EB2FE3247A340700AA6A24 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
INFOPLIST_FILE = PrivyetUITests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.erbosoft.PrivyetUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_TARGET_NAME = Privyet;
};
name = Debug;
};
E1EB2FE4247A340700AA6A24 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
INFOPLIST_FILE = PrivyetUITests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.erbosoft.PrivyetUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_TARGET_NAME = Privyet;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
E1EB2FA9247A33F200AA6A24 /* Build configuration list for PBXProject "Privyet" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E1EB2FDA247A340700AA6A24 /* Debug */,
E1EB2FDB247A340700AA6A24 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E1EB2FDC247A340700AA6A24 /* Build configuration list for PBXNativeTarget "Privyet" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E1EB2FDD247A340700AA6A24 /* Debug */,
E1EB2FDE247A340700AA6A24 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E1EB2FDF247A340700AA6A24 /* Build configuration list for PBXNativeTarget "PrivyetTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E1EB2FE0247A340700AA6A24 /* Debug */,
E1EB2FE1247A340700AA6A24 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E1EB2FE2247A340700AA6A24 /* Build configuration list for PBXNativeTarget "PrivyetUITests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E1EB2FE3247A340700AA6A24 /* Debug */,
E1EB2FE4247A340700AA6A24 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = E1EB2FA6247A33F200AA6A24 /* Project object */;
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:Privyet.xcodeproj">
</FileRef>
</Workspace>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildLocationStyle</key>
<string>UseAppPreferences</string>
<key>CustomBuildLocationType</key>
<string>RelativeToDerivedData</string>
<key>DerivedDataLocationStyle</key>
<string>Default</string>
<key>IssueFilterStyle</key>
<string>ShowActiveSchemeOnly</string>
<key>LiveSourceIssuesEnabled</key>
<true/>
<key>ShowSharedSchemesAutomaticallyEnabled</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
uuid = "C3E51D97-D250-4086-A414-DBC5B08EF20F"
type = "1"
version = "2.0">
</Bucket>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>Privyet.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
</dict>
</plist>

BIN
Privyet/Actions.sks Normal file

Binary file not shown.

41
Privyet/AppDelegate.swift Normal file
View File

@ -0,0 +1,41 @@
//
// AppDelegate.swift
// Privyet
//
// Created by Amy Bowersox on 5/23/20.
// Copyright © 2020 Erbosoft Metaverse Design Solutions. All rights reserved.
//
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
}

32
Privyet/Array2D.swift Normal file
View File

@ -0,0 +1,32 @@
//
// Array2D.swift
// Privyet
//
// Created by Amy Bowersox on 5/23/20.
// Copyright © 2020 Erbosoft Metaverse Design Solutions. All rights reserved.
//
import Foundation
class Array2D<T> {
let columns: Int
let rows: Int
var array: Array<T?>
init(columns: Int, rows: Int) {
self.columns = columns
self.rows = rows
array = Array<T?>(repeating: nil, count: rows * columns)
}
subscript(column: Int, row: Int) -> T? {
get {
return array[(row * columns) + column]
}
set(newValue) {
array[(row * columns) + column] = newValue
}
}
}

View File

@ -0,0 +1,101 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"filename" : "icon-29pt.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"filename" : "icon-40pt.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"filename" : "icon-60pt.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"filename" : "background.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "background@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"filename" : "gameboard.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "gameboard@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"filename" : "whitebg.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "whitebg@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 915 B

75
Privyet/Block.swift Normal file
View File

@ -0,0 +1,75 @@
//
// Block.swift
// Privyet
//
// Created by Amy Bowersox on 5/23/20.
// Copyright © 2020 Erbosoft Metaverse Design Solutions. All rights reserved.
//
import Foundation
import SpriteKit
let NumberOfColors: UInt32 = 6
enum BlockColor: Int, CustomStringConvertible {
case Blue = 0, Orange, Purple, Red, Teal, Yellow
var spriteName: String {
switch self {
case .Blue:
return "blue"
case .Orange:
return "orange"
case .Purple:
return "purple"
case .Red:
return "red"
case .Teal:
return "teal"
case .Yellow:
return "yellow"
}
}
var description: String {
return self.spriteName
}
static func random() -> BlockColor {
return BlockColor(rawValue:Int(arc4random_uniform(NumberOfColors)))!
}
}
class Block: Hashable, CustomStringConvertible {
// Constants
let color: BlockColor
// Properties
var column: Int
var row: Int
var sprite: SKSpriteNode?
var spriteName: String {
return color.spriteName
}
static func == (lhs: Block, rhs: Block) -> Bool {
return lhs.column == rhs.column && lhs.row == rhs.row
&& lhs.color.rawValue == rhs.color.rawValue
}
func hash(into hasher: inout Hasher) {
hasher.combine(column)
hasher.combine(row)
}
var description: String {
return "\(color): [\(column), \(row)]"
}
init(column: Int, row: Int, color: BlockColor) {
self.column = column
self.row = row
self.color = color
}
}

191
Privyet/GameScene.swift Normal file
View File

@ -0,0 +1,191 @@
//
// GameScene.swift
// Privyet
//
// Created by Amy Bowersox on 5/23/20.
// Copyright © 2020 Erbosoft Metaverse Design Solutions. All rights reserved.
//
import SpriteKit
import GameplayKit
let BlockSize: CGFloat = 20.0
let TickLengthLevelOne = TimeInterval(600)
class GameScene: SKScene {
let gameLayer = SKNode()
let shapeLayer = SKNode()
let LayerPosition = CGPoint(x: 6, y: -6)
var tick: (() -> ())?
var tickLengthMillis = TickLengthLevelOne
var lastTick: NSDate?
var textureCache = Dictionary<String, SKTexture>()
var textureAtlas: SKTextureAtlas?
required init(coder aDecoder: NSCoder) {
fatalError("NSCoder not supported")
}
override init(size: CGSize) {
super.init(size: size)
print("Init scene with size \(size)")
textureAtlas = SKTextureAtlas(named: "Sprites")
anchorPoint = CGPoint(x: 0, y: 1.0)
let background = SKSpriteNode(imageNamed: "background")
print("Background is sized \(background.size)")
background.position = CGPoint(x: 0, y: 0)
background.anchorPoint = CGPoint(x: 0, y: 1.0)
addChild(background)
addChild(gameLayer)
let gameBoardTexture = SKTexture(imageNamed: "gameboard")
let gameBoard = SKSpriteNode(texture: gameBoardTexture, size: CGSize(width: BlockSize * CGFloat(NumColumns), height: BlockSize * CGFloat(NumRows)))
gameBoard.anchorPoint = CGPoint(x: 0, y: 1.0)
gameBoard.position = LayerPosition
shapeLayer.position = LayerPosition
shapeLayer.addChild(gameBoard)
gameLayer.addChild(shapeLayer)
run(SKAction.repeatForever(SKAction.playSoundFileNamed("Sounds/theme.mp3", waitForCompletion: true)))
}
func playSound(sound: String) {
run(SKAction.playSoundFileNamed(sound, waitForCompletion: false))
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
guard let lastTick = lastTick else {
return
}
let timePassed = lastTick.timeIntervalSinceNow * -1000.0
if timePassed > tickLengthMillis {
self.lastTick = NSDate()
tick?()
}
}
func startTicking() {
lastTick = NSDate()
}
func stopTicking() {
lastTick = nil
}
func pointForColumn(column: Int, row: Int) -> CGPoint {
let x = LayerPosition.x + (CGFloat(column) * BlockSize) + (BlockSize / 2)
let y = LayerPosition.y - ((CGFloat(row) * BlockSize) + (BlockSize / 2))
return CGPoint(x: x, y: y)
}
func addPreviewShapeToScene(shape: Shape, completion: @escaping () -> ()) {
for block in shape.blocks {
var texture = textureCache[block.spriteName]
if texture == nil {
texture = textureAtlas?.textureNamed(block.spriteName)
textureCache[block.spriteName] = texture
}
let sprite = SKSpriteNode(texture: texture)
sprite.position = pointForColumn(column: block.column, row: block.row - 2)
shapeLayer.addChild(sprite)
block.sprite = sprite
// Animation
sprite.alpha = 0
let moveAction = SKAction.move(to: pointForColumn(column: block.column, row: block.row), duration: TimeInterval(0.2))
moveAction.timingMode = .easeOut
let fadeInAction = SKAction.fadeAlpha(to: 0.7, duration: 0.4)
fadeInAction.timingMode = .easeOut
sprite.run(SKAction.group([moveAction, fadeInAction]))
}
let waitAction = SKAction.wait(forDuration: 0.4)
let completeAction = SKAction.run(completion)
run(SKAction.sequence([waitAction, completeAction]))
}
func movePreviewShape(shape: Shape, completion: @escaping () -> ()) {
for block in shape.blocks {
let sprite = block.sprite!
let moveTo = pointForColumn(column: block.column, row: block.row)
let moveToAction: SKAction = SKAction.move(to: moveTo, duration: 0.4)
moveToAction.timingMode = .easeOut
sprite.run(SKAction.group([moveToAction, SKAction.fadeAlpha(to: 1.0, duration: 0.2)]))
}
let waitAction = SKAction.wait(forDuration: 0.2)
let completeAction = SKAction.run(completion)
run(SKAction.sequence([waitAction, completeAction]))
}
func redrawShape(shape: Shape, completion: @escaping () -> ()) {
for block in shape.blocks {
let sprite = block.sprite!
let moveTo = pointForColumn(column: block.column, row: block.row)
let moveToAction: SKAction = SKAction.move(to: moveTo, duration: 0.05)
moveToAction.timingMode = .easeOut
sprite.run(moveToAction)
if block == shape.blocks.last {
sprite.run(SKAction.run(completion))
}
}
}
func animateCollapsingLines(linesToRemove: Array<Array<Block>>, fallenBlocks: Array<Array<Block>>, completion: @escaping () -> ()) {
var longestDuration: TimeInterval = 0
for (columnIdx, column) in fallenBlocks.enumerated() {
for (blockIdx, block) in column.enumerated() {
let newPosition = pointForColumn(column: block.column, row: block.row)
let sprite = block.sprite!
let delay = (TimeInterval(columnIdx) * 0.05) + (TimeInterval(blockIdx) * 0.05)
let duration = TimeInterval(((sprite.position.y - newPosition.y) / BlockSize) * 0.1)
let moveAction = SKAction.move(to: newPosition, duration: duration)
moveAction.timingMode = .easeOut
sprite.run(SKAction.sequence([SKAction.wait(forDuration: delay), moveAction]))
longestDuration = max(longestDuration, duration + delay)
}
}
for rowToRemove in linesToRemove {
for block in rowToRemove {
let randomRadius = CGFloat(UInt(arc4random_uniform(400) + 100))
let goLeft = arc4random_uniform(100) % 2 == 0
var point = pointForColumn(column: block.column, row: block.row)
point = CGPoint(x: point.x + (goLeft ? -randomRadius : randomRadius), y: point.y)
let randomDuration = TimeInterval(arc4random_uniform(2)) + 0.5
var startAngle = CGFloat(Double.pi)
var endAngle = startAngle * 2
if (goLeft) {
endAngle = startAngle
startAngle = 0
}
let archPath = UIBezierPath(arcCenter: point, radius: randomRadius, startAngle: startAngle, endAngle: endAngle, clockwise: goLeft)
let archAction = SKAction.follow(archPath.cgPath, asOffset: false, orientToPath: true, duration: randomDuration)
archAction.timingMode = .easeIn
let sprite = block.sprite!
sprite.zPosition = 100
sprite.run(SKAction.sequence([
SKAction.group([archAction, SKAction.fadeOut(withDuration: TimeInterval(randomDuration))]),
SKAction.removeFromParent()]))
}
}
run(SKAction.sequence([SKAction.wait(forDuration: longestDuration), SKAction.run(completion)]))
}
}

View File

@ -0,0 +1,164 @@
//
// GameViewController.swift
// Privyet
//
// Created by Amy Bowersox on 5/23/20.
// Copyright © 2020 Erbosoft Metaverse Design Solutions. All rights reserved.
//
import UIKit
import SpriteKit
import GameplayKit
class GameViewController: UIViewController, PrivyetDelegate, UIGestureRecognizerDelegate {
var scene: GameScene!
var privyet: Privyet!
var panPointReference: CGPoint?
@IBOutlet weak var scoreLabel: UILabel!
@IBOutlet weak var levelLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Configure the view
let skView = view as! SKView
skView.isMultipleTouchEnabled = false
// Create and configure the scene
scene = GameScene(size: skView.bounds.size)
scene.scaleMode = .aspectFill
scene.tick = didTick
privyet = Privyet()
privyet.delegate = self
privyet.beginGame()
// Present the scene
skView.presentScene(scene)
}
override var prefersStatusBarHidden: Bool {
return true
}
@IBAction func didTap(_ sender: UITapGestureRecognizer) {
privyet.rotateShape()
}
@IBAction func didPan(_ sender: UIPanGestureRecognizer) {
let currentPoint = sender.translation(in: self.view)
if let originalPoint = panPointReference {
if abs(currentPoint.x - originalPoint.x) > (BlockSize * 0.9) {
if sender.velocity(in: self.view).x > CGFloat(0) {
privyet.moveShapeRight()
panPointReference = currentPoint
} else {
privyet.moveShapeLeft()
panPointReference = currentPoint
}
}
} else if sender.state == .began {
panPointReference = currentPoint
}
}
@IBAction func didSwipe(_ sender: UISwipeGestureRecognizer) {
privyet.dropShape()
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer is UISwipeGestureRecognizer {
if otherGestureRecognizer is UIPanGestureRecognizer {
return true
}
} else if gestureRecognizer is UIPanGestureRecognizer {
if otherGestureRecognizer is UITapGestureRecognizer {
return true
}
}
return false
}
func didTick() {
privyet.letShapeFall()
}
func nextShape() {
let newShapes = privyet.newShape()
guard let fallingShape = newShapes.fallingShape else {
return
}
self.scene.addPreviewShapeToScene(shape: newShapes.nextShape!) { }
self.scene.movePreviewShape(shape: fallingShape) {
self.view.isUserInteractionEnabled = true
self.scene.startTicking()
}
}
func gameDidBegin(privyet: Privyet) {
levelLabel.text = "\(privyet.level)"
scoreLabel.text = "\(privyet.score)"
scene.tickLengthMillis = TickLengthLevelOne
// The following is false when restarting a new game
if privyet.nextShape != nil && privyet.nextShape!.blocks[0].sprite == nil {
scene.addPreviewShapeToScene(shape: privyet.nextShape!) {
self.nextShape()
}
} else {
nextShape()
}
}
func gameDidEnd(privyet: Privyet) {
view.isUserInteractionEnabled = false
scene.stopTicking()
scene.playSound(sound: "Sounds/gameover.mp3")
scene.animateCollapsingLines(linesToRemove: privyet.removeAllBlocks(), fallenBlocks: privyet.removeAllBlocks()) {
privyet.beginGame()
}
}
func gameDidLevelUp(privyet: Privyet) {
levelLabel.text = "\(privyet.level)"
if scene.tickLengthMillis >= 100 {
scene.tickLengthMillis -= 100
} else if scene.tickLengthMillis >= 50 {
scene.tickLengthMillis -= 50
}
scene.playSound(sound: "Sounds/levelup.mp3")
}
func gameShapeDidDrop(privyet: Privyet) {
scene.stopTicking()
scene.redrawShape(shape: privyet.fallingShape!) {
privyet.letShapeFall()
}
scene.playSound(sound: "Sounds/drop.mp3")
}
func gameShapeDidLand(privyet: Privyet) {
scene.stopTicking()
self.view.isUserInteractionEnabled = false
let removedLines = privyet.removeCompletedLines()
if removedLines.linesRemoved.count > 0 {
self.scoreLabel.text = "\(privyet.score)"
scene.animateCollapsingLines(linesToRemove: removedLines.linesRemoved, fallenBlocks: removedLines.fallenBlocks) {
self.gameShapeDidLand(privyet: privyet)
}
self.scene.playSound(sound: "Sounds/bomb.mp3")
} else {
nextShape()
}
}
func gameShapeDidMove(privyet: Privyet) {
scene.redrawShape(shape: privyet.fallingShape!) { }
}
}

45
Privyet/Info.plist Normal file
View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UIStatusBarHidden</key>
<true/>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

51
Privyet/JShape.swift Normal file
View File

@ -0,0 +1,51 @@
//
// JShape.swift
// Privyet
//
// Created by Amy Bowersox on 5/24/20.
// Copyright © 2020 Erbosoft Metaverse Design Solutions. All rights reserved.
//
import Foundation
class JShape: Shape {
/*
Orientation 0:
| * | 0 |
| | 1 |
| 3 | 2 |
Orientation 90:
| 3 | * | |
| 2 | 1 | 0 |
Orientation 180:
| 2*| 3 |
| 1 | |
| 0 | |
Orientation 270:
| 0 | 1*| 2 |
| | | 3 |
* marks the row/column indicator for the shape
*/
// Rotates around block #1
override var blockRowColumnPositions: [Orientation : Array<(columnDiff: Int, rowDiff: Int)>] {
return [
Orientation.Zero: [(1, 0), (1, 1), (1, 2), (0, 2)],
Orientation.Ninety: [(1, 1), (0, 1), (-1, 1), (-1, 0)],
Orientation.OneEighty: [(0, 2), (0, 1), (0, 0), (1, 0)],
Orientation.TwoSeventy: [(-1, 0), (0, 0), (1, 0), (1, 1)]
]
}
override var bottomBlocksForOrientations: [Orientation : Array<Block>] {
return [
Orientation.Zero: [blocks[ThirdBlockIdx], blocks[FourthBlockIdx]],
Orientation.Ninety: [blocks[FirstBlockIdx], blocks[SecondBlockIdx], blocks[ThirdBlockIdx]],
Orientation.OneEighty: [blocks[FirstBlockIdx], blocks[FourthBlockIdx]],
Orientation.TwoSeventy: [blocks[FirstBlockIdx], blocks[SecondBlockIdx], blocks[FourthBlockIdx]]
]
}
}

52
Privyet/LShape.swift Normal file
View File

@ -0,0 +1,52 @@
//
// LShape.swift
// Privyet
//
// Created by Amy Bowersox on 5/24/20.
// Copyright © 2020 Erbosoft Metaverse Design Solutions. All rights reserved.
//
import Foundation
class LShape: Shape {
/*
Orientation 0:
| 0*| |
| 1 | |
| 2 | 3 |
Orientation 90:
| | * | |
| 2 | 1 | 0 |
| 3 | | |
Orientation 180:
| 3 | 2*| |
| | 1 | |
| | 0 | |
Orientation 270:
| | * | 3 |
| 0 | 1 | 2 |
* marks the row/column indicator for the shape
*/
// Pivots about block #1
override var blockRowColumnPositions: [Orientation : Array<(columnDiff: Int, rowDiff: Int)>] {
return [
Orientation.Zero: [(0, 0), (0, 1), (0, 2), (1, 2)],
Orientation.Ninety: [(1, 1), (0, 1), (-1, 1), (-1, 2)],
Orientation.OneEighty: [(0, 2), (0, 1), (0, 0), (-1, 0)],
Orientation.TwoSeventy: [(-1, 1), (0, 1), (1, 1), (1, 0)]
]
}
override var bottomBlocksForOrientations: [Orientation : Array<Block>] {
return [
Orientation.Zero: [blocks[ThirdBlockIdx], blocks[FourthBlockIdx]],
Orientation.Ninety: [blocks[FirstBlockIdx], blocks[SecondBlockIdx], blocks[FourthBlockIdx]],
Orientation.OneEighty: [blocks[FirstBlockIdx], blocks[FourthBlockIdx]],
Orientation.TwoSeventy: [blocks[FirstBlockIdx], blocks[SecondBlockIdx], blocks[ThirdBlockIdx]]
]
}
}

42
Privyet/LineShape.swift Normal file
View File

@ -0,0 +1,42 @@
//
// LineShape.swift
// Privyet
//
// Created by Amy Bowersox on 5/24/20.
// Copyright © 2020 Erbosoft Metaverse Design Solutions. All rights reserved.
//
import Foundation
class LineShape: Shape {
/*
Orientations 0 and 180:
| 0*|
| 1 |
| 2 |
| 3 |
Orientations 90 and 270:
| 0 | 1*| 2 | 3 |
* markes the row-column indicator for the shape
*/
// Hinges about the second block
override var blockRowColumnPositions: [Orientation : Array<(columnDiff: Int, rowDiff: Int)>] {
return [
Orientation.Zero: [(0, 0), (0, 1), (0, 2), (0, 3)],
Orientation.Ninety: [(-1, 0), (0, 0), (1, 0), (2, 0)],
Orientation.OneEighty: [(0, 0), (0, 1), (0, 2), (0, 3)],
Orientation.TwoSeventy: [(-1, 0), (0, 0), (1, 0), (2, 0)]
]
}
override var bottomBlocksForOrientations: [Orientation : Array<Block>] {
return [
Orientation.Zero: [blocks[FourthBlockIdx]],
Orientation.Ninety: blocks,
Orientation.OneEighty: [blocks[FourthBlockIdx]],
Orientation.TwoSeventy: blocks
]
}
}

255
Privyet/Privyet.swift Normal file
View File

@ -0,0 +1,255 @@
//
// Privyet.swift
// Privyet
//
// Created by Amy Bowersox on 5/24/20.
// Copyright © 2020 Erbosoft Metaverse Design Solutions. All rights reserved.
//
import Foundation
let NumColumns = 10
let NumRows = 20
let StartingColumn = 4
let StartingRow = 0
let PreviewColumn = 12
let PreviewRow = 1
let PointsPerLine = 10
let LevelThreshold = 500
protocol PrivyetDelegate {
// Invoked when the current round of Privyet ends
func gameDidEnd(privyet: Privyet)
// Invoked after a game has begun
func gameDidBegin(privyet: Privyet)
// Invoked when the falling shape has become part of the game board
func gameShapeDidLand(privyet: Privyet)
// Invoked when the falling shape has changed its location
func gameShapeDidMove(privyet: Privyet)
// invoked when the falling shape has changed its location after being dropped
func gameShapeDidDrop(privyet: Privyet)
// invoked when the game has reached a new level
func gameDidLevelUp(privyet: Privyet)
}
class Privyet {
var blockArray: Array2D<Block>
var nextShape: Shape?
var fallingShape: Shape?
var delegate: PrivyetDelegate?
var score = 0
var level = 1
init() {
fallingShape = nil
nextShape = nil
blockArray = Array2D<Block>(columns: NumColumns, rows: NumRows)
}
func beginGame() {
if (nextShape == nil) {
nextShape = Shape.random(startingColumn: PreviewColumn, startingRow: PreviewRow)
}
delegate?.gameDidBegin(privyet: self)
}
func newShape() -> (fallingShape: Shape?, nextShape: Shape?) {
fallingShape = nextShape
nextShape = Shape.random(startingColumn: PreviewColumn, startingRow: PreviewRow)
fallingShape?.moveTo(column: StartingColumn, row: StartingRow)
guard detectIllegalPlacement() == false else {
nextShape = fallingShape
nextShape!.moveTo(column: PreviewColumn, row: PreviewRow)
endGame()
return (nil, nil)
}
return (fallingShape, nextShape)
}
func detectIllegalPlacement() -> Bool {
guard let shape = fallingShape else {
return false
}
for block in shape.blocks {
if block.column < 0 || block.column >= NumColumns || block.row < 0 || block.row >= NumRows {
return true
} else if blockArray[block.column, block.row] != nil {
return true
}
}
return false
}
func settleShape() {
guard let shape = fallingShape else {
return
}
for block in shape.blocks {
blockArray[block.column, block.row] = block
}
fallingShape = nil
delegate?.gameShapeDidLand(privyet: self)
}
func detectTouch() -> Bool {
guard let shape = fallingShape else {
return false
}
for bottomBlock in shape.bottomBlocks {
if bottomBlock.row == NumRows - 1 || blockArray[bottomBlock.column, bottomBlock.row + 1] != nil {
return true
}
}
return false
}
func endGame() {
score = 0
level = 1
delegate?.gameDidEnd(privyet: self)
}
func removeCompletedLines() -> (linesRemoved: Array<Array<Block>>, fallenBlocks: Array<Array<Block>>) {
var removedLines = Array<Array<Block>>()
for row in (1..<NumRows).reversed() {
var rowOfBlocks = Array<Block>()
for column in 0..<NumColumns {
guard let block = blockArray[column, row] else {
continue
}
rowOfBlocks.append(block)
}
if rowOfBlocks.count == NumColumns {
removedLines.append(rowOfBlocks)
for block in rowOfBlocks {
blockArray[block.column, block.row] = nil
}
}
}
if removedLines.count == 0 {
return ([], [])
}
let pointsEarned = removedLines.count * PointsPerLine * level
score += pointsEarned
if score >= level * LevelThreshold {
level += 1
delegate?.gameDidLevelUp(privyet: self)
}
var fallenBlocks = Array<Array<Block>>()
for column in 0..<NumColumns {
var fallenBlocksArray = Array<Block>()
for row in (1..<removedLines[0][0].row).reversed() {
guard let block = blockArray[column, row] else {
continue
}
var newRow = row
while (newRow < NumRows - 1 && blockArray[column, newRow + 1] == nil) {
newRow += 1
}
block.row = newRow
blockArray[column, row] = nil
blockArray[column, newRow] = block
fallenBlocksArray.append(block)
}
if fallenBlocksArray.count > 0 {
fallenBlocks.append(fallenBlocksArray)
}
}
return (removedLines, fallenBlocks)
}
func removeAllBlocks() -> Array<Array<Block>> {
var allBlocks = Array<Array<Block>>()
for row in 0..<NumRows {
var rowOfBlocks = Array<Block>()
for column in 0..<NumColumns {
guard let block = blockArray[column, row] else {
continue
}
rowOfBlocks.append(block)
blockArray[column, row] = nil
}
allBlocks.append(rowOfBlocks)
}
return allBlocks
}
func dropShape() {
guard let shape = fallingShape else {
return
}
while detectIllegalPlacement() == false {
shape.lowerShapeByOneRow()
}
shape.raiseShapeByOneRow()
delegate?.gameShapeDidDrop(privyet: self)
}
func letShapeFall() {
guard let shape = fallingShape else {
return
}
shape.lowerShapeByOneRow()
if detectIllegalPlacement() {
shape.raiseShapeByOneRow()
if detectIllegalPlacement() {
endGame()
} else {
settleShape()
}
} else {
delegate?.gameShapeDidMove(privyet: self)
if detectTouch() {
settleShape()
}
}
}
func rotateShape() {
guard let shape = fallingShape else {
return
}
shape.rotateClockwise()
guard detectIllegalPlacement() == false else {
shape.rotateCounterClockwise()
return
}
delegate?.gameShapeDidMove(privyet: self)
}
func moveShapeLeft() {
guard let shape = fallingShape else {
return
}
shape.shiftLeftByOneColumn()
guard detectIllegalPlacement() == false else {
shape.shiftRightByOneColumn()
return
}
delegate?.gameShapeDidMove(privyet: self)
}
func moveShapeRight() {
guard let shape = fallingShape else {
return
}
shape.shiftRightByOneColumn()
guard detectIllegalPlacement() == false else {
shape.shiftLeftByOneColumn()
return
}
delegate?.gameShapeDidMove(privyet: self)
}
}

41
Privyet/SShape.swift Normal file
View File

@ -0,0 +1,41 @@
//
// SShape.swift
// Privyet
//
// Created by Amy Bowersox on 5/24/20.
// Copyright © 2020 Erbosoft Metaverse Design Solutions. All rights reserved.
//
import Foundation
class SShape: Shape {
/*
Orientations 0 and 180:
| 0*| |
| 1 | 2 |
| | 3 |
Orientations 90 and 270:
| * | 1 | 0 |
| 3 | 2 | |
* marks the row/column indicator for the shape
*/
override var blockRowColumnPositions: [Orientation : Array<(columnDiff: Int, rowDiff: Int)>] {
return [
Orientation.Zero: [(0, 0), (0, 1), (1, 1), (1, 2)],
Orientation.Ninety: [(2, 0), (1, 0), (1, 1), (0, 1)],
Orientation.OneEighty: [(0, 0), (0, 1), (1, 1), (1, 2)],
Orientation.TwoSeventy: [(2, 0), (1, 0), (1, 1), (0, 1)]
]
}
override var bottomBlocksForOrientations: [Orientation : Array<Block>] {
return [
Orientation.Zero: [blocks[SecondBlockIdx], blocks[FourthBlockIdx]],
Orientation.Ninety: [blocks[FirstBlockIdx], blocks[ThirdBlockIdx], blocks[FourthBlockIdx]],
Orientation.OneEighty: [blocks[SecondBlockIdx], blocks[FourthBlockIdx]],
Orientation.TwoSeventy: [blocks[FirstBlockIdx], blocks[ThirdBlockIdx], blocks[FourthBlockIdx]]
]
}
}

194
Privyet/Shape.swift Normal file
View File

@ -0,0 +1,194 @@
//
// Shape.swift
// Privyet
//
// Created by Amy Bowersox on 5/24/20.
// Copyright © 2020 Erbosoft Metaverse Design Solutions. All rights reserved.
//
import Foundation
import SpriteKit
let NumOrientations: UInt32 = 4
enum Orientation: Int, CustomStringConvertible {
case Zero = 0, Ninety, OneEighty, TwoSeventy
var description: String {
switch self {
case .Zero:
return "0"
case .Ninety:
return "90"
case .OneEighty:
return "180"
case .TwoSeventy:
return "270"
}
}
static func random() -> Orientation {
return Orientation(rawValue:Int(arc4random_uniform(NumOrientations)))!
}
static func rotate(orientation: Orientation, clockwise: Bool) -> Orientation {
var rotated = orientation.rawValue + (clockwise ? 1 : -1)
if rotated > Orientation.TwoSeventy.rawValue {
rotated = Orientation.Zero.rawValue
} else if rotated < 0 {
rotated = Orientation.TwoSeventy.rawValue
}
return Orientation(rawValue:rotated)!
}
}
// The number of total shape varieties
let NumShapeTypes: UInt32 = 7
// Shape indexes
let FirstBlockIdx: Int = 0
let SecondBlockIdx: Int = 1
let ThirdBlockIdx: Int = 2
let FourthBlockIdx: Int = 3
class Shape: Hashable, CustomStringConvertible {
// The color of the shape
let color: BlockColor
// The blocks comprising the shape
var blocks = Array<Block>()
// The current orientation of the shape
var orientation: Orientation
// The column and row representing the shape's anchor point
var column, row: Int
// Required overrides
// Subclasses must override this property
var blockRowColumnPositions: [Orientation: Array<(columnDiff: Int, rowDiff: Int)>] {
return [:]
}
// Subclasses must override this property
var bottomBlocksForOrientations: [Orientation: Array<Block>] {
return [:]
}
var bottomBlocks: Array<Block> {
guard let bottomBlocks = bottomBlocksForOrientations[orientation] else {
return []
}
return bottomBlocks
}
// Equatable
static func == (lhs: Shape, rhs: Shape) -> Bool {
return lhs.row == rhs.row && lhs.column == rhs.column
}
// Hashable
func hash(into hasher: inout Hasher) {
blocks.forEach {b in
hasher.combine(b.hashValue)
}
}
// CustomStringConvertible
var description: String {
return "\(color) block facing \(orientation): \(blocks[FirstBlockIdx]), \(blocks[SecondBlockIdx]), \(blocks[ThirdBlockIdx]), \(blocks[FourthBlockIdx])"
}
init(column: Int, row: Int, color: BlockColor, orientation: Orientation) {
self.color = color
self.column = column
self.row = row
self.orientation = orientation
initializeBlocks()
}
convenience init(column: Int, row: Int) {
self.init(column: column, row: row, color: BlockColor.random(), orientation: Orientation.random())
}
final func initializeBlocks() {
guard let blockRowColumnTranslations = blockRowColumnPositions[orientation] else {
return
}
blocks = blockRowColumnTranslations.map { (diff) -> Block in
return Block(column: column + diff.columnDiff, row: row + diff.rowDiff, color: color)
}
}
final func rotateBlocks(orientation: Orientation) {
guard let blockRowColumnTranslation: Array<(columnDiff: Int, rowDiff: Int)> = blockRowColumnPositions[orientation] else {
return
}
for (idx, diff) in blockRowColumnTranslation.enumerated() {
blocks[idx].column = column + diff.columnDiff
blocks[idx].row = row + diff.rowDiff
}
}
final func rotateClockwise() {
let newOrientation = Orientation.rotate(orientation: orientation, clockwise: true)
rotateBlocks(orientation: newOrientation)
orientation = newOrientation
}
final func rotateCounterClockwise() {
let newOrientation = Orientation.rotate(orientation: orientation, clockwise: false)
rotateBlocks(orientation: newOrientation)
orientation = newOrientation
}
final func lowerShapeByOneRow() {
shiftBy(columns: 0, rows: 1)
}
final func raiseShapeByOneRow() {
shiftBy(columns: 0, rows: -1)
}
final func shiftRightByOneColumn() {
shiftBy(columns: 1, rows: 0)
}
final func shiftLeftByOneColumn() {
shiftBy(columns: -1, rows: 0)
}
final func shiftBy(columns: Int, rows: Int) {
self.column += columns
self.row += rows
for block in blocks {
block.column += columns
block.row += rows
}
}
final func moveTo(column: Int, row: Int) {
self.column = column
self.row = row
rotateBlocks(orientation: orientation)
}
final class func random(startingColumn: Int, startingRow: Int) -> Shape {
switch Int(arc4random_uniform(NumShapeTypes)) {
case 0:
return SquareShape(column: startingColumn, row: startingRow)
case 1:
return LineShape(column: startingColumn, row: startingRow)
case 2:
return TShape(column: startingColumn, row: startingRow)
case 3:
return LShape(column: startingColumn, row: startingRow)
case 4:
return JShape(column: startingColumn, row: startingRow)
case 5:
return SShape(column: startingColumn, row: startingRow)
default:
return ZShape(column: startingColumn, row: startingRow)
}
}
}

BIN
Privyet/Sounds/bomb.mp3 Executable file

Binary file not shown.

BIN
Privyet/Sounds/drop.mp3 Executable file

Binary file not shown.

BIN
Privyet/Sounds/gameover.mp3 Executable file

Binary file not shown.

BIN
Privyet/Sounds/levelup.mp3 Executable file

Binary file not shown.

BIN
Privyet/Sounds/theme.mp3 Executable file

Binary file not shown.

BIN
Privyet/Sprites.atlas/blue.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

BIN
Privyet/Sprites.atlas/blue@2x.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

BIN
Privyet/Sprites.atlas/orange.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 B

BIN
Privyet/Sprites.atlas/purple.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

BIN
Privyet/Sprites.atlas/red.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

BIN
Privyet/Sprites.atlas/red@2x.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

BIN
Privyet/Sprites.atlas/teal.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

BIN
Privyet/Sprites.atlas/teal@2x.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 B

BIN
Privyet/Sprites.atlas/yellow.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 B

36
Privyet/SquareShape.swift Normal file
View File

@ -0,0 +1,36 @@
//
// SquareShape.swift
// Privyet
//
// Created by Amy Bowersox on 5/24/20.
// Copyright © 2020 Erbosoft Metaverse Design Solutions. All rights reserved.
//
import Foundation
class SquareShape: Shape {
/*
| 0*| 1 |
| 2 | 3 |
* marks the row/column indicator for this shape
*/
// The square shape wll not rotate
override var blockRowColumnPositions: [Orientation : Array<(columnDiff: Int, rowDiff: Int)>] {
return [
Orientation.Zero: [(0, 0), (1, 0), (0, 1), (1, 1)],
Orientation.Ninety: [(0, 0), (1, 0), (0, 1), (1, 1)],
Orientation.OneEighty: [(0, 0), (1, 0), (0, 1), (1, 1)],
Orientation.TwoSeventy: [(0, 0), (1, 0), (0, 1), (1, 1)]
]
}
override var bottomBlocksForOrientations: [Orientation : Array<Block>] {
return [
Orientation.Zero: [blocks[ThirdBlockIdx], blocks[FourthBlockIdx]],
Orientation.Ninety: [blocks[ThirdBlockIdx], blocks[FourthBlockIdx]],
Orientation.OneEighty: [blocks[ThirdBlockIdx], blocks[FourthBlockIdx]],
Orientation.TwoSeventy: [blocks[ThirdBlockIdx], blocks[FourthBlockIdx]]
]
}
}

51
Privyet/TShape.swift Normal file
View File

@ -0,0 +1,51 @@
//
// TShape.swift
// Privyet
//
// Created by Amy Bowersox on 5/24/20.
// Copyright © 2020 Erbosoft Metaverse Design Solutions. All rights reserved.
//
import Foundation
class TShape: Shape {
/*
Orientation 0:
| * | 0 | |
| 1 | 2 | 3 |
Orientation 90:
| * | 1 | |
| | 2 | 0 |
| | 3 | |
Orientation 180:
| * | | |
| 3 | 2 | 1 |
| | 0 | |
Orientation 270:
| * | 3 | |
| 0 | 2 | |
| | 1 | |
* marks the row/column indicator for the shape
*/
override var blockRowColumnPositions: [Orientation : Array<(columnDiff: Int, rowDiff: Int)>] {
return [
Orientation.Zero: [(1, 0), (0, 1), (1, 1), (2, 1)],
Orientation.Ninety: [(2, 1), (1, 0), (1, 1), (1, 2)],
Orientation.OneEighty: [(1, 2), (2, 1), (1, 1), (0, 1)],
Orientation.TwoSeventy: [(0, 1), (1, 2), (1, 1), (1, 0)]
]
}
override var bottomBlocksForOrientations: [Orientation : Array<Block>] {
return [
Orientation.Zero: [blocks[SecondBlockIdx], blocks[ThirdBlockIdx], blocks[FourthBlockIdx]],
Orientation.Ninety: [blocks[FirstBlockIdx], blocks[FourthBlockIdx]],
Orientation.OneEighty: [blocks[FirstBlockIdx], blocks[SecondBlockIdx], blocks[FourthBlockIdx]],
Orientation.TwoSeventy: [blocks[FirstBlockIdx], blocks[SecondBlockIdx]]
]
}
}

41
Privyet/ZShape.swift Normal file
View File

@ -0,0 +1,41 @@
//
// ZShape.swift
// Privyet
//
// Created by Amy Bowersox on 5/24/20.
// Copyright © 2020 Erbosoft Metaverse Design Solutions. All rights reserved.
//
import Foundation
class ZShape: Shape {
/*
Orientations 0 and 180:
| * | 0 |
| 2 | 1 |
| 3 | |
Orientations 90 and 270:
| 0*| 1 | |
| | 2 | 3 |
* marks the row/column indicator for the shape
*/
override var blockRowColumnPositions: [Orientation : Array<(columnDiff: Int, rowDiff: Int)>] {
return [
Orientation.Zero: [(1, 0), (1, 1), (0, 1), (0, 2)],
Orientation.Ninety: [(0, 0), (1, 0), (1, 1), (2, 1)],
Orientation.OneEighty: [(1, 0), (1, 1), (0, 1), (0, 2)],
Orientation.TwoSeventy: [(0, 0), (1, 0), (1, 1), (2, 1)]
]
}
override var bottomBlocksForOrientations: [Orientation : Array<Block>] {
return [
Orientation.Zero: [blocks[SecondBlockIdx], blocks[FourthBlockIdx]],
Orientation.Ninety: [blocks[FirstBlockIdx], blocks[ThirdBlockIdx], blocks[FourthBlockIdx]],
Orientation.OneEighty: [blocks[SecondBlockIdx], blocks[FourthBlockIdx]],
Orientation.TwoSeventy: [blocks[FirstBlockIdx], blocks[ThirdBlockIdx], blocks[FourthBlockIdx]]
]
}
}