├── _etc
├── cat.png
├── Fire.sks
├── braid.png
├── coin.png
├── icon.pxm
├── spark.png
├── wall.png
├── zelda.png
├── 8BitLoop.mp3
├── cescofry.png
├── elf
│ ├── elf.png
│ ├── elf.atlas
│ │ ├── slice01.png
│ │ ├── slice02.png
│ │ ├── slice03.png
│ │ ├── slice04.png
│ │ ├── slice05.png
│ │ ├── slice06.png
│ │ ├── slice07.png
│ │ ├── slice08.png
│ │ ├── slice09.png
│ │ ├── slice10.png
│ │ ├── slice11.png
│ │ ├── slice12.png
│ │ ├── slice13.png
│ │ ├── slice14.png
│ │ ├── slice15.png
│ │ ├── slice16.png
│ │ ├── slice17.png
│ │ ├── slice18.png
│ │ ├── slice19.png
│ │ ├── slice20.png
│ │ ├── slice21.png
│ │ ├── slice22.png
│ │ ├── slice23.png
│ │ ├── slice24.png
│ │ ├── slice25.png
│ │ ├── slice26.png
│ │ ├── slice27.png
│ │ ├── slice28.png
│ │ ├── slice29.png
│ │ ├── slice30.png
│ │ ├── slice31.png
│ │ ├── slice32.png
│ │ ├── slice33.png
│ │ ├── slice34.png
│ │ ├── slice35.png
│ │ ├── slice36.png
│ │ ├── slice37.png
│ │ ├── slice38.png
│ │ ├── slice39.png
│ │ ├── slice40.png
│ │ ├── slice41.png
│ │ ├── slice42.png
│ │ ├── slice43.png
│ │ ├── slice44.png
│ │ ├── slice45.png
│ │ ├── slice46.png
│ │ ├── slice47.png
│ │ ├── slice48.png
│ │ ├── slice49.png
│ │ └── slice50.png
│ └── elf.png.txt
├── icon_152.png
├── icon_300.png
├── portal.png
├── rpg_bkg.jpg
├── action_ask.png
├── action_cat.png
├── action_run.png
├── mario_bkg.jpg
├── mario_bkg.pxm
├── mario_pipe.png
├── overworld.mp3
├── professor.png
├── action_enemy.png
├── action_fire.png
├── action_moving.png
├── action_path.png
├── action_speak.png
├── mario_bkg_1.png
├── mario_bkg_2.jpg
├── action_falling.png
├── action_strategy.png
├── dn-smb-coinblock.jpg
└── html
│ ├── source_5.html
│ ├── source_template.html
│ ├── source_10.html
│ ├── source_2.html
│ ├── source_4.html
│ ├── source_6.html
│ ├── source_8.html
│ ├── source_3.html
│ ├── css
│ ├── font.css
│ ├── pygments14.css
│ ├── pygments.css
│ └── basic.css
│ ├── source_7.html
│ ├── source_9.html
│ └── source_1.html
├── SpriteKitTankTalk
├── Piro.sks
├── spark.png
├── Images.xcassets
│ ├── Contents.json
│ ├── cat.imageset
│ │ ├── cat.png
│ │ └── Contents.json
│ ├── coin.imageset
│ │ ├── coin.png
│ │ └── Contents.json
│ ├── wall.imageset
│ │ ├── wall.png
│ │ └── Contents.json
│ ├── zelda.imageset
│ │ ├── zelda.png
│ │ └── Contents.json
│ ├── portal.imageset
│ │ ├── portal.png
│ │ └── Contents.json
│ ├── rpg_bkg.imageset
│ │ ├── rpg_bkg.jpg
│ │ └── Contents.json
│ ├── icon_300.imageset
│ │ ├── icon_300.png
│ │ └── Contents.json
│ ├── AppIcon.appiconset
│ │ ├── icon_152.png
│ │ └── Contents.json
│ ├── professor.imageset
│ │ ├── professor.png
│ │ └── Contents.json
│ ├── action_ask.imageset
│ │ ├── action_ask.png
│ │ └── Contents.json
│ ├── action_cat.imageset
│ │ ├── action_cat.png
│ │ └── Contents.json
│ ├── action_run.imageset
│ │ ├── action_run.png
│ │ └── Contents.json
│ ├── mario_pipe.imageset
│ │ ├── mario_pipe.png
│ │ └── Contents.json
│ ├── action_enemy.imageset
│ │ ├── action_enemy.png
│ │ └── Contents.json
│ ├── action_fire.imageset
│ │ ├── action_fire.png
│ │ └── Contents.json
│ ├── action_path.imageset
│ │ ├── action_path.png
│ │ └── Contents.json
│ ├── action_speak.imageset
│ │ ├── action_speak.png
│ │ └── Contents.json
│ ├── mario_bkg_1.imageset
│ │ ├── mario_bkg_1.png
│ │ └── Contents.json
│ ├── mario_bkg_2.imageset
│ │ ├── mario_bkg_2.jpg
│ │ └── Contents.json
│ ├── action_moving.imageset
│ │ ├── action_moving.png
│ │ └── Contents.json
│ ├── action_falling.imageset
│ │ ├── action_falling.png
│ │ └── Contents.json
│ └── action_strategy.imageset
│ │ ├── action_strategy.png
│ │ └── Contents.json
├── scenes
│ ├── GameScene1.sks
│ ├── GameScene2.sks
│ ├── GameScene3.sks
│ ├── GameScene4.sks
│ ├── GameScene5.sks
│ ├── GameScene6.sks
│ ├── GameScene7.sks
│ ├── GameScene8.sks
│ ├── GameScene9.sks
│ └── GameScene10.sks
├── Config.plist
├── Extensions.swift
├── Info.plist
├── AppDelegate.swift
├── GameSceneGenerator.swift
├── OptionsViewController.swift
├── GameViewController.swift
├── CodeViewController.swift
├── Base.lproj
│ ├── LaunchScreen.xib
│ └── Main.storyboard
├── Config.swift
├── SpeakBoxController.swift
├── TestViewController.swift
├── SpeechSynthesizer.swift
├── Character.swift
├── GameScene.swift
└── GameExtensions.swift
├── SpriteKitTankTalk.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ ├── ffrison.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ │ └── cescofry.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcshareddata
│ │ ├── SpriteKitTankTalk.xcscmblueprint
│ │ └── SpriteKitTankTalk.xccheckout
└── xcuserdata
│ ├── cescofry.xcuserdatad
│ ├── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── SpriteKitTankTalk.xcscheme
│ └── ffrison.xcuserdatad
│ ├── xcdebugger
│ └── Breakpoints_v2.xcbkptlist
│ └── xcschemes
│ ├── xcschememanagement.plist
│ └── SpriteKitTankTalk.xcscheme
├── README.md
└── SpriteKitTankTalkTests
├── Info.plist
└── SpriteKitTankTalkTests.swift
/_etc/cat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/cat.png
--------------------------------------------------------------------------------
/_etc/Fire.sks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/Fire.sks
--------------------------------------------------------------------------------
/_etc/braid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/braid.png
--------------------------------------------------------------------------------
/_etc/coin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/coin.png
--------------------------------------------------------------------------------
/_etc/icon.pxm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/icon.pxm
--------------------------------------------------------------------------------
/_etc/spark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/spark.png
--------------------------------------------------------------------------------
/_etc/wall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/wall.png
--------------------------------------------------------------------------------
/_etc/zelda.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/zelda.png
--------------------------------------------------------------------------------
/_etc/8BitLoop.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/8BitLoop.mp3
--------------------------------------------------------------------------------
/_etc/cescofry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/cescofry.png
--------------------------------------------------------------------------------
/_etc/elf/elf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.png
--------------------------------------------------------------------------------
/_etc/icon_152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/icon_152.png
--------------------------------------------------------------------------------
/_etc/icon_300.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/icon_300.png
--------------------------------------------------------------------------------
/_etc/portal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/portal.png
--------------------------------------------------------------------------------
/_etc/rpg_bkg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/rpg_bkg.jpg
--------------------------------------------------------------------------------
/_etc/action_ask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/action_ask.png
--------------------------------------------------------------------------------
/_etc/action_cat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/action_cat.png
--------------------------------------------------------------------------------
/_etc/action_run.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/action_run.png
--------------------------------------------------------------------------------
/_etc/mario_bkg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/mario_bkg.jpg
--------------------------------------------------------------------------------
/_etc/mario_bkg.pxm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/mario_bkg.pxm
--------------------------------------------------------------------------------
/_etc/mario_pipe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/mario_pipe.png
--------------------------------------------------------------------------------
/_etc/overworld.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/overworld.mp3
--------------------------------------------------------------------------------
/_etc/professor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/professor.png
--------------------------------------------------------------------------------
/_etc/action_enemy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/action_enemy.png
--------------------------------------------------------------------------------
/_etc/action_fire.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/action_fire.png
--------------------------------------------------------------------------------
/_etc/action_moving.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/action_moving.png
--------------------------------------------------------------------------------
/_etc/action_path.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/action_path.png
--------------------------------------------------------------------------------
/_etc/action_speak.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/action_speak.png
--------------------------------------------------------------------------------
/_etc/mario_bkg_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/mario_bkg_1.png
--------------------------------------------------------------------------------
/_etc/mario_bkg_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/mario_bkg_2.jpg
--------------------------------------------------------------------------------
/_etc/action_falling.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/action_falling.png
--------------------------------------------------------------------------------
/_etc/action_strategy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/action_strategy.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Piro.sks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Piro.sks
--------------------------------------------------------------------------------
/SpriteKitTankTalk/spark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/spark.png
--------------------------------------------------------------------------------
/_etc/dn-smb-coinblock.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/dn-smb-coinblock.jpg
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice01.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice02.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice03.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice04.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice05.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice06.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice07.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice07.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice08.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice08.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice09.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice09.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice10.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice11.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice12.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice13.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice14.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice15.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice16.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice17.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice18.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice19.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice20.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice21.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice22.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice22.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice23.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice23.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice24.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice25.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice26.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice26.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice27.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice27.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice28.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice29.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice30.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice31.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice31.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice32.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice33.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice33.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice34.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice34.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice35.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice35.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice36.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice37.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice37.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice38.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice38.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice39.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice39.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice40.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice41.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice41.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice42.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice42.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice43.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice43.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice44.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice44.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice45.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice45.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice46.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice46.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice47.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice47.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice48.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice49.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice49.png
--------------------------------------------------------------------------------
/_etc/elf/elf.atlas/slice50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/_etc/elf/elf.atlas/slice50.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/scenes/GameScene1.sks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/scenes/GameScene1.sks
--------------------------------------------------------------------------------
/SpriteKitTankTalk/scenes/GameScene2.sks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/scenes/GameScene2.sks
--------------------------------------------------------------------------------
/SpriteKitTankTalk/scenes/GameScene3.sks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/scenes/GameScene3.sks
--------------------------------------------------------------------------------
/SpriteKitTankTalk/scenes/GameScene4.sks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/scenes/GameScene4.sks
--------------------------------------------------------------------------------
/SpriteKitTankTalk/scenes/GameScene5.sks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/scenes/GameScene5.sks
--------------------------------------------------------------------------------
/SpriteKitTankTalk/scenes/GameScene6.sks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/scenes/GameScene6.sks
--------------------------------------------------------------------------------
/SpriteKitTankTalk/scenes/GameScene7.sks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/scenes/GameScene7.sks
--------------------------------------------------------------------------------
/SpriteKitTankTalk/scenes/GameScene8.sks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/scenes/GameScene8.sks
--------------------------------------------------------------------------------
/SpriteKitTankTalk/scenes/GameScene9.sks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/scenes/GameScene9.sks
--------------------------------------------------------------------------------
/SpriteKitTankTalk/scenes/GameScene10.sks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/scenes/GameScene10.sks
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/cat.imageset/cat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/cat.imageset/cat.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/coin.imageset/coin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/coin.imageset/coin.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/wall.imageset/wall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/wall.imageset/wall.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/zelda.imageset/zelda.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/zelda.imageset/zelda.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/portal.imageset/portal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/portal.imageset/portal.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/rpg_bkg.imageset/rpg_bkg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/rpg_bkg.imageset/rpg_bkg.jpg
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/icon_300.imageset/icon_300.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/icon_300.imageset/icon_300.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/AppIcon.appiconset/icon_152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/AppIcon.appiconset/icon_152.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/professor.imageset/professor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/professor.imageset/professor.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_ask.imageset/action_ask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/action_ask.imageset/action_ask.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_cat.imageset/action_cat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/action_cat.imageset/action_cat.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_run.imageset/action_run.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/action_run.imageset/action_run.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/mario_pipe.imageset/mario_pipe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/mario_pipe.imageset/mario_pipe.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_enemy.imageset/action_enemy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/action_enemy.imageset/action_enemy.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_fire.imageset/action_fire.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/action_fire.imageset/action_fire.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_path.imageset/action_path.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/action_path.imageset/action_path.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_speak.imageset/action_speak.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/action_speak.imageset/action_speak.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/mario_bkg_1.imageset/mario_bkg_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/mario_bkg_1.imageset/mario_bkg_1.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/mario_bkg_2.imageset/mario_bkg_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/mario_bkg_2.imageset/mario_bkg_2.jpg
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_moving.imageset/action_moving.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/action_moving.imageset/action_moving.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_falling.imageset/action_falling.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/action_falling.imageset/action_falling.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_strategy.imageset/action_strategy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk/Images.xcassets/action_strategy.imageset/action_strategy.png
--------------------------------------------------------------------------------
/SpriteKitTankTalk.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SpriteKitTankTalk.xcodeproj/project.xcworkspace/xcuserdata/ffrison.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk.xcodeproj/project.xcworkspace/xcuserdata/ffrison.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/SpriteKitTankTalk.xcodeproj/project.xcworkspace/xcuserdata/cescofry.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescofry/SpriteKitAndFriends/HEAD/SpriteKitTankTalk.xcodeproj/project.xcworkspace/xcuserdata/cescofry.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Config.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | isDebug
6 |
7 | speakText
8 |
9 | fontName
10 | Menlo-Regular
11 |
12 |
13 |
--------------------------------------------------------------------------------
/_etc/html/source_5.html:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 | There is no Code for scene 5!
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SpriteKitAndFriends
2 | SpriteKit game that explains itself
3 |
4 | A level based game that adds functioanlities at every level. At the end of each level the new piece of functionality is explaind in code.
5 | Requires Swift 2.0 (Xcode 7)
6 |
7 | ##List of levels
8 |
9 | - Scene and Nodes
10 | - Actions
11 | - Sprite Texttures
12 | - Physics
13 | - Gravity
14 | - Particle Emitters
15 | - Speak
16 |
17 |
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/cat.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "cat.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/coin.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "coin.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/wall.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "wall.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/portal.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "portal.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/zelda.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "zelda.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/icon_300.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "icon_300.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/professor.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "professor.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/rpg_bkg.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "rpg_bkg.jpg",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_ask.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "action_ask.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_cat.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "action_cat.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_fire.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "action_fire.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_path.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "action_path.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_run.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "action_run.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/mario_bkg_1.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "mario_bkg_1.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/mario_bkg_2.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "mario_bkg_2.jpg",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/mario_pipe.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "mario_pipe.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_enemy.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "action_enemy.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_falling.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "action_falling.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_moving.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "action_moving.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_speak.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "action_speak.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/action_strategy.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "action_strategy.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk.xcodeproj/xcuserdata/cescofry.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
8 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/SpriteKitTankTalk.xcodeproj/xcuserdata/ffrison.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
8 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/_etc/html/source_template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | {{SOURCE_CODE}}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/_etc/html/source_10.html:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 | - Thanks to @dantomi and @abizern for the copy editing.
12 | - Pygmewnts.org for generating HTML out of swift.
13 | - Raywenderlich.com has a nice Spritekit for Beginners tutorial
14 | - Happy Beat music loop from ElectroBaptist
15 |
16 |
17 |
--------------------------------------------------------------------------------
/SpriteKitTankTalk.xcodeproj/xcuserdata/ffrison.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | SpriteKitTankTalk.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | A5013AE41B8D9EB600AD3B6C
16 |
17 | primary
18 |
19 |
20 | A5013AFD1B8D9EB600AD3B6C
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/SpriteKitTankTalk.xcodeproj/xcuserdata/cescofry.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | SpriteKitTankTalk.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | A5013AE41B8D9EB600AD3B6C
16 |
17 | primary
18 |
19 |
20 | A5013AFD1B8D9EB600AD3B6C
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/_etc/elf/elf.png.txt:
--------------------------------------------------------------------------------
1 | 01.png 10 15, 02.png 130 15, 03.png 250 15, 04.png 20 150, 05.png 140 150, 06.png 260 150, 07.png 15 285, 08.png 15 410, 09.png 130 410, 10.png 255 410, 11.png 15 535, 12.png 135 530, 13.png 255 530, 14.png 375 530, 15.png 495 530, 16.png 615 535, 17.png 735 530, 18.png 855 530, 19.png 975 530, 20.png 1095 530, 21.png 5 670, 22.png 130 670, 23.png 245 665, 24.png 370 665, 25.png 490 665, 26.png 605 670, 27.png 730 670, 28.png 850 665, 29.png 975 665, 30.png 1090 665, 31.png 15 790, 32.png 135 790, 33.png 255 780, 34.png 375 780, 35.png 495 780, 36.png 615 790, 37.png 735 790, 38.png 855 780, 39.png 975 785, 40.png 1095 780, 41.png 5 925, 42.png 135 925, 43.png 255 925, 44.png 370 930, 45.png 480 930, 46.png 610 925, 47.png 730 925, 48.png 860 925, 49.png 980 930, 50.png 1080 930.
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "ipad",
5 | "size" : "29x29",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "ipad",
10 | "size" : "29x29",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "ipad",
15 | "size" : "40x40",
16 | "scale" : "1x"
17 | },
18 | {
19 | "idiom" : "ipad",
20 | "size" : "40x40",
21 | "scale" : "2x"
22 | },
23 | {
24 | "idiom" : "ipad",
25 | "size" : "76x76",
26 | "scale" : "1x"
27 | },
28 | {
29 | "size" : "76x76",
30 | "idiom" : "ipad",
31 | "filename" : "icon_152.png",
32 | "scale" : "2x"
33 | }
34 | ],
35 | "info" : {
36 | "version" : 1,
37 | "author" : "xcode"
38 | }
39 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalkTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/SpriteKitTankTalkTests/SpriteKitTankTalkTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SpriteKitTankTalkTests.swift
3 | // SpriteKitTankTalkTests
4 | //
5 | // Created by Francesco Frison on 26/08/2015.
6 | // Copyright (c) 2015 frison. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import XCTest
11 |
12 | class SpriteKitTankTalkTests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testExample() {
25 | // This is an example of a functional test case.
26 | XCTAssert(true, "Pass")
27 | }
28 |
29 | func testPerformanceExample() {
30 | // This is an example of a performance test case.
31 | self.measureBlock() {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Extensions.swift
3 | // SpriteKitTankTalk
4 | //
5 | // Created by Francesco Frison on 27/08/2015.
6 | // Copyright (c) 2015 frison. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | struct Dispatch {
12 | static func after(time: NSTimeInterval, block: ()->()) {
13 | let nanoTime = Int64(time * Double(NSEC_PER_SEC))
14 | let time = dispatch_time(DISPATCH_TIME_NOW, nanoTime)
15 | dispatch_after(time, dispatch_get_main_queue(), { () -> Void in
16 | block()
17 | })
18 | }
19 | }
20 |
21 | extension CGSize {
22 | var center : CGPoint {
23 | return CGPoint(x: (self.width / 2.0), y: (self.height / 2.0))
24 | }
25 | }
26 |
27 | extension CGPoint {
28 | func radiantsToPoint(point: CGPoint) -> CGFloat {
29 | let xD = Float(self.x - point.x)
30 | let yD = Float(point.y - self.y)
31 | let radiants = CGFloat(atan2f(xD, yD))
32 | return radiants
33 | }
34 |
35 | func distanceToPoint(point: CGPoint) -> CGFloat {
36 | let xD = self.x - point.x
37 | let yD = point.y - self.y
38 | return sqrt(pow(xD, 2.0) + pow(yD, 2.0))
39 | }
40 | }
41 |
42 | func radiansToDegrees(angleRadians: CGFloat) -> CGFloat {
43 | return CGFloat(Double(angleRadians) * 180.0 / M_PI)
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UIRequiresFullScreen
34 |
35 | UIStatusBarHidden
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/_etc/html/source_2.html:
--------------------------------------------------------------------------------
1 |
8 | // SKAction
9 |
10 | func addActionToNode(node: SKSpriteNode) {
11 | let position = CGPoint(x: 50.0, y: 40.0)
12 | let move = SKAction.moveTo(position, duration: 1.0)
13 |
14 | node.runAction(move)
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/_etc/html/source_4.html:
--------------------------------------------------------------------------------
1 |
8 | // Physics
9 | func addPhysicsToNode(node: SKSpriteNode) {
10 | let radius = node.size.width / 2.0
11 | let physics = SKPhysicsBody(circleOfRadius: radius)
12 | physics.dynamic = false
13 | physics.friction = 0.2
14 |
15 | node.physicsBody = physics
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/_etc/html/source_6.html:
--------------------------------------------------------------------------------
1 |
8 |
9 | // Gravity
10 |
11 | func addGravity(scene: SKScene, node: SKSpriteNode) {
12 | scene.physicsWorld.gravity = CGVector(dx: 0.0, dy: -1.0)
13 |
14 | let radius = node.size.width / 2.0
15 | let physics = SKPhysicsBody(circleOfRadius: radius)
16 | //...
17 |
18 | physics.affectedByGravity = true
19 | physics.dynamic = true
20 | }
21 |
22 |
23 |
--------------------------------------------------------------------------------
/_etc/html/source_8.html:
--------------------------------------------------------------------------------
1 |
8 |
9 | // Particle Emitters
10 |
11 | func addEmitterToNode(node : SKNode) {
12 | // Create a new File of type Spritekit Partle File name Fire.
13 | let bundle = NSBundle.mainBundle()
14 | let path: String = bundle.pathForResource("Fire", ofType: "sks")!
15 | let emitter = NSKeyedUnarchiver.unarchiveObjectWithFile(path)
16 |
17 | node.addChild(emitter as! SKEmitterNode)
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/SpriteKitTankTalk.xcodeproj/project.xcworkspace/xcshareddata/SpriteKitTankTalk.xcscmblueprint:
--------------------------------------------------------------------------------
1 | {
2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "A484F80C5008B1EE1B9D58352CE2199D13051DC0",
3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
4 |
5 | },
6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
7 | "A484F80C5008B1EE1B9D58352CE2199D13051DC0" : 0,
8 | "18C6131BB033E3746A29A72AA86083EB9763EA9C" : 0,
9 | "C6F4526546B4B12E617D8E7B32795E9BB51ADE24" : 0
10 | },
11 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "52FEC97E-2E06-4826-8231-355F76589C5C",
12 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
13 | "A484F80C5008B1EE1B9D58352CE2199D13051DC0" : "SpriteKitTankTalk",
14 | "18C6131BB033E3746A29A72AA86083EB9763EA9C" : "",
15 | "C6F4526546B4B12E617D8E7B32795E9BB51ADE24" : ".."
16 | },
17 | "DVTSourceControlWorkspaceBlueprintNameKey" : "SpriteKitTankTalk",
18 | "DVTSourceControlWorkspaceBlueprintVersion" : 204,
19 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "SpriteKitTankTalk.xcodeproj",
20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
21 | {
22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "iptx.org:prezel.git",
23 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
24 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "18C6131BB033E3746A29A72AA86083EB9763EA9C"
25 | },
26 | {
27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "\/Users\/cescofry\/Dropbox\/gitRepo\/SpriteKitTankTalk.git\/",
28 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
29 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "A484F80C5008B1EE1B9D58352CE2199D13051DC0"
30 | },
31 | {
32 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "iptx.org:prezel.git",
33 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
34 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "C6F4526546B4B12E617D8E7B32795E9BB51ADE24"
35 | }
36 | ]
37 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk.xcodeproj/project.xcworkspace/xcshareddata/SpriteKitTankTalk.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | 52FEC97E-2E06-4826-8231-355F76589C5C
9 | IDESourceControlProjectName
10 | SpriteKitTankTalk
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | A484F80C5008B1EE1B9D58352CE2199D13051DC0
14 | /Users/cescofry/Dropbox/gitRepo/SpriteKitTankTalk.git/
15 | C6F4526546B4B12E617D8E7B32795E9BB51ADE24
16 | iptx.org:prezel.git
17 |
18 | IDESourceControlProjectPath
19 | SpriteKitTankTalk.xcodeproj
20 | IDESourceControlProjectRelativeInstallPathDictionary
21 |
22 | A484F80C5008B1EE1B9D58352CE2199D13051DC0
23 | ../..
24 | C6F4526546B4B12E617D8E7B32795E9BB51ADE24
25 | ../../../..
26 |
27 | IDESourceControlProjectURL
28 | /Users/cescofry/Dropbox/gitRepo/SpriteKitTankTalk.git/
29 | IDESourceControlProjectVersion
30 | 111
31 | IDESourceControlProjectWCCIdentifier
32 | A484F80C5008B1EE1B9D58352CE2199D13051DC0
33 | IDESourceControlProjectWCConfigurations
34 |
35 |
36 | IDESourceControlRepositoryExtensionIdentifierKey
37 | public.vcs.git
38 | IDESourceControlWCCIdentifierKey
39 | C6F4526546B4B12E617D8E7B32795E9BB51ADE24
40 | IDESourceControlWCCName
41 | ..
42 |
43 |
44 | IDESourceControlRepositoryExtensionIdentifierKey
45 | public.vcs.git
46 | IDESourceControlWCCIdentifierKey
47 | A484F80C5008B1EE1B9D58352CE2199D13051DC0
48 | IDESourceControlWCCName
49 | SpriteKitTankTalk
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/SpriteKitTankTalk/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // SpriteKitTankTalk
4 | //
5 | // Created by Francesco Frison on 26/08/2015.
6 | // Copyright (c) 2015 frison. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import AVFoundation
11 |
12 | @UIApplicationMain
13 | class AppDelegate: UIResponder, UIApplicationDelegate {
14 |
15 | var window: UIWindow?
16 |
17 |
18 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
19 | // Override point for customization after application launch.
20 |
21 | //self.window!.rootViewController = HtmlTestViewController.fromDummyVC()
22 |
23 |
24 | return true
25 | }
26 |
27 | func applicationWillResignActive(application: UIApplication) {
28 | // 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.
29 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
30 | }
31 |
32 | func applicationDidEnterBackground(application: UIApplication) {
33 | // 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.
34 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
35 | }
36 |
37 | func applicationWillEnterForeground(application: UIApplication) {
38 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
39 | }
40 |
41 | func applicationDidBecomeActive(application: UIApplication) {
42 | // 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.
43 | }
44 |
45 | func applicationWillTerminate(application: UIApplication) {
46 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
47 | }
48 |
49 |
50 | }
51 |
52 |
--------------------------------------------------------------------------------
/_etc/html/source_3.html:
--------------------------------------------------------------------------------
1 |
8 | // Sprite textures
9 |
10 | func addSpritesToNode(node: SKSpriteNode) {
11 | var textures = [SKTexture]()
12 | for i in 1...10 {
13 | let name = NSString(format: "slice%.2d", i) as String
14 | let texture = SKTexture(imageNamed: name)
15 | textures.append(texture)
16 | }
17 |
18 | let sprite = SKAction.animateWithTextures(textures, timePerFrame: 0.05)
19 | node.runAction(SKAction.repeatActionForever(sprite))
20 | }
21 |
--------------------------------------------------------------------------------
/_etc/html/css/font.css:
--------------------------------------------------------------------------------
1 | /* cyrillic-ext */
2 | @font-face {
3 | font-family: 'PT Sans';
4 | font-style: normal;
5 | font-weight: 400;
6 | src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/fhNmDCnjccoUYyU4ZASaLVKPGs1ZzpMvnHX-7fPOuAc.woff2) format('woff2');
7 | unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
8 | }
9 | /* cyrillic */
10 | @font-face {
11 | font-family: 'PT Sans';
12 | font-style: normal;
13 | font-weight: 400;
14 | src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/BJVWev7_auVaQ__OU8Qih1KPGs1ZzpMvnHX-7fPOuAc.woff2) format('woff2');
15 | unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
16 | }
17 | /* latin-ext */
18 | @font-face {
19 | font-family: 'PT Sans';
20 | font-style: normal;
21 | font-weight: 400;
22 | src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/oysROHFTu1eTZ74Hcf8V-VKPGs1ZzpMvnHX-7fPOuAc.woff2) format('woff2');
23 | unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
24 | }
25 | /* latin */
26 | @font-face {
27 | font-family: 'PT Sans';
28 | font-style: normal;
29 | font-weight: 400;
30 | src: local('PT Sans'), local('PTSans-Regular'), url(http://fonts.gstatic.com/s/ptsans/v8/CWlc_g68BGYDSGdpJvpktgLUuEpTyoUstqEm5AMlJo4.woff2) format('woff2');
31 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
32 | }
33 | /* cyrillic-ext */
34 | @font-face {
35 | font-family: 'PT Sans';
36 | font-style: normal;
37 | font-weight: 700;
38 | src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/kTYfCWJhlldPf5LnG4ZnHAsYbbCjybiHxArTLjt7FRU.woff2) format('woff2');
39 | unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
40 | }
41 | /* cyrillic */
42 | @font-face {
43 | font-family: 'PT Sans';
44 | font-style: normal;
45 | font-weight: 700;
46 | src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/g46X4VH_KHOWAAa-HpnGPgsYbbCjybiHxArTLjt7FRU.woff2) format('woff2');
47 | unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
48 | }
49 | /* latin-ext */
50 | @font-face {
51 | font-family: 'PT Sans';
52 | font-style: normal;
53 | font-weight: 700;
54 | src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/hpORcvLZtemlH8gI-1S-7gsYbbCjybiHxArTLjt7FRU.woff2) format('woff2');
55 | unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
56 | }
57 | /* latin */
58 | @font-face {
59 | font-family: 'PT Sans';
60 | font-style: normal;
61 | font-weight: 700;
62 | src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://fonts.gstatic.com/s/ptsans/v8/0XxGQsSc1g4rdRdjJKZrNAzyDMXhdD8sAj6OAJTFsBI.woff2) format('woff2');
63 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
64 | }
65 |
--------------------------------------------------------------------------------
/_etc/html/source_7.html:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 | // Gravity and Inpulses
11 |
12 | func shootNodeWithPhysics(node: SKSpriteNode) {
13 | let radius = node.size.width / 2.0
14 | let physics = SKPhysicsBody(circleOfRadius: radius)
15 | physics.dynamic = false
16 | physics.mass = 1.2 // resistence to impulses
17 | physics.density = 1.2
18 |
19 | physics.restitution = 0.9 // bouncing
20 | physics.friction = 0.2 // sliding
21 |
22 |
23 | physics.applyForce(CGVector(dx: 20.0, dy: -30.0))
24 | // remember inverted coordinates
25 |
26 | node.physicsBody = physics
27 | }
28 |
--------------------------------------------------------------------------------
/_etc/html/source_9.html:
--------------------------------------------------------------------------------
1 |
8 |
9 | // Speech Synthesizer
10 |
11 | import AVFoundation
12 |
13 | class Synth : NSObject, AVSpeechSynthesizerDelegate {
14 | let synth = AVSpeechSynthesizer()
15 |
16 | func speakText(text : String) {
17 | let utterance = AVSpeechUtterance(string: text)
18 | utterance.rate = 0.5
19 | utterance.pitchMultiplier = 1.0
20 |
21 | let voice = AVSpeechSynthesisVoice(language: "fr-FR")
22 | utterance.voice = voice
23 |
24 | synth.delegate = self
25 | synth.speakUtterance(utterance)
26 | }
27 |
28 | func speechSynthesizer(synthesizer: AVSpeechSynthesizer,
29 | didFinishSpeechUtterance utterance: AVSpeechUtterance) {
30 | print("ended")
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/SpriteKitTankTalk/GameSceneGenerator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GameSceneGenerator.swift
3 | // SpriteKitTankTalk
4 | //
5 | // Created by Francesco Frison on 26/08/2015.
6 | // Copyright (c) 2015 frison. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SpriteKit
11 |
12 | extension SKNode {
13 | class func unarchiveFromFile(file : String) -> SKNode? {
14 | if let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks") {
15 | let sceneData = try! NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe)
16 | let archiver = NSKeyedUnarchiver(forReadingWithData: sceneData)
17 |
18 | archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene")
19 | let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as! GameScene
20 | archiver.finishDecoding()
21 | return scene
22 | } else {
23 | return nil
24 | }
25 | }
26 | }
27 |
28 | struct GameSceneGenerator {
29 | static func fromIndex(index: Int) -> GameScene? {
30 | let config = Config.sharedConfig()
31 | let scene = GameScene.unarchiveFromFile("GameScene\(index)") as? GameScene
32 | if let scene = scene {
33 |
34 | let realIndex = index - 1
35 | scene.sceneDescription = config.scenes[realIndex]
36 |
37 | switch index {
38 | case 1: scene.setup = scene.setUp1
39 | case 2: scene.setup = scene.setUp2
40 | case 3: scene.setup = scene.setUp3
41 | case 4: scene.setup = scene.setUp4
42 | case 5: scene.setup = scene.setUp5
43 | case 6: scene.setup = scene.setUp6
44 | case 7: scene.setup = scene.setUp7
45 | case 8: scene.setup = scene.setUp8
46 | case 9: scene.setup = scene.setUp9
47 | case 10: scene.setup = scene.setUp10
48 | default:
49 | scene.title.text = "This scene has not been implemented yet"
50 | }
51 |
52 | }
53 |
54 |
55 | return scene
56 | }
57 | }
58 |
59 |
60 |
61 | struct LocationGenerator {
62 | let sceneSize : CGSize
63 | let outSpan: CGFloat
64 |
65 | enum Position : Int {
66 | case Top = 0
67 | case Right = 1
68 | case Bottom = 2
69 | case Left = 3
70 |
71 | static func random() -> Position {
72 | return Position(rawValue: Int(arc4random()%4))!
73 | }
74 |
75 | func opssiteToPosition(position: Position) -> Bool {
76 | return (abs(self.rawValue - position.rawValue) == 2)
77 | }
78 | }
79 |
80 | func randomLocation() -> CGPoint {
81 |
82 | let position = Position.random()
83 | return randomLocation(size: sceneSize, span: outSpan, position: position)
84 | }
85 |
86 | private func randomLocation(size size: CGSize, span: CGFloat, position: Position) -> CGPoint {
87 |
88 | var location = CGPoint(
89 | x: CGFloat(arc4random()) % size.width,
90 | y: CGFloat(arc4random()) % size.height)
91 |
92 | switch position {
93 | case .Top:
94 | location.y = size.height + span
95 | case .Right:
96 | location.x = size.width + span
97 | case .Bottom:
98 | location.y = -span
99 | default:
100 | location.x = -span
101 | }
102 |
103 | return location
104 | }
105 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/OptionsViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OptionsViewController.swift
3 | // SpriteKitTankTalk
4 | //
5 | // Created by Francesco Frison on 27/08/2015.
6 | // Copyright (c) 2015 frison. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 |
12 | class OptionsViewController : UITableViewController {
13 |
14 | var didSelectIndex : ((index: Int)->())?
15 | var currentIndex : Int? {
16 | didSet {
17 | if let currentIndex = currentIndex {
18 | if (currentIndex - 1) < self.titles.count {
19 | self.tableView.selectRowAtIndexPath(NSIndexPath(forRow: (currentIndex - 1), inSection: 0), animated: true, scrollPosition: UITableViewScrollPosition.Middle)
20 | }
21 | }
22 | }
23 | }
24 |
25 | let titles = Config.sharedConfig().scenes.map({ (scene: SceneDescription) in
26 | return scene.title
27 | })
28 |
29 | var options : [(title: String, value: Bool)] {
30 | let config = Config.sharedConfig()
31 | var options = [(title: String, value: Bool)]()
32 | options.append(("Debug", config.isDebug))
33 | options.append(("Speak", config.speakText))
34 |
35 | return options
36 | }
37 |
38 | func switchOptionAtIndex(index: Int) {
39 | var config = Config.sharedConfig()
40 |
41 | switch index {
42 | case 0:
43 | config.isDebug = !config.isDebug
44 | default:
45 | config.speakText = !config.speakText
46 | }
47 | config.save()
48 |
49 | }
50 |
51 | override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
52 | return 2
53 | }
54 |
55 | override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
56 | return (section == 0) ? titles.count : 2
57 | }
58 |
59 | override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
60 | return (section == 0) ? "Select Level" : "Change Options"
61 | }
62 |
63 | @IBAction func dismiss(sender: AnyObject?) {
64 | self.dismissViewControllerAnimated(true, completion: nil)
65 | }
66 |
67 | override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
68 |
69 | let title : String
70 | let subtitle : String?
71 | let cellID : String
72 |
73 |
74 | switch indexPath.section {
75 | case 0:
76 | cellID = "sceneCell"
77 | title = self.titles[indexPath.row]
78 | subtitle = nil
79 | default:
80 | cellID = "configCell"
81 | let option = self.options[indexPath.row]
82 | title = option.title
83 | subtitle = "\(option.value)"
84 | }
85 |
86 | let cell = tableView.dequeueReusableCellWithIdentifier(cellID, forIndexPath: indexPath)
87 | cell.textLabel!.text = title
88 |
89 | if let subtitle = subtitle {
90 | cell.detailTextLabel!.text = subtitle
91 | }
92 |
93 | return cell
94 | }
95 |
96 | override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
97 | if indexPath.section == 0 {
98 | if let didSelectIndex = didSelectIndex {
99 | didSelectIndex(index: (indexPath.row + 1))
100 | }
101 | dismiss(nil)
102 | }
103 | else {
104 | switchOptionAtIndex(indexPath.row)
105 | self.tableView.reloadData()
106 | }
107 | }
108 |
109 |
110 | }
111 |
112 | extension UINavigationController {
113 | func optionsViewController() -> OptionsViewController? {
114 | return self.viewControllers.first as? OptionsViewController
115 | }
116 | }
--------------------------------------------------------------------------------
/_etc/html/source_1.html:
--------------------------------------------------------------------------------
1 |
8 | // SKScene and SKNode
9 |
10 | override func viewDidLoad() {
11 | super.viewDidLoad()
12 |
13 | let scene = SKScene(size: self.view.bounds.size)
14 |
15 | // Not Needed if from Storyboard
16 | self.view = SKView(frame: self.view.bounds)
17 |
18 | let skView = self.view as! SKView
19 | skView.presentScene(scene)
20 |
21 | addNodeToScene(scene)
22 | }
23 |
24 | func addNodeToScene(scene : SKScene) {
25 |
26 | // Y Coordinate System inverted
27 | let size = CGSize(width: 50.0, height: 50.0)
28 | let node = SKSpriteNode(color: UIColor.redColor(), size: size)
29 | node.position = CGPoint(x: 100.0, y: 100.0)
30 |
31 | scene.addChild(node)
32 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/GameViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GameViewController.swift
3 | // SpriteKitTankTalk
4 | //
5 | // Created by Francesco Frison on 26/08/2015.
6 | // Copyright (c) 2015 frison. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SpriteKit
11 |
12 | class GameViewController: UIViewController {
13 |
14 | var index = 0
15 | var scene : GameScene?
16 | let audioController = AudioController()
17 | var speakBoxController: SpeakBoxController!
18 |
19 | var isDebug : Bool? {
20 | didSet {
21 | let skView = self.view as! SKView
22 |
23 | let debug = isDebug != nil ? isDebug! : false
24 | skView.showsFPS = debug
25 | skView.showsNodeCount = debug
26 | skView.showsPhysics = debug
27 | }
28 | }
29 |
30 | func nextScene(showCode: Bool) {
31 | self.index++
32 | if showCode {
33 | self.presentCode()
34 | }
35 | else {
36 | loadCurrentScene()
37 | }
38 | }
39 |
40 | func loadCurrentScene(){
41 |
42 | self.speakBoxController.stopSpeaking()
43 |
44 | self.cleanUpScene()
45 | self.scene = GameSceneGenerator.fromIndex(index)
46 |
47 | guard let scene = scene else {
48 | self.dismissViewControllerAnimated(true, completion: nil)
49 | return
50 | }
51 |
52 | scene.audioController = self.audioController
53 | scene.speakBoxController = self.speakBoxController
54 |
55 | self.isDebug = Config.sharedConfig().isDebug
56 |
57 | let skView = self.view as! SKView
58 | /* Sprite Kit applies additional optimizations to improve rendering performance */
59 | skView.ignoresSiblingOrder = true
60 |
61 | /* Set the scale mode to scale to fit the window */
62 | scene.scaleMode = .AspectFill
63 |
64 | skView.presentScene(scene)
65 | scene.nextScene = nextScene
66 |
67 | }
68 |
69 | func cleanUpScene() {
70 | if let scene = self.scene {
71 | scene.removeAllChildren()
72 | }
73 | }
74 |
75 | override func viewDidAppear(animated: Bool) {
76 | super.viewDidAppear(animated)
77 |
78 | self.speakBoxController = SpeakBoxController(viewController: self, type: .Character)
79 |
80 | nextScene(false)
81 | self.audioController.playBackgroundMusic()
82 | }
83 |
84 | override func shouldAutorotate() -> Bool {
85 | return true
86 | }
87 |
88 | override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
89 | if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
90 | return UIInterfaceOrientationMask.AllButUpsideDown
91 | } else {
92 | return UIInterfaceOrientationMask.All
93 | }
94 | }
95 |
96 | override func didReceiveMemoryWarning() {
97 | super.didReceiveMemoryWarning()
98 | // Release any cached data, images, etc that aren't in use.
99 | }
100 |
101 | override func prefersStatusBarHidden() -> Bool {
102 | return true
103 | }
104 |
105 | func presentCode() {
106 | if let sceneDescription = self.scene?.sceneDescription {
107 | self.speakBoxController.stopSpeaking()
108 | CodeViewController.presentInNavigationController(self, sceneDescription: sceneDescription, dismissBlock: loadCurrentScene)
109 | }
110 | else {
111 | loadCurrentScene()
112 | }
113 | }
114 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
115 | guard let identifier = segue.identifier where
116 | identifier == "OptionsViewController",
117 | let navVC = segue.destinationViewController as? UINavigationController else {
118 | return
119 | }
120 |
121 | guard let optionsVC = navVC.viewControllers.first as? OptionsViewController else {
122 | return
123 | }
124 |
125 | optionsVC.currentIndex = self.index
126 | optionsVC.didSelectIndex = {(index: Int) in
127 | self.index = index
128 | self.loadCurrentScene()
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/SpriteKitTankTalk/CodeViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CodeViewController.swift
3 | // SpriteKitTankTalk
4 | //
5 | // Created by Francesco Frison on 26/08/2015.
6 | // Copyright (c) 2015 frison. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import WebKit
11 |
12 | class CodeViewController : UIViewController {
13 |
14 | var sceneDescription : SceneDescription? {
15 | didSet {
16 | self.html = sceneDescription!.html
17 | self.navigationItem.title = self.sceneDescription!.title
18 | }
19 | }
20 |
21 | var html : String? {
22 | didSet {
23 | if let html = html {
24 | self.webView.loadHTMLString(html, baseURL: NSBundle.mainBundle().bundleURL)
25 | }
26 | }
27 | }
28 |
29 | var webView = WKWebView(frame: CGRectZero, configuration: CodeViewController.webViewConfiguration())
30 | var speakBoxController : SpeakBoxController!
31 |
32 | var aboutToDismiss : (()->())?
33 |
34 | override func viewDidLoad() {
35 | super.viewDidLoad()
36 | self.view.backgroundColor = UIColor(red: 0.4, green: 0.4, blue: 0.4, alpha: 1.0)
37 |
38 | let(_, webViewRect) = self.view.bounds.divide(120, fromEdge: CGRectEdge.MaxYEdge)
39 |
40 | // Webview
41 | self.webView.frame = webViewRect
42 | self.webView.backgroundColor = self.view.backgroundColor
43 | self.webView.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
44 | self.view.addSubview(self.webView)
45 |
46 | self.speakBoxController.layoutSpeakBox()
47 | }
48 |
49 | override func viewDidAppear(animated: Bool) {
50 | super.viewDidAppear(animated)
51 |
52 | guard let texts = self.sceneDescription?.code else {
53 | return
54 | }
55 |
56 | self.speakBoxController.speakMultipleTextAndAdvance(texts, willStart: nil, completion: nil)
57 | }
58 |
59 | static func presentInNavigationController(presenterViewController: UIViewController, sceneDescription: SceneDescription, dismissBlock: (()->())?) {
60 |
61 | let vc = CodeViewController(nibName: nil, bundle: nil)
62 | vc.sceneDescription = sceneDescription
63 | vc.aboutToDismiss = dismissBlock
64 | vc.speakBoxController = SpeakBoxController(viewController: vc, type: .Professor)
65 |
66 | let navVC = UINavigationController(rootViewController: vc)
67 | navVC.modalPresentationStyle = UIModalPresentationStyle.PageSheet
68 |
69 | let closeBtn = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: vc, action: Selector("dismiss"))
70 | vc.navigationItem.rightBarButtonItem = closeBtn
71 |
72 | presenterViewController.presentViewController(navVC, animated: true, completion: nil)
73 | }
74 |
75 | static func webViewConfiguration() -> WKWebViewConfiguration {
76 |
77 | let config = WKWebViewConfiguration()
78 | return config
79 | /*
80 | let contentController = WKUserContentController()
81 |
82 | for name in ["font", "pugments", "pygments14"] {
83 | guard let path = NSBundle.mainBundle().pathForResource(name, ofType: "css"),
84 | let scriptContent = try? String(contentsOfFile: path, encoding: NSUTF8StringEncoding)
85 | else {
86 | return config
87 | }
88 |
89 | let css = WKUserScript(source: scriptContent, injectionTime: WKUserScriptInjectionTime.AtDocumentStart, forMainFrameOnly: false)
90 |
91 | contentController.addUserScript(css)
92 | }
93 |
94 |
95 | config.userContentController = contentController
96 | */
97 |
98 | /*
99 | guard let path = NSBundle.mainBundle().pathForResource("InjectCSS", ofType: "js") else {
100 | return config
101 | }
102 |
103 | guard let scriptContent = try? String(contentsOfFile: path, encoding: NSUTF8StringEncoding) else {
104 | return config
105 | }
106 |
107 |
108 |
109 | let script = WKUserScript(source: scriptContent, injectionTime: .AtDocumentStart, forMainFrameOnly: true)
110 | config.userContentController.addUserScript(script)
111 |
112 | return config
113 | */
114 | }
115 |
116 | func dismiss() {
117 | self.dismissViewControllerAnimated(true, completion: { () -> Void in
118 | self.speakBoxController.stopSpeaking()
119 | if let aboutToDismiss = self.aboutToDismiss {
120 | aboutToDismiss()
121 | }
122 | })
123 | }
124 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/SpriteKitTankTalk.xcodeproj/xcuserdata/cescofry.xcuserdatad/xcschemes/SpriteKitTankTalk.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
65 |
66 |
75 |
77 |
83 |
84 |
85 |
86 |
87 |
88 |
94 |
96 |
102 |
103 |
104 |
105 |
107 |
108 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/SpriteKitTankTalk.xcodeproj/xcuserdata/ffrison.xcuserdatad/xcschemes/SpriteKitTankTalk.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
65 |
66 |
67 |
68 |
78 |
80 |
86 |
87 |
88 |
89 |
90 |
91 |
97 |
99 |
105 |
106 |
107 |
108 |
110 |
111 |
114 |
115 |
116 |
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Config.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Config.swift
3 | // SpriteKitTankTalk
4 | //
5 | // Created by Francesco Frison on 27/08/2015.
6 | // Copyright (c) 2015 frison. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | typealias GenericDictionary = [String: AnyObject]
12 |
13 | struct Config {
14 | var isDebug : Bool
15 | var speakText : Bool
16 | let fontName: String
17 | let scenes : [SceneDescription]
18 |
19 | private static var cachedSharedConfig : Config?
20 | static func sharedConfig() -> Config! {
21 |
22 | if let cachedSC = cachedSharedConfig {
23 | return cachedSC
24 | }
25 |
26 | let configDict = plistDictionary()
27 | let isDebug = configDict["isDebug"]!.boolValue!
28 | let speakText = configDict["speakText"]!.boolValue!
29 | let fontName = configDict["fontName"]! as! String
30 |
31 | var index = 0
32 | var stop = false
33 | var scenes = [SceneDescription]()
34 |
35 | while (!stop) {
36 | index++
37 |
38 | guard let path = NSBundle.mainBundle().pathForResource("source_\(index)", ofType: "html"),
39 | let scene = SceneDescription.fromCodePath(path) else {
40 | stop = true
41 | continue
42 | }
43 |
44 | scenes.append(scene)
45 | }
46 |
47 | self.cachedSharedConfig = Config(isDebug: isDebug, speakText: speakText, fontName: fontName, scenes: scenes)
48 | return self.cachedSharedConfig
49 | }
50 |
51 | private static func plistPath() -> String {
52 | return NSBundle.mainBundle().pathForResource("Config", ofType: "plist")!
53 | }
54 |
55 | private static func plistDictionary() -> NSDictionary {
56 | return NSDictionary(contentsOfFile: plistPath())!
57 | }
58 |
59 | private static func codeForIndex(index: Int) -> String {
60 | let path = NSBundle.mainBundle().pathForResource("source_\(index)", ofType: "html")!
61 | return try! NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding) as String
62 | }
63 | }
64 |
65 | extension Config {
66 | func save() {
67 | let dictionary = Config.plistDictionary().mutableCopy() as! NSMutableDictionary
68 | dictionary.setValue(NSNumber(bool: self.isDebug), forKey: "isDebug")
69 | dictionary.setValue(NSNumber(bool: self.speakText), forKey: "speakText")
70 |
71 | let path = Config.plistPath()
72 | if dictionary.writeToFile(path, atomically: true) {
73 | Config.cachedSharedConfig = nil
74 | }
75 | }
76 | }
77 |
78 | struct SceneDescription {
79 | let title : String
80 | let codePath : String
81 | let code : [String]
82 | let actions : [String]
83 |
84 | var html : String? {
85 | return SceneDescription.fullHtmlFromPath(self.codePath)
86 | }
87 |
88 | static func fromCodePath(codePath: String) -> SceneDescription? {
89 | guard let html = htmlFromPath(codePath),
90 | let jsonDict = jsonConfigFromHTML(html)
91 | else {
92 | return nil
93 | }
94 |
95 | guard let codeS = jsonDict["code"],
96 | let actionsS = jsonDict["action"],
97 | let title = jsonDict["title"]
98 | else {
99 | return nil
100 | }
101 |
102 | func isNotEmpty(text : String) -> Bool { return text.lengthOfBytesUsingEncoding(NSUTF8StringEncoding) > 0 }
103 |
104 | let code = codeS.componentsSeparatedByString(".").filter(isNotEmpty)
105 | let actions = actionsS.componentsSeparatedByString(".").filter(isNotEmpty)
106 |
107 | return SceneDescription(title: title, codePath: codePath, code: code, actions: actions)
108 |
109 | }
110 |
111 |
112 | //MARK: JSON
113 | private static func jsonConfigFromHTML(html : String) -> [String: String]? {
114 |
115 | let regEx = try? NSRegularExpression(pattern: "", options: [.CaseInsensitive, .DotMatchesLineSeparators])
116 | let range = NSMakeRange(0, html.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
117 | let findings = regEx!.matchesInString(html, options: NSMatchingOptions.ReportCompletion, range: range)
118 |
119 | if let first = findings.first {
120 | let range = first.rangeAtIndex(1)
121 | let json = (html as NSString).substringWithRange(range)
122 |
123 | if let data = json.dataUsingEncoding(NSUTF8StringEncoding) {
124 | let jsonAnyObj = try? NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments)
125 | return jsonAnyObj as? [String : String]
126 | }
127 |
128 | }
129 |
130 |
131 | return nil
132 | }
133 |
134 |
135 | //MARK: HTML
136 |
137 | private static func htmlFromPath(path : String) -> String? {
138 | return try? NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding) as String
139 | }
140 |
141 | static func fullHtmlFromPath(path : String) -> String? {
142 | guard let codeHtml = htmlFromPath(path),
143 | let templates = htmlTemplates else {
144 | return nil
145 | }
146 |
147 | return "\(templates.pre)\n\(codeHtml)\n\(templates.post)"
148 | }
149 |
150 |
151 | static var htmlTemplates : (pre: String, post: String)? {
152 | guard let path = NSBundle.mainBundle().pathForResource("source_template", ofType: "html"),
153 | let template = try? NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding) as String else {
154 | return nil
155 | }
156 |
157 | let components = template.componentsSeparatedByString("{{SOURCE_CODE}}")
158 | return (components[0], components[1])
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/SpriteKitTankTalk/SpeakBoxController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SpeakBoxNode.swift
3 | // SpriteKitTankTalk
4 | //
5 | // Created by Francesco Frison on 28/08/2015.
6 | // Copyright © 2015 frison. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SpriteKit
11 |
12 |
13 | enum SpeakerType {
14 | case Character, Professor
15 |
16 | func toImage() -> UIImage {
17 | switch self {
18 | case .Character: return UIImage(named: "zelda")!
19 | case .Professor: return UIImage(named: "professor")!
20 | }
21 | }
22 |
23 | func toLanguage() -> String {
24 | switch self {
25 | case .Character: return "en-US"
26 | case .Professor: return "en-GB"
27 | }
28 | }
29 | }
30 |
31 |
32 | class SpeakBoxView : UIView {
33 | private var textLabel: UILabel!
34 | private var speakerImageView: UIImageView!
35 | var text : String? {
36 | didSet {
37 | if let text = text {
38 | self.textLabel.text = text
39 | }
40 | }
41 | }
42 |
43 | var type: SpeakerType? {
44 | didSet {
45 | guard let type = self.type else {
46 | return
47 | }
48 |
49 | self.speakerImageView.image = type.toImage()
50 |
51 | let fontSize = (type == .Professor) ? CGFloat(20.0) : CGFloat(24.0)
52 | self.textLabel.font = UIFont(name: Config.sharedConfig().fontName, size: fontSize)
53 | }
54 | }
55 |
56 | var speakerType: SpeakerType!
57 |
58 | override init(frame: CGRect) {
59 | super.init(frame: frame)
60 | let resizingMask : UIViewAutoresizing = [.FlexibleHeight, .FlexibleWidth, .FlexibleLeftMargin, .FlexibleRightMargin, .FlexibleBottomMargin]
61 |
62 | self.autoresizingMask = autoresizingMask
63 |
64 | self.backgroundColor = UIColor.blueColor()
65 | self.layer.borderColor = UIColor.whiteColor().CGColor
66 | self.layer.borderWidth = 2.0
67 | self.layer.cornerRadius = 10.0
68 |
69 | let(speakerFrame, labelFrame) = self.bounds.divide(self.bounds.size.height, fromEdge: .MinXEdge)
70 | let insetLabelFrame = labelFrame.insetBy(dx: 20, dy: 20)
71 |
72 | self.speakerImageView = UIImageView(frame: speakerFrame)
73 | self.speakerImageView.contentMode = .ScaleAspectFill
74 | self.speakerImageView.autoresizingMask = resizingMask
75 | self.addSubview(self.speakerImageView)
76 |
77 | self.textLabel = UILabel(frame: insetLabelFrame)
78 | self.textLabel.textColor = UIColor.whiteColor()
79 | self.textLabel.font = UIFont(name: Config.sharedConfig().fontName, size: 24)
80 | self.textLabel.numberOfLines = 0
81 | self.textLabel.adjustsFontSizeToFitWidth = true
82 | self.textLabel.autoresizingMask = resizingMask
83 | self.addSubview(self.textLabel)
84 | }
85 |
86 | required init?(coder aDecoder: NSCoder) {
87 | fatalError("init(coder:) has not been implemented")
88 | }
89 |
90 | override func layoutSubviews() {
91 | let(speakerFrame, labelFrame) = self.bounds.divide(self.bounds.size.height, fromEdge: .MinXEdge)
92 | let insetLabelFrame = labelFrame.insetBy(dx: 20, dy: 20)
93 | self.speakerImageView.frame = speakerFrame
94 | self.textLabel.frame = insetLabelFrame
95 | }
96 | }
97 |
98 |
99 | class SpeakBoxController {
100 | private var presenterViewController: UIViewController?
101 | var speechSynthesizer: SpeechSynthesizer
102 | var speakBox: SpeakBoxView
103 | var text : String?
104 | var type : SpeakerType
105 |
106 | init(viewController: UIViewController, type: SpeakerType) {
107 | self.speechSynthesizer = SpeechSynthesizer()
108 | self.type = type
109 |
110 | self.presenterViewController = viewController
111 |
112 | self.speakBox = SpeakBoxView(frame: CGRectMake(0, 0, 600, 100))
113 | self.speakBox.type = type
114 | }
115 |
116 | func layoutSpeakBox() {
117 |
118 | let frame = self.presenterViewController!.view.bounds.divide(140.0, fromEdge: .MaxYEdge).slice.insetBy(dx: 20, dy: 20)
119 | self.speakBox.frame = frame
120 |
121 | if self.speakBox.superview == nil {
122 | self.presenterViewController!.view.addSubview(self.speakBox)
123 | }
124 |
125 | }
126 |
127 |
128 | func speakMultipleTextAndAdvance(texts: [String], willStart:((text: String)->())?, completion:((cancelled: Bool, text: String)->())?) {
129 |
130 | for text in texts {
131 | self.speakText(text, willStart: willStart, completion: completion)
132 | }
133 | }
134 |
135 | func speakText(text: String, willStart:((text: String)->())?, completion:((cancelled: Bool, text: String)->())?) {
136 |
137 | func willStart(text: String) {
138 | self.text = text
139 | if text.lengthOfBytesUsingEncoding(NSUTF8StringEncoding) > 0 {
140 | self.layoutSpeakBox()
141 | }
142 | self.speakBox.text = text
143 | if let willStart = willStart {
144 | willStart(text: text)
145 | }
146 | }
147 |
148 | func didFinish(cancelled: Bool, text: String) {
149 | self.didEndShowingText(text)
150 | if let completion = completion {
151 | completion(cancelled: cancelled, text: text)
152 | }
153 | }
154 |
155 | self.speechSynthesizer.speakText(text, language: self.type.toLanguage(), willStart: willStart, completion: didFinish)
156 | }
157 |
158 | func stopSpeaking() {
159 | self.speechSynthesizer.stopSpeaking()
160 | self.speakBox.removeFromSuperview()
161 | }
162 |
163 | private func didEndShowingText(text: String) {
164 | Dispatch.after(0.5) { () -> () in
165 | guard let currentText = self.text else {
166 | return
167 | }
168 |
169 | if currentText == text {
170 | self.speakBox.removeFromSuperview()
171 | }
172 |
173 | }
174 | }
175 |
176 | func runDemo(completion: ((cancelled: Bool, text: String) -> ())?) {
177 |
178 | func willStart(text: String) {
179 | self.layoutSpeakBox()
180 | self.text = text
181 | self.speakBox.text = text
182 | }
183 |
184 | func didFinish(cancelled: Bool, text: String) {
185 | self.didEndShowingText(text)
186 | if let completion = completion {
187 | completion(cancelled: cancelled, text: text)
188 | }
189 | }
190 |
191 | self.speechSynthesizer.runDemo(willStart: willStart, completion: didFinish)
192 | }
193 |
194 | }
--------------------------------------------------------------------------------
/SpriteKitTankTalk/TestViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TestViewController.swift
3 | // SpriteKitTankTalk
4 | //
5 | // Created by Francesco Frison on 27/08/2015.
6 | // Copyright (c) 2015 frison. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SpriteKit
11 | import AVFoundation
12 |
13 |
14 | class HtmlTestViewController : UINavigationController {
15 |
16 | private var index = 0
17 | private var scenes = Config.sharedConfig().scenes
18 | private var presenterViewController : UIViewController!
19 |
20 | func nextScene() {
21 |
22 | guard let vc = self.nextViewController() else {
23 | return
24 | }
25 |
26 | let closeBtn = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self, action: Selector("nextScene"))
27 | vc.navigationItem.rightBarButtonItem = closeBtn
28 |
29 | self.pushViewController(vc, animated: true)
30 | }
31 |
32 | func nextViewController() -> CodeViewController? {
33 |
34 | if index >= scenes.count {
35 | return nil
36 | }
37 |
38 | let scene = scenes[index]
39 |
40 | let vc = CodeViewController(nibName: nil, bundle: nil)
41 | vc.sceneDescription = scene
42 | vc.speakBoxController = SpeakBoxController(viewController: vc, type: .Professor)
43 |
44 | index++
45 |
46 | return vc
47 | }
48 |
49 |
50 | convenience init() {
51 | self.init(nibName: nil, bundle: nil)
52 | self.nextScene()
53 | }
54 |
55 | static func fromDummyVC() -> UIViewController {
56 | let navVC = HtmlTestViewController()
57 | navVC.modalPresentationStyle = UIModalPresentationStyle.PageSheet
58 |
59 |
60 | let vc = UIViewController(nibName: nil, bundle: nil)
61 |
62 | Dispatch.after(1.0) { () -> () in
63 | vc.presentViewController(navVC, animated: true) { () -> Void in
64 | }
65 |
66 | }
67 |
68 | return vc
69 | }
70 |
71 | }
72 |
73 | class TestViewController: UIViewController {
74 |
75 | // SKScene and SKNode
76 |
77 | // override func viewDidLoad() {
78 | // let speechSynthesizer = SpeechSynthesizer().runDemo { (cancelled) -> () in
79 | // //nil
80 | // }
81 | // }
82 |
83 | // override func loadView() {
84 | // self.view = SKView(frame: UIScreen.mainScreen().bounds)
85 | // }
86 |
87 |
88 | // SKScene and SKAction
89 |
90 | override func viewDidLoad() {
91 | super.viewDidLoad()
92 |
93 | let scene = SKScene(size: self.view.bounds.size)
94 |
95 | // Not Needed if from Storyboard
96 | self.view = SKView(frame: self.view.bounds)
97 |
98 | let skView = self.view as! SKView
99 | skView.presentScene(scene)
100 |
101 | addNodeToScene(scene)
102 | }
103 |
104 | func addNodeToScene(scene : SKScene) {
105 |
106 | // Y Coordinate System inverted
107 | let size = CGSize(width: 50.0, height: 50.0)
108 | let node = SKSpriteNode(color: UIColor.redColor(), size: size)
109 | node.position = CGPoint(x: 100.0, y: 100.0)
110 |
111 | scene.addChild(node)
112 | }
113 |
114 | // SKAction
115 |
116 | func addActionToNode(node: SKSpriteNode) {
117 | let position = CGPoint(x: 50.0, y: 40.0)
118 | let move = SKAction.moveTo(position, duration: 1.0)
119 |
120 | node.runAction(move)
121 |
122 | }
123 |
124 | // Sprite textures
125 |
126 | func addSpritesToNode(node: SKSpriteNode) {
127 | var textures = [SKTexture]()
128 | for i in 1...10 {
129 | let name = NSString(format: "slice%.2d", i) as String
130 | let texture = SKTexture(imageNamed: name)
131 | textures.append(texture)
132 | }
133 |
134 | let sprite = SKAction.animateWithTextures(textures, timePerFrame: 0.05)
135 | node.runAction(SKAction.repeatActionForever(sprite))
136 | }
137 |
138 | // Physics
139 |
140 | func addPhysicsToNode(node: SKSpriteNode) {
141 | let radius = node.size.width / 2.0
142 | let physics = SKPhysicsBody(circleOfRadius: radius)
143 | physics.dynamic = false
144 | physics.friction = 0.2
145 |
146 | node.physicsBody = physics
147 | }
148 |
149 | // Gravity
150 |
151 | func addGravity(scene: SKScene, node: SKSpriteNode) {
152 | scene.physicsWorld.gravity = CGVector(dx: 0.0, dy: -1.0)
153 |
154 | let radius = node.size.width / 2.0
155 | let physics = SKPhysicsBody(circleOfRadius: radius)
156 | //...
157 |
158 | physics.affectedByGravity = true
159 | physics.dynamic = true
160 | }
161 |
162 | // Gravity and Inpulses
163 |
164 | func shootNodeWithPhysics(node: SKSpriteNode) {
165 | let radius = node.size.width / 2.0
166 | let physics = SKPhysicsBody(circleOfRadius: radius)
167 | physics.dynamic = false
168 | physics.mass = 1.2 // resistence to impulses
169 | physics.density = 1.2
170 |
171 | physics.restitution = 0.9 // bouncing
172 | physics.friction = 0.2 // sliding
173 |
174 |
175 | physics.applyForce(CGVector(dx: 20.0, dy: -30.0))
176 | // remember inverted coordinates
177 |
178 | node.physicsBody = physics
179 | }
180 |
181 | // Particle Emitter
182 |
183 | func addEmitterToNode(node : SKNode) {
184 | // Create a new File of type Spritekit Partle File name Fire.
185 | let bundle = NSBundle.mainBundle()
186 | let path: String = bundle.pathForResource("Fire", ofType: "sks")!
187 | let emitter = NSKeyedUnarchiver.unarchiveObjectWithFile(path)
188 |
189 | node.addChild(emitter as! SKEmitterNode)
190 | }
191 |
192 | // Path Finding
193 |
194 | func setupPathFinding(scene: SKScene, node: SKSpriteNode) {
195 |
196 | }
197 |
198 | // MaxminStrategist
199 |
200 | func setupStrategist() {
201 |
202 | }
203 | }
204 |
205 | // Speech Synthesizer
206 |
207 | import AVFoundation
208 |
209 | class Synth : NSObject, AVSpeechSynthesizerDelegate {
210 | let synth = AVSpeechSynthesizer()
211 |
212 | func speakText(text : String) {
213 | let utterance = AVSpeechUtterance(string: text)
214 | utterance.rate = 0.5
215 | utterance.pitchMultiplier = 1.0
216 |
217 | let voice = AVSpeechSynthesisVoice(language: "fr-FR")
218 | utterance.voice = voice
219 |
220 | synth.delegate = self
221 | synth.speakUtterance(utterance)
222 | }
223 |
224 | func speechSynthesizer(synthesizer: AVSpeechSynthesizer,
225 | didFinishSpeechUtterance utterance: AVSpeechUtterance) {
226 | print("ended")
227 | }
228 | }
229 |
230 |
--------------------------------------------------------------------------------
/SpriteKitTankTalk/SpeechSynthesizer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SpeechSynthesizer.swift
3 | // SpriteKitTankTalk
4 | //
5 | // Created by Francesco Frison on 27/08/2015.
6 | // Copyright (c) 2015 frison. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import AVFoundation
11 |
12 | class SpeechSynthesizer : NSObject, AVSpeechSynthesizerDelegate {
13 | private let synth = AVSpeechSynthesizer()
14 | private var completion: ((cancelled: Bool, text: String)->())?
15 | private var willStart:((text: String)->())?
16 | private var speakText : Bool {
17 | return Config.sharedConfig().speakText
18 | }
19 |
20 | func speakText(text: String, willStart: ((text: String)->())?, completion:((cancelled: Bool, text: String)->())?) {
21 | speakText(text, language: nil, willStart: willStart, completion: completion)
22 | }
23 |
24 | func speakText(text: String, language: String?, willStart: ((text: String)->())?, completion:((cancelled: Bool, text: String)->())?) {
25 |
26 | if !speakText {
27 | if let completion = completion {
28 | completion(cancelled: true, text: text)
29 | }
30 | return
31 | }
32 |
33 | let textAndFullStop = text.hasSuffix(".") ? text : "\(text)."
34 |
35 | synth.delegate = self
36 | self.completion = completion
37 | self.willStart = willStart
38 | let utterance = AVSpeechUtterance(string: textAndFullStop)
39 | utterance.rate = 0.5
40 | utterance.voice = self.voiceFromLanguage(language)
41 |
42 | synth.speakUtterance(utterance)
43 | }
44 |
45 | func stopSpeaking() {
46 | self.synth.stopSpeakingAtBoundary(.Word)
47 | }
48 |
49 |
50 | private func voiceFromLanguage(language: String?) -> AVSpeechSynthesisVoice? {
51 | if let lang = language {
52 | return AVSpeechSynthesisVoice(language: lang)
53 | }
54 | else {
55 | return AVSpeechSynthesisVoice(language: "en-US")
56 | }
57 | }
58 |
59 |
60 | //MARK: - speechSynthesizer delegate -
61 |
62 | func speechSynthesizer(synthesizer: AVSpeechSynthesizer, didFinishSpeechUtterance utterance: AVSpeechUtterance) {
63 | if let completion = completion {
64 | completion(cancelled: false, text: utterance.speechString)
65 | }
66 | }
67 |
68 | func speechSynthesizer(synthesizer: AVSpeechSynthesizer, didCancelSpeechUtterance utterance: AVSpeechUtterance) {
69 | if let completion = completion {
70 | completion(cancelled: true, text: utterance.speechString)
71 | }
72 | }
73 |
74 | func speechSynthesizer(synthesizer: AVSpeechSynthesizer, didStartSpeechUtterance utterance: AVSpeechUtterance) {
75 | if let willStart = willStart {
76 | willStart(text: utterance.speechString)
77 | }
78 | }
79 |
80 | }
81 |
82 | extension SpeechSynthesizer {
83 |
84 | func entryFromString(string: String, pitch: Float?, rate: Float?, language: String?) -> AVSpeechUtterance {
85 | let utterance = AVSpeechUtterance(string: string)
86 | if let pitch = pitch {
87 | utterance.pitchMultiplier = pitch
88 | }
89 |
90 | if let rate = rate {
91 | utterance.rate = rate
92 | }
93 |
94 | utterance.voice = self.voiceFromLanguage(language)
95 |
96 | return utterance
97 | }
98 |
99 | func demoScript() -> [AVSpeechUtterance] {
100 | var entries = [AVSpeechUtterance]()
101 |
102 | entries.append(entryFromString("By the way, I am speaking using an A V Speech Synthesizer.", pitch: nil, rate: nil, language: nil))
103 | entries.append(entryFromString("This thing is crazy.", pitch: nil, rate: nil, language: nil))
104 | entries.append(entryFromString("Of course I speak English.", pitch: nil, rate: nil, language: nil))
105 | entries.append(entryFromString("Mais je peux parler français", pitch: nil, rate: nil, language: "fr-FR"))
106 | entries.append(entryFromString("y español también", pitch: nil, rate: nil, language: "es-ES"))
107 | entries.append(entryFromString("Ordinare una pizza in italiano", pitch: nil, rate: nil, language: "it-IT"))
108 | entries.append(entryFromString("要求一个中国翻译", pitch: nil, rate: nil, language: "zh-CN"))
109 | entries.append(entryFromString("But don't speak Welsh though", pitch: nil, rate: nil, language: nil))
110 | entries.append(entryFromString("go down with the tone", pitch: 0.5, rate: nil, language: nil))
111 | entries.append(entryFromString("and then up again", pitch: 2.0, rate: nil, language: nil))
112 | entries.append(entryFromString("slowing", pitch: nil, rate: 0.2, language: nil))
113 | entries.append(entryFromString("and fast, so fast that you can barely understand what I am saying", pitch: nil, rate: 0.7, language: nil))
114 | entries.append(entryFromString("Wow, that was something. Right!?", pitch: nil, rate: nil, language: nil))
115 |
116 | return entries
117 | }
118 |
119 |
120 |
121 | func runDemo(willStart willStart: ((text: String)->())?, completion:((cancelled: Bool, text: String)->())?) {
122 |
123 | if !speakText {
124 | if let completion = completion {
125 | completion(cancelled: true, text: "")
126 | }
127 | return
128 | }
129 |
130 | synth.pauseSpeakingAtBoundary(.Word)
131 | synth.delegate = self
132 | self.completion = completion
133 | self.willStart = willStart
134 |
135 | let entries = demoScript()
136 |
137 | for utterance in entries {
138 | synth.speakUtterance(utterance)
139 | }
140 |
141 | }
142 | }
143 |
144 | class AudioController : NSObject, AVAudioPlayerDelegate {
145 |
146 | static func mainTuneURL() -> NSURL {
147 | return NSBundle.mainBundle().URLForResource("8BitLoop", withExtension: "mp3")!
148 | }
149 |
150 | static func overworldURL() -> NSURL {
151 | return NSBundle.mainBundle().URLForResource("overworld", withExtension: "mp3")!
152 | }
153 |
154 | let mainAudioPlayer = try? AVAudioPlayer(contentsOfURL: AudioController.mainTuneURL())
155 | let overworldAudioPlayer = try? AVAudioPlayer(contentsOfURL: AudioController.overworldURL())
156 |
157 | func playBackgroundMusic() {
158 | if let player = self.mainAudioPlayer {
159 | player.volume = 0.3
160 | player.play()
161 | player.delegate = self
162 | }
163 | }
164 |
165 | func playMarioBackgroundMusic() {
166 | if let player = self.overworldAudioPlayer {
167 | player.volume = 0.3
168 | player.play()
169 | player.delegate = self
170 | }
171 | }
172 |
173 | func stopBackgroundMusic() {
174 | if let player = self.mainAudioPlayer {
175 | player.stop()
176 | }
177 |
178 | if let overworldAudioPlayer = self.overworldAudioPlayer {
179 | overworldAudioPlayer.stop()
180 | }
181 | }
182 |
183 |
184 | //MARK: Delegate
185 |
186 | @objc func audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool) {
187 | if flag {
188 | player.play()
189 | }
190 | }
191 |
192 | }
--------------------------------------------------------------------------------
/_etc/html/css/pygments14.css:
--------------------------------------------------------------------------------
1 | /*
2 | * pygments14.css
3 | * ~~~~~~~~~~~~~~
4 | *
5 | * Sphinx stylesheet -- pygments14 theme. Heavily copied from sphinx13.
6 | *
7 | * :copyright: Copyright 2006-2014 by the Pygments team, see AUTHORS.
8 | * :license: BSD, see LICENSE for details.
9 | *
10 | */
11 |
12 | @import url("basic.css");
13 |
14 | /* -- page layout ----------------------------------------------------------- */
15 |
16 | body {
17 | font-family: PT Sans, 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
18 | 'Verdana', sans-serif;
19 | font-size: 14px;
20 | text-align: center;
21 | background-color: #666;
22 | color: black;
23 | padding: 0;
24 | /*
25 | border-right: 1px solid #66b55e;
26 | border-left: 1px solid #66b55e;
27 | */
28 |
29 | margin: 0 auto;
30 | min-width: 780px;
31 | max-width: 1080px;
32 | }
33 |
34 | .outerwrapper {
35 | background-image: url(docbg.png);
36 | background-attachment: fixed;
37 | }
38 |
39 | .pageheader {
40 | text-align: left;
41 | padding: 10px 15px;
42 | }
43 |
44 | .pageheader ul {
45 | float: right;
46 | color: white;
47 | list-style-type: none;
48 | padding-left: 0;
49 | margin-top: 40px;
50 | margin-right: 10px;
51 | }
52 |
53 | .pageheader li {
54 | float: left;
55 | margin: 0 0 0 10px;
56 | }
57 |
58 | .pageheader li a {
59 | border-radius: 3px;
60 | padding: 8px 12px;
61 | color: #666666;
62 | text-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
63 | }
64 |
65 | .pageheader li a:hover {
66 | background-color: #f4cd00;
67 | color: black;
68 | text-shadow: none;
69 | }
70 |
71 | div.document {
72 | text-align: left;
73 | /*border-left: 1em solid #fffbe3;*/
74 | }
75 |
76 | div.bodywrapper {
77 | margin: 0 12px 0 240px;
78 | background-color: white;
79 | /* border-right: 1px solid #66b55e; */
80 | }
81 |
82 | div.fullbodywrapper {
83 | margin: 0 24px;
84 | background-color: white;
85 | }
86 |
87 | div.body {
88 | margin: 0;
89 | }
90 |
91 | div.related {
92 | font-size: 1em;
93 | color: #666666;
94 | }
95 |
96 | div.related ul {
97 | background-image: url(relbg.png);
98 | background-repeat: repeat-y;
99 | background-color: #f4cd00;
100 | height: 1.9em;
101 | /*
102 | border-top: 1px solid #66b55e;
103 | border-bottom: 1px solid #66b55e;
104 | */
105 | }
106 |
107 | div.related ul li {
108 | margin: 0 5px 0 0;
109 | padding: 0;
110 | float: left;
111 | }
112 |
113 | div.related ul li.right {
114 | float: right;
115 | margin-right: 5px;
116 | }
117 |
118 | div.related ul li a {
119 | margin: 0;
120 | padding: 0 5px 0 5px;
121 | line-height: 1.75em;
122 | color: #666666;
123 | /*text-shadow: 0px 0px 1px rgba(0, 0, 0, 0.5);*/
124 | }
125 |
126 | div.related ul li a:hover {
127 | text-decoration: underline;
128 | text-shadow: 0px 0px 1px rgba(255, 255, 255, 0.5);
129 | }
130 |
131 |
132 | #try {
133 | clear: both;
134 | background-color: #f6f6f6;
135 | border-radius: 5px;
136 | border: 1px solid #ddd;
137 | margin-top: 15px;
138 | padding: 10px 15px 5px 10px;
139 | }
140 |
141 | #try h2 {
142 | margin-top: 0;
143 | }
144 |
145 | #try textarea {
146 | border: 1px solid #999;
147 | padding: 2px;
148 | width: 100%;
149 | min-height: 150px;
150 | }
151 |
152 | #filter_form {
153 | float: right;
154 | background-color: #f6f6f6;
155 | border: 1px solid #ddd;
156 | border-radius: 4px;
157 | padding: 10px;
158 | margin-bottom: 15px;
159 | clear: right;
160 | }
161 |
162 | .syntax {
163 | clear: both;
164 | }
165 |
166 | .syntax pre {
167 | background-color: transparent;
168 | }
169 |
170 | /* -- body styles ----------------------------------------------------------- */
171 |
172 | p {
173 | margin: 0.8em 0 0.5em 0;
174 | }
175 |
176 | a {
177 | color: #36852e;
178 | text-decoration: none;
179 | }
180 |
181 | a:hover {
182 | color: #d4ad00;
183 | }
184 |
185 | div.body a {
186 | text-decoration: underline;
187 | }
188 |
189 | h1 {
190 | margin: 10px 0 0 0;
191 | font-size: 2.4em;
192 | color: #666666;
193 | font-weight: 300;
194 | }
195 |
196 | h2 {
197 | margin: 1.em 0 0.2em 0;
198 | font-size: 1.5em;
199 | font-weight: 300;
200 | padding: 0;
201 | color: #36852e;
202 | }
203 |
204 | h3 {
205 | margin: 1em 0 -0.3em 0;
206 | font-size: 1.3em;
207 | font-weight: 300;
208 | }
209 |
210 | div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a {
211 | text-decoration: none;
212 | }
213 |
214 | div.body h1 a tt, div.body h2 a tt, div.body h3 a tt, div.body h4 a tt, div.body h5 a tt, div.body h6 a tt {
215 | color: #36852e !important;
216 | font-size: inherit !important;
217 | }
218 |
219 | a.headerlink {
220 | color: #66b55e !important;
221 | font-size: 12px;
222 | margin-left: 6px;
223 | padding: 0 4px 0 4px;
224 | text-decoration: none !important;
225 | float: right;
226 | }
227 |
228 | a.headerlink:hover {
229 | background-color: #ccc;
230 | color: white!important;
231 | }
232 |
233 | cite, code, tt {
234 | font-family: 'Consolas', 'DejaVu Sans Mono',
235 | 'Bitstream Vera Sans Mono', monospace;
236 | font-size: 14px;
237 | letter-spacing: -0.02em;
238 | }
239 |
240 | tt {
241 | background-color: #f2f2f2;
242 | border: 1px solid #ddd;
243 | border-radius: 2px;
244 | color: #333;
245 | padding: 1px;
246 | }
247 |
248 | tt.descname, tt.descclassname, tt.xref {
249 | border: 0;
250 | }
251 |
252 | hr {
253 | border: 1px solid #abc;
254 | margin: 2em;
255 | }
256 |
257 | a tt {
258 | border: 0;
259 | color: #36852e;
260 | }
261 |
262 | a tt:hover {
263 | color: #d4ad00;
264 | }
265 |
266 | pre {
267 | font-family: 'Consolas', 'DejaVu Sans Mono',
268 | 'Bitstream Vera Sans Mono', monospace;
269 | font-size: 20px;
270 | letter-spacing: 0.015em;
271 | line-height: 120%;
272 | padding: 0.5em;
273 | border: 1px solid #ccc;
274 | border-radius: 2px;
275 | background-color: #f8f8f8;
276 | }
277 |
278 | pre a {
279 | color: inherit;
280 | text-decoration: underline;
281 | }
282 |
283 | td.linenos pre {
284 | padding: 0.5em 0;
285 | }
286 |
287 | div.quotebar {
288 | background-color: #f8f8f8;
289 | max-width: 250px;
290 | float: right;
291 | padding: 0px 7px;
292 | border: 1px solid #ccc;
293 | margin-left: 1em;
294 | }
295 |
296 | div.topic {
297 | background-color: #f8f8f8;
298 | }
299 |
300 | table {
301 | border-collapse: collapse;
302 | margin: 0 -0.5em 0 -0.5em;
303 | }
304 |
305 | table td, table th {
306 | padding: 0.2em 0.5em 0.2em 0.5em;
307 | }
308 |
309 | div.admonition, div.warning {
310 | font-size: 0.9em;
311 | margin: 1em 0 1em 0;
312 | border: 1px solid #86989B;
313 | border-radius: 2px;
314 | background-color: #f7f7f7;
315 | padding: 0;
316 | }
317 |
318 | div.admonition p, div.warning p {
319 | margin: 0.5em 1em 0.5em 1em;
320 | padding: 0;
321 | }
322 |
323 | div.admonition pre, div.warning pre {
324 | margin: 0.4em 1em 0.4em 1em;
325 | }
326 |
327 | div.admonition p.admonition-title,
328 | div.warning p.admonition-title {
329 | margin-top: 1em;
330 | padding-top: 0.5em;
331 | font-weight: bold;
332 | }
333 |
334 | div.warning {
335 | border: 1px solid #940000;
336 | /* background-color: #FFCCCF;*/
337 | }
338 |
339 | div.warning p.admonition-title {
340 | }
341 |
342 | div.admonition ul, div.admonition ol,
343 | div.warning ul, div.warning ol {
344 | margin: 0.1em 0.5em 0.5em 3em;
345 | padding: 0;
346 | }
347 |
348 | .viewcode-back {
349 | font-family: PT Sans, 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
350 | 'Verdana', sans-serif;
351 | }
352 |
353 | div.viewcode-block:target {
354 | background-color: #f4debf;
355 | border-top: 1px solid #ac9;
356 | border-bottom: 1px solid #ac9;
357 | }
--------------------------------------------------------------------------------
/_etc/html/css/pygments.css:
--------------------------------------------------------------------------------
1 | pre .hll { background-color: #ffffcc }
2 | pre { background: #f0f0f0; }
3 | pre .c { color: #60a0b0; font-style: italic } /* Comment */
4 | pre .err { border: 1px solid #FF0000 } /* Error */
5 | pre .k { color: #007020; font-weight: bold } /* Keyword */
6 | pre .o { color: #666666 } /* Operator */
7 | pre .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */
8 | pre .cp { color: #007020 } /* Comment.Preproc */
9 | pre .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */
10 | pre .cs { color: #60a0b0; background-color: #fff0f0 } /* Comment.Special */
11 | pre .gd { color: #A00000 } /* Generic.Deleted */
12 | pre .ge { font-style: italic } /* Generic.Emph */
13 | pre .gr { color: #FF0000 } /* Generic.Error */
14 | pre .gh { color: #000080; font-weight: bold } /* Generic.Heading */
15 | pre .gi { color: #00A000 } /* Generic.Inserted */
16 | pre .go { color: #888888 } /* Generic.Output */
17 | pre .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
18 | pre .gs { font-weight: bold } /* Generic.Strong */
19 | pre .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
20 | pre .gt { color: #0044DD } /* Generic.Traceback */
21 | pre .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
22 | pre .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
23 | pre .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
24 | pre .kp { color: #007020 } /* Keyword.Pseudo */
25 | pre .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
26 | pre .kt { color: #902000 } /* Keyword.Type */
27 | pre .m { color: #40a070 } /* Literal.Number */
28 | pre .s { color: #4070a0 } /* Literal.String */
29 | pre .na { color: #4070a0 } /* Name.Attribute */
30 | pre .nb { color: #007020 } /* Name.Builtin */
31 | pre .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
32 | pre .no { color: #60add5 } /* Name.Constant */
33 | pre .nd { color: #555555; font-weight: bold } /* Name.Decorator */
34 | pre .ni { color: #d55537; font-weight: bold } /* Name.Entity */
35 | pre .ne { color: #007020 } /* Name.Exception */
36 | pre .nf { color: #06287e } /* Name.Function */
37 | pre .nl { color: #002070; font-weight: bold } /* Name.Label */
38 | pre .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
39 | pre .nt { color: #062873; font-weight: bold } /* Name.Tag */
40 | pre .nv { color: #bb60d5 } /* Name.Variable */
41 | pre .ow { color: #007020; font-weight: bold } /* Operator.Word */
42 | pre .w { color: #bbbbbb } /* Text.Whitespace */
43 | pre .mb { color: #40a070 } /* Literal.Number.Bin */
44 | pre .mf { color: #40a070 } /* Literal.Number.Float */
45 | pre .mh { color: #40a070 } /* Literal.Number.Hex */
46 | pre .mi { color: #40a070 } /* Literal.Number.Integer */
47 | pre .mo { color: #40a070 } /* Literal.Number.Oct */
48 | pre .sb { color: #4070a0 } /* Literal.String.Backtick */
49 | pre .sc { color: #4070a0 } /* Literal.String.Char */
50 | pre .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
51 | pre .s2 { color: #4070a0 } /* Literal.String.Double */
52 | pre .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
53 | pre .sh { color: #4070a0 } /* Literal.String.Heredoc */
54 | pre .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
55 | pre .sx { color: #c65d09 } /* Literal.String.Other */
56 | pre .sr { color: #235388 } /* Literal.String.Regex */
57 | pre .s1 { color: #4070a0 } /* Literal.String.Single */
58 | pre .ss { color: #517918 } /* Literal.String.Symbol */
59 | pre .bp { color: #007020 } /* Name.Builtin.Pseudo */
60 | pre .vc { color: #bb60d5 } /* Name.Variable.Class */
61 | pre .vg { color: #bb60d5 } /* Name.Variable.Global */
62 | pre .vi { color: #bb60d5 } /* Name.Variable.Instance */
63 | pre .il { color: #40a070 } /* Literal.Number.Integer.Long */.syntax pre .hll { background-color: #222222 }
64 | .syntax pre { background: #000000; color: #cccccc }
65 | .syntax pre .c { color: #000080 } /* Comment */
66 | .syntax pre .err { color: #cccccc; border: 1px solid #FF0000 } /* Error */
67 | .syntax pre .esc { color: #cccccc } /* Escape */
68 | .syntax pre .g { color: #cccccc } /* Generic */
69 | .syntax pre .k { color: #cdcd00 } /* Keyword */
70 | .syntax pre .l { color: #cccccc } /* Literal */
71 | .syntax pre .n { color: #cccccc } /* Name */
72 | .syntax pre .o { color: #3399cc } /* Operator */
73 | .syntax pre .x { color: #cccccc } /* Other */
74 | .syntax pre .p { color: #cccccc } /* Punctuation */
75 | .syntax pre .cm { color: #000080 } /* Comment.Multiline */
76 | .syntax pre .cp { color: #000080 } /* Comment.Preproc */
77 | .syntax pre .cs { color: #cd0000; font-weight: bold } /* Comment.Special */
78 | .syntax pre .gd { color: #cd0000 } /* Generic.Deleted */
79 | .syntax pre .ge { color: #cccccc; font-style: italic } /* Generic.Emph */
80 | .syntax pre .gr { color: #FF0000 } /* Generic.Error */
81 | .syntax pre .gh { color: #000080; font-weight: bold } /* Generic.Heading */
82 | .syntax pre .gi { color: #00cd00 } /* Generic.Inserted */
83 | .syntax pre .go { color: #888888 } /* Generic.Output */
84 | .syntax pre .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
85 | .syntax pre .gs { color: #cccccc; font-weight: bold } /* Generic.Strong */
86 | .syntax pre .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
87 | .syntax pre .gt { color: #0044DD } /* Generic.Traceback */
88 | .syntax pre .kc { color: #cdcd00 } /* Keyword.Constant */
89 | .syntax pre .kd { color: #00cd00 } /* Keyword.Declaration */
90 | .syntax pre .kn { color: #cd00cd } /* Keyword.Namespace */
91 | .syntax pre .kp { color: #cdcd00 } /* Keyword.Pseudo */
92 | .syntax pre .kr { color: #cdcd00 } /* Keyword.Reserved */
93 | .syntax pre .kt { color: #00cd00 } /* Keyword.Type */
94 | .syntax pre .ld { color: #cccccc } /* Literal.Date */
95 | .syntax pre .m { color: #cd00cd } /* Literal.Number */
96 | .syntax pre .s { color: #cd0000 } /* Literal.String */
97 | .syntax pre .na { color: #cccccc } /* Name.Attribute */
98 | .syntax pre .nb { color: #cd00cd } /* Name.Builtin */
99 | .syntax pre .nc { color: #00cdcd } /* Name.Class */
100 | .syntax pre .no { color: #cccccc } /* Name.Constant */
101 | .syntax pre .nd { color: #cccccc } /* Name.Decorator */
102 | .syntax pre .ni { color: #cccccc } /* Name.Entity */
103 | .syntax pre .ne { color: #666699; font-weight: bold } /* Name.Exception */
104 | .syntax pre .nf { color: #cccccc } /* Name.Function */
105 | .syntax pre .nl { color: #cccccc } /* Name.Label */
106 | .syntax pre .nn { color: #cccccc } /* Name.Namespace */
107 | .syntax pre .nx { color: #cccccc } /* Name.Other */
108 | .syntax pre .py { color: #cccccc } /* Name.Property */
109 | .syntax pre .nt { color: #cccccc } /* Name.Tag */
110 | .syntax pre .nv { color: #00cdcd } /* Name.Variable */
111 | .syntax pre .ow { color: #cdcd00 } /* Operator.Word */
112 | .syntax pre .w { color: #cccccc } /* Text.Whitespace */
113 | .syntax pre .mb { color: #cd00cd } /* Literal.Number.Bin */
114 | .syntax pre .mf { color: #cd00cd } /* Literal.Number.Float */
115 | .syntax pre .mh { color: #cd00cd } /* Literal.Number.Hex */
116 | .syntax pre .mi { color: #cd00cd } /* Literal.Number.Integer */
117 | .syntax pre .mo { color: #cd00cd } /* Literal.Number.Oct */
118 | .syntax pre .sb { color: #cd0000 } /* Literal.String.Backtick */
119 | .syntax pre .sc { color: #cd0000 } /* Literal.String.Char */
120 | .syntax pre .sd { color: #cd0000 } /* Literal.String.Doc */
121 | .syntax pre .s2 { color: #cd0000 } /* Literal.String.Double */
122 | .syntax pre .se { color: #cd0000 } /* Literal.String.Escape */
123 | .syntax pre .sh { color: #cd0000 } /* Literal.String.Heredoc */
124 | .syntax pre .si { color: #cd0000 } /* Literal.String.Interpol */
125 | .syntax pre .sx { color: #cd0000 } /* Literal.String.Other */
126 | .syntax pre .sr { color: #cd0000 } /* Literal.String.Regex */
127 | .syntax pre .s1 { color: #cd0000 } /* Literal.String.Single */
128 | .syntax pre .ss { color: #cd0000 } /* Literal.String.Symbol */
129 | .syntax pre .bp { color: #cd00cd } /* Name.Builtin.Pseudo */
130 | .syntax pre .vc { color: #00cdcd } /* Name.Variable.Class */
131 | .syntax pre .vg { color: #00cdcd } /* Name.Variable.Global */
132 | .syntax pre .vi { color: #00cdcd } /* Name.Variable.Instance */
133 | .syntax pre .il { color: #cd00cd } /* Literal.Number.Integer.Long */
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Character.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Character.swift
3 | // SpriteKitTankTalk
4 | //
5 | // Created by Francesco Frison on 26/08/2015.
6 | // Copyright (c) 2015 frison. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SpriteKit
11 |
12 | class Character: SKSpriteNode {
13 |
14 | private var restAtlasses : [Direction: [SKTexture]]
15 | private var runAtlasses : [Direction: [SKTexture]]
16 |
17 | override init(texture: SKTexture?, color: UIColor, size: CGSize) {
18 | self.restAtlasses = Textures.forRest()
19 | self.runAtlasses = Textures.forRun()
20 | super.init(texture: texture, color: color, size: size)
21 | self.rest(.Front)
22 | }
23 |
24 | required init?(coder aDecoder: NSCoder) {
25 | fatalError("init(coder:) has not been implemented")
26 | }
27 |
28 |
29 |
30 | func runToPosition(position: CGPoint, completion: (()->())?) {
31 | let radiants = self.position.radiantsToPoint(position)
32 | let direction = Direction.fromRadiants(radiants)
33 | let duration = NSTimeInterval(self.position.distanceToPoint(position) / 200)
34 |
35 | // run textures
36 | let runAction = SKAction.animateWithTextures(self.runAtlasses[direction]!, timePerFrame: 0.05)
37 | self.runAction(SKAction.repeatActionForever(runAction), withKey: "runTexture")
38 |
39 | // move
40 | let move = SKAction.moveTo(position, duration: duration)
41 | self.runAction(move, completion: { () -> Void in
42 | self.removeActionForKey("runTexture")
43 | self.rest(.Front)
44 | if let completion = completion {
45 | completion()
46 | }
47 | })
48 |
49 | /*
50 | // This may work with a bit more twigging!
51 | self.physicsBody!.mass = 1.0
52 | self.physicsBody!.linearDamping = 0.80
53 | let vector = CGVectorMake(position.x - self.position.x, position.y - self.position.y)
54 | self.physicsBody!.velocity = vector
55 | */
56 |
57 |
58 | }
59 |
60 | func rest(direction: Direction) {
61 | let restAction = SKAction.animateWithTextures(self.restAtlasses[direction]!, timePerFrame: 0.05)
62 | self.runAction(restAction)
63 | }
64 | }
65 |
66 | enum Direction {
67 | case Front, Left, Back, Right
68 | }
69 |
70 | extension Direction {
71 | func restAtlasRange() -> Range{
72 | switch self {
73 | case .Front:
74 | return restFront
75 | case .Left:
76 | return restLeft
77 | case .Back:
78 | return restBack
79 | case .Right:
80 | return restRight
81 | }
82 | }
83 |
84 | func runAtlasRange() -> Range{
85 | switch self {
86 | case .Front:
87 | return runFront
88 | case .Left:
89 | return runLeft
90 | case .Back:
91 | return runBack
92 | case .Right:
93 | return runRight
94 | }
95 | }
96 |
97 | static func fromRadiants(radiants : CGFloat) -> Direction {
98 |
99 | if radiants < -0.8 && radiants > -2.4 {
100 | return .Right
101 | }
102 | else if radiants > 0.8 && radiants < 2.4 {
103 | return .Left
104 | }
105 | else if abs(radiants) > 1.5 {
106 | return .Front
107 | }
108 | else {
109 | return .Back
110 | }
111 | }
112 |
113 | }
114 |
115 |
116 | enum NodeType {
117 | case Character, ActionBox, Portal, Cat, Wall, Pipe, Other
118 |
119 | static func fromString(string : String) -> NodeType {
120 | switch string {
121 | case "character": return .Character
122 | case "actionBox": return .ActionBox
123 | case "portal": return .Portal
124 | case "cat": return .Cat
125 | case "wall": return .Wall
126 | case "pipe": return .Pipe
127 | default: return .Other
128 | }
129 | }
130 |
131 | func toString() -> String {
132 | switch self {
133 | case .Character: return "character"
134 | case .ActionBox: return "actionBox"
135 | case .Portal: return "portal"
136 | case .Cat: return "cat"
137 | case .Wall: return "wall"
138 | case .Pipe: return "pipe"
139 | default: return "other"
140 | }
141 | }
142 | }
143 |
144 |
145 | struct PhysicBody {
146 |
147 | static func physicsForNode(node: SKSpriteNode) -> SKPhysicsBody {
148 |
149 | let name = (node.name != nil) ? node.name! : "other"
150 | let type = NodeType.fromString(name)
151 | var physic : SKPhysicsBody
152 |
153 | if type == .Cat {
154 | physic = SKPhysicsBody(circleOfRadius: node.size.width / 2.2)
155 | }
156 | else if let texture = node.texture {
157 | physic = SKPhysicsBody(texture: texture, size: node.size)
158 | }
159 | else {
160 | physic = SKPhysicsBody(rectangleOfSize: node.size)
161 | }
162 |
163 | physic.usesPreciseCollisionDetection = false
164 | physic.dynamic = true
165 | physic.allowsRotation = false
166 | physic.affectedByGravity = false
167 |
168 | switch type {
169 | case .Character:
170 | physic.categoryBitMask = 0x1 << 0
171 | physic.contactTestBitMask = 0x1 << 1
172 | physic.collisionBitMask = 0x1 << 1
173 | case .ActionBox:
174 | physic.categoryBitMask = 0x1 << 1
175 | physic.contactTestBitMask = 0x1 << 0
176 | physic.collisionBitMask = 0x1 << 0
177 | case .Portal:
178 | physic.categoryBitMask = 0x1 << 2
179 | physic.contactTestBitMask = 0x1 << 0
180 | physic.collisionBitMask = 0x1 << 0
181 | case .Cat:
182 | physic.categoryBitMask = 0x1 << 3
183 | physic.contactTestBitMask = 0x1 << 0
184 | physic.collisionBitMask = 0x1 << 0
185 | physic.allowsRotation = true
186 | case .Wall:
187 | physic.categoryBitMask = 0x1 << 4
188 | physic.contactTestBitMask = 0x1 << 0
189 | physic.collisionBitMask = 0x1 << 0
190 | case .Pipe:
191 | physic.categoryBitMask = 0x1 << 5
192 | physic.contactTestBitMask = 0x1 << 0
193 | physic.collisionBitMask = 0x1 << 0
194 | physic.pinned = true
195 | default:
196 | physic.categoryBitMask = 0x1 << 8
197 | physic.contactTestBitMask = 0x1 << 0
198 | physic.collisionBitMask = 0x1 << 0
199 | physic.allowsRotation = true
200 | }
201 |
202 | return physic
203 | }
204 | }
205 |
206 | struct Textures {
207 |
208 | static func forRest() -> [Direction: [SKTexture]] {
209 | return forRest(true)
210 | }
211 |
212 | static func forRun() -> [Direction: [SKTexture]] {
213 | return forRest(false)
214 | }
215 |
216 | private static func forRest(isRest: Bool) -> [Direction: [SKTexture]] {
217 |
218 | let directions = [Direction.Front, Direction.Left, Direction.Back, Direction.Right]
219 |
220 | var textureDictionary = [Direction: [SKTexture]]()
221 | for direction in directions {
222 | // load all textures form direction.restAtlasRange()
223 | var textures = [SKTexture]()
224 | let range = isRest ? direction.restAtlasRange() : direction.runAtlasRange()
225 | for i in range {
226 | let name = NSString(format: "slice%.2d", i) as String
227 | let texture = SKTexture(imageNamed: name)
228 | textures.append(texture)
229 | }
230 | textureDictionary[direction] = textures
231 | }
232 |
233 | return textureDictionary
234 | }
235 | }
236 |
237 | private let restFront = 1...3
238 | private let restLeft = 4...6
239 | private let restBack = 7...7
240 | private let restRight = 8...10
241 |
242 | private let runFront = 11...20
243 | private let runLeft = 21...30
244 | private let runBack = 31...40
245 | private let runRight = 41...50
246 |
247 |
--------------------------------------------------------------------------------
/SpriteKitTankTalk/GameScene.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GameScene.swift
3 | // SpriteKitTankTalk
4 | //
5 | // Created by Francesco Frison on 26/08/2015.
6 | // Copyright (c) 2015 frison. All rights reserved.
7 | //
8 |
9 | import SpriteKit
10 |
11 | extension SKScene {
12 | func childNodeFromType(type: NodeType) -> SKNode? {
13 | if (type == .Other) {
14 | return nil
15 | }
16 |
17 | return self.childNodeWithName(type.toString())
18 | }
19 |
20 | func childrenFromType(type: NodeType) -> [SKNode] {
21 | if (type == .Other) {
22 | return [SKNode]()
23 | }
24 |
25 | return self.children.filter({$0.name != nil && $0.name == type.toString()})
26 | }
27 | }
28 |
29 | typealias DidContactBlock = (nodes: [NodeType : SKNode])->()
30 |
31 | class GameScene: SKScene, SKPhysicsContactDelegate {
32 |
33 | var nextScene: ((showCode: Bool)->())?
34 | var setup: (()->())?
35 | var shouldRunEntranceAnimation = true
36 | var didContact: DidContactBlock?
37 | var audioController : AudioController?
38 | var speakBoxController : SpeakBoxController?
39 |
40 | var currentActionIndex = 0
41 |
42 | var sceneDescription: SceneDescription? {
43 | didSet {
44 | if let sceneD = sceneDescription {
45 | self.title.text = sceneD.title
46 | }
47 | }
48 | }
49 |
50 | var character: Character! {
51 | return self.childNodeFromType(.Character) as? Character
52 | }
53 |
54 | var runToPosition : ((position: CGPoint, completion: (()->())?) -> ())?
55 |
56 | var title: SKLabelNode {
57 | return self.childNodeWithName("title") as! SKLabelNode
58 | }
59 |
60 | var nextPortal: SKSpriteNode {
61 | return self.childNodeFromType(.Portal) as! SKSpriteNode
62 | }
63 |
64 | var actionBox: SKSpriteNode? {
65 | return self.childNodeFromType(.ActionBox) as? SKSpriteNode
66 | }
67 |
68 | override func didMoveToView(view: SKView) {
69 |
70 | setupTitle()
71 | addCharacterToScene()
72 | setDefaultPhysicBodies()
73 | setDefaultActions()
74 |
75 | self.nextPortal.alpha = 0.0
76 | checkPortalActivation()
77 |
78 | if let setup = self.setup {
79 | setup()
80 | }
81 |
82 | if shouldRunEntranceAnimation {
83 | entranceAnimation()
84 | }
85 | else {
86 | speakAllActions()
87 | }
88 | }
89 |
90 | private func setupTitle() {
91 |
92 | self.title.fontName = Config.sharedConfig().fontName
93 | self.title.fontSize = 50.0
94 | self.title.color = UIColor.whiteColor()
95 | self.title.position = CGPoint(x: self.scene!.size.center.x, y: self.title.position.y)
96 | }
97 |
98 | private func addCharacterToScene() {
99 | let character = Character(imageNamed: "slice01.png")
100 | character.name = NodeType.Character.toString()
101 | character.setScale(0.6)
102 | character.zPosition = 10.0
103 | character.position = self.view!.center
104 | self.addChild(character)
105 | }
106 |
107 | private func setDefaultActions() {
108 | runToPosition = { (position: CGPoint, completion: (()->())?) in
109 | guard let character = self.character else {
110 | return
111 | }
112 |
113 | character.runToPosition(position, completion: { () -> () in
114 | if let completion = completion {
115 | completion()
116 | }
117 | })
118 | }
119 |
120 | didContact = { (nodes: [NodeType : SKNode]) in
121 |
122 | }
123 | }
124 |
125 | private func setDefaultPhysicBodies() {
126 | self.physicsWorld.contactDelegate = self
127 |
128 | self.character.physicsBody = PhysicBody.physicsForNode(self.character)
129 | self.nextPortal.physicsBody = PhysicBody.physicsForNode(self.nextPortal)
130 | self.nextPortal.physicsBody!.dynamic = false
131 | if let actionBox = self.actionBox {
132 | actionBox.physicsBody = PhysicBody.physicsForNode(self.actionBox!)
133 | actionBox.physicsBody!.dynamic = false
134 |
135 | }
136 | }
137 |
138 | func entranceAnimation(){
139 | self.character.position = CGPoint(x: -50.0, y: self.view!.center.y)
140 | let startPosition = CGPoint(x: 80.0, y: self.view!.center.y)
141 |
142 |
143 | self.runToPosition!(position: startPosition, completion: { () -> () in
144 | self.speakAllActions()
145 | })
146 | }
147 |
148 | func speakAllActions() {
149 | guard let actions = self.sceneDescription?.actions,
150 | let speakBoxController = self.speakBoxController else {
151 | return
152 | }
153 |
154 | speakBoxController.speakMultipleTextAndAdvance(actions, willStart: nil, completion: nil)
155 | }
156 |
157 | func checkPortalActivation() {
158 | let alpha : CGFloat = (self.actionBox == nil) ? 1.0 : 0.0
159 | if alpha == self.nextPortal.alpha {
160 | return
161 | }
162 |
163 | let alphaAction = SKAction.fadeAlphaTo(alpha, duration: 0.5)
164 | self.nextPortal.runAction(alphaAction)
165 | }
166 |
167 | func popActionNode(node : SKSpriteNode) {
168 | // avoid double collisions
169 | node.physicsBody = nil
170 |
171 | let shrink = SKAction.scaleBy(0.2, duration: 0.3)
172 | node.runAction(shrink)
173 |
174 | let fade = SKAction.fadeAlphaTo(0.0, duration: 0.3)
175 | node.runAction(fade, completion: { () -> Void in
176 | node.removeFromParent()
177 | self.checkPortalActivation()
178 | })
179 | }
180 |
181 | func portalAnimation(completion:(()->())?) {
182 | self.character.physicsBody = nil
183 |
184 | let center = self.nextPortal.position
185 | self.character.removeAllActions()
186 |
187 | self.character.rest(.Front)
188 |
189 | let move = SKAction.moveTo(center, duration: 0.7)
190 | self.character.runAction(move)
191 | let spin = SKAction.rotateByAngle(CGFloat(M_PI), duration: 0.5)
192 | self.character.runAction(spin)
193 | let fade = SKAction.fadeAlphaTo(0.0, duration: 0.5)
194 | if let completion = completion {
195 | self.character.runAction(fade, completion: completion)
196 | }
197 | else {
198 | self.character.runAction(fade)
199 | }
200 |
201 | }
202 |
203 | override func touchesBegan(touches: Set, withEvent event: UIEvent?) {
204 | /* Called when a touch begins */
205 |
206 |
207 | for touch in (touches ) {
208 | let location = touch.locationInNode(self)
209 | print(location)
210 |
211 | if let character = self.character {
212 | character.removeAllActions()
213 | }
214 |
215 | if let runToPosition = self.runToPosition {
216 | runToPosition(position: location, completion: { () -> () in
217 | //
218 | })
219 | }
220 | }
221 | }
222 |
223 | override func update(currentTime: CFTimeInterval) {
224 | /* Called before each frame is rendered */
225 | }
226 |
227 | private func nodesOutOfContact(contact: SKPhysicsContact) -> [NodeType : SKNode] {
228 | let nodeA = contact.bodyA.node
229 | let nodeB = contact.bodyB.node
230 |
231 | var others = [NodeType : SKNode]()
232 | if let nodeA = nodeA {
233 | if let name = nodeA.name {
234 | let type = NodeType.fromString(name)
235 | if type != .Other {
236 | others[type] = nodeA
237 | }
238 | }
239 | }
240 |
241 | if let nodeB = nodeB {
242 | if let name = nodeB.name {
243 | let type = NodeType.fromString(name)
244 | if type != .Other {
245 | others[type] = nodeB
246 | }
247 | }
248 | }
249 | return others
250 | }
251 |
252 | func didBeginContact(contact: SKPhysicsContact) {
253 |
254 | let nodes = nodesOutOfContact(contact)
255 |
256 | if let contactFunc = self.didContact {
257 | contactFunc(nodes: nodes)
258 | }
259 |
260 | guard let _ = nodes[.Character],
261 | let nextScene = nextScene,
262 | let portal = nodes[.Portal] where
263 | portal.alpha == 1.0 else {
264 | return
265 | }
266 |
267 | portalAnimation({ () -> () in
268 | self.character.removeFromParent()
269 | Dispatch.after(0.5, block: { () -> () in
270 | nextScene(showCode: true)
271 | })
272 | })
273 | }
274 | }
275 |
276 |
--------------------------------------------------------------------------------
/_etc/html/css/basic.css:
--------------------------------------------------------------------------------
1 | /*
2 | * basic.css
3 | * ~~~~~~~~~
4 | *
5 | * Sphinx stylesheet -- basic theme.
6 | *
7 | * :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
8 | * :license: BSD, see LICENSE for details.
9 | *
10 | */
11 |
12 | /* -- main layout ----------------------------------------------------------- */
13 |
14 | div.clearer {
15 | clear: both;
16 | }
17 |
18 | /* -- relbar ---------------------------------------------------------------- */
19 |
20 | div.related {
21 | width: 100%;
22 | font-size: 90%;
23 | }
24 |
25 | div.related h3 {
26 | display: none;
27 | }
28 |
29 | div.related ul {
30 | margin: 0;
31 | padding: 0 0 0 10px;
32 | list-style: none;
33 | }
34 |
35 | div.related li {
36 | display: inline;
37 | }
38 |
39 | div.related li.right {
40 | float: right;
41 | margin-right: 5px;
42 | }
43 |
44 | /* -- sidebar --------------------------------------------------------------- */
45 |
46 | div.sphinxsidebarwrapper {
47 | padding: 10px 5px 0 10px;
48 | }
49 |
50 | div.sphinxsidebar {
51 | float: left;
52 | width: 230px;
53 | margin-left: -100%;
54 | font-size: 90%;
55 | }
56 |
57 | div.sphinxsidebar ul {
58 | list-style: none;
59 | }
60 |
61 | div.sphinxsidebar ul ul,
62 | div.sphinxsidebar ul.want-points {
63 | margin-left: 20px;
64 | list-style: square;
65 | }
66 |
67 | div.sphinxsidebar ul ul {
68 | margin-top: 0;
69 | margin-bottom: 0;
70 | }
71 |
72 | div.sphinxsidebar form {
73 | margin-top: 10px;
74 | }
75 |
76 | div.sphinxsidebar input {
77 | border: 1px solid #98dbcc;
78 | font-family: sans-serif;
79 | font-size: 1em;
80 | }
81 |
82 | div.sphinxsidebar #searchbox input[type="text"] {
83 | width: 170px;
84 | }
85 |
86 | div.sphinxsidebar #searchbox input[type="submit"] {
87 | width: 30px;
88 | }
89 |
90 | img {
91 | border: 0;
92 | max-width: 100%;
93 | }
94 |
95 | /* -- search page ----------------------------------------------------------- */
96 |
97 | ul.search {
98 | margin: 10px 0 0 20px;
99 | padding: 0;
100 | }
101 |
102 | ul.search li {
103 | padding: 5px 0 5px 20px;
104 | background-image: url(file.png);
105 | background-repeat: no-repeat;
106 | background-position: 0 7px;
107 | }
108 |
109 | ul.search li a {
110 | font-weight: bold;
111 | }
112 |
113 | ul.search li div.context {
114 | color: #888;
115 | margin: 2px 0 0 30px;
116 | text-align: left;
117 | }
118 |
119 | ul.keywordmatches li.goodmatch a {
120 | font-weight: bold;
121 | }
122 |
123 | /* -- index page ------------------------------------------------------------ */
124 |
125 | table.contentstable {
126 | width: 90%;
127 | }
128 |
129 | table.contentstable p.biglink {
130 | line-height: 150%;
131 | }
132 |
133 | a.biglink {
134 | font-size: 1.3em;
135 | }
136 |
137 | span.linkdescr {
138 | font-style: italic;
139 | padding-top: 5px;
140 | font-size: 90%;
141 | }
142 |
143 | /* -- general index --------------------------------------------------------- */
144 |
145 | table.indextable {
146 | width: 100%;
147 | }
148 |
149 | table.indextable td {
150 | text-align: left;
151 | vertical-align: top;
152 | }
153 |
154 | table.indextable dl, table.indextable dd {
155 | margin-top: 0;
156 | margin-bottom: 0;
157 | }
158 |
159 | table.indextable tr.pcap {
160 | height: 10px;
161 | }
162 |
163 | table.indextable tr.cap {
164 | margin-top: 10px;
165 | background-color: #f2f2f2;
166 | }
167 |
168 | img.toggler {
169 | margin-right: 3px;
170 | margin-top: 3px;
171 | cursor: pointer;
172 | }
173 |
174 | div.modindex-jumpbox {
175 | border-top: 1px solid #ddd;
176 | border-bottom: 1px solid #ddd;
177 | margin: 1em 0 1em 0;
178 | padding: 0.4em;
179 | }
180 |
181 | div.genindex-jumpbox {
182 | border-top: 1px solid #ddd;
183 | border-bottom: 1px solid #ddd;
184 | margin: 1em 0 1em 0;
185 | padding: 0.4em;
186 | }
187 |
188 | /* -- general body styles --------------------------------------------------- */
189 |
190 | a.headerlink {
191 | visibility: hidden;
192 | }
193 |
194 | h1:hover > a.headerlink,
195 | h2:hover > a.headerlink,
196 | h3:hover > a.headerlink,
197 | h4:hover > a.headerlink,
198 | h5:hover > a.headerlink,
199 | h6:hover > a.headerlink,
200 | dt:hover > a.headerlink {
201 | visibility: visible;
202 | }
203 |
204 | div.body p.caption {
205 | text-align: inherit;
206 | }
207 |
208 | div.body td {
209 | text-align: left;
210 | }
211 |
212 | .field-list ul {
213 | padding-left: 1em;
214 | }
215 |
216 | .first {
217 | margin-top: 0 !important;
218 | }
219 |
220 | p.rubric {
221 | margin-top: 30px;
222 | font-weight: bold;
223 | }
224 |
225 | img.align-left, .figure.align-left, object.align-left {
226 | clear: left;
227 | float: left;
228 | margin-right: 1em;
229 | }
230 |
231 | img.align-right, .figure.align-right, object.align-right {
232 | clear: right;
233 | float: right;
234 | margin-left: 1em;
235 | }
236 |
237 | img.align-center, .figure.align-center, object.align-center {
238 | display: block;
239 | margin-left: auto;
240 | margin-right: auto;
241 | }
242 |
243 | .align-left {
244 | text-align: left;
245 | }
246 |
247 | .align-center {
248 | text-align: center;
249 | }
250 |
251 | .align-right {
252 | text-align: right;
253 | }
254 |
255 | /* -- sidebars -------------------------------------------------------------- */
256 |
257 | div.sidebar {
258 | margin: 0 0 0.5em 1em;
259 | border: 1px solid #ddb;
260 | padding: 7px 7px 0 7px;
261 | background-color: #ffe;
262 | width: 40%;
263 | float: right;
264 | }
265 |
266 | p.sidebar-title {
267 | font-weight: bold;
268 | }
269 |
270 | /* -- topics ---------------------------------------------------------------- */
271 |
272 | div.topic {
273 | border: 1px solid #ccc;
274 | padding: 7px 7px 0 7px;
275 | margin: 10px 0 10px 0;
276 | }
277 |
278 | p.topic-title {
279 | font-size: 1.1em;
280 | font-weight: bold;
281 | margin-top: 10px;
282 | }
283 |
284 | /* -- admonitions ----------------------------------------------------------- */
285 |
286 | div.admonition {
287 | margin-top: 10px;
288 | margin-bottom: 10px;
289 | padding: 7px;
290 | }
291 |
292 | div.admonition dt {
293 | font-weight: bold;
294 | }
295 |
296 | div.admonition dl {
297 | margin-bottom: 0;
298 | }
299 |
300 | p.admonition-title {
301 | margin: 0px 10px 5px 0px;
302 | font-weight: bold;
303 | }
304 |
305 | div.body p.centered {
306 | text-align: center;
307 | margin-top: 25px;
308 | }
309 |
310 | /* -- tables ---------------------------------------------------------------- */
311 |
312 | table.docutils {
313 | border: 0;
314 | border-collapse: collapse;
315 | }
316 |
317 | table.docutils td, table.docutils th {
318 | padding: 1px 8px 1px 5px;
319 | border-top: 0;
320 | border-left: 0;
321 | border-right: 0;
322 | border-bottom: 1px solid #aaa;
323 | }
324 |
325 | table.field-list td, table.field-list th {
326 | border: 0 !important;
327 | }
328 |
329 | table.footnote td, table.footnote th {
330 | border: 0 !important;
331 | }
332 |
333 | th {
334 | text-align: left;
335 | padding-right: 5px;
336 | }
337 |
338 | table.citation {
339 | border-left: solid 1px gray;
340 | margin-left: 1px;
341 | }
342 |
343 | table.citation td {
344 | border-bottom: none;
345 | }
346 |
347 | /* -- other body styles ----------------------------------------------------- */
348 |
349 | ol.arabic {
350 | list-style: decimal;
351 | }
352 |
353 | ol.loweralpha {
354 | list-style: lower-alpha;
355 | }
356 |
357 | ol.upperalpha {
358 | list-style: upper-alpha;
359 | }
360 |
361 | ol.lowerroman {
362 | list-style: lower-roman;
363 | }
364 |
365 | ol.upperroman {
366 | list-style: upper-roman;
367 | }
368 |
369 | dl {
370 | margin-bottom: 15px;
371 | }
372 |
373 | dd p {
374 | margin-top: 0px;
375 | }
376 |
377 | dd ul, dd table {
378 | margin-bottom: 10px;
379 | }
380 |
381 | dd {
382 | margin-top: 3px;
383 | margin-bottom: 10px;
384 | margin-left: 30px;
385 | }
386 |
387 | dt:target, .highlighted {
388 | background-color: #fbe54e;
389 | }
390 |
391 | dl.glossary dt {
392 | font-weight: bold;
393 | font-size: 1.1em;
394 | }
395 |
396 | .field-list ul {
397 | margin: 0;
398 | padding-left: 1em;
399 | }
400 |
401 | .field-list p {
402 | margin: 0;
403 | }
404 |
405 | .optional {
406 | font-size: 1.3em;
407 | }
408 |
409 | .versionmodified {
410 | font-style: italic;
411 | }
412 |
413 | .system-message {
414 | background-color: #fda;
415 | padding: 5px;
416 | border: 3px solid red;
417 | }
418 |
419 | .footnote:target {
420 | background-color: #ffa;
421 | }
422 |
423 | .line-block {
424 | display: block;
425 | margin-top: 1em;
426 | margin-bottom: 1em;
427 | }
428 |
429 | .line-block .line-block {
430 | margin-top: 0;
431 | margin-bottom: 0;
432 | margin-left: 1.5em;
433 | }
434 |
435 | .guilabel, .menuselection {
436 | font-family: sans-serif;
437 | }
438 |
439 | .accelerator {
440 | text-decoration: underline;
441 | }
442 |
443 | .classifier {
444 | font-style: oblique;
445 | }
446 |
447 | abbr, acronym {
448 | border-bottom: dotted 1px;
449 | cursor: help;
450 | }
451 |
452 | /* -- code displays --------------------------------------------------------- */
453 |
454 | pre {
455 | overflow: auto;
456 | overflow-y: hidden; /* fixes display issues on Chrome browsers */
457 | }
458 |
459 | td.linenos pre {
460 | padding: 5px 0px;
461 | border: 0;
462 | background-color: transparent;
463 | color: #aaa;
464 | }
465 |
466 | table.highlighttable {
467 | margin-left: 0.5em;
468 | }
469 |
470 | table.highlighttable td {
471 | padding: 0 0.5em 0 0.5em;
472 | }
473 |
474 | tt.descname {
475 | background-color: transparent;
476 | font-weight: bold;
477 | font-size: 1.2em;
478 | }
479 |
480 | tt.descclassname {
481 | background-color: transparent;
482 | }
483 |
484 | tt.xref, a tt {
485 | background-color: transparent;
486 | font-weight: bold;
487 | }
488 |
489 | h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
490 | background-color: transparent;
491 | }
492 |
493 | .viewcode-link {
494 | float: right;
495 | }
496 |
497 | .viewcode-back {
498 | float: right;
499 | font-family: sans-serif;
500 | }
501 |
502 | div.viewcode-block:target {
503 | margin: -1px -10px;
504 | padding: 0 10px;
505 | }
506 |
507 | /* -- math display ---------------------------------------------------------- */
508 |
509 | img.math {
510 | vertical-align: middle;
511 | }
512 |
513 | div.body div.math p {
514 | text-align: center;
515 | }
516 |
517 | span.eqno {
518 | float: right;
519 | }
520 |
521 | /* -- printout stylesheet --------------------------------------------------- */
522 |
523 | @media print {
524 | div.document,
525 | div.documentwrapper,
526 | div.bodywrapper {
527 | margin: 0 !important;
528 | width: 100%;
529 | }
530 |
531 | div.sphinxsidebar,
532 | div.related,
533 | div.footer,
534 | #top-link {
535 | display: none;
536 | }
537 | }
538 |
--------------------------------------------------------------------------------
/SpriteKitTankTalk/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
75 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
156 |
157 |
158 |
159 |
167 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
--------------------------------------------------------------------------------
/SpriteKitTankTalk/GameExtensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GameExtensions.swift
3 | // SpriteKitTankTalk
4 | //
5 | // Created by Francesco Frison on 27/08/2015.
6 | // Copyright (c) 2015 frison. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SpriteKit
11 | import GameKit
12 |
13 |
14 | extension GameScene {
15 | func setUp1() {
16 | runToPosition = { (position: CGPoint, completion: (()->())?) in
17 | if let character = self.character {
18 | character.position = position
19 | }
20 |
21 | if let completion = completion {
22 | Dispatch.after(0.5, block: completion)
23 | }
24 | }
25 | }
26 | func action1() {
27 |
28 | }
29 | }
30 |
31 | extension GameScene {
32 | func setUp2() {
33 | self.didContact = didContact2
34 |
35 | runToPosition = { (position: CGPoint, completion: (()->())?) in
36 | self.character.position = position
37 |
38 | if let completion = completion {
39 | Dispatch.after(0.5, block: completion)
40 | }
41 | }
42 |
43 |
44 | self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
45 | }
46 |
47 | func didContact2(nodes: [NodeType : SKNode]) {
48 |
49 | if let actionBox = nodes[.ActionBox] as? SKSpriteNode {
50 | self.popActionNode(actionBox)
51 |
52 |
53 | runToPosition = { (position: CGPoint, completion: (()->())?) in
54 | guard let character = self.character else {
55 | return
56 | }
57 |
58 | let duration = NSTimeInterval(character.position.distanceToPoint(position) / 200)
59 |
60 | // move
61 | let move = SKAction.moveTo(position, duration: duration)
62 | character.runAction(move, completion: { () -> Void in
63 | if let completion = completion {
64 | completion()
65 | }
66 | })
67 | }
68 |
69 | }
70 |
71 |
72 | }
73 | }
74 |
75 | extension GameScene {
76 | func setUp3() {
77 | self.didContact = didContact3
78 |
79 | runToPosition = { (position: CGPoint, completion: (()->())?) in
80 |
81 | let duration = NSTimeInterval(self.character.position.distanceToPoint(position) / 200)
82 |
83 | // move
84 | let move = SKAction.moveTo(position, duration: duration)
85 | self.character.runAction(move, completion: { () -> Void in
86 | if let completion = completion {
87 | completion()
88 | }
89 | })
90 | }
91 |
92 | }
93 |
94 | func didContact3(nodes: [NodeType : SKNode]) {
95 | if let actionBox = nodes[.ActionBox] as? SKSpriteNode {
96 | self.popActionNode(actionBox)
97 |
98 | runToPosition = { (position: CGPoint, completion: (()->())?) in
99 |
100 | guard let character = self.character else {
101 | return
102 | }
103 | character.runToPosition(position, completion: { () -> () in
104 | if let completion = completion {
105 | completion()
106 | }
107 | })
108 | }
109 | }
110 | }
111 | }
112 |
113 | extension GameScene {
114 | func setUp4() {
115 |
116 | self.didContact = didContact4
117 |
118 | self.character.removeAllActions()
119 |
120 | let characterPhysic = self.character.physicsBody!
121 | characterPhysic.friction = 0.01
122 | characterPhysic.affectedByGravity = false
123 | self.character.physicsBody = characterPhysic
124 | }
125 |
126 | func didContact4(nodes: [NodeType : SKNode]) {
127 | if let actionBox = nodes[.ActionBox] as? SKSpriteNode {
128 | self.popActionNode(actionBox)
129 | }
130 | }
131 | }
132 |
133 | extension GameScene {
134 | func setUp5() {
135 | self.didContact = didContact5
136 |
137 | let characterPhysic = self.character.physicsBody!
138 | characterPhysic.friction = 0.01
139 | characterPhysic.mass = 10
140 | characterPhysic.affectedByGravity = false
141 | self.character.physicsBody = characterPhysic
142 | }
143 |
144 | func didContact5(nodes: [NodeType : SKNode]) {
145 |
146 | guard let actionBox = nodes[.ActionBox] as? SKSpriteNode,
147 | let _ = nodes[.Character] as? SKSpriteNode else {
148 | return
149 | }
150 |
151 | self.popActionNode(actionBox)
152 |
153 | if let speakBoxController = self.speakBoxController {
154 | speakBoxController.speakText("Ahhhhhh!", willStart: nil, completion: nil)
155 | }
156 |
157 | self.character.physicsBody!.affectedByGravity = true
158 | self.physicsWorld.gravity = CGVector(dx: 0.0, dy: -5.0)
159 |
160 | for child in self.children {
161 | if (child.name == nil && child.physicsBody != nil) {
162 | child.physicsBody!.affectedByGravity = true
163 | }
164 | }
165 |
166 | Dispatch.after(2.0, block: { () -> () in
167 | if let nextScene = self.nextScene {
168 | nextScene(showCode: false)
169 | }
170 | })
171 |
172 | }
173 | }
174 |
175 |
176 | extension GameScene {
177 | func setUp6() {
178 | self.didContact = didContact6
179 | self.shouldRunEntranceAnimation = false
180 |
181 | if let audioController = self.audioController {
182 | audioController.stopBackgroundMusic()
183 | audioController.playMarioBackgroundMusic()
184 | }
185 | hidewalls()
186 |
187 | self.physicsWorld.gravity = CGVector(dx: 0.0, dy: -5.0)
188 |
189 | self.character.removeAllActions()
190 | self.character.position = CGPoint(x: 700.0, y: self.size.height + 50)
191 |
192 | let characterPhysic = self.character.physicsBody!
193 | characterPhysic.friction = 0.01
194 | characterPhysic.affectedByGravity = true
195 | self.character.physicsBody = characterPhysic
196 |
197 | if let speakBoxController = self.speakBoxController {
198 | speakBoxController.speakText("Ahhhhhh!", willStart: nil, completion: nil)
199 | }
200 | }
201 |
202 | func didContact6(nodes: [NodeType : SKNode]) {
203 | if let actionBox = nodes[.ActionBox] as? SKSpriteNode {
204 | if let character = nodes[.Character] as? SKSpriteNode {
205 | actionBox.physicsBody = nil
206 | let deltaY = character.position.y - character.size.height
207 |
208 | let move = SKAction.moveToY(deltaY, duration: 1.5)
209 | self.character.runAction(move, completion: { () -> Void in
210 | if let nextScene = self.nextScene {
211 | nextScene(showCode: false)
212 | }
213 | })
214 | }
215 | }
216 | }
217 |
218 | func hidewalls() {
219 | let walls = self.childrenFromType(.Wall)
220 | for wall in walls {
221 | wall.alpha = 0.0
222 | }
223 | }
224 | }
225 |
226 | extension GameScene {
227 | func setUp7() {
228 | self.didContact = didContact7
229 | self.shouldRunEntranceAnimation = false
230 |
231 | hidewalls()
232 |
233 | self.physicsWorld.gravity = CGVector(dx: 0.0, dy: -5.0)
234 |
235 | let pipe = self.childNodeWithName("pipe") as! SKSpriteNode
236 | self.character.position = CGPoint(x: pipe.position.x, y: pipe.position.y)
237 | self.character.physicsBody!.affectedByGravity = false
238 |
239 | let deltaY = pipe.position.y + self.character.size.height + 40
240 | let move = SKAction.moveToY(deltaY, duration: 1.5)
241 |
242 | let originalPipePhysics = pipe.physicsBody
243 | pipe.physicsBody = nil
244 |
245 | self.character.runAction(move) { () -> Void in
246 | pipe.physicsBody = originalPipePhysics
247 | self.character.physicsBody!.affectedByGravity = true
248 | }
249 |
250 | }
251 |
252 | func didContact7(nodes: [NodeType : SKNode]) {
253 | if let actionBox = nodes[.ActionBox] as? SKSpriteNode {
254 | self.popActionNode(actionBox)
255 |
256 | for i in 0...5 {
257 | let delay = Double(i) * 0.6
258 | Dispatch.after(delay, block: { () -> () in
259 | let cat = self.cat()
260 |
261 | self.addChild(cat)
262 | let dx = (CGFloat(arc4random()%50) + 20) * -1.0
263 | let dy = CGFloat(arc4random()%50) + 40
264 | let vector = CGVector(dx: dx, dy: dy)
265 |
266 | cat.physicsBody!.applyImpulse(vector)
267 | })
268 |
269 | }
270 | }
271 | }
272 |
273 | func cat() -> SKNode {
274 | var characterPosition = CGPointZero
275 | if let character = self.character {
276 | characterPosition = character.position
277 | }
278 | let cat = SKSpriteNode(imageNamed: "cat")
279 | cat.name = NodeType.Cat.toString()
280 | cat.position = CGPointApplyAffineTransform(characterPosition, CGAffineTransformMakeTranslation(-60, 60))
281 | cat.setScale(0.15)
282 | cat.zRotation = CGFloat(Double(arc4random())%M_PI)
283 |
284 | // Physic body
285 | let physicBody = PhysicBody.physicsForNode(cat)
286 | physicBody.friction = 0.1
287 | physicBody.affectedByGravity = true
288 | physicBody.restitution = 0.9
289 | physicBody.mass = 0.15
290 | physicBody.dynamic = true
291 | cat.physicsBody = physicBody
292 |
293 | return cat
294 | }
295 | }
296 |
297 | extension GameScene {
298 | func setUp8() {
299 | self.didContact = didContact8
300 | self.character.physicsBody!.affectedByGravity = false
301 |
302 | if let audioController = self.audioController {
303 | audioController.stopBackgroundMusic()
304 | audioController.playBackgroundMusic()
305 | }
306 | }
307 |
308 | func didContact8(nodes: [NodeType : SKNode]) {
309 | if let actionBox = nodes[.ActionBox] as? SKSpriteNode {
310 | self.popActionNode(actionBox)
311 |
312 | self.setPiros()
313 |
314 | Dispatch.after(2.0, block: { () -> () in
315 | self.setFires()
316 | })
317 |
318 | Dispatch.after(6.0, block: { () -> () in
319 | if let speakBoxController = self.speakBoxController {
320 | speakBoxController.speakText("Oh crap. let's get out of here", willStart: nil, completion: nil)
321 | }
322 | })
323 |
324 | }
325 | }
326 |
327 | func setPiros() {
328 | let validSize = CGSizeApplyAffineTransform(self.size, CGAffineTransformMakeScale(0.8, 0.8))
329 |
330 | var delay = 0.0
331 | for _ in 0...4 {
332 | Dispatch.after(delay, block: { () -> () in
333 | let piroEmitter = self.piroEmitter()
334 |
335 | let x = CGFloat(arc4random()%UInt32(validSize.width))
336 | let y = CGFloat(arc4random()%UInt32(validSize.height))
337 |
338 | piroEmitter.position = CGPoint(x: x, y: y)
339 | self.addChild(piroEmitter)
340 | Dispatch.after(1.0, block: { () -> () in
341 | piroEmitter.removeFromParent()
342 | })
343 | })
344 | delay += 0.5
345 |
346 | }
347 |
348 | }
349 |
350 | func setFires() {
351 | let fireLocations = [
352 | CGPoint(x: 816.0, y: 102.0),
353 | CGPoint(x: 122.0, y: 598.0),
354 | CGPoint(x: 24.0, y: 245.0)
355 | ]
356 |
357 | var delay = 0.0
358 | for location in fireLocations {
359 | Dispatch.after(delay, block: { () -> () in
360 | let delay = (delay + 0.1)
361 | let fireEmitter = self.fireEmitter()
362 | fireEmitter.position = location
363 |
364 | self.addChild(fireEmitter)
365 |
366 | Dispatch.after(1.0 * delay, block: { () -> () in
367 | fireEmitter.setScale(1.2)
368 | })
369 |
370 | Dispatch.after(2.0 * delay, block: { () -> () in
371 | fireEmitter.setScale(1.8)
372 | })
373 | })
374 | delay += 0.4
375 |
376 | }
377 | }
378 |
379 |
380 | func fireEmitter() -> SKEmitterNode{
381 | let emitterPath: String = NSBundle.mainBundle().pathForResource("Fire", ofType: "sks")!
382 | let emitterNode = NSKeyedUnarchiver.unarchiveObjectWithFile(emitterPath) as! SKEmitterNode
383 | emitterNode.setScale(0.8)
384 |
385 | return emitterNode
386 | }
387 |
388 | func piroEmitter() -> SKEmitterNode{
389 | let emitterPath: String = NSBundle.mainBundle().pathForResource("Piro", ofType: "sks")!
390 | let emitterNode = NSKeyedUnarchiver.unarchiveObjectWithFile(emitterPath) as! SKEmitterNode
391 | emitterNode.setScale(0.8)
392 |
393 | return emitterNode
394 | }
395 | }
396 |
397 |
398 | extension GameScene {
399 | func setUp9() {
400 | self.didContact = didContact9
401 | }
402 |
403 | func didContact9(nodes: [NodeType : SKNode]) {
404 |
405 | guard let actionBox = nodes[.ActionBox] as? SKSpriteNode,
406 | let speakBoxController = self.speakBoxController else {
407 | return
408 | }
409 |
410 | self.popActionNode(actionBox)
411 | speakBoxController.runDemo({ (cancelled, text) -> () in
412 | //
413 |
414 | })
415 | }
416 |
417 | }
418 |
419 |
420 | extension GameScene {
421 | func setUp10() {
422 | self.didContact = didContact10
423 | self.shouldRunEntranceAnimation = false
424 | self.nextPortal.alpha = 0.0
425 | self.title.color = UIColor.whiteColor()
426 |
427 | self.character.removeAllActions()
428 | let lines = ["@cescofry - francesco.co", "github.com/cescofry/SpriteKitAndFriends", "developer.apple.com/spritekit"]
429 |
430 |
431 | var position = CGPoint(x: 100, y: self.size.height + 100)
432 | self.character.position = position
433 |
434 | position.y = self.title.position.y - 100
435 | self.character.runToPosition(position) { () -> () in
436 |
437 | self.moveToLines(lines) { () -> () in
438 | if let speakBoxController = self.speakBoxController {
439 | speakBoxController.speakText("Thank You", willStart: nil, completion: nil)
440 | }
441 |
442 | Dispatch.after(2.0, block: { () -> () in
443 | // Do Something to close
444 | })
445 | }
446 | }
447 |
448 |
449 | }
450 |
451 | func didContact10(nodes: [NodeType : SKNode]) {
452 |
453 | }
454 |
455 | func moveToLines(var lines : [String], completedAll: (()->())) {
456 |
457 | guard let line = lines.first else {
458 | completedAll()
459 | return
460 | }
461 |
462 | lines.removeFirst()
463 |
464 | let lineGap : CGFloat = 100.0
465 | var position = self.character.position
466 | position.y -= lineGap
467 | self.character.runToPosition(position) { () -> () in
468 | let label = self.labelForString(line)
469 | var labelPosition = self.character.position
470 | labelPosition.x += 100
471 | label.position = labelPosition
472 |
473 | self.addChild(label)
474 |
475 | let fireWall = self.fireNodeForSize(label.frame.size)
476 | fireWall.position = label.position
477 |
478 | self.addChild(fireWall)
479 |
480 | Dispatch.after(1.6, block: { () -> () in
481 | self.moveToLines(lines, completedAll: completedAll)
482 | })
483 | }
484 |
485 | }
486 |
487 | func labelForString(string: String) -> SKLabelNode {
488 | let label = SKLabelNode(text: string)
489 | var labelPosition = self.character.position
490 | labelPosition.x += 100
491 | label.position = labelPosition
492 | label.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Left
493 | label.color = UIColor.whiteColor()
494 | label.fontSize = 38.0
495 | label.alpha = 0.0
496 |
497 |
498 | let fadeIn = SKAction.fadeInWithDuration(0.6)
499 | label.runAction(fadeIn)
500 |
501 | return label
502 | }
503 |
504 | func fireNodeForSize(size: CGSize) -> SKNode {
505 | var x : CGFloat = 0.0
506 |
507 | let node = SKNode()
508 | while (x < size.width) {
509 | let fire = fireEmitter()
510 | fire.position = CGPoint(x: x, y: 0.0)
511 | node.addChild(fire)
512 | x += 50.0
513 | }
514 |
515 | let remove = SKAction.fadeOutWithDuration(1.5)
516 | node.runAction(remove) { () -> Void in
517 | node.removeFromParent()
518 | }
519 |
520 | return node
521 | }
522 |
523 | }
524 |
--------------------------------------------------------------------------------