diff --git a/QuackFight/Assets.xcassets/Background/Game/1.imageset/1.png b/QuackFight/Assets.xcassets/Background/Game/Background1.imageset/1.png similarity index 100% rename from QuackFight/Assets.xcassets/Background/Game/1.imageset/1.png rename to QuackFight/Assets.xcassets/Background/Game/Background1.imageset/1.png diff --git a/QuackFight/Assets.xcassets/Background/Game/1.imageset/Contents.json b/QuackFight/Assets.xcassets/Background/Game/Background1.imageset/Contents.json similarity index 100% rename from QuackFight/Assets.xcassets/Background/Game/1.imageset/Contents.json rename to QuackFight/Assets.xcassets/Background/Game/Background1.imageset/Contents.json diff --git a/QuackFight/Assets.xcassets/Background/Game/2.imageset/2.png b/QuackFight/Assets.xcassets/Background/Game/Background2.imageset/2.png similarity index 100% rename from QuackFight/Assets.xcassets/Background/Game/2.imageset/2.png rename to QuackFight/Assets.xcassets/Background/Game/Background2.imageset/2.png diff --git a/QuackFight/Assets.xcassets/Background/Game/2.imageset/Contents.json b/QuackFight/Assets.xcassets/Background/Game/Background2.imageset/Contents.json similarity index 100% rename from QuackFight/Assets.xcassets/Background/Game/2.imageset/Contents.json rename to QuackFight/Assets.xcassets/Background/Game/Background2.imageset/Contents.json diff --git a/QuackFight/Assets.xcassets/Background/Game/3.imageset/3.png b/QuackFight/Assets.xcassets/Background/Game/Background3.imageset/3.png similarity index 100% rename from QuackFight/Assets.xcassets/Background/Game/3.imageset/3.png rename to QuackFight/Assets.xcassets/Background/Game/Background3.imageset/3.png diff --git a/QuackFight/Assets.xcassets/Background/Game/3.imageset/Contents.json b/QuackFight/Assets.xcassets/Background/Game/Background3.imageset/Contents.json similarity index 100% rename from QuackFight/Assets.xcassets/Background/Game/3.imageset/Contents.json rename to QuackFight/Assets.xcassets/Background/Game/Background3.imageset/Contents.json diff --git a/QuackFight/Assets.xcassets/Background/Game/4.imageset/4.png b/QuackFight/Assets.xcassets/Background/Game/Background4.imageset/4.png similarity index 100% rename from QuackFight/Assets.xcassets/Background/Game/4.imageset/4.png rename to QuackFight/Assets.xcassets/Background/Game/Background4.imageset/4.png diff --git a/QuackFight/Assets.xcassets/Background/Game/4.imageset/Contents.json b/QuackFight/Assets.xcassets/Background/Game/Background4.imageset/Contents.json similarity index 100% rename from QuackFight/Assets.xcassets/Background/Game/4.imageset/Contents.json rename to QuackFight/Assets.xcassets/Background/Game/Background4.imageset/Contents.json diff --git a/QuackFight/Assets.xcassets/Background/Game/5.imageset/5.png b/QuackFight/Assets.xcassets/Background/Game/Background5.imageset/5.png similarity index 100% rename from QuackFight/Assets.xcassets/Background/Game/5.imageset/5.png rename to QuackFight/Assets.xcassets/Background/Game/Background5.imageset/5.png diff --git a/QuackFight/Assets.xcassets/Background/Game/5.imageset/Contents.json b/QuackFight/Assets.xcassets/Background/Game/Background5.imageset/Contents.json similarity index 100% rename from QuackFight/Assets.xcassets/Background/Game/5.imageset/Contents.json rename to QuackFight/Assets.xcassets/Background/Game/Background5.imageset/Contents.json diff --git a/QuackFight/Assets.xcassets/Background/Game/6.imageset/6.png b/QuackFight/Assets.xcassets/Background/Game/Background6.imageset/6.png similarity index 100% rename from QuackFight/Assets.xcassets/Background/Game/6.imageset/6.png rename to QuackFight/Assets.xcassets/Background/Game/Background6.imageset/6.png diff --git a/QuackFight/Assets.xcassets/Background/Game/6.imageset/Contents.json b/QuackFight/Assets.xcassets/Background/Game/Background6.imageset/Contents.json similarity index 100% rename from QuackFight/Assets.xcassets/Background/Game/6.imageset/Contents.json rename to QuackFight/Assets.xcassets/Background/Game/Background6.imageset/Contents.json diff --git a/QuackFight/Assets.xcassets/Background/Game/7.imageset/7.png b/QuackFight/Assets.xcassets/Background/Game/Background7.imageset/7.png similarity index 100% rename from QuackFight/Assets.xcassets/Background/Game/7.imageset/7.png rename to QuackFight/Assets.xcassets/Background/Game/Background7.imageset/7.png diff --git a/QuackFight/Assets.xcassets/Background/Game/7.imageset/Contents.json b/QuackFight/Assets.xcassets/Background/Game/Background7.imageset/Contents.json similarity index 100% rename from QuackFight/Assets.xcassets/Background/Game/7.imageset/Contents.json rename to QuackFight/Assets.xcassets/Background/Game/Background7.imageset/Contents.json diff --git a/QuackFight/Assets.xcassets/Background/Game/8.imageset/8.png b/QuackFight/Assets.xcassets/Background/Game/Background8.imageset/8.png similarity index 100% rename from QuackFight/Assets.xcassets/Background/Game/8.imageset/8.png rename to QuackFight/Assets.xcassets/Background/Game/Background8.imageset/8.png diff --git a/QuackFight/Assets.xcassets/Background/Game/8.imageset/Contents.json b/QuackFight/Assets.xcassets/Background/Game/Background8.imageset/Contents.json similarity index 100% rename from QuackFight/Assets.xcassets/Background/Game/8.imageset/Contents.json rename to QuackFight/Assets.xcassets/Background/Game/Background8.imageset/Contents.json diff --git a/QuackFight/Assets.xcassets/Background/Menu/Background.imageset/Background.png b/QuackFight/Assets.xcassets/Background/Menu/BackgroundMenu.imageset/Background.png similarity index 100% rename from QuackFight/Assets.xcassets/Background/Menu/Background.imageset/Background.png rename to QuackFight/Assets.xcassets/Background/Menu/BackgroundMenu.imageset/Background.png diff --git a/QuackFight/Assets.xcassets/Background/Menu/Background.imageset/Contents.json b/QuackFight/Assets.xcassets/Background/Menu/BackgroundMenu.imageset/Contents.json similarity index 100% rename from QuackFight/Assets.xcassets/Background/Menu/Background.imageset/Contents.json rename to QuackFight/Assets.xcassets/Background/Menu/BackgroundMenu.imageset/Contents.json diff --git a/QuackFight/Assets.xcassets/Color/Contents.json b/QuackFight/Assets.xcassets/Color/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/QuackFight/Assets.xcassets/Color/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Color/YellowQuack.colorset/Contents.json b/QuackFight/Assets.xcassets/Color/YellowQuack.colorset/Contents.json new file mode 100644 index 0000000..8948a16 --- /dev/null +++ b/QuackFight/Assets.xcassets/Color/YellowQuack.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x47", + "green" : "0xB3", + "red" : "0xF8" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x47", + "green" : "0xB3", + "red" : "0xF8" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Contents.json b/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-1.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-1.imageset/Contents.json new file mode 100644 index 0000000..22667a1 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Duck_Missile-1.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-1.imageset/Duck_Missile-1.png b/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-1.imageset/Duck_Missile-1.png new file mode 100644 index 0000000..021e943 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-1.imageset/Duck_Missile-1.png differ diff --git a/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-2.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-2.imageset/Contents.json new file mode 100644 index 0000000..59b46c3 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-2.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Duck_Missile-2.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-2.imageset/Duck_Missile-2.png b/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-2.imageset/Duck_Missile-2.png new file mode 100644 index 0000000..58b4c98 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-2.imageset/Duck_Missile-2.png differ diff --git a/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-3.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-3.imageset/Contents.json new file mode 100644 index 0000000..27ae7bb --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-3.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Duck_Missile-3.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-3.imageset/Duck_Missile-3.png b/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-3.imageset/Duck_Missile-3.png new file mode 100644 index 0000000..385b529 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-3.imageset/Duck_Missile-3.png differ diff --git a/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-4.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-4.imageset/Contents.json new file mode 100644 index 0000000..79fcf10 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-4.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Duck_Missile-4.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-4.imageset/Duck_Missile-4.png b/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-4.imageset/Duck_Missile-4.png new file mode 100644 index 0000000..68060e2 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Duck/CallingMissile/Duck_Missile-4.imageset/Duck_Missile-4.png differ diff --git a/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-1.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-1.imageset/Contents.json new file mode 100644 index 0000000..d6d1a34 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Duck_Heal-1.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-1.imageset/Duck_Heal-1.png b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-1.imageset/Duck_Heal-1.png new file mode 100644 index 0000000..2bf7b50 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-1.imageset/Duck_Heal-1.png differ diff --git a/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-2.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-2.imageset/Contents.json new file mode 100644 index 0000000..b1d0fbb --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-2.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Duck_Heal-2.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-2.imageset/Duck_Heal-2.png b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-2.imageset/Duck_Heal-2.png new file mode 100644 index 0000000..f533970 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-2.imageset/Duck_Heal-2.png differ diff --git a/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-3.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-3.imageset/Contents.json new file mode 100644 index 0000000..dbf2493 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-3.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Duck_Heal-3.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-3.imageset/Duck_Heal-3.png b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-3.imageset/Duck_Heal-3.png new file mode 100644 index 0000000..ce4e930 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-3.imageset/Duck_Heal-3.png differ diff --git a/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-4.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-4.imageset/Contents.json new file mode 100644 index 0000000..17a93bb --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-4.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Duck_Heal-4.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-4.imageset/Duck_Heal-4.png b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-4.imageset/Duck_Heal-4.png new file mode 100644 index 0000000..4599471 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-4.imageset/Duck_Heal-4.png differ diff --git a/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-5.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-5.imageset/Contents.json new file mode 100644 index 0000000..635cdd3 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-5.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Duck_Heal-5.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-5.imageset/Duck_Heal-5.png b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-5.imageset/Duck_Heal-5.png new file mode 100644 index 0000000..dfa9fdf Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-5.imageset/Duck_Heal-5.png differ diff --git a/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-6.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-6.imageset/Contents.json new file mode 100644 index 0000000..a25e7be --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-6.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Duck_Heal-6.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-6.imageset/Duck_Heal-6.png b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-6.imageset/Duck_Heal-6.png new file mode 100644 index 0000000..b07f7d3 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-6.imageset/Duck_Heal-6.png differ diff --git a/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-7.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-7.imageset/Contents.json new file mode 100644 index 0000000..3299f0b --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-7.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Duck_Heal-7.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-7.imageset/Duck_Heal-7.png b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-7.imageset/Duck_Heal-7.png new file mode 100644 index 0000000..f38ffd1 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Duck/Heal/Duck_Heal-7.imageset/Duck_Heal-7.png differ diff --git a/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-1.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-1.imageset/Contents.json new file mode 100644 index 0000000..a3eb9ce --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Duck_Hit-1.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-1.imageset/Duck_Hit-1.png b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-1.imageset/Duck_Hit-1.png new file mode 100644 index 0000000..2e192fd Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-1.imageset/Duck_Hit-1.png differ diff --git a/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-2.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-2.imageset/Contents.json new file mode 100644 index 0000000..4615f1e --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-2.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Duck_Hit-2.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-2.imageset/Duck_Hit-2.png b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-2.imageset/Duck_Hit-2.png new file mode 100644 index 0000000..44716c2 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-2.imageset/Duck_Hit-2.png differ diff --git a/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-3.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-3.imageset/Contents.json new file mode 100644 index 0000000..80bffd8 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-3.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Duck_Hit-3.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-3.imageset/Duck_Hit-3.png b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-3.imageset/Duck_Hit-3.png new file mode 100644 index 0000000..7e0b687 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-3.imageset/Duck_Hit-3.png differ diff --git a/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-4.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-4.imageset/Contents.json new file mode 100644 index 0000000..05cf367 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-4.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Duck_Hit-4.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-4.imageset/Duck_Hit-4.png b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-4.imageset/Duck_Hit-4.png new file mode 100644 index 0000000..8162b5a Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-4.imageset/Duck_Hit-4.png differ diff --git a/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-5.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-5.imageset/Contents.json new file mode 100644 index 0000000..726afa5 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-5.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Duck_Hit-5.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-5.imageset/Duck_Hit-5.png b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-5.imageset/Duck_Hit-5.png new file mode 100644 index 0000000..105b007 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Duck/Hit/Duck_Hit-5.imageset/Duck_Hit-5.png differ diff --git a/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Contents.json b/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-1.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-1.imageset/Contents.json new file mode 100644 index 0000000..8f5d61a --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Goose_Missile-1.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-1.imageset/Goose_Missile-1.png b/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-1.imageset/Goose_Missile-1.png new file mode 100644 index 0000000..c25e4e3 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-1.imageset/Goose_Missile-1.png differ diff --git a/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-2.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-2.imageset/Contents.json new file mode 100644 index 0000000..2c59e56 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-2.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Goose_Missile-2.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-2.imageset/Goose_Missile-2.png b/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-2.imageset/Goose_Missile-2.png new file mode 100644 index 0000000..9032495 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-2.imageset/Goose_Missile-2.png differ diff --git a/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-3.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-3.imageset/Contents.json new file mode 100644 index 0000000..e3c21fe --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-3.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Goose_Missile-3.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-3.imageset/Goose_Missile-3.png b/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-3.imageset/Goose_Missile-3.png new file mode 100644 index 0000000..162f690 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-3.imageset/Goose_Missile-3.png differ diff --git a/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-4.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-4.imageset/Contents.json new file mode 100644 index 0000000..27a3572 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-4.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Goose_Missile-4.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-4.imageset/Goose_Missile-4.png b/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-4.imageset/Goose_Missile-4.png new file mode 100644 index 0000000..10fcc91 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Goose/CallingMissile/Goose_Missile-4.imageset/Goose_Missile-4.png differ diff --git a/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-1.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-1.imageset/Contents.json new file mode 100644 index 0000000..0366955 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Goose_Heal-1.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-1.imageset/Goose_Heal-1.png b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-1.imageset/Goose_Heal-1.png new file mode 100644 index 0000000..471636e Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-1.imageset/Goose_Heal-1.png differ diff --git a/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-2.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-2.imageset/Contents.json new file mode 100644 index 0000000..4d0916b --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-2.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Goose_Heal-2.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-2.imageset/Goose_Heal-2.png b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-2.imageset/Goose_Heal-2.png new file mode 100644 index 0000000..163e198 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-2.imageset/Goose_Heal-2.png differ diff --git a/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-3.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-3.imageset/Contents.json new file mode 100644 index 0000000..4b4e4a0 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-3.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Goose_Heal-3.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-3.imageset/Goose_Heal-3.png b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-3.imageset/Goose_Heal-3.png new file mode 100644 index 0000000..369bbd7 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-3.imageset/Goose_Heal-3.png differ diff --git a/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-4.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-4.imageset/Contents.json new file mode 100644 index 0000000..974ec16 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-4.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Goose_Heal-4.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-4.imageset/Goose_Heal-4.png b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-4.imageset/Goose_Heal-4.png new file mode 100644 index 0000000..c702982 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-4.imageset/Goose_Heal-4.png differ diff --git a/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-5.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-5.imageset/Contents.json new file mode 100644 index 0000000..73ebcbf --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-5.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Goose_Heal-5.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-5.imageset/Goose_Heal-5.png b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-5.imageset/Goose_Heal-5.png new file mode 100644 index 0000000..169b77d Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-5.imageset/Goose_Heal-5.png differ diff --git a/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-6.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-6.imageset/Contents.json new file mode 100644 index 0000000..45bbc82 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-6.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Goose_Heal-6.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-6.imageset/Goose_Heal-6.png b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-6.imageset/Goose_Heal-6.png new file mode 100644 index 0000000..6622932 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-6.imageset/Goose_Heal-6.png differ diff --git a/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-7.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-7.imageset/Contents.json new file mode 100644 index 0000000..598a0d4 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-7.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Goose_Heal-7.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-7.imageset/Goose_Heal-7.png b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-7.imageset/Goose_Heal-7.png new file mode 100644 index 0000000..8a8f49f Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Goose/Heal/Goose_Heal-7.imageset/Goose_Heal-7.png differ diff --git a/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-1.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-1.imageset/Contents.json new file mode 100644 index 0000000..d78bee0 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Goose_Hit-1.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-1.imageset/Goose_Hit-1.png b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-1.imageset/Goose_Hit-1.png new file mode 100644 index 0000000..9e26283 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-1.imageset/Goose_Hit-1.png differ diff --git a/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-2.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-2.imageset/Contents.json new file mode 100644 index 0000000..95a7187 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-2.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Goose_Hit-2.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-2.imageset/Goose_Hit-2.png b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-2.imageset/Goose_Hit-2.png new file mode 100644 index 0000000..0a5256e Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-2.imageset/Goose_Hit-2.png differ diff --git a/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-3.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-3.imageset/Contents.json new file mode 100644 index 0000000..7593621 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-3.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Goose_Hit-3.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-3.imageset/Goose_Hit-3.png b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-3.imageset/Goose_Hit-3.png new file mode 100644 index 0000000..8329d3d Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-3.imageset/Goose_Hit-3.png differ diff --git a/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-4.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-4.imageset/Contents.json new file mode 100644 index 0000000..443d2e0 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-4.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Goose_Hit-4.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-4.imageset/Goose_Hit-4.png b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-4.imageset/Goose_Hit-4.png new file mode 100644 index 0000000..2bb1197 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-4.imageset/Goose_Hit-4.png differ diff --git a/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-5.imageset/Contents.json b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-5.imageset/Contents.json new file mode 100644 index 0000000..1276738 --- /dev/null +++ b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-5.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Goose_Hit-5.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-5.imageset/Goose_Hit-5.png b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-5.imageset/Goose_Hit-5.png new file mode 100644 index 0000000..cf81e35 Binary files /dev/null and b/QuackFight/Assets.xcassets/Player/Goose/Hit/Goose_Hit-5.imageset/Goose_Hit-5.png differ diff --git a/QuackFight/GameScene.sks b/QuackFight/GameScene.sks deleted file mode 100644 index 8249ec3..0000000 Binary files a/QuackFight/GameScene.sks and /dev/null differ diff --git a/QuackFight/GameViewController.swift b/QuackFight/GameViewController.swift index 5371065..9d722a9 100644 --- a/QuackFight/GameViewController.swift +++ b/QuackFight/GameViewController.swift @@ -17,7 +17,7 @@ class GameViewController: UIViewController { if let view = self.view as? SKView { // Attempt to load 'GameScene.sks' as a GKScene if let scene = GKScene(fileNamed: "GameScene"), let sceneNode = scene.rootNode as? GameScene { - // Copy gameplay related content over to the scene + // Copy gameplay relatedx content over to the scene sceneNode.entities = scene.entities sceneNode.graphs = scene.graphs sceneNode.scaleMode = .aspectFill diff --git a/QuackFight/MainScene.sks b/QuackFight/MainScene.sks deleted file mode 100644 index 69c954f..0000000 Binary files a/QuackFight/MainScene.sks and /dev/null differ diff --git a/QuackFight/Sources/Scenes/GameScene.swift b/QuackFight/Sources/Scenes/GameScene.swift index 738a659..09a058d 100644 --- a/QuackFight/Sources/Scenes/GameScene.swift +++ b/QuackFight/Sources/Scenes/GameScene.swift @@ -14,89 +14,47 @@ class GameScene: SKScene { var graphs = [String : GKGraph]() private var lastUpdateTime : TimeInterval = 0 - private var label : SKLabelNode? - private var spinnyNode : SKShapeNode? - override func sceneDidLoad() { - + override func didMove(to view: SKView) { self.lastUpdateTime = 0 - // Get label node from scene and store it for use later - self.label = self.childNode(withName: "//helloLabel") as? SKLabelNode - if let label = self.label { - label.alpha = 0.0 - label.run(SKAction.fadeIn(withDuration: 2.0)) - } + // 1. Setup Camera + let cameraEntity = CameraEntity(scene: self) - // Create shape node to use during mouse interaction - let w = (self.size.width + self.size.height) * 0.05 - self.spinnyNode = SKShapeNode.init(rectOf: CGSize.init(width: w, height: w), cornerRadius: w * 0.3) + // 2. Setup Players + let p1 = PlayerEntity(playerIndex: 0, scene: self) + let p2 = PlayerEntity(playerIndex: 1, scene: self) - if let spinnyNode = self.spinnyNode { - spinnyNode.lineWidth = 2.5 - - spinnyNode.run(SKAction.repeatForever(SKAction.rotate(byAngle: CGFloat(Double.pi), duration: 1))) - spinnyNode.run(SKAction.sequence([SKAction.wait(forDuration: 0.5), - SKAction.fadeOut(withDuration: 0.5), - SKAction.removeFromParent()])) - } - } - - - func touchDown(atPoint pos : CGPoint) { - if let n = self.spinnyNode?.copy() as! SKShapeNode? { - n.position = pos - n.strokeColor = SKColor.green - self.addChild(n) - } - } - - func touchMoved(toPoint pos : CGPoint) { - if let n = self.spinnyNode?.copy() as! SKShapeNode? { - n.position = pos - n.strokeColor = SKColor.blue - self.addChild(n) - } - } - - func touchUp(atPoint pos : CGPoint) { - if let n = self.spinnyNode?.copy() as! SKShapeNode? { - n.position = pos - n.strokeColor = SKColor.red - self.addChild(n) - } - } - - override func touchesBegan(_ touches: Set, with event: UIEvent?) { - if let label = self.label { - label.run(SKAction.init(named: "Pulse")!, withKey: "fadeInOut") - } + GameManager.shared.registerPlayers(p1, p2, scene: self) - for t in touches { self.touchDown(atPoint: t.location(in: self)) } - } - - override func touchesMoved(_ touches: Set, with event: UIEvent?) { - for t in touches { self.touchMoved(toPoint: t.location(in: self)) } - } - - override func touchesEnded(_ touches: Set, with event: UIEvent?) { - for t in touches { self.touchUp(atPoint: t.location(in: self)) } + // 3. Setup UI and attach to Camera + setupUI(cameraNode: cameraEntity.cameraNode) + + // 4. Start Game State Machine + GameStateMachine.shared.start() } - override func touchesCancelled(_ touches: Set, with event: UIEvent?) { - for t in touches { self.touchUp(atPoint: t.location(in: self)) } + private func setupUI(cameraNode: SKCameraNode) { + let hud = HUDNode(size: self.size) + let powerBar = PowerBarNode() + let turnHandoff = TurnHandoffOverlay(size: self.size) + let skillSelection = SkillSelection(size: self.size) + + // Add all to camera so they stay on screen + cameraNode.addChild(hud) + cameraNode.addChild(powerBar) + cameraNode.addChild(turnHandoff) + cameraNode.addChild(skillSelection) + + // Bind UI nodes to the system + UISystem.shared.setup(hud: hud, powerBar: powerBar, turnHandoff: turnHandoff, skillSelection: skillSelection) } - override func update(_ currentTime: TimeInterval) { - // Called before each frame is rendered - - // Initialize _lastUpdateTime if it has not already been if (self.lastUpdateTime == 0) { self.lastUpdateTime = currentTime } - // Calculate time since last update let dt = currentTime - self.lastUpdateTime // Update state machine and systems @@ -116,14 +74,12 @@ class GameScene: SKScene { // MARK: - ECS Management - /// Registers an entity with the scene so it receives `update(deltaTime:)` calls. func registerEntity(_ entity: GKEntity) { if !entities.contains(entity) { entities.append(entity) } } - /// Removes an entity from the scene's update loop. func removeEntity(_ entity: GKEntity) { if let index = entities.firstIndex(of: entity) { entities.remove(at: index) diff --git a/QuackFight/Sources/StateMachine/GameStateMachine.swift b/QuackFight/Sources/StateMachine/GameStateMachine.swift index 1fb702a..8374be3 100644 --- a/QuackFight/Sources/StateMachine/GameStateMachine.swift +++ b/QuackFight/Sources/StateMachine/GameStateMachine.swift @@ -31,12 +31,13 @@ import GameplayKit // Current State │ Trigger │ Next State // ─────────────────────────────────────────────────────────────────────────────── // InitState │ first match │ PreviewPanState -// InitState │ rematch │ SkillSelectState -// PreviewPanState │ .previewPanComplete event │ SkillSelectState -// SkillSelectState │ skill == .heal selected │ HealResolveState -// SkillSelectState │ skill == .fixedHit selected │ FixedHitResolveState -// SkillSelectState │ skill == .damageMultiplier / skip │ AimState +// InitState │ rematch │ AimState +// PreviewPanState │ .previewPanComplete event │ AimState +// AimState │ skill == .heal selected │ HealResolveState +// AimState │ skill == .fixedHit selected │ FixedHitResolveState // AimState │ .aimLockConfirmed event │ PowerState +// PowerState │ skill == .heal selected │ HealResolveState +// PowerState │ skill == .fixedHit selected │ FixedHitResolveState // PowerState │ .powerLockConfirmed event │ ThrowResolveState // ThrowResolveState │ miss (.throwResolved hit:false) │ TurnHandoffState // ThrowResolveState │ hit + no KO (.turnEnded) │ TurnHandoffState @@ -44,7 +45,7 @@ import GameplayKit // HealResolveState │ .healApplied event │ TurnHandoffState // FixedHitResolveState │ no KO (.turnEnded) │ TurnHandoffState // FixedHitResolveState │ KO (.gameOver) │ GameOverState -// TurnHandoffState │ .handoffDismissed, round cap not hit │ SkillSelectState +// TurnHandoffState │ .handoffDismissed, round cap not hit │ AimState // TurnHandoffState │ .handoffDismissed, round cap hit │ RoundOverState // RoundOverState │ 1.5 s elapsed │ GameOverState // GameOverState │ rematch (via GameScene / UISystem) │ InitState @@ -79,7 +80,6 @@ final class GameStateMachine { machine = GKStateMachine(states: [ InitState(), PreviewPanState(), - SkillSelectState(), AimState(), PowerState(), ThrowResolveState(), diff --git a/QuackFight/Sources/StateMachine/States/AimState.swift b/QuackFight/Sources/StateMachine/States/AimState.swift index c4a7aec..f14aa7c 100644 --- a/QuackFight/Sources/StateMachine/States/AimState.swift +++ b/QuackFight/Sources/StateMachine/States/AimState.swift @@ -35,11 +35,12 @@ final class AimState: GKState { // MARK: - Tokens private var aimToken: SubscriptionToken? + private var skillToken: SubscriptionToken? // MARK: - Valid Transitions override func isValidNextState(_ stateClass: AnyClass) -> Bool { - stateClass == PowerState.self + stateClass == PowerState.self || stateClass == HealResolveState.self || stateClass == FixedHitResolveState.self } // MARK: - Entry @@ -60,6 +61,27 @@ final class AimState: GKState { guard self != nil else { return } GameStateMachine.shared.enter(PowerState.self) } + + // Listen for skill selection + skillToken = EventBus.shared.subscribe(.skillSelected) { [weak self] event in + guard self != nil, case .skillSelected(let skill) = event else { return } + + let activePlayer = GameManager.shared.activePlayerIndex + let player = GameManager.shared.player(index: activePlayer) + + if let skillComp = player.component(ofType: SkillComponent.self), skillComp.activate(skill) { + EventBus.shared.post(.skillUsed(playerIndex: activePlayer, skill: skill)) + EventBus.shared.post(.showSkillSelection) // Update skill buttons UI + + if skill == .heal { + GameStateMachine.shared.enter(HealResolveState.self) + } else if skill == .fixedHit { + GameStateMachine.shared.enter(FixedHitResolveState.self) + } + } + } + + EventBus.shared.post(.showSkillSelection) // Ensure skills UI is updated when turn starts } // MARK: - Exit @@ -73,5 +95,10 @@ final class AimState: GKState { EventBus.shared.unsubscribe(token) } aimToken = nil + + if let token = skillToken { + EventBus.shared.unsubscribe(token) + } + skillToken = nil } } diff --git a/QuackFight/Sources/StateMachine/States/InitState.swift b/QuackFight/Sources/StateMachine/States/InitState.swift index 07b60d7..6b8ca82 100644 --- a/QuackFight/Sources/StateMachine/States/InitState.swift +++ b/QuackFight/Sources/StateMachine/States/InitState.swift @@ -35,7 +35,7 @@ final class InitState: GKState { // MARK: - Valid Transitions override func isValidNextState(_ stateClass: AnyClass) -> Bool { - stateClass == PreviewPanState.self || stateClass == SkillSelectState.self + stateClass == PreviewPanState.self || stateClass == AimState.self } // MARK: - Entry @@ -67,7 +67,7 @@ final class InitState: GKState { if isFirst { GameStateMachine.shared.setFirstMatchComplete() } - GameStateMachine.shared.enter(isFirst ? PreviewPanState.self : SkillSelectState.self) + GameStateMachine.shared.enter(isFirst ? PreviewPanState.self : AimState.self) } // MARK: - Private Helpers diff --git a/QuackFight/Sources/StateMachine/States/PowerState.swift b/QuackFight/Sources/StateMachine/States/PowerState.swift index 727b2f9..6d267ad 100644 --- a/QuackFight/Sources/StateMachine/States/PowerState.swift +++ b/QuackFight/Sources/StateMachine/States/PowerState.swift @@ -30,11 +30,12 @@ final class PowerState: GKState { // MARK: - Tokens private var powerToken: SubscriptionToken? + private var skillToken: SubscriptionToken? // MARK: - Valid Transitions override func isValidNextState(_ stateClass: AnyClass) -> Bool { - stateClass == ThrowResolveState.self + stateClass == ThrowResolveState.self || stateClass == HealResolveState.self || stateClass == FixedHitResolveState.self } // MARK: - Entry @@ -51,6 +52,25 @@ final class PowerState: GKState { guard self != nil else { return } GameStateMachine.shared.enter(ThrowResolveState.self) } + + // Listen for skill selection + skillToken = EventBus.shared.subscribe(.skillSelected) { [weak self] event in + guard self != nil, case .skillSelected(let skill) = event else { return } + + let activePlayer = GameManager.shared.activePlayerIndex + let player = GameManager.shared.player(index: activePlayer) + + if let skillComp = player.component(ofType: SkillComponent.self), skillComp.activate(skill) { + EventBus.shared.post(.skillUsed(playerIndex: activePlayer, skill: skill)) + EventBus.shared.post(.showSkillSelection) // Update skill buttons UI + + if skill == .heal { + GameStateMachine.shared.enter(HealResolveState.self) + } else if skill == .fixedHit { + GameStateMachine.shared.enter(FixedHitResolveState.self) + } + } + } } // MARK: - Exit @@ -64,5 +84,10 @@ final class PowerState: GKState { EventBus.shared.unsubscribe(token) } powerToken = nil + + if let token = skillToken { + EventBus.shared.unsubscribe(token) + } + skillToken = nil } } diff --git a/QuackFight/Sources/StateMachine/States/PreviewPanState.swift b/QuackFight/Sources/StateMachine/States/PreviewPanState.swift index fcd99ba..2f4e354 100644 --- a/QuackFight/Sources/StateMachine/States/PreviewPanState.swift +++ b/QuackFight/Sources/StateMachine/States/PreviewPanState.swift @@ -32,7 +32,7 @@ final class PreviewPanState: GKState { // MARK: - Valid Transitions override func isValidNextState(_ stateClass: AnyClass) -> Bool { - stateClass == SkillSelectState.self + stateClass == AimState.self } // MARK: - Entry @@ -44,7 +44,7 @@ final class PreviewPanState: GKState { panToken = EventBus.shared.subscribe(.previewPanComplete) { [weak self] _ in guard self != nil else { return } - GameStateMachine.shared.enter(SkillSelectState.self) + GameStateMachine.shared.enter(AimState.self) } } diff --git a/QuackFight/Sources/StateMachine/States/SkillSelectState.swift b/QuackFight/Sources/StateMachine/States/SkillSelectState.swift deleted file mode 100644 index 0321434..0000000 --- a/QuackFight/Sources/StateMachine/States/SkillSelectState.swift +++ /dev/null @@ -1,102 +0,0 @@ -// -// SkillSelectState.swift -// QuackFight -// -// Created by Justin Chow on 12/05/26. -// - -import GameplayKit - -// MARK: - Entry / Exit Feedback (#27) -// -// didEnter → Skill selection UI slides up from the bottom of the screen. -// Active player's available skills are shown as tappable cards. -// If the player has no skills left, the UI is skipped entirely -// and the state machine immediately enters AimState. -// willExit → Skill UI slides out. HUD returns to normal layout. -// If a skill was selected, its icon is highlighted in the HUD. - -/// Presents the skill selection UI and routes to the appropriate resolve state. -/// -/// ## Routing logic -/// - **No skills remaining** → skip UI, enter `AimState` immediately. -/// - **.heal selected** → enter `HealResolveState`. -/// - **.fixedHit selected** → enter `FixedHitResolveState`. -/// - **.damageMultiplier selected** → activate on player, then enter `AimState`. -/// - **skipped** → enter `AimState`. -/// -/// The active player's `SkillComponent.activeSkill` is set here on selection. -/// The appropriate resolve state or `DamageSystem` calls `consumeActive()` later. -final class SkillSelectState: GKState { - - // MARK: - Tokens - - private var skillToken: SubscriptionToken? - private var skipToken: SubscriptionToken? - - // MARK: - Valid Transitions - - override func isValidNextState(_ stateClass: AnyClass) -> Bool { - stateClass == AimState.self || - stateClass == HealResolveState.self || - stateClass == FixedHitResolveState.self - } - - // MARK: - Entry - - override func didEnter(from previousState: GKState?) { - let activePlayer = GameManager.shared.activePlayer - let skillComp = activePlayer.component(ofType: SkillComponent.self) - - // Ensure any lingering active skill from a prior turn is cleared. - skillComp?.clearActive() - - // If the player has burned all skills, skip straight to aim phase. - if skillComp?.availableSkills.isEmpty == true { - GameStateMachine.shared.enter(AimState.self) - return - } - - // Show the skill selection UI (UISystem observes this event). - EventBus.shared.post(.showSkillSelection) - - // Subscribe for the player's choice. - skillToken = EventBus.shared.subscribe(.skillSelected) { [weak self] event in - guard let self, case .skillSelected(let skill) = event else { return } - self.handleSkillSelected(skill) - } - - skipToken = EventBus.shared.subscribe(.skillSkipped) { [weak self] _ in - guard self != nil else { return } - GameStateMachine.shared.enter(AimState.self) - } - } - - // MARK: - Exit - - override func willExit(to nextState: GKState) { - [skillToken, skipToken].compactMap { $0 }.forEach { EventBus.shared.unsubscribe($0) } - skillToken = nil - skipToken = nil - } - - // MARK: - Routing - - private func handleSkillSelected(_ skill: SkillType) { - let activePlayer = GameManager.shared.activePlayer - activePlayer.component(ofType: SkillComponent.self)?.activate(skill) - - // Notify UISystem so the skill icon can be highlighted in the HUD. - EventBus.shared.post(.skillUsed(playerIndex: activePlayer.playerIndex, skill: skill)) - - switch skill { - case .heal: - GameStateMachine.shared.enter(HealResolveState.self) - case .fixedHit: - GameStateMachine.shared.enter(FixedHitResolveState.self) - case .damageMultiplier: - // Multiplier is applied during the throw; route to normal aim phase. - GameStateMachine.shared.enter(AimState.self) - } - } -} diff --git a/QuackFight/Sources/StateMachine/States/TurnHandoffState.swift b/QuackFight/Sources/StateMachine/States/TurnHandoffState.swift index e1a8d83..02ffff6 100644 --- a/QuackFight/Sources/StateMachine/States/TurnHandoffState.swift +++ b/QuackFight/Sources/StateMachine/States/TurnHandoffState.swift @@ -45,7 +45,7 @@ final class TurnHandoffState: GKState { // MARK: - Valid Transitions override func isValidNextState(_ stateClass: AnyClass) -> Bool { - stateClass == SkillSelectState.self || stateClass == RoundOverState.self + stateClass == AimState.self || stateClass == RoundOverState.self } // MARK: - Entry @@ -90,7 +90,7 @@ final class TurnHandoffState: GKState { determineRoundCapOutcome() GameStateMachine.shared.enter(RoundOverState.self) } else { - GameStateMachine.shared.enter(SkillSelectState.self) + GameStateMachine.shared.enter(AimState.self) } } diff --git a/QuackFight/Sources/Systems/Render/UISystem.swift b/QuackFight/Sources/Systems/Render/UISystem.swift index 0a40590..e7d239b 100644 --- a/QuackFight/Sources/Systems/Render/UISystem.swift +++ b/QuackFight/Sources/Systems/Render/UISystem.swift @@ -2,7 +2,105 @@ // UISystem.swift // QuackFight // -// Created by Justin Chow on 12/05/26. -// -import Foundation +import SpriteKit +import GameplayKit + +/// Coordinates UI updates by subscribing to the EventBus. +/// Holds references to the visual SKNode overlays and passes data to them. +final class UISystem { + + static let shared = UISystem() + + private var hudNode: HUDNode? + private var powerBar: PowerBarNode? + private var turnHandoff: TurnHandoffOverlay? + private var skillSelection: SkillSelection? + + private init() {} + + /// Binds the system to the scene's UI nodes. + func setup(hud: HUDNode, powerBar: PowerBarNode, turnHandoff: TurnHandoffOverlay, skillSelection: SkillSelection) { + self.hudNode = hud + self.powerBar = powerBar + self.turnHandoff = turnHandoff + self.skillSelection = skillSelection + + setupSubscriptions() + } + + private func setupSubscriptions() { + EventBus.shared.subscribe(.hpChanged) { [weak self] event in + guard let self, case .hpChanged(let playerIndex, let hp) = event else { return } + self.hudNode?.updateHP(playerIndex: playerIndex, current: hp, max: GameConstants.maxHP) + } + + EventBus.shared.subscribe(.timerTick) { [weak self] event in + guard let self, case .timerTick(let remaining) = event else { return } + let maxTime: TimeInterval = 5.0 // Aim/Power time limit + self.hudNode?.updateTimer(percentage: CGFloat(remaining / maxTime)) + } + + EventBus.shared.subscribe(.damageApplied) { [weak self] event in + guard let self, case .damageApplied(let amount, let target) = event else { return } + self.hudNode?.showDamagePopup(playerIndex: target, amount: amount) + } + + EventBus.shared.subscribe(.amplitudeUpdated) { [weak self] event in + guard let self, case .amplitudeUpdated(let amplitude) = event else { return } + self.powerBar?.updateFill(CGFloat(amplitude)) + } + + EventBus.shared.subscribe(.roundCountUpdated) { [weak self] event in + guard let self, case .roundCountUpdated(let turn, _) = event else { return } + self.hudNode?.updateRoundCounter(round: turn) + } + + EventBus.shared.subscribe(.showTurnHandoff) { [weak self] event in + guard let self, case .showTurnHandoff(let nextPlayer) = event else { return } + self.hudNode?.showActivePlayerGlow(playerIndex: nextPlayer) + self.turnHandoff?.show(forPlayer: nextPlayer) + + // Hide after a delay + DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { + self.turnHandoff?.hide() + } + } + + EventBus.shared.subscribe(.showInstruction) { [weak self] event in + guard let self, case .showInstruction(let text) = event else { return } + self.turnHandoff?.showInstruction(text) + + // Show power bar only if instruction is Shout! + if text == "Shout!" { + self.powerBar?.show() + } else { + self.powerBar?.hide() + } + + DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { + self.turnHandoff?.hide() + } + } + + EventBus.shared.subscribe(.throwStarted) { [weak self] _ in + guard let self else { return } + self.powerBar?.hide() + } + + EventBus.shared.subscribe(.showSkillSelection) { [weak self] _ in + guard let self else { return } + let activePlayer = GameManager.shared.activePlayerIndex + let player = GameManager.shared.player(index: activePlayer) + + if let skillComp = player.component(ofType: SkillComponent.self) { + self.skillSelection?.show(forPlayer: activePlayer, availableSkills: skillComp.availableSkills) + } + } + + EventBus.shared.subscribe(.skillUsed) { [weak self] _ in + guard let self else { return } + // Let the HUD trigger any specific animations if needed, though state is handled automatically. + } + } +} diff --git a/QuackFight/Sources/Types/GameTypes.swift b/QuackFight/Sources/Types/GameTypes.swift index 5470860..d2436f1 100644 --- a/QuackFight/Sources/Types/GameTypes.swift +++ b/QuackFight/Sources/Types/GameTypes.swift @@ -147,6 +147,7 @@ enum GameEvent { // MARK: UI case showTurnHandoff(nextPlayerIndex: Int) + case showInstruction(String) case hpChanged(playerIndex: Int, hp: Int) // MARK: - Key @@ -159,7 +160,7 @@ enum GameEvent { case healApplied, turnEnded, gameOver, timerTick, amplitudeUpdated case cycleAdvanced, roundCountUpdated, previewPanComplete case cameraReturnComplete, showSkillSelection, skillSelected - case skillSkipped, skillUsed, showTurnHandoff, hpChanged + case skillSkipped, skillUsed, showTurnHandoff, showInstruction, hpChanged } /// Derives the `Key` from `self`, stripping associated values so it can @@ -188,6 +189,7 @@ enum GameEvent { case .skillSkipped: return .skillSkipped case .skillUsed: return .skillUsed case .showTurnHandoff: return .showTurnHandoff + case .showInstruction: return .showInstruction case .hpChanged: return .hpChanged } } diff --git a/QuackFight/Sources/UI/HUDNode.swift b/QuackFight/Sources/UI/HUDNode.swift index f706755..16bc94f 100644 --- a/QuackFight/Sources/UI/HUDNode.swift +++ b/QuackFight/Sources/UI/HUDNode.swift @@ -2,7 +2,181 @@ // HUDNode.swift // QuackFight // -// Created by Justin Chow on 12/05/26. -// -import Foundation +import SpriteKit + +/// The main UI wrapper that sits over the game scene, attached to the SKCameraNode. +class HUDNode: SKNode { + + // MARK: - Top HUD + private let p1HPBarBG: SKSpriteNode + private let p2HPBarBG: SKSpriteNode + private let p1HPFill: SKSpriteNode + private let p2HPFill: SKSpriteNode + private let roundLabel: SKLabelNode + private let roundCycle: SKSpriteNode + + // MARK: - Bottom HUD + private let bottomBackground: SKSpriteNode + private let timerBar: SKSpriteNode + + // MARK: - Active Player Glow + private let p1Glow: SKShapeNode + private let p2Glow: SKShapeNode + + init(size: CGSize) { + let halfW = size.width / 2.0 + let halfH = size.height / 2.0 + + // Setup HP Bars + p1HPBarBG = SKSpriteNode(imageNamed: "GooseHPBar") + p1HPBarBG.position = CGPoint(x: -halfW + 95, y:halfH - 80) + p1HPBarBG.setScale(0.3) + p1HPBarBG.zPosition = 900 + + p2HPBarBG = SKSpriteNode(imageNamed: "DuckHPBar") + p2HPBarBG.position = CGPoint(x: halfW - 95, y: halfH - 80) + p2HPBarBG.setScale(0.3) + p2HPBarBG.zPosition = 900 + + p1HPFill = SKSpriteNode(color: .systemGreen, size: CGSize(width: 140, height: 30)) + p1HPFill.anchorPoint = CGPoint(x: 0, y: 0.5) + p1HPFill.position = CGPoint(x: p1HPBarBG.position.x - 50, y: p1HPBarBG.position.y - 5) + p1HPFill.zPosition = 899 + + p2HPFill = SKSpriteNode(color: .systemGreen, size: CGSize(width: 140, height: 30)) + p2HPFill.anchorPoint = CGPoint(x: 1, y: 0.5) + p2HPFill.position = CGPoint(x: p2HPBarBG.position.x + 50, y: p2HPBarBG.position.y - 5) + p2HPFill.zPosition = 899 + + // Round Cycle + roundCycle = SKSpriteNode(imageNamed: "Cycle1") + roundCycle.position = CGPoint(x: 0, y: halfH - 90) + roundCycle.setScale(0.2) + roundCycle.zPosition = 901 + + // Setup Round Label + roundLabel = SKLabelNode(fontNamed: "SFProRounded-Black") + roundLabel.text = "12" + roundLabel.fontSize = 24 + roundLabel.fontColor = .yellowQuack + roundLabel.position = CGPoint(x: roundCycle.position.x, y: roundCycle.position.y - 28) + roundLabel.zPosition = 902 + + // Group Top HUD Position + let modifyX: CGFloat = 0 + let modifyY: CGFloat = -20 + p1HPBarBG.position.x += modifyX + p2HPBarBG.position.x += modifyX + p1HPFill.position.x += modifyX + p2HPFill.position.x += modifyX + roundCycle.position.x += modifyX + p1HPBarBG.position.y += modifyY + p2HPBarBG.position.y += modifyY + p1HPFill.position.y += modifyY + p2HPFill.position.y += modifyY + roundCycle.position.y += modifyY + + + // Setup Bottom HUD + bottomBackground = SKSpriteNode(imageNamed: "BottomHUDBackground") + bottomBackground.position = CGPoint(x: 0, y: -halfH + bottomBackground.size.height / 4) + bottomBackground.setScale(0.5) + bottomBackground.zPosition = 900 + + timerBar = SKSpriteNode(imageNamed: "BottomHUDTimerBar") +// timerBar.anchorPoint = CGPoint(x: 1, y: 0.5) + timerBar.position = CGPoint(x: bottomBackground.position.x, y: bottomBackground.position.y) + timerBar.setScale(0.5) + timerBar.zPosition = 901 + + // Setup Active Glows (Pulsing circles behind avatars) + p1Glow = SKShapeNode(circleOfRadius: 60) + p1Glow.fillColor = .systemYellow + p1Glow.strokeColor = .clear + p1Glow.alpha = 0.0 + p1Glow.position = CGPoint(x: p1HPBarBG.position.x - 120, y: p1HPBarBG.position.y) + p1Glow.zPosition = 898 + + p2Glow = SKShapeNode(circleOfRadius: 60) + p2Glow.fillColor = .systemYellow + p2Glow.strokeColor = .clear + p2Glow.alpha = 0.0 + p2Glow.position = CGPoint(x: p2HPBarBG.position.x + 120, y: p2HPBarBG.position.y) + p2Glow.zPosition = 898 + + super.init() + + addChild(p1HPBarBG) + addChild(p2HPBarBG) + addChild(p1HPFill) + addChild(p2HPFill) + addChild(roundCycle) + addChild(roundLabel) + addChild(bottomBackground) + addChild(timerBar) + addChild(p1Glow) + addChild(p2Glow) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func updateHP(playerIndex: Int, current: Int, max: Int) { + let percentage = CGFloat(current) / CGFloat(max) + let fill = playerIndex == 0 ? p1HPFill : p2HPFill + let targetWidth = 200.0 * percentage + fill.run(SKAction.resize(toWidth: targetWidth, duration: 0.3)) + } + + func updateTimer(percentage: CGFloat) { + timerBar.xScale = max(0, percentage) + if percentage <= 0.4 { + timerBar.color = .systemRed + timerBar.colorBlendFactor = 1.0 + } else { + timerBar.colorBlendFactor = 0.0 + } + } + + func updateRoundCounter(round: Int) { + roundLabel.text = "Turn \(round)/20" + } + + func showActivePlayerGlow(playerIndex: Int) { + p1Glow.removeAllActions() + p2Glow.removeAllActions() + p1Glow.alpha = 0 + p2Glow.alpha = 0 + + let glow = playerIndex == 0 ? p1Glow : p2Glow + let pulse = SKAction.sequence([ + SKAction.fadeAlpha(to: 0.6, duration: 0.8), + SKAction.fadeAlpha(to: 0.2, duration: 0.8) + ]) + glow.run(SKAction.repeatForever(pulse)) + } + + func showDamagePopup(playerIndex: Int, amount: Int) { + let label = SKLabelNode(fontNamed: ".SFProRounded-Bold") + label.text = "-\(amount)" + label.fontColor = .systemRed + label.fontSize = 36 + + // Base it roughly around the HP bar location + let baseX = playerIndex == 0 ? p1HPBarBG.position.x : p2HPBarBG.position.x + let baseY = p1HPBarBG.position.y - 80 + label.position = CGPoint(x: baseX, y: baseY) + label.zPosition = 1000 + + addChild(label) + + let moveUp = SKAction.moveBy(x: 0, y: 50, duration: 1.0) + let fadeOut = SKAction.fadeOut(withDuration: 1.0) + let group = SKAction.group([moveUp, fadeOut]) + let remove = SKAction.removeFromParent() + + label.run(SKAction.sequence([group, remove])) + } +} diff --git a/QuackFight/Sources/UI/PowerBarNode.swift b/QuackFight/Sources/UI/PowerBarNode.swift index a4280a5..68a4f4f 100644 --- a/QuackFight/Sources/UI/PowerBarNode.swift +++ b/QuackFight/Sources/UI/PowerBarNode.swift @@ -2,7 +2,69 @@ // PowerBarNode.swift // QuackFight // -// Created by Justin Chow on 12/05/26. -// -import Foundation +import SpriteKit + +/// A vertical meter that tracks Voice Power input. +class PowerBarNode: SKNode { + + private let background: SKSpriteNode + private let fillNode: SKSpriteNode + private let micIcon: SKSpriteNode + + private let maxFillHeight: CGFloat = 300.0 + private let fillWidth: CGFloat = 40.0 + + override init() { + // Use the asset "Voice Input" + background = SKSpriteNode(imageNamed: "VoiceInputBar") + background.anchorPoint = CGPoint(x: 0.5, y: 0.0) + background.zPosition = 100 + + // We use a white sprite and tint it for the fill + fillNode = SKSpriteNode(color: .white, size: CGSize(width: fillWidth, height: 0)) + fillNode.anchorPoint = CGPoint(x: 0.5, y: 0.0) + // Position it slightly above the bottom of the background to fit within the frame visually + fillNode.position = CGPoint(x: 0, y: 50) + fillNode.zPosition = 101 + + micIcon = SKSpriteNode(imageNamed: "Voice Input") // We could add a separate mic icon here if needed, but the BG might already have it. + micIcon.isHidden = true // The background asset already has the mic on it + + super.init() + + addChild(background) + addChild(fillNode) + + self.alpha = 0.0 // Hidden by default + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + /// Updates the fill level (0.0 to 1.0) and transitions color + func updateFill(_ value: CGFloat) { + let clamped = max(0, min(1, value)) + fillNode.size.height = maxFillHeight * clamped + + // 0.0-0.4 = Green, 0.4-0.7 = Yellow, 0.7-1.0 = Red + if clamped < 0.4 { + fillNode.color = .systemGreen + } else if clamped < 0.7 { + fillNode.color = .systemYellow + } else { + fillNode.color = .systemRed + } + fillNode.colorBlendFactor = 1.0 + } + + func show() { + self.run(SKAction.fadeAlpha(to: 1.0, duration: 0.2)) + } + + func hide() { + self.run(SKAction.fadeAlpha(to: 0.0, duration: 0.2)) + updateFill(0) + } +} diff --git a/QuackFight/Sources/UI/SkillSelection.swift b/QuackFight/Sources/UI/SkillSelection.swift new file mode 100644 index 0000000..13ef891 --- /dev/null +++ b/QuackFight/Sources/UI/SkillSelection.swift @@ -0,0 +1,96 @@ +// +// SkillSelection.swift +// QuackFight +// + +import SpriteKit + +/// A SpriteKit modal overlay for selecting a skill. +class SkillSelection: SKNode { + + private let container: SKNode + private var skillButtons: [SkillType: SKSpriteNode] = [:] + + private var playerIndex: Int = 0 + private var availableSkills: Set = [] + + init(size: CGSize) { + container = SKNode() + container.zPosition = 2001 + + // Position container at bottom HUD area + container.position = CGPoint(x: 0, y: -size.height / 2.0 + 120) + + super.init() + addChild(container) + self.isUserInteractionEnabled = true + setupButtons() + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupButtons() { + let skills: [SkillType] = [.damageMultiplier, .heal, .fixedHit] + let spacing: CGFloat = 120.0 + let startX: CGFloat = -CGFloat(skills.count - 1) * spacing / 2.0 + + for (i, skill) in skills.enumerated() { + let assetName = getAssetPrefix(for: skill) + "_Enabled" + let btn = SKSpriteNode(imageNamed: assetName) + btn.name = "skill_\(skill.rawValue)" + btn.position = CGPoint(x: startX + CGFloat(i) * spacing, y: 0) + + skillButtons[skill] = btn + container.addChild(btn) + } + } + + private func getAssetPrefix(for skill: SkillType) -> String { + switch skill { + case .damageMultiplier: return "2x" + case .heal: return "heal" + case .fixedHit: return "auto hit" + } + } + + func show(forPlayer index: Int, availableSkills: Set) { + self.playerIndex = index + self.availableSkills = availableSkills + + for (skill, button) in skillButtons { + if availableSkills.contains(skill) { + button.texture = SKTexture(imageNamed: getAssetPrefix(for: skill)) + button.alpha = 1.0 + } else { + button.texture = SKTexture(imageNamed: getAssetPrefix(for: skill) + " disabled") + button.alpha = 0.4 + } + } + + // Don't fade the whole node, just update visually + } + + func hide() { + // No-op since skills are always visible + } + + override func touchesBegan(_ touches: Set, with event: UIEvent?) { + guard let touch = touches.first else { return } + + let location = touch.location(in: container) + let nodesAtTouch = container.nodes(at: location) + + for node in nodesAtTouch { + + if let name = node.name, name.hasPrefix("skill_") { + let rawValue = String(name.dropFirst("skill_".count)) + if let skill = SkillType(rawValue: rawValue), availableSkills.contains(skill) { + EventBus.shared.post(.skillSelected(skill)) + return + } + } + } + } +} diff --git a/QuackFight/Sources/UI/SkillSelectionViewController.swift b/QuackFight/Sources/UI/SkillSelectionViewController.swift deleted file mode 100644 index e55940f..0000000 --- a/QuackFight/Sources/UI/SkillSelectionViewController.swift +++ /dev/null @@ -1,8 +0,0 @@ -// -// SkillSelectionViewController.swift -// QuackFight -// -// Created by Justin Chow on 12/05/26. -// - -import Foundation diff --git a/QuackFight/Sources/UI/TurnHandoffOverlay.swift b/QuackFight/Sources/UI/TurnHandoffOverlay.swift index 33598b8..a836fcd 100644 --- a/QuackFight/Sources/UI/TurnHandoffOverlay.swift +++ b/QuackFight/Sources/UI/TurnHandoffOverlay.swift @@ -2,7 +2,60 @@ // TurnHandoffOverlay.swift // QuackFight // -// Created by Justin Chow on 12/05/26. -// -import Foundation +import SpriteKit + +/// Handles full-screen instructional overlays like "Goose's Turn", "Tilt to Aim", and "Shout!" +class TurnHandoffOverlay: SKNode { + + private let background: SKSpriteNode + private let titleLabel: SKLabelNode + + init(size: CGSize) { + // Dark background + background = SKSpriteNode(color: UIColor.black.withAlphaComponent(0.6), size: size) + + // Title Label + titleLabel = SKLabelNode(fontNamed: ".SFProRounded-Bold") + titleLabel.fontSize = 64 + titleLabel.fontColor = .white + titleLabel.verticalAlignmentMode = .center + titleLabel.horizontalAlignmentMode = .center + + super.init() + + // Z-Positioning to ensure it sits on top of everything + self.zPosition = 1000 + self.alpha = 0.0 // Hidden by default + + addChild(background) + addChild(titleLabel) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + /// Shows a player turn handoff + func show(forPlayer playerIndex: Int) { + titleLabel.text = playerIndex == 0 ? "Goose's Turn" : "Duck's Turn" + fadeIn() + } + + /// Shows a generic instruction + func showInstruction(_ text: String) { + titleLabel.text = text + fadeIn() + } + + private func fadeIn() { + removeAllActions() + self.run(SKAction.fadeAlpha(to: 1.0, duration: 0.3)) + } + + /// Fades out the overlay + func hide() { + removeAllActions() + self.run(SKAction.fadeAlpha(to: 0.0, duration: 0.2)) + } +}