├── .gitignore ├── SpaceInvaders ├── .gitignore ├── .rubocop.yml ├── Gemfile ├── Gemfile.lock ├── Rakefile ├── app │ ├── app_delegate.rb │ ├── game_scene.rb │ ├── game_view_controller.rb │ └── top_level.rb ├── live_reload.rb ├── readme.md ├── resources │ ├── Default-375w-667h@2x.png │ ├── Default-414w-736h@3x.png │ ├── Default-568h@2x.png │ ├── Default-667h@2x.png │ ├── Default-736h@3x.png │ ├── large.png │ ├── medium.png │ ├── small.png │ └── square.png ├── space-invaders.gif └── spec │ └── main_spec.rb ├── actions ├── .gitignore ├── Gemfile ├── Gemfile.lock ├── Rakefile ├── actions.gif ├── app │ ├── app_delegate.rb │ ├── game_scene.rb │ ├── game_view_controller.rb │ └── screen_sizes.rb ├── readme.md ├── resources │ ├── Default-375w-667h@2x.png │ ├── Default-414w-736h@3x.png │ ├── Default-568h@2x.png │ ├── Default-667h@2x.png │ ├── Default-736h@3x.png │ ├── ball.png │ ├── button.png │ ├── large.png │ ├── medium.png │ ├── small.png │ └── square.png └── spec │ └── main_spec.rb ├── animated-sprite ├── .gitignore ├── Gemfile ├── Gemfile.lock ├── Rakefile ├── animated-sprite.gif ├── app │ ├── app_delegate.rb │ ├── game_scene.rb │ ├── game_view_controller.rb │ └── screen_sizes.rb ├── readme.md ├── resources │ ├── Default-375w-667h@2x.png │ ├── Default-414w-736h@3x.png │ ├── Default-568h@2x.png │ ├── Default-667h@2x.png │ ├── Default-736h@3x.png │ ├── ball.png │ ├── button.png │ ├── large.png │ ├── medium.png │ ├── small.png │ ├── sprite_1.png │ ├── sprite_2.png │ ├── sprite_3.png │ ├── sprite_4.png │ ├── sprite_5.png │ └── square.png └── spec │ └── main_spec.rb ├── collision-detection ├── .gitignore ├── Gemfile ├── Gemfile.lock ├── Rakefile ├── app │ ├── app_delegate.rb │ ├── game_scene.rb │ ├── game_view_controller.rb │ └── screen_sizes.rb ├── collision-detection.gif ├── readme.md ├── resources │ ├── Default-375w-667h@2x.png │ ├── Default-414w-736h@3x.png │ ├── Default-568h@2x.png │ ├── Default-667h@2x.png │ ├── Default-736h@3x.png │ ├── ball.png │ ├── explosion_particle.png │ ├── large.png │ ├── medium.png │ ├── small.png │ └── wall.png └── spec │ └── main_spec.rb ├── create-sprite ├── .gitignore ├── Gemfile ├── Gemfile.lock ├── Rakefile ├── app │ ├── app_delegate.rb │ ├── game_scene.rb │ ├── game_view_controller.rb │ └── screen_sizes.rb ├── create-sprite.gif ├── readme.md ├── resources │ ├── Default-375w-667h@2x.png │ ├── Default-414w-736h@3x.png │ ├── Default-568h@2x.png │ ├── Default-667h@2x.png │ ├── Default-736h@3x.png │ ├── large.png │ ├── medium.png │ ├── small.png │ └── square.png └── spec │ └── main_spec.rb ├── hello-world ├── .gitignore ├── Gemfile ├── Gemfile.lock ├── Rakefile ├── app │ ├── app_delegate.rb │ ├── game_scene.rb │ └── game_view_controller.rb ├── hello-world.gif ├── readme.md ├── resources │ ├── Default-375w-667h@2x.png │ ├── Default-414w-736h@3x.png │ ├── Default-568h@2x.png │ ├── Default-667h@2x.png │ ├── Default-736h@3x.png │ ├── large.png │ ├── medium.png │ └── small.png └── spec │ └── main_spec.rb ├── license.txt ├── particle-effects ├── .gitignore ├── Gemfile ├── Gemfile.lock ├── Rakefile ├── app │ ├── app_delegate.rb │ ├── game_scene.rb │ ├── game_view_controller.rb │ └── screen_sizes.rb ├── particle-effects.gif ├── readme.md ├── resources │ ├── Default-375w-667h@2x.png │ ├── Default-414w-736h@3x.png │ ├── Default-568h@2x.png │ ├── Default-667h@2x.png │ ├── Default-736h@3x.png │ ├── ball.png │ ├── button.png │ ├── large.png │ ├── medium.png │ ├── small.png │ └── square.png └── spec │ └── main_spec.rb ├── physics ├── .gitignore ├── Gemfile ├── Gemfile.lock ├── Rakefile ├── app │ ├── app_delegate.rb │ ├── game_scene.rb │ ├── game_view_controller.rb │ └── screen_sizes.rb ├── physics.gif ├── readme.md ├── resources │ ├── Default-375w-667h@2x.png │ ├── Default-414w-736h@3x.png │ ├── Default-568h@2x.png │ ├── Default-667h@2x.png │ ├── Default-736h@3x.png │ ├── ball.png │ ├── explosion_particle.png │ ├── large.png │ ├── medium.png │ ├── small.png │ └── wall.png └── spec │ └── main_spec.rb ├── putting-it-together ├── .gitignore ├── Gemfile ├── Gemfile.lock ├── Rakefile ├── app │ ├── .#game_scene.rb │ ├── app_delegate.rb │ ├── arrow.rb │ ├── game_scene.rb │ ├── game_view_controller.rb │ └── screen_sizes.rb ├── readme.md ├── resources │ ├── Default-375w-667h@2x.png │ ├── Default-414w-736h@3x.png │ ├── Default-568h@2x.png │ ├── Default-667h@2x.png │ ├── Default-736h@3x.png │ ├── ball.png │ ├── explosion_particle.png │ ├── large.png │ ├── medium.png │ ├── small.png │ └── wall.png └── spec │ └── main_spec.rb ├── readme.md └── touch-event ├── .gitignore ├── Gemfile ├── Gemfile.lock ├── Rakefile ├── app ├── app_delegate.rb ├── game_scene.rb ├── game_view_controller.rb └── screen_sizes.rb ├── readme.md ├── resources ├── Default-375w-667h@2x.png ├── Default-414w-736h@3x.png ├── Default-568h@2x.png ├── Default-667h@2x.png ├── Default-736h@3x.png ├── large.png ├── medium.png ├── small.png └── square.png ├── spec └── main_spec.rb └── touch-event.gif /.gitignore: -------------------------------------------------------------------------------- 1 | /.DS_Store 2 | */profiles 3 | -------------------------------------------------------------------------------- /SpaceInvaders/.gitignore: -------------------------------------------------------------------------------- 1 | .repl_history 2 | build 3 | tags 4 | app/pixate_code.rb 5 | resources/*.nib 6 | resources/*.momd 7 | resources/*.storyboardc 8 | .DS_Store 9 | nbproject 10 | .redcar 11 | #*# 12 | *~ 13 | *.sw[po] 14 | .eprj 15 | .sass-cache 16 | .idea 17 | .dat*.* 18 | -------------------------------------------------------------------------------- /SpaceInvaders/.rubocop.yml: -------------------------------------------------------------------------------- 1 | Style/Documentation: 2 | Enabled: false 3 | 4 | Metrics/ClassLength: 5 | Enabled: false 6 | 7 | Metrics/MethodLength: 8 | Enabled: false 9 | 10 | Metrics/AbcSize: 11 | Enabled: false 12 | 13 | Style/MethodDefParentheses: 14 | Enabled: false 15 | 16 | MultilineBlockChain: 17 | Enabled: false 18 | 19 | Metrics/CyclomaticComplexity: 20 | Enabled: false 21 | 22 | Metrics/PerceivedComplexity: 23 | Enabled: false 24 | 25 | Metrics/ParameterLists: 26 | Enabled: false 27 | 28 | Style/BlockComments: 29 | Enabled: false 30 | 31 | Metrics/LineLength: 32 | Enabled: false 33 | 34 | Style/BracesAroundHashParameters: 35 | Enabled: false 36 | -------------------------------------------------------------------------------- /SpaceInvaders/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'rake' 4 | # Add your dependencies here: 5 | -------------------------------------------------------------------------------- /SpaceInvaders/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | rake (11.3.0) 5 | 6 | PLATFORMS 7 | ruby 8 | 9 | DEPENDENCIES 10 | rake 11 | 12 | BUNDLED WITH 13 | 1.13.5 14 | -------------------------------------------------------------------------------- /SpaceInvaders/Rakefile: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | $:.unshift("/Library/RubyMotion/lib") 3 | require 'motion/project/template/ios' 4 | 5 | begin 6 | require 'bundler' 7 | Bundler.require 8 | rescue LoadError 9 | end 10 | 11 | Motion::Project::App.setup do |app| 12 | app.name = 'Space Invaders' 13 | app.frameworks = %w(CoreGraphics AVFoundation UIKit QuartzCore SpriteKit Foundation AudioToolbox) 14 | app.info_plist['UIRequiresFullScreen'] = true 15 | app.device_family = [:iphone, :ipad] 16 | app.icons = ['large', 'medium', 'small'] 17 | 18 | # development 19 | app.codesign_certificate = 'iPhone Developer: Amirali Rajan' 20 | app.provisioning_profile = './profiles/Development.mobileprovision' 21 | 22 | # test 23 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 24 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 25 | # app.entitlements['beta-reports-active'] = true 26 | 27 | # production 28 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 29 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 30 | end 31 | 32 | namespace :sim do 33 | task :five do 34 | system("rake simulator device_name='iPhone 5'") 35 | end 36 | 37 | task :six do 38 | system("rake simulator device_name='iPhone 6'") 39 | end 40 | 41 | task :plus do 42 | system("rake simulator device_name='iPhone 6 Plus'") 43 | end 44 | 45 | task :ipad do 46 | system("rake simulator device_name='iPad Pro (9.7 inch)'") 47 | end 48 | 49 | task :ipadpro do 50 | system("rake simulator device_name='iPad Pro (12.9 inch)'") 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /SpaceInvaders/app/app_delegate.rb: -------------------------------------------------------------------------------- 1 | class AppDelegate 2 | def application(application, didFinishLaunchingWithOptions:launchOptions) 3 | @game_view_controller = GameViewController.new 4 | 5 | UIApplication.sharedApplication.setIdleTimerDisabled true 6 | @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds) 7 | @window.rootViewController = @game_view_controller 8 | @window.makeKeyAndVisible 9 | 10 | true 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /SpaceInvaders/app/game_scene.rb: -------------------------------------------------------------------------------- 1 | class GameScene < SKScene 2 | BULLET_SPEED = 2.5 3 | BOOST_POWER = 0.95 4 | BOOST_DRAG_PERCENTAGE = 0.95 5 | WORLD_WIDTH = UIScreen.mainScreen.bounds.size.width 6 | WORLD_HEIGHT = UIScreen.mainScreen.bounds.size.height 7 | SHIP_SIZE = WORLD_WIDTH.fdiv(14) 8 | BULLET_SIZE = SHIP_SIZE.fdiv(2) 9 | ENEMY_MOVEMENT_SPACE = 7 10 | PLAYER_SHIP_ENEMY_BULLET_CATEGORY = 2 11 | ENEMY_SHIP_PLAYER_BULLET_CATEGORY = 4 12 | PLAYER_Y_POSITION = 150 13 | INSTRUCTIONS_FONT = 17 14 | 15 | def didMoveToView view 16 | $self = self 17 | self.scaleMode = SKSceneScaleModeAspectFit 18 | physicsWorld.gravity = CGVectorMake 0, 0 19 | physicsWorld.contactDelegate = self 20 | @live_canvas = SKNode.new 21 | @dead_canvas = SKNode.new 22 | addChild @live_canvas 23 | addChild @dead_canvas 24 | @bullets = [] 25 | @enemies = [] 26 | @score_label = add_label '', WORLD_WIDTH.fdiv(2), WORLD_HEIGHT.fdiv(2), 100 27 | @instructions_label_one = add_label 'Tap hereish to move right.', 28 | WORLD_WIDTH - WORLD_WIDTH.fdiv(4), 29 | PLAYER_Y_POSITION.fdiv(2), 30 | INSTRUCTIONS_FONT 31 | @instructions_label_two = add_label 'Tap hereish to move left.', 32 | WORLD_WIDTH.fdiv(4), 33 | PLAYER_Y_POSITION.fdiv(2), 34 | INSTRUCTIONS_FONT 35 | @instructions_label_three = add_label 'Tap anywhere ABOVE the ship to shoot.', 36 | WORLD_WIDTH.fdiv(2), 37 | PLAYER_Y_POSITION + SHIP_SIZE * 1.5, 38 | INSTRUCTIONS_FONT 39 | @ship = add_sprite 'ship', 0, 0, SHIP_SIZE, PLAYER_SHIP_ENEMY_BULLET_CATEGORY 40 | reset_game 41 | end 42 | 43 | def reset_game 44 | @dx = 0 45 | @hide_instructions = false 46 | @instructions_label_one.alpha = 47 | @instructions_label_two.alpha = 48 | @instructions_label_three.alpha = 1 49 | @ship.position = CGPointMake WORLD_WIDTH.fdiv(2), PLAYER_Y_POSITION 50 | reset_enemies 51 | @time_between_enemy_bullets = 600 52 | @bullets.each(&:removeFromParent) 53 | @bullets.clear 54 | @ship_bullet && @ship_bullet.removeFromParent 55 | @ship_bullet = nil 56 | flash_score 0 57 | end 58 | 59 | def reset_enemies 60 | @enemies.each(&:removeFromParent) 61 | @enemies = (0..3).to_a.product((0..6).to_a).map do |tuple| 62 | row, column = tuple 63 | add_sprite 'enemy', 64 | (column * SHIP_SIZE) + SHIP_SIZE.fdiv(2), 65 | WORLD_HEIGHT - (row * SHIP_SIZE) - SHIP_SIZE.fdiv(2) - 40, 66 | SHIP_SIZE, 67 | ENEMY_SHIP_PLAYER_BULLET_CATEGORY 68 | end 69 | 70 | @movement_direction = 1 71 | @move_movement_direction_tick = ENEMY_MOVEMENT_SPACE 72 | end 73 | 74 | def add_sprite name, x, y, size, collision_category 75 | sprite = SKSpriteNode.spriteNodeWithTexture SKTexture.textureWithImageNamed('square.png') 76 | sprite.name = name 77 | sprite.position = CGPointMake x, y 78 | scale = size.fdiv(sprite.size.width) 79 | sprite.xScale = sprite.yScale = scale 80 | sprite.physicsBody = SKPhysicsBody.bodyWithRectangleOfSize sprite.size 81 | sprite.physicsBody.collisionBitMask = 0 82 | sprite.physicsBody.categoryBitMask = collision_category 83 | sprite.physicsBody.contactTestBitMask = collision_category 84 | sprite.alpha = 0 85 | @live_canvas.addChild sprite 86 | sprite 87 | end 88 | 89 | def add_label text, x, y, font_size 90 | label = SKLabelNode.labelNodeWithText text 91 | label.position = CGPointMake(x, y) 92 | label.fontSize = font_size 93 | addChild label 94 | label 95 | end 96 | 97 | def update _ 98 | fade_in_fade_out_labels 99 | fade_in_fade_out_sprites 100 | move_enemies 101 | generate_bullet 102 | move_bullets 103 | move_ship 104 | reset_enemies if @enemies.length.zero? 105 | end 106 | 107 | def fade_in_fade_out_labels 108 | @score_label.alpha -= 0.1 if @score_label.alpha > 0 109 | @instructions_label_one.alpha -= rand.fdiv(5) if @instructions_label_one.alpha > 0 && @hide_instructions 110 | @instructions_label_two.alpha -= rand.fdiv(5) if @instructions_label_two.alpha > 0 && @hide_instructions 111 | @instructions_label_three.alpha -= rand.fdiv(5) if @instructions_label_three.alpha > 0 && @hide_instructions 112 | end 113 | 114 | def fade_in_fade_out_sprites 115 | @live_canvas.children.find_all { |c| c.alpha < 1 }.each { |c| c.alpha += rand.fdiv(5) } 116 | @dead_canvas.children.find_all { |c| c.alpha > 0 }.each { |c| c.alpha -= rand.fdiv(5) } 117 | @dead_canvas.children.find_all { |c| c.alpha <= 0 }.each(&:removeFromParent) 118 | end 119 | 120 | def move_ship 121 | @ship.position = CGPointMake(@ship.position.x + @dx, @ship.position.y) 122 | 123 | if @ship.position.x - SHIP_SIZE.fdiv(2) < 0 124 | @ship.position = CGPointMake SHIP_SIZE.fdiv(2), @ship.position.y 125 | @dx = 0 126 | end 127 | 128 | if @ship.position.x + SHIP_SIZE.fdiv(2) > WORLD_WIDTH 129 | @ship.position = CGPointMake WORLD_WIDTH - SHIP_SIZE.fdiv(2), @ship.position.y 130 | @dx = 0 131 | end 132 | 133 | @dx *= BOOST_DRAG_PERCENTAGE 134 | 135 | @boost_direction && @dx += BOOST_POWER * @boost_direction 136 | end 137 | 138 | def touchesBegan touches, withEvent: _ 139 | @hide_instructions = true 140 | first_touch = touches.allObjects.first.locationInNode(self) 141 | if first_touch.y < PLAYER_Y_POSITION 142 | @boost_direction = 1 143 | @boost_direction = -1 if first_touch.x < WORLD_WIDTH.fdiv(2) 144 | elsif !@ship_bullet 145 | @ship_bullet = add_sprite 'ship_bullet', 146 | @ship.position.x, 147 | @ship.position.y + SHIP_SIZE.fdiv(2), 148 | BULLET_SIZE, 149 | ENEMY_SHIP_PLAYER_BULLET_CATEGORY 150 | else 151 | @instructions_label_three.text = 'You can only shoot one bullet at a time. Wait.' 152 | @instructions_label_three.alpha = 10 153 | end 154 | end 155 | 156 | def touchesEnded touches, withEvent: _ 157 | @boost_direction = nil 158 | end 159 | 160 | def move_bullets 161 | @bullets.each { |b| b.position = CGPointMake(b.position.x, b.position.y - BULLET_SPEED) } 162 | bullets_to_remove = @bullets.find_all { |b| b.position.y + BULLET_SIZE < 0 } 163 | bullets_to_remove.each(&:removeFromParent) 164 | @bullets -= bullets_to_remove 165 | return unless @ship_bullet 166 | @ship_bullet.position = CGPointMake(@ship_bullet.position.x, @ship_bullet.position.y + BULLET_SPEED) 167 | return unless @ship_bullet.position.y > WORLD_HEIGHT 168 | @ship_bullet.removeFromParent 169 | @ship_bullet = nil 170 | end 171 | 172 | def generate_bullet 173 | @fire_tick_count ||= rand(@time_between_enemy_bullets) + 10 174 | @fire_tick_count -= 1 175 | return unless @fire_tick_count <= 0 176 | @fire_tick_count = nil 177 | return if @bullets.count >= @enemies.count 178 | random_enemy = @enemies.sample 179 | @bullets << add_sprite('enemy_bullet', 180 | random_enemy.position.x, 181 | random_enemy.position.y - SHIP_SIZE.fdiv(2) - BULLET_SIZE.fdiv(2), 182 | BULLET_SIZE, 183 | PLAYER_SHIP_ENEMY_BULLET_CATEGORY) 184 | end 185 | 186 | def move_enemies 187 | @move_unit_tick_count ||= 60 188 | @move_unit_tick_count -= 1 189 | return unless @move_unit_tick_count <= 0 190 | @enemies.each do |e| 191 | e.position = CGPointMake(e.position.x + SHIP_SIZE * @movement_direction, e.position.y) 192 | end 193 | @move_movement_direction_tick -= 1 194 | @move_unit_tick_count = nil 195 | return if @move_movement_direction_tick > 0 196 | @move_movement_direction_tick = ENEMY_MOVEMENT_SPACE 197 | @movement_direction *= -1 198 | end 199 | 200 | def flash_score score 201 | @score = score 202 | @score_label.text = @score.to_s 203 | @score_label.alpha = 10 204 | end 205 | 206 | def didBeginContact contact 207 | return if !contact.bodyA.node || !contact.bodyB.node 208 | if contact.bodyA.node.name == 'ship_bullet' || contact.bodyB.node.name == 'ship_bullet' 209 | [contact.bodyA.node, contact.bodyB.node].each do |n| 210 | n.removeFromParent 211 | @dead_canvas.addChild n 212 | @enemies -= [n] 213 | n.physicsBody = nil 214 | end 215 | flash_score(@score += 1) 216 | @time_between_enemy_bullets *= 0.95 217 | @time_between_enemy_bullets = @time_between_enemy_bullets.floor 218 | @ship_bullet = nil 219 | elsif contact.bodyA.node.name == 'ship' || contact.bodyB.node.name == 'ship' 220 | reset_game 221 | end 222 | end 223 | end 224 | -------------------------------------------------------------------------------- /SpaceInvaders/app/game_view_controller.rb: -------------------------------------------------------------------------------- 1 | class GameViewController < UIViewController 2 | def viewDidLoad 3 | super 4 | @sk_view = SKView.alloc.initWithFrame CGRectMake(0, 0, UIScreen.mainScreen.bounds.size.width, UIScreen.mainScreen.bounds.size.height) 5 | self.view = @sk_view 6 | @scene = GameScene.sceneWithSize(@sk_view.frame.size) 7 | @sk_view.presentScene @scene 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /SpaceInvaders/app/top_level.rb: -------------------------------------------------------------------------------- 1 | class TopLevel 2 | def do_live_reload 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /SpaceInvaders/live_reload.rb: -------------------------------------------------------------------------------- 1 | require 'readline' 2 | 3 | def restart 4 | result = IO.popen('rake device', 'w') 5 | result.puts 'do_live_reload' 6 | result 7 | end 8 | 9 | ios_io = restart 10 | first_time = true 11 | 12 | Signal.trap('SIGUSR1') do 13 | if first_time 14 | first_time = false 15 | else 16 | repl_pid = `pgrep repl` 17 | Process.kill('INT', repl_pid.to_i) 18 | ios_io.close 19 | ios_io = restart 20 | end 21 | end 22 | 23 | `echo rerun \\"kill -30 #{Process.pid}\\" --no-notify | pbcopy` 24 | 25 | Readline.readline('Press any key to exit..', true) 26 | -------------------------------------------------------------------------------- /SpaceInvaders/readme.md: -------------------------------------------------------------------------------- 1 | # Space Invaders Clone 2 | 3 | This sample app is a Space Invaders clone. 4 | 5 | To run the application: 6 | 7 | `rake` will run the app in the iPhone 6 simulator. 8 | 9 | Here's what it looks like: 10 | 11 |

12 | 13 |

14 | 15 | This combines all the techniques learned in the previous sample apps into a game. 16 | -------------------------------------------------------------------------------- /SpaceInvaders/resources/Default-375w-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/SpaceInvaders/resources/Default-375w-667h@2x.png -------------------------------------------------------------------------------- /SpaceInvaders/resources/Default-414w-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/SpaceInvaders/resources/Default-414w-736h@3x.png -------------------------------------------------------------------------------- /SpaceInvaders/resources/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/SpaceInvaders/resources/Default-568h@2x.png -------------------------------------------------------------------------------- /SpaceInvaders/resources/Default-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/SpaceInvaders/resources/Default-667h@2x.png -------------------------------------------------------------------------------- /SpaceInvaders/resources/Default-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/SpaceInvaders/resources/Default-736h@3x.png -------------------------------------------------------------------------------- /SpaceInvaders/resources/large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/SpaceInvaders/resources/large.png -------------------------------------------------------------------------------- /SpaceInvaders/resources/medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/SpaceInvaders/resources/medium.png -------------------------------------------------------------------------------- /SpaceInvaders/resources/small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/SpaceInvaders/resources/small.png -------------------------------------------------------------------------------- /SpaceInvaders/resources/square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/SpaceInvaders/resources/square.png -------------------------------------------------------------------------------- /SpaceInvaders/space-invaders.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/SpaceInvaders/space-invaders.gif -------------------------------------------------------------------------------- /SpaceInvaders/spec/main_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Application 'sprite-kit-hello-world'" do 2 | before do 3 | @app = UIApplication.sharedApplication 4 | end 5 | 6 | it "has one window" do 7 | @app.windows.size.should == 1 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /actions/.gitignore: -------------------------------------------------------------------------------- 1 | .repl_history 2 | build 3 | tags 4 | app/pixate_code.rb 5 | resources/*.nib 6 | resources/*.momd 7 | resources/*.storyboardc 8 | .DS_Store 9 | nbproject 10 | .redcar 11 | #*# 12 | *~ 13 | *.sw[po] 14 | .eprj 15 | .sass-cache 16 | .idea 17 | .dat*.* 18 | -------------------------------------------------------------------------------- /actions/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'rake' 4 | # Add your dependencies here: 5 | -------------------------------------------------------------------------------- /actions/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | rake (11.3.0) 5 | 6 | PLATFORMS 7 | ruby 8 | 9 | DEPENDENCIES 10 | rake 11 | 12 | BUNDLED WITH 13 | 1.13.5 14 | -------------------------------------------------------------------------------- /actions/Rakefile: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | $:.unshift("/Library/RubyMotion/lib") 3 | require 'motion/project/template/ios' 4 | 5 | begin 6 | require 'bundler' 7 | Bundler.require 8 | rescue LoadError 9 | end 10 | 11 | Motion::Project::App.setup do |app| 12 | app.name = 'actions' 13 | app.frameworks = %w(CoreGraphics AVFoundation UIKit QuartzCore SpriteKit Foundation AudioToolbox) 14 | app.info_plist['UIRequiresFullScreen'] = true 15 | app.device_family = [:iphone, :ipad] 16 | app.icons = ['large', 'medium', 'small'] 17 | 18 | # development 19 | app.codesign_certificate = 'iPhone Developer: Amirali Rajan' 20 | app.provisioning_profile = './profiles/Development.mobileprovision' 21 | 22 | # test 23 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 24 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 25 | # app.entitlements['beta-reports-active'] = true 26 | 27 | # production 28 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 29 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 30 | end 31 | 32 | namespace :sim do 33 | task :five do 34 | system("rake simulator device_name='iPhone 5'") 35 | end 36 | 37 | task :six do 38 | system("rake simulator device_name='iPhone 6'") 39 | end 40 | 41 | task :plus do 42 | system("rake simulator device_name='iPhone 6 Plus'") 43 | end 44 | 45 | task :ipad do 46 | system("rake simulator device_name='iPad Pro (9.7 inch)'") 47 | end 48 | 49 | task :ipadpro do 50 | system("rake simulator device_name='iPad Pro (12.9 inch)'") 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /actions/actions.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/actions/actions.gif -------------------------------------------------------------------------------- /actions/app/app_delegate.rb: -------------------------------------------------------------------------------- 1 | class AppDelegate 2 | def application(application, didFinishLaunchingWithOptions:launchOptions) 3 | @game_view_controller = GameViewController.new 4 | 5 | UIApplication.sharedApplication.setIdleTimerDisabled true 6 | @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds) 7 | @window.rootViewController = @game_view_controller 8 | @window.makeKeyAndVisible 9 | 10 | true 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /actions/app/game_scene.rb: -------------------------------------------------------------------------------- 1 | class GameScene < SKScene 2 | include ScreenSizes 3 | 4 | def didMoveToView view 5 | self.scaleMode = SKSceneScaleModeAspectFit 6 | self.backgroundColor = UIColor.whiteColor 7 | @camera = SKNode.new 8 | @camera.position = CGPointMake(0, 0) 9 | addChild @camera 10 | @button_2 = add_sprite(190, 60, 'button.png', 'button 2') 11 | particle_2 12 | end 13 | 14 | def touchesBegan touches, withEvent: _ 15 | node = nodeAtPoint(touches.allObjects.first.locationInNode(self)) 16 | case node.name 17 | when 'button 2' 18 | shake 19 | end 20 | end 21 | 22 | def add_sprite x, y, path, name 23 | texture = SKTexture.textureWithImageNamed path 24 | sprite = SKSpriteNode.spriteNodeWithTexture texture 25 | sprite.position = CGPointMake x, y 26 | sprite.name = name 27 | @camera.addChild sprite 28 | sprite 29 | end 30 | 31 | def shake 32 | randomActions = [] 33 | direction_x = 1 34 | direction = [1, -1] 35 | how_many = 10 36 | max_distance = 100 37 | duration = 0.25 38 | 39 | how_many.times do |i| 40 | from = max_distance - (max_distance.fdiv(how_many) * i) 41 | to = from + 10 42 | randX = @camera.position.x + (rand(from..to) * direction_x) 43 | randY = @camera.position.y + (rand(from..to) * direction.sample) 44 | action = SKAction.moveTo(CGPointMake(randX, randY), duration: (duration).fdiv(how_many)) 45 | randomActions << action 46 | direction_x *= -1 47 | end 48 | 49 | randomActions << SKAction.moveTo(CGPointMake(0, 0), duration: (duration).fdiv(how_many)) 50 | 51 | rep = SKAction.sequence(randomActions) 52 | 53 | @camera.runAction(rep) 54 | end 55 | 56 | def particle_2 57 | particle = SKEmitterNode.alloc.init 58 | particle.setParticleTexture SKTexture.textureWithImageNamed('square.png') 59 | particle.setParticleBirthRate 50 60 | particle.setEmissionAngleRange 360 61 | particle.setParticleSpeed 30 62 | particle.setParticleLifetime 10 63 | particle.setParticleLifetimeRange 20 64 | particle.setParticleAlphaSpeed(-0.5) 65 | particle.setPosition CGPointMake(device_screen_width.fdiv(2), device_screen_height.fdiv(2)) 66 | particle.setParticleRotation 0.1 67 | particle.setParticleRotationRange 6 68 | particle.setParticlePositionRange CGVectorMake(120, 120) 69 | particle.setParticleBlendMode SKBlendModeAlpha 70 | @camera.addChild particle 71 | end 72 | 73 | def update currentTime 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /actions/app/game_view_controller.rb: -------------------------------------------------------------------------------- 1 | class GameViewController < UIViewController 2 | include ScreenSizes 3 | 4 | def viewDidLoad 5 | super 6 | 7 | self.view = sk_view 8 | 9 | @scene = GameScene.sceneWithSize(sk_view.frame.size) 10 | sk_view.presentScene @scene 11 | end 12 | 13 | def sk_view 14 | @sk_view ||= SKView.alloc.initWithFrame screen_rect 15 | end 16 | 17 | def prefersStatusBarHidden 18 | true 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /actions/app/screen_sizes.rb: -------------------------------------------------------------------------------- 1 | module ScreenSizes 2 | def device_screen_width 3 | UIScreen.mainScreen.bounds.size.width 4 | end 5 | 6 | def device_screen_height 7 | UIScreen.mainScreen.bounds.size.height 8 | end 9 | 10 | def screen_rect 11 | CGRectMake(0, 0, device_screen_width, device_screen_height) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /actions/readme.md: -------------------------------------------------------------------------------- 1 | # Actions 2 | 3 | This sample app shows how to use declarative animations (`SKActions`) 4 | to create a camera shake. 5 | 6 | To run the application: 7 | 8 | `rake` will run the app in the iPhone 6 simulator. 9 | 10 | Here's what it looks like: 11 | 12 |

13 | 14 |

15 | 16 | High level project structure: 17 | 18 | - The camera shake will occur when the button at the button is 19 | pressed. 20 | - All nodes are contained in a top level `SKNode` called `@camera`. 21 | - The `shake` function alternates shaking in the x direction (denoted 22 | by `direction_x`. 23 | - The number of shakes is denoted by the `how_many` variable. 24 | - The random distance the camera moves lessens with every shake, which 25 | is calculated and stored in the `from` and `to` variables. 26 | - An array of `SKAction`s are collected with a random x and random y 27 | (denoted by the `randX` and `randY` variables). 28 | - A final `SKAction` is applied to the camera which places the node 29 | back at postion (0, 0). 30 | - The sequence of `SKAction`'s are applied to `@camera` using the 31 | `runAction` function. 32 | -------------------------------------------------------------------------------- /actions/resources/Default-375w-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/actions/resources/Default-375w-667h@2x.png -------------------------------------------------------------------------------- /actions/resources/Default-414w-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/actions/resources/Default-414w-736h@3x.png -------------------------------------------------------------------------------- /actions/resources/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/actions/resources/Default-568h@2x.png -------------------------------------------------------------------------------- /actions/resources/Default-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/actions/resources/Default-667h@2x.png -------------------------------------------------------------------------------- /actions/resources/Default-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/actions/resources/Default-736h@3x.png -------------------------------------------------------------------------------- /actions/resources/ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/actions/resources/ball.png -------------------------------------------------------------------------------- /actions/resources/button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/actions/resources/button.png -------------------------------------------------------------------------------- /actions/resources/large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/actions/resources/large.png -------------------------------------------------------------------------------- /actions/resources/medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/actions/resources/medium.png -------------------------------------------------------------------------------- /actions/resources/small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/actions/resources/small.png -------------------------------------------------------------------------------- /actions/resources/square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/actions/resources/square.png -------------------------------------------------------------------------------- /actions/spec/main_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Application 'sprite-kit-hello-world'" do 2 | before do 3 | @app = UIApplication.sharedApplication 4 | end 5 | 6 | it "has one window" do 7 | @app.windows.size.should == 1 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /animated-sprite/.gitignore: -------------------------------------------------------------------------------- 1 | .repl_history 2 | build 3 | tags 4 | app/pixate_code.rb 5 | resources/*.nib 6 | resources/*.momd 7 | resources/*.storyboardc 8 | .DS_Store 9 | nbproject 10 | .redcar 11 | #*# 12 | *~ 13 | *.sw[po] 14 | .eprj 15 | .sass-cache 16 | .idea 17 | .dat*.* 18 | -------------------------------------------------------------------------------- /animated-sprite/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'rake' 4 | # Add your dependencies here: 5 | -------------------------------------------------------------------------------- /animated-sprite/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | rake (11.3.0) 5 | 6 | PLATFORMS 7 | ruby 8 | 9 | DEPENDENCIES 10 | rake 11 | 12 | BUNDLED WITH 13 | 1.13.5 14 | -------------------------------------------------------------------------------- /animated-sprite/Rakefile: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | $:.unshift("/Library/RubyMotion/lib") 3 | require 'motion/project/template/ios' 4 | 5 | begin 6 | require 'bundler' 7 | Bundler.require 8 | rescue LoadError 9 | end 10 | 11 | Motion::Project::App.setup do |app| 12 | app.name = 'animated-sprite' 13 | app.frameworks = %w(CoreGraphics AVFoundation UIKit QuartzCore SpriteKit Foundation AudioToolbox) 14 | app.info_plist['UIRequiresFullScreen'] = true 15 | app.device_family = [:iphone, :ipad] 16 | app.icons = ['large', 'medium', 'small'] 17 | 18 | # development 19 | app.codesign_certificate = 'iPhone Developer: Amirali Rajan' 20 | app.provisioning_profile = './profiles/Development.mobileprovision' 21 | 22 | # test 23 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 24 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 25 | # app.entitlements['beta-reports-active'] = true 26 | 27 | # production 28 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 29 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 30 | end 31 | 32 | namespace :sim do 33 | task :five do 34 | system("rake simulator device_name='iPhone 5'") 35 | end 36 | 37 | task :six do 38 | system("rake simulator device_name='iPhone 6'") 39 | end 40 | 41 | task :plus do 42 | system("rake simulator device_name='iPhone 6 Plus'") 43 | end 44 | 45 | task :ipad do 46 | system("rake simulator device_name='iPad Pro (9.7 inch)'") 47 | end 48 | 49 | task :ipadpro do 50 | system("rake simulator device_name='iPad Pro (12.9 inch)'") 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /animated-sprite/animated-sprite.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/animated-sprite/animated-sprite.gif -------------------------------------------------------------------------------- /animated-sprite/app/app_delegate.rb: -------------------------------------------------------------------------------- 1 | class AppDelegate 2 | def application(application, didFinishLaunchingWithOptions:launchOptions) 3 | @game_view_controller = GameViewController.new 4 | 5 | UIApplication.sharedApplication.setIdleTimerDisabled true 6 | @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds) 7 | @window.rootViewController = @game_view_controller 8 | @window.makeKeyAndVisible 9 | 10 | true 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /animated-sprite/app/game_scene.rb: -------------------------------------------------------------------------------- 1 | class GameScene < SKScene 2 | include ScreenSizes 3 | 4 | def didMoveToView view 5 | self.scaleMode = SKSceneScaleModeAspectFit 6 | self.backgroundColor = UIColor.whiteColor 7 | @flying_thingy = add_sprite( 8 | device_screen_width.fdiv(2), 9 | device_screen_height.fdiv(2), 10 | "sprite_1.png", 11 | "flying thingy") 12 | @flying_thingy.xScale = 0.5 13 | @flying_thingy.yScale = 0.5 14 | @animation = SKAction.animateWithTextures( 15 | [ 16 | texture("sprite_1.png"), 17 | texture("sprite_2.png"), 18 | texture("sprite_3.png"), 19 | texture("sprite_4.png"), 20 | texture("sprite_5.png") 21 | ], 22 | timePerFrame: 0.1) 23 | @flying_thingy.runAction(SKAction.repeatActionForever(@animation)) 24 | end 25 | 26 | def texture path 27 | SKTexture.textureWithImageNamed(path) 28 | end 29 | 30 | def add_sprite x, y, path, name 31 | texture = SKTexture.textureWithImageNamed path 32 | sprite = SKSpriteNode.spriteNodeWithTexture texture 33 | sprite.position = CGPointMake x, y 34 | sprite.name = name 35 | addChild sprite 36 | sprite 37 | end 38 | 39 | def update currentTime 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /animated-sprite/app/game_view_controller.rb: -------------------------------------------------------------------------------- 1 | class GameViewController < UIViewController 2 | include ScreenSizes 3 | 4 | def viewDidLoad 5 | super 6 | 7 | self.view = sk_view 8 | 9 | @scene = GameScene.sceneWithSize(sk_view.frame.size) 10 | sk_view.presentScene @scene 11 | end 12 | 13 | def sk_view 14 | @sk_view ||= SKView.alloc.initWithFrame screen_rect 15 | end 16 | 17 | def prefersStatusBarHidden 18 | true 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /animated-sprite/app/screen_sizes.rb: -------------------------------------------------------------------------------- 1 | module ScreenSizes 2 | def device_screen_width 3 | UIScreen.mainScreen.bounds.size.width 4 | end 5 | 6 | def device_screen_height 7 | UIScreen.mainScreen.bounds.size.height 8 | end 9 | 10 | def screen_rect 11 | CGRectMake(0, 0, device_screen_width, device_screen_height) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /animated-sprite/readme.md: -------------------------------------------------------------------------------- 1 | # Animating a Sprite 2 | 3 | This sample app shows how to use declarative animations (`SKActions`) 4 | to animate a sprite as if it were moving. 5 | 6 | To run the application: 7 | 8 | `rake` will run the app in the iPhone 6 simulator. 9 | 10 | Here's what it looks like: 11 | 12 |

13 | 14 |

15 | 16 | High level project structure: 17 | 18 | - This is very similar to the `actions` sample code. 19 | - Each sprite is loaded into an array. 20 | - The `SKAction.animateWithTextures` is used to enumerate the sprites. 21 | - The action is repeated forever using `SKAction.repeatActionForever`. 22 | -------------------------------------------------------------------------------- /animated-sprite/resources/Default-375w-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/animated-sprite/resources/Default-375w-667h@2x.png -------------------------------------------------------------------------------- /animated-sprite/resources/Default-414w-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/animated-sprite/resources/Default-414w-736h@3x.png -------------------------------------------------------------------------------- /animated-sprite/resources/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/animated-sprite/resources/Default-568h@2x.png -------------------------------------------------------------------------------- /animated-sprite/resources/Default-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/animated-sprite/resources/Default-667h@2x.png -------------------------------------------------------------------------------- /animated-sprite/resources/Default-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/animated-sprite/resources/Default-736h@3x.png -------------------------------------------------------------------------------- /animated-sprite/resources/ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/animated-sprite/resources/ball.png -------------------------------------------------------------------------------- /animated-sprite/resources/button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/animated-sprite/resources/button.png -------------------------------------------------------------------------------- /animated-sprite/resources/large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/animated-sprite/resources/large.png -------------------------------------------------------------------------------- /animated-sprite/resources/medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/animated-sprite/resources/medium.png -------------------------------------------------------------------------------- /animated-sprite/resources/small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/animated-sprite/resources/small.png -------------------------------------------------------------------------------- /animated-sprite/resources/sprite_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/animated-sprite/resources/sprite_1.png -------------------------------------------------------------------------------- /animated-sprite/resources/sprite_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/animated-sprite/resources/sprite_2.png -------------------------------------------------------------------------------- /animated-sprite/resources/sprite_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/animated-sprite/resources/sprite_3.png -------------------------------------------------------------------------------- /animated-sprite/resources/sprite_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/animated-sprite/resources/sprite_4.png -------------------------------------------------------------------------------- /animated-sprite/resources/sprite_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/animated-sprite/resources/sprite_5.png -------------------------------------------------------------------------------- /animated-sprite/resources/square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/animated-sprite/resources/square.png -------------------------------------------------------------------------------- /animated-sprite/spec/main_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Application 'sprite-kit-hello-world'" do 2 | before do 3 | @app = UIApplication.sharedApplication 4 | end 5 | 6 | it "has one window" do 7 | @app.windows.size.should == 1 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /collision-detection/.gitignore: -------------------------------------------------------------------------------- 1 | .repl_history 2 | build 3 | tags 4 | app/pixate_code.rb 5 | resources/*.nib 6 | resources/*.momd 7 | resources/*.storyboardc 8 | .DS_Store 9 | nbproject 10 | .redcar 11 | #*# 12 | *~ 13 | *.sw[po] 14 | .eprj 15 | .sass-cache 16 | .idea 17 | .dat*.* 18 | -------------------------------------------------------------------------------- /collision-detection/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'rake' 4 | # Add your dependencies here: 5 | -------------------------------------------------------------------------------- /collision-detection/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | rake (11.3.0) 5 | 6 | PLATFORMS 7 | ruby 8 | 9 | DEPENDENCIES 10 | rake 11 | 12 | BUNDLED WITH 13 | 1.13.5 14 | -------------------------------------------------------------------------------- /collision-detection/Rakefile: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | $:.unshift("/Library/RubyMotion/lib") 3 | require 'motion/project/template/ios' 4 | 5 | begin 6 | require 'bundler' 7 | Bundler.require 8 | rescue LoadError 9 | end 10 | 11 | Motion::Project::App.setup do |app| 12 | app.name = 'collision-detection' 13 | app.frameworks = %w(CoreGraphics AVFoundation UIKit QuartzCore SpriteKit Foundation AudioToolbox) 14 | app.info_plist['UIRequiresFullScreen'] = true 15 | app.device_family = [:iphone, :ipad] 16 | app.icons = ['large', 'medium', 'small'] 17 | 18 | # development 19 | app.codesign_certificate = 'iPhone Developer: Amirali Rajan' 20 | app.provisioning_profile = './profiles/Development.mobileprovision' 21 | 22 | # test 23 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 24 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 25 | # app.entitlements['beta-reports-active'] = true 26 | 27 | # production 28 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 29 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 30 | end 31 | 32 | namespace :sim do 33 | task :five do 34 | system("rake simulator device_name='iPhone 5'") 35 | end 36 | 37 | task :six do 38 | system("rake simulator device_name='iPhone 6'") 39 | end 40 | 41 | task :plus do 42 | system("rake simulator device_name='iPhone 6 Plus'") 43 | end 44 | 45 | task :ipad do 46 | system("rake simulator device_name='iPad Pro (9.7 inch)'") 47 | end 48 | 49 | task :ipadpro do 50 | system("rake simulator device_name='iPad Pro (12.9 inch)'") 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /collision-detection/app/app_delegate.rb: -------------------------------------------------------------------------------- 1 | class AppDelegate 2 | def application(application, didFinishLaunchingWithOptions:launchOptions) 3 | @game_view_controller = GameViewController.new 4 | 5 | UIApplication.sharedApplication.setIdleTimerDisabled true 6 | @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds) 7 | @window.rootViewController = @game_view_controller 8 | @window.makeKeyAndVisible 9 | 10 | true 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /collision-detection/app/game_scene.rb: -------------------------------------------------------------------------------- 1 | class GameScene < SKScene 2 | include ScreenSizes 3 | 4 | def didMoveToView view 5 | self.scaleMode = SKSceneScaleModeAspectFit 6 | self.backgroundColor = UIColor.whiteColor 7 | self.physicsWorld.gravity = CGVectorMake(0, 0) 8 | self.physicsWorld.contactDelegate = self 9 | self.view.showsPhysics = true 10 | 11 | @ball = add_sprite(device_screen_width.fdiv(2), 12 | 60, 13 | 'ball.png', 14 | 'circle') 15 | 16 | @ball.physicsBody = SKPhysicsBody.bodyWithCircleOfRadius(20) 17 | @ball.physicsBody.dynamic = true 18 | @ball.physicsBody.categoryBitMask = 2 19 | @ball.physicsBody.contactTestBitMask = 4 20 | @ball.physicsBody.collisionBitMask = 0 21 | 22 | @wall = add_sprite(device_screen_width.fdiv(2), 23 | device_screen_height.fdiv(2), 24 | 'wall.png', 25 | 'wall') 26 | 27 | @wall.physicsBody = SKPhysicsBody.bodyWithRectangleOfSize CGSizeMake(500, 35) 28 | 29 | @wall.physicsBody.dynamic = true 30 | @wall.physicsBody.categoryBitMask = 4 31 | @wall.physicsBody.contactTestBitMask = 2 32 | @wall.physicsBody.collisionBitMask = 0 33 | end 34 | 35 | def init_explosion 36 | @explosion = SKEmitterNode.alloc.init 37 | @explosion.setParticleTexture SKTexture.textureWithImageNamed('explosion_particle.png') 38 | @explosion.setNumParticlesToEmit 200 39 | @explosion.setParticleBirthRate 450 40 | @explosion.setEmissionAngleRange 360 41 | @explosion.setParticleSpeed 1000 42 | @explosion.setParticleLifetimeRange 0.5 43 | @explosion.setParticleAlphaSpeed(-0.5) 44 | @explosion.setPosition CGPointMake(0, 0) 45 | @explosion.setParticleRotation 0.1 46 | @explosion.setParticleRotationRange 6 47 | @explosion.setParticlePositionRange CGVectorMake(10, 10) 48 | @explosion.setParticleBlendMode SKBlendModeAlpha 49 | @ball.addChild @explosion 50 | end 51 | 52 | def add_sprite x, y, path, name 53 | texture = SKTexture.textureWithImageNamed path 54 | sprite = SKSpriteNode.spriteNodeWithTexture texture 55 | sprite.position = CGPointMake x, y 56 | sprite.name = name 57 | addChild sprite 58 | sprite 59 | end 60 | 61 | def update currentTime 62 | @ball_direction ||= 1 63 | 64 | if @ball.position.y > device_screen_height || @ball.position.y < 0 65 | @ball_direction = @ball_direction * -1 66 | end 67 | 68 | @ball.position = CGPointMake( 69 | @ball.position.x, 70 | (@ball.position.y) + 5 * @ball_direction 71 | ) 72 | end 73 | 74 | def didBeginContact _ 75 | if @explosion 76 | @explosion.resetSimulation 77 | else 78 | init_explosion 79 | end 80 | end 81 | end 82 | -------------------------------------------------------------------------------- /collision-detection/app/game_view_controller.rb: -------------------------------------------------------------------------------- 1 | class GameViewController < UIViewController 2 | include ScreenSizes 3 | 4 | def viewDidLoad 5 | super 6 | 7 | self.view = sk_view 8 | 9 | @scene = GameScene.sceneWithSize(sk_view.frame.size) 10 | sk_view.presentScene @scene 11 | end 12 | 13 | def sk_view 14 | @sk_view ||= SKView.alloc.initWithFrame screen_rect 15 | end 16 | 17 | def prefersStatusBarHidden 18 | true 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /collision-detection/app/screen_sizes.rb: -------------------------------------------------------------------------------- 1 | module ScreenSizes 2 | def device_screen_width 3 | UIScreen.mainScreen.bounds.size.width 4 | end 5 | 6 | def device_screen_height 7 | UIScreen.mainScreen.bounds.size.height 8 | end 9 | 10 | def screen_rect 11 | CGRectMake(0, 0, device_screen_width, device_screen_height) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /collision-detection/collision-detection.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/collision-detection/collision-detection.gif -------------------------------------------------------------------------------- /collision-detection/readme.md: -------------------------------------------------------------------------------- 1 | # Collision Detection 2 | 3 | This sample app shows how to set up a physics body and apply collision 4 | detection to sprites. 5 | 6 | To run the application: 7 | 8 | `rake` will run the app in the iPhone 6 simulator. 9 | 10 | Here's what it looks like: 11 | 12 |

13 | 14 |

15 | 16 | High level structure: 17 | 18 | - In `didMoveToView`, `gravity` is removed and a `contactDelegate` is 19 | set to `self`. 20 | - The `@ball` is giving a `categoryBitMask`, and a 21 | `contactTestBitMask`. 22 | - The `@wall` is given the opposite `categoryBitMask`, and a 23 | `contactTestBitMask`. 24 | - The `@ball` and `@wall` are each given a `physicsBody` via apis 25 | provide by `SKPhysicsBody`. 26 | - During the `update` loop, the `@ball` is moved up and down within 27 | the bounds of the screen. 28 | - The `didBeginContact` method is called whenever a collision occurs 29 | (I do a particle effect whenever a collision occurs). 30 | -------------------------------------------------------------------------------- /collision-detection/resources/Default-375w-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/collision-detection/resources/Default-375w-667h@2x.png -------------------------------------------------------------------------------- /collision-detection/resources/Default-414w-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/collision-detection/resources/Default-414w-736h@3x.png -------------------------------------------------------------------------------- /collision-detection/resources/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/collision-detection/resources/Default-568h@2x.png -------------------------------------------------------------------------------- /collision-detection/resources/Default-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/collision-detection/resources/Default-667h@2x.png -------------------------------------------------------------------------------- /collision-detection/resources/Default-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/collision-detection/resources/Default-736h@3x.png -------------------------------------------------------------------------------- /collision-detection/resources/ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/collision-detection/resources/ball.png -------------------------------------------------------------------------------- /collision-detection/resources/explosion_particle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/collision-detection/resources/explosion_particle.png -------------------------------------------------------------------------------- /collision-detection/resources/large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/collision-detection/resources/large.png -------------------------------------------------------------------------------- /collision-detection/resources/medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/collision-detection/resources/medium.png -------------------------------------------------------------------------------- /collision-detection/resources/small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/collision-detection/resources/small.png -------------------------------------------------------------------------------- /collision-detection/resources/wall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/collision-detection/resources/wall.png -------------------------------------------------------------------------------- /collision-detection/spec/main_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Application 'sprite-kit-hello-world'" do 2 | before do 3 | @app = UIApplication.sharedApplication 4 | end 5 | 6 | it "has one window" do 7 | @app.windows.size.should == 1 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /create-sprite/.gitignore: -------------------------------------------------------------------------------- 1 | .repl_history 2 | build 3 | tags 4 | app/pixate_code.rb 5 | resources/*.nib 6 | resources/*.momd 7 | resources/*.storyboardc 8 | .DS_Store 9 | nbproject 10 | .redcar 11 | #*# 12 | *~ 13 | *.sw[po] 14 | .eprj 15 | .sass-cache 16 | .idea 17 | .dat*.* 18 | -------------------------------------------------------------------------------- /create-sprite/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'rake' 4 | # Add your dependencies here: 5 | -------------------------------------------------------------------------------- /create-sprite/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | rake (11.3.0) 5 | 6 | PLATFORMS 7 | ruby 8 | 9 | DEPENDENCIES 10 | rake 11 | 12 | BUNDLED WITH 13 | 1.13.5 14 | -------------------------------------------------------------------------------- /create-sprite/Rakefile: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | $:.unshift("/Library/RubyMotion/lib") 3 | require 'motion/project/template/ios' 4 | 5 | begin 6 | require 'bundler' 7 | Bundler.require 8 | rescue LoadError 9 | end 10 | 11 | Motion::Project::App.setup do |app| 12 | app.name = 'create-sprite' 13 | app.frameworks = %w(CoreGraphics AVFoundation UIKit QuartzCore SpriteKit Foundation AudioToolbox) 14 | app.info_plist['UIRequiresFullScreen'] = true 15 | app.device_family = [:iphone, :ipad] 16 | app.icons = ['large', 'medium', 'small'] 17 | 18 | # development 19 | app.codesign_certificate = 'iPhone Developer: Amirali Rajan' 20 | app.provisioning_profile = './profiles/Development.mobileprovision' 21 | 22 | # test 23 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 24 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 25 | # app.entitlements['beta-reports-active'] = true 26 | 27 | # production 28 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 29 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 30 | end 31 | 32 | namespace :sim do 33 | task :five do 34 | system("rake simulator device_name='iPhone 5'") 35 | end 36 | 37 | task :six do 38 | system("rake simulator device_name='iPhone 6'") 39 | end 40 | 41 | task :plus do 42 | system("rake simulator device_name='iPhone 6 Plus'") 43 | end 44 | 45 | task :ipad do 46 | system("rake simulator device_name='iPad Pro (9.7 inch)'") 47 | end 48 | 49 | task :ipadpro do 50 | system("rake simulator device_name='iPad Pro (12.9 inch)'") 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /create-sprite/app/app_delegate.rb: -------------------------------------------------------------------------------- 1 | class AppDelegate 2 | def application(application, didFinishLaunchingWithOptions:launchOptions) 3 | @game_view_controller = GameViewController.new 4 | 5 | UIApplication.sharedApplication.setIdleTimerDisabled true 6 | @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds) 7 | @window.rootViewController = @game_view_controller 8 | @window.makeKeyAndVisible 9 | 10 | true 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /create-sprite/app/game_scene.rb: -------------------------------------------------------------------------------- 1 | class GameScene < SKScene 2 | include ScreenSizes 3 | 4 | def didMoveToView view 5 | self.scaleMode = SKSceneScaleModeAspectFit 6 | self.backgroundColor = UIColor.whiteColor 7 | @square = add_sprite device_screen_width.fdiv(2), 8 | device_screen_height.fdiv(2), 9 | 'square.png' 10 | end 11 | 12 | def add_sprite x, y, path 13 | texture = SKTexture.textureWithImageNamed path 14 | sprite = SKSpriteNode.spriteNodeWithTexture texture 15 | sprite.position = CGPointMake x, y 16 | addChild sprite 17 | sprite 18 | end 19 | 20 | def update currentTime 21 | @square.zRotation += 0.1 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /create-sprite/app/game_view_controller.rb: -------------------------------------------------------------------------------- 1 | class GameViewController < UIViewController 2 | include ScreenSizes 3 | 4 | def viewDidLoad 5 | super 6 | 7 | self.view = sk_view 8 | 9 | @scene = GameScene.sceneWithSize(sk_view.frame.size) 10 | sk_view.presentScene @scene 11 | end 12 | 13 | def sk_view 14 | @sk_view ||= SKView.alloc.initWithFrame screen_rect 15 | end 16 | 17 | def prefersStatusBarHidden 18 | true 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /create-sprite/app/screen_sizes.rb: -------------------------------------------------------------------------------- 1 | module ScreenSizes 2 | def device_screen_width 3 | UIScreen.mainScreen.bounds.size.width 4 | end 5 | 6 | def device_screen_height 7 | UIScreen.mainScreen.bounds.size.height 8 | end 9 | 10 | def screen_rect 11 | CGRectMake(0, 0, device_screen_width, device_screen_height) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /create-sprite/create-sprite.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/create-sprite/create-sprite.gif -------------------------------------------------------------------------------- /create-sprite/readme.md: -------------------------------------------------------------------------------- 1 | # Create a Single Sprite 2 | 3 | This sample app shows how to create a single sprite and make it spin. 4 | 5 | To run the application: 6 | 7 | `rake` will run the app in the iPhone 6 simulator. 8 | 9 | Here's what it looks like: 10 | 11 |

12 | 13 |

14 | 15 | High level structure: 16 | 17 | - Sprites are created using `SKSpriteNode`. 18 | - Sprite textures are located in the `resources` directory. 19 | - There is a property on `SKSpriteNode` called `zRotation` (radians) which you 20 | can use to turn a sprite. 21 | - The sprite is turned within the `update` method. 22 | -------------------------------------------------------------------------------- /create-sprite/resources/Default-375w-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/create-sprite/resources/Default-375w-667h@2x.png -------------------------------------------------------------------------------- /create-sprite/resources/Default-414w-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/create-sprite/resources/Default-414w-736h@3x.png -------------------------------------------------------------------------------- /create-sprite/resources/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/create-sprite/resources/Default-568h@2x.png -------------------------------------------------------------------------------- /create-sprite/resources/Default-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/create-sprite/resources/Default-667h@2x.png -------------------------------------------------------------------------------- /create-sprite/resources/Default-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/create-sprite/resources/Default-736h@3x.png -------------------------------------------------------------------------------- /create-sprite/resources/large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/create-sprite/resources/large.png -------------------------------------------------------------------------------- /create-sprite/resources/medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/create-sprite/resources/medium.png -------------------------------------------------------------------------------- /create-sprite/resources/small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/create-sprite/resources/small.png -------------------------------------------------------------------------------- /create-sprite/resources/square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/create-sprite/resources/square.png -------------------------------------------------------------------------------- /create-sprite/spec/main_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Application 'sprite-kit-hello-world'" do 2 | before do 3 | @app = UIApplication.sharedApplication 4 | end 5 | 6 | it "has one window" do 7 | @app.windows.size.should == 1 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /hello-world/.gitignore: -------------------------------------------------------------------------------- 1 | .repl_history 2 | build 3 | tags 4 | app/pixate_code.rb 5 | resources/*.nib 6 | resources/*.momd 7 | resources/*.storyboardc 8 | .DS_Store 9 | nbproject 10 | .redcar 11 | #*# 12 | *~ 13 | *.sw[po] 14 | .eprj 15 | .sass-cache 16 | .idea 17 | .dat*.* 18 | -------------------------------------------------------------------------------- /hello-world/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'rake' 4 | # Add your dependencies here: 5 | -------------------------------------------------------------------------------- /hello-world/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | rake (11.3.0) 5 | 6 | PLATFORMS 7 | ruby 8 | 9 | DEPENDENCIES 10 | rake 11 | 12 | BUNDLED WITH 13 | 1.13.5 14 | -------------------------------------------------------------------------------- /hello-world/Rakefile: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | $:.unshift("/Library/RubyMotion/lib") 3 | require 'motion/project/template/ios' 4 | 5 | begin 6 | require 'bundler' 7 | Bundler.require 8 | rescue LoadError 9 | end 10 | 11 | Motion::Project::App.setup do |app| 12 | app.name = 'hello-world' 13 | app.frameworks = %w(CoreGraphics AVFoundation UIKit QuartzCore SpriteKit Foundation AudioToolbox) 14 | app.info_plist['UIRequiresFullScreen'] = true 15 | app.device_family = [:iphone, :ipad] 16 | app.icons = ['large', 'medium', 'small'] 17 | 18 | # development 19 | app.codesign_certificate = 'iPhone Developer: Amirali Rajan' 20 | app.provisioning_profile = './profiles/Development.mobileprovision' 21 | 22 | # test 23 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 24 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 25 | # app.entitlements['beta-reports-active'] = true 26 | 27 | # production 28 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 29 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 30 | end 31 | 32 | namespace :sim do 33 | task :five do 34 | system("rake simulator device_name='iPhone 5'") 35 | end 36 | 37 | task :six do 38 | system("rake simulator device_name='iPhone 6'") 39 | end 40 | 41 | task :plus do 42 | system("rake simulator device_name='iPhone 6 Plus'") 43 | end 44 | 45 | task :ipad do 46 | system("rake simulator device_name='iPad Pro (9.7 inch)'") 47 | end 48 | 49 | task :ipadpro do 50 | system("rake simulator device_name='iPad Pro (12.9 inch)'") 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /hello-world/app/app_delegate.rb: -------------------------------------------------------------------------------- 1 | class AppDelegate 2 | def application(application, didFinishLaunchingWithOptions:launchOptions) 3 | @game_view_controller = GameViewController.new 4 | 5 | UIApplication.sharedApplication.setIdleTimerDisabled true 6 | @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds) 7 | @window.rootViewController = @game_view_controller 8 | @window.makeKeyAndVisible 9 | 10 | true 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /hello-world/app/game_scene.rb: -------------------------------------------------------------------------------- 1 | class GameScene < SKScene 2 | def didMoveToView view 3 | self.scaleMode = SKSceneScaleModeAspectFit 4 | self.backgroundColor = UIColor.whiteColor 5 | @time_label = add_label(10, 10) 6 | end 7 | 8 | def add_label x, y 9 | label = SKLabelNode.labelNodeWithText '0' 10 | label.position = CGPointMake(x, y) 11 | label.fontColor = UIColor.blackColor 12 | label.fontSize = 15 13 | label.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeLeft 14 | label.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter 15 | label.zPosition = 100 16 | label.fontName = 'Courier New' 17 | addChild label 18 | label 19 | end 20 | 21 | def update currentTime 22 | @time_label.text = "#{currentTime}" 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /hello-world/app/game_view_controller.rb: -------------------------------------------------------------------------------- 1 | class GameViewController < UIViewController 2 | def viewDidLoad 3 | super 4 | 5 | self.view = sk_view 6 | 7 | @scene = GameScene.sceneWithSize(sk_view.frame.size) 8 | sk_view.presentScene @scene 9 | end 10 | 11 | def sk_view 12 | @sk_view ||= SKView.alloc.initWithFrame screen_rect 13 | end 14 | 15 | def prefersStatusBarHidden 16 | true 17 | end 18 | 19 | def device_screen_width 20 | UIScreen.mainScreen.bounds.size.width 21 | end 22 | 23 | def device_screen_height 24 | UIScreen.mainScreen.bounds.size.height 25 | end 26 | 27 | def screen_rect 28 | CGRectMake(0, 0, device_screen_width, device_screen_height) 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /hello-world/hello-world.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/hello-world/hello-world.gif -------------------------------------------------------------------------------- /hello-world/readme.md: -------------------------------------------------------------------------------- 1 | # Sprite Kit Hello World 2 | 3 | SpriteKit is a framework created by Apple specifically designed to 4 | build 2D games. 5 | 6 | This is a really really simple applications that shows how to display 7 | an `SKScene` (`SpriteKit` scene) with an update loop (where all the 8 | work is done). Inside of this loop, an `SKLabelNode` is updated with 9 | the `currentTime`. 10 | 11 | To run the application: 12 | 13 | `rake` will run the app in the iPhone 6 simulator. 14 | 15 | Here's what it looks like: 16 | 17 |

18 | 19 |

20 | 21 | I've added a couple of helper rake tasks to run on different types of 22 | devices, but keep in mind that the simulators are _not_ a replacement 23 | for testing on a real device (_especially_ for games): 24 | 25 | - `rake sim:five` 26 | - `rake sim:six` 27 | - `rake sim:plus` 28 | - `rake sim:ipad` 29 | - `rake sim:ipadpro` 30 | 31 | Feel free to create your own aliases in the `Rakefile`. If any of the 32 | rake tasks above don't work: 33 | 34 | - Run `rake`. 35 | - When the simulator starts up, click Hardware->Device->iOS 10.0. 36 | - You'll see a list of simulator names there. You may have to use 37 | XCode to download new simulators. 38 | - You can run any of the simulators by running: 39 | 40 | ``` 41 | rake simulator device_name='THE SIMULATOR NAME' 42 | ``` 43 | 44 | High level structure: 45 | 46 | - All code is located in the `app` folder. 47 | - Icons and splash screens are located in the `resources`. 48 | - `app_delegate.rb` is the entry point of the application. This is 49 | where the work is done to present a container view that houses our 50 | scene. `app_delegate.rb` is also where you'd put code for different 51 | types of top level iOS events (such memory warnings, events for 52 | when the app is about to terminate/go into the background). 53 | - `game_view_controller.rb` is just a container for the game, nothing 54 | really interesting there. 55 | - `game_scene.rb` is where all the meat is. 56 | -------------------------------------------------------------------------------- /hello-world/resources/Default-375w-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/hello-world/resources/Default-375w-667h@2x.png -------------------------------------------------------------------------------- /hello-world/resources/Default-414w-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/hello-world/resources/Default-414w-736h@3x.png -------------------------------------------------------------------------------- /hello-world/resources/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/hello-world/resources/Default-568h@2x.png -------------------------------------------------------------------------------- /hello-world/resources/Default-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/hello-world/resources/Default-667h@2x.png -------------------------------------------------------------------------------- /hello-world/resources/Default-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/hello-world/resources/Default-736h@3x.png -------------------------------------------------------------------------------- /hello-world/resources/large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/hello-world/resources/large.png -------------------------------------------------------------------------------- /hello-world/resources/medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/hello-world/resources/medium.png -------------------------------------------------------------------------------- /hello-world/resources/small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/hello-world/resources/small.png -------------------------------------------------------------------------------- /hello-world/spec/main_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Application 'sprite-kit-hello-world'" do 2 | before do 3 | @app = UIApplication.sharedApplication 4 | end 5 | 6 | it "has one window" do 7 | @app.windows.size.should == 1 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Amir Rajan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /particle-effects/.gitignore: -------------------------------------------------------------------------------- 1 | .repl_history 2 | build 3 | tags 4 | app/pixate_code.rb 5 | resources/*.nib 6 | resources/*.momd 7 | resources/*.storyboardc 8 | .DS_Store 9 | nbproject 10 | .redcar 11 | #*# 12 | *~ 13 | *.sw[po] 14 | .eprj 15 | .sass-cache 16 | .idea 17 | .dat*.* 18 | -------------------------------------------------------------------------------- /particle-effects/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'rake' 4 | # Add your dependencies here: 5 | -------------------------------------------------------------------------------- /particle-effects/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | rake (11.3.0) 5 | 6 | PLATFORMS 7 | ruby 8 | 9 | DEPENDENCIES 10 | rake 11 | 12 | BUNDLED WITH 13 | 1.13.5 14 | -------------------------------------------------------------------------------- /particle-effects/Rakefile: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | $:.unshift("/Library/RubyMotion/lib") 3 | require 'motion/project/template/ios' 4 | 5 | begin 6 | require 'bundler' 7 | Bundler.require 8 | rescue LoadError 9 | end 10 | 11 | Motion::Project::App.setup do |app| 12 | app.name = 'particle-effects' 13 | app.frameworks = %w(CoreGraphics AVFoundation UIKit QuartzCore SpriteKit Foundation AudioToolbox) 14 | app.info_plist['UIRequiresFullScreen'] = true 15 | app.device_family = [:iphone, :ipad] 16 | app.icons = ['large', 'medium', 'small'] 17 | 18 | # development 19 | app.codesign_certificate = 'iPhone Developer: Amirali Rajan' 20 | app.provisioning_profile = './profiles/Development.mobileprovision' 21 | 22 | # test 23 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 24 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 25 | # app.entitlements['beta-reports-active'] = true 26 | 27 | # production 28 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 29 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 30 | end 31 | 32 | namespace :sim do 33 | task :five do 34 | system("rake simulator device_name='iPhone 5'") 35 | end 36 | 37 | task :six do 38 | system("rake simulator device_name='iPhone 6'") 39 | end 40 | 41 | task :plus do 42 | system("rake simulator device_name='iPhone 6 Plus'") 43 | end 44 | 45 | task :ipad do 46 | system("rake simulator device_name='iPad Pro (9.7 inch)'") 47 | end 48 | 49 | task :ipadpro do 50 | system("rake simulator device_name='iPad Pro (12.9 inch)'") 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /particle-effects/app/app_delegate.rb: -------------------------------------------------------------------------------- 1 | class AppDelegate 2 | def application(application, didFinishLaunchingWithOptions:launchOptions) 3 | @game_view_controller = GameViewController.new 4 | 5 | UIApplication.sharedApplication.setIdleTimerDisabled true 6 | @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds) 7 | @window.rootViewController = @game_view_controller 8 | @window.makeKeyAndVisible 9 | 10 | true 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /particle-effects/app/game_scene.rb: -------------------------------------------------------------------------------- 1 | class GameScene < SKScene 2 | include ScreenSizes 3 | 4 | def didMoveToView view 5 | self.scaleMode = SKSceneScaleModeAspectFit 6 | self.backgroundColor = UIColor.whiteColor 7 | @button_1 = add_sprite( 50, 60, 'button.png', 'button 1') 8 | @button_2 = add_sprite(190, 60, 'button.png', 'button 2') 9 | @button_3 = add_sprite(330, 60, 'button.png', 'button 3') 10 | end 11 | 12 | def touchesBegan touches, withEvent: _ 13 | node = nodeAtPoint(touches.allObjects.first.locationInNode(self)) 14 | case node.name 15 | when 'button 1' 16 | particle_1 17 | when 'button 2' 18 | particle_2 19 | when 'button 3' 20 | particle_3 21 | end 22 | end 23 | 24 | def add_sprite x, y, path, name 25 | texture = SKTexture.textureWithImageNamed path 26 | sprite = SKSpriteNode.spriteNodeWithTexture texture 27 | sprite.position = CGPointMake x, y 28 | sprite.name = name 29 | addChild sprite 30 | sprite 31 | end 32 | 33 | def particle_1 34 | particle = SKEmitterNode.alloc.init 35 | particle.setParticleTexture SKTexture.textureWithImageNamed('square.png') 36 | particle.setNumParticlesToEmit 200 37 | particle.setParticleBirthRate 450 38 | particle.setEmissionAngleRange 360 39 | particle.setParticleSpeed 1000 40 | particle.setParticleLifetimeRange 0.5 41 | particle.setParticleAlphaSpeed(-0.5) 42 | particle.setPosition CGPointMake(device_screen_width.fdiv(2), device_screen_height.fdiv(2)) 43 | particle.setParticleRotation 0.1 44 | particle.setParticleRotationRange 6 45 | particle.setParticlePositionRange CGVectorMake(10, 10) 46 | particle.setParticleBlendMode SKBlendModeAlpha 47 | addChild particle 48 | end 49 | 50 | def particle_2 51 | particle = SKEmitterNode.alloc.init 52 | particle.setParticleTexture SKTexture.textureWithImageNamed('square.png') 53 | particle.setNumParticlesToEmit 200 54 | particle.setParticleBirthRate 50 55 | particle.setEmissionAngleRange 360 56 | particle.setParticleSpeed 30 57 | particle.setParticleLifetime 10 58 | particle.setParticleLifetimeRange 20 59 | particle.setParticleAlphaSpeed(-0.5) 60 | particle.setPosition CGPointMake(device_screen_width.fdiv(2), device_screen_height.fdiv(2)) 61 | particle.setParticleRotation 0.1 62 | particle.setParticleRotationRange 6 63 | particle.setParticlePositionRange CGVectorMake(120, 120) 64 | particle.setParticleBlendMode SKBlendModeAlpha 65 | addChild particle 66 | end 67 | 68 | def particle_3 69 | particle = SKEmitterNode.alloc.init 70 | particle.setParticleTexture SKTexture.textureWithImageNamed('square.png') 71 | particle.setNumParticlesToEmit 100 72 | particle.particleBirthRate = 20 73 | particle.particleLifetime = 3 74 | particle.emissionAngle = 3.14159 / 2.0 75 | particle.emissionAngleRange = 3.14159 / 3.0 76 | particle.particleSpeed = 90 77 | particle.yAcceleration = -70 78 | particle.particleAlphaSpeed = -0.3 79 | particle.setPosition CGPointMake(device_screen_width.fdiv(2), device_screen_height.fdiv(2)) 80 | particle.setParticlePositionRange(CGVectorMake(10, 10)) 81 | particle.particleBlendMode = SKBlendModeAlpha 82 | addChild particle 83 | end 84 | 85 | def update currentTime 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /particle-effects/app/game_view_controller.rb: -------------------------------------------------------------------------------- 1 | class GameViewController < UIViewController 2 | include ScreenSizes 3 | 4 | def viewDidLoad 5 | super 6 | 7 | self.view = sk_view 8 | 9 | @scene = GameScene.sceneWithSize(sk_view.frame.size) 10 | sk_view.presentScene @scene 11 | end 12 | 13 | def sk_view 14 | @sk_view ||= SKView.alloc.initWithFrame screen_rect 15 | end 16 | 17 | def prefersStatusBarHidden 18 | true 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /particle-effects/app/screen_sizes.rb: -------------------------------------------------------------------------------- 1 | module ScreenSizes 2 | def device_screen_width 3 | UIScreen.mainScreen.bounds.size.width 4 | end 5 | 6 | def device_screen_height 7 | UIScreen.mainScreen.bounds.size.height 8 | end 9 | 10 | def screen_rect 11 | CGRectMake(0, 0, device_screen_width, device_screen_height) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /particle-effects/particle-effects.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/particle-effects/particle-effects.gif -------------------------------------------------------------------------------- /particle-effects/readme.md: -------------------------------------------------------------------------------- 1 | # Particle Effects 2 | 3 | This sample app shows how to create assorted particle effects programmatically. 4 | 5 | To run the application: 6 | 7 | `rake` will run the app in the iPhone 6 simulator. 8 | 9 | Here's what it looks like: 10 | 11 |

12 | 13 |

14 | 15 | High level project structure: 16 | 17 | - There are three buttons sprites at the bottom. When each one is 18 | tapped a differt particle effect is created via an `SKEmitterNode`. 19 | -------------------------------------------------------------------------------- /particle-effects/resources/Default-375w-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/particle-effects/resources/Default-375w-667h@2x.png -------------------------------------------------------------------------------- /particle-effects/resources/Default-414w-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/particle-effects/resources/Default-414w-736h@3x.png -------------------------------------------------------------------------------- /particle-effects/resources/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/particle-effects/resources/Default-568h@2x.png -------------------------------------------------------------------------------- /particle-effects/resources/Default-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/particle-effects/resources/Default-667h@2x.png -------------------------------------------------------------------------------- /particle-effects/resources/Default-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/particle-effects/resources/Default-736h@3x.png -------------------------------------------------------------------------------- /particle-effects/resources/ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/particle-effects/resources/ball.png -------------------------------------------------------------------------------- /particle-effects/resources/button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/particle-effects/resources/button.png -------------------------------------------------------------------------------- /particle-effects/resources/large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/particle-effects/resources/large.png -------------------------------------------------------------------------------- /particle-effects/resources/medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/particle-effects/resources/medium.png -------------------------------------------------------------------------------- /particle-effects/resources/small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/particle-effects/resources/small.png -------------------------------------------------------------------------------- /particle-effects/resources/square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/particle-effects/resources/square.png -------------------------------------------------------------------------------- /particle-effects/spec/main_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Application 'sprite-kit-hello-world'" do 2 | before do 3 | @app = UIApplication.sharedApplication 4 | end 5 | 6 | it "has one window" do 7 | @app.windows.size.should == 1 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /physics/.gitignore: -------------------------------------------------------------------------------- 1 | .repl_history 2 | build 3 | tags 4 | app/pixate_code.rb 5 | resources/*.nib 6 | resources/*.momd 7 | resources/*.storyboardc 8 | .DS_Store 9 | nbproject 10 | .redcar 11 | #*# 12 | *~ 13 | *.sw[po] 14 | .eprj 15 | .sass-cache 16 | .idea 17 | .dat*.* 18 | -------------------------------------------------------------------------------- /physics/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'rake' 4 | # Add your dependencies here: 5 | -------------------------------------------------------------------------------- /physics/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | rake (11.3.0) 5 | 6 | PLATFORMS 7 | ruby 8 | 9 | DEPENDENCIES 10 | rake 11 | 12 | BUNDLED WITH 13 | 1.13.5 14 | -------------------------------------------------------------------------------- /physics/Rakefile: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | $:.unshift("/Library/RubyMotion/lib") 3 | require 'motion/project/template/ios' 4 | 5 | begin 6 | require 'bundler' 7 | Bundler.require 8 | rescue LoadError 9 | end 10 | 11 | Motion::Project::App.setup do |app| 12 | app.name = 'physics' 13 | app.frameworks = %w(CoreGraphics AVFoundation UIKit QuartzCore SpriteKit Foundation AudioToolbox) 14 | app.info_plist['UIRequiresFullScreen'] = true 15 | app.device_family = [:iphone, :ipad] 16 | app.icons = ['large', 'medium', 'small'] 17 | 18 | # development 19 | app.codesign_certificate = 'iPhone Developer: Amirali Rajan' 20 | app.provisioning_profile = './profiles/Development.mobileprovision' 21 | 22 | # test 23 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 24 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 25 | # app.entitlements['beta-reports-active'] = true 26 | 27 | # production 28 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 29 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 30 | end 31 | 32 | namespace :sim do 33 | task :five do 34 | system("rake simulator device_name='iPhone 5'") 35 | end 36 | 37 | task :six do 38 | system("rake simulator device_name='iPhone 6'") 39 | end 40 | 41 | task :plus do 42 | system("rake simulator device_name='iPhone 6 Plus'") 43 | end 44 | 45 | task :ipad do 46 | system("rake simulator device_name='iPad Pro (9.7 inch)'") 47 | end 48 | 49 | task :ipadpro do 50 | system("rake simulator device_name='iPad Pro (12.9 inch)'") 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /physics/app/app_delegate.rb: -------------------------------------------------------------------------------- 1 | class AppDelegate 2 | def application(application, didFinishLaunchingWithOptions:launchOptions) 3 | @game_view_controller = GameViewController.new 4 | 5 | UIApplication.sharedApplication.setIdleTimerDisabled true 6 | @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds) 7 | @window.rootViewController = @game_view_controller 8 | @window.makeKeyAndVisible 9 | 10 | true 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /physics/app/game_scene.rb: -------------------------------------------------------------------------------- 1 | class GameScene < SKScene 2 | include ScreenSizes 3 | 4 | def didMoveToView view 5 | self.scaleMode = SKSceneScaleModeAspectFit 6 | self.backgroundColor = UIColor.whiteColor 7 | self.view.showsPhysics = true 8 | 9 | @ball = add_sprite(10, 10 | device_screen_height, 11 | 'ball.png', 12 | 'circle') 13 | 14 | @ball.physicsBody = SKPhysicsBody.bodyWithCircleOfRadius(15) 15 | @wall = add_sprite(device_screen_width.fdiv(2), 16 | 60, 17 | 'wall.png', 18 | 'wall') 19 | 20 | @wall.physicsBody = SKPhysicsBody.bodyWithRectangleOfSize CGSizeMake(1000, 25) 21 | @wall.physicsBody.dynamic = false 22 | @wall.zRotation = 0.5 23 | 24 | 25 | @wall2 = add_sprite(-200, 26 | 500, 27 | 'wall.png', 28 | 'wall') 29 | 30 | @wall2.physicsBody = SKPhysicsBody.bodyWithRectangleOfSize CGSizeMake(1000, 25) 31 | @wall2.physicsBody.dynamic = false 32 | @wall2.zRotation = -0.5 33 | end 34 | 35 | def add_sprite x, y, path, name 36 | texture = SKTexture.textureWithImageNamed path 37 | sprite = SKSpriteNode.spriteNodeWithTexture texture 38 | sprite.position = CGPointMake x, y 39 | sprite.name = name 40 | addChild sprite 41 | sprite 42 | end 43 | 44 | def update currentTime 45 | if(@ball.position.y < -100) 46 | @ball.position = CGPointMake 10, device_screen_height 47 | @ball.physicsBody = SKPhysicsBody.bodyWithCircleOfRadius(15) 48 | end 49 | end 50 | 51 | def didBeginContact _ 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /physics/app/game_view_controller.rb: -------------------------------------------------------------------------------- 1 | class GameViewController < UIViewController 2 | include ScreenSizes 3 | 4 | def viewDidLoad 5 | super 6 | 7 | self.view = sk_view 8 | 9 | @scene = GameScene.sceneWithSize(sk_view.frame.size) 10 | sk_view.presentScene @scene 11 | end 12 | 13 | def sk_view 14 | @sk_view ||= SKView.alloc.initWithFrame screen_rect 15 | end 16 | 17 | def prefersStatusBarHidden 18 | true 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /physics/app/screen_sizes.rb: -------------------------------------------------------------------------------- 1 | module ScreenSizes 2 | def device_screen_width 3 | UIScreen.mainScreen.bounds.size.width 4 | end 5 | 6 | def device_screen_height 7 | UIScreen.mainScreen.bounds.size.height 8 | end 9 | 10 | def screen_rect 11 | CGRectMake(0, 0, device_screen_width, device_screen_height) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /physics/physics.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/physics/physics.gif -------------------------------------------------------------------------------- /physics/readme.md: -------------------------------------------------------------------------------- 1 | # Physics 2 | 3 | This sample app shows how to set up a physics body and apply collision 4 | detection. 5 | 6 | To run the application: 7 | 8 | `rake` will run the app in the iPhone 6 simulator. 9 | 10 | Here's what it looks like: 11 | 12 |

13 | 14 |

15 | 16 | High level structure: 17 | 18 | - The `@ball` is given an `SKPhysicsBody`. 19 | - The walls `@wall` and `@wall2` are each given an `SKPhysicsBody` 20 | with `dynamic` set to false (this ensures that they don't move). 21 | - During the `update` loop, the `@ball` has it's position reset if 22 | it's `position.y` is off the screen (it is also given a new 23 | `physicsBody` to remove an carried momentum. 24 | -------------------------------------------------------------------------------- /physics/resources/Default-375w-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/physics/resources/Default-375w-667h@2x.png -------------------------------------------------------------------------------- /physics/resources/Default-414w-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/physics/resources/Default-414w-736h@3x.png -------------------------------------------------------------------------------- /physics/resources/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/physics/resources/Default-568h@2x.png -------------------------------------------------------------------------------- /physics/resources/Default-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/physics/resources/Default-667h@2x.png -------------------------------------------------------------------------------- /physics/resources/Default-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/physics/resources/Default-736h@3x.png -------------------------------------------------------------------------------- /physics/resources/ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/physics/resources/ball.png -------------------------------------------------------------------------------- /physics/resources/explosion_particle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/physics/resources/explosion_particle.png -------------------------------------------------------------------------------- /physics/resources/large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/physics/resources/large.png -------------------------------------------------------------------------------- /physics/resources/medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/physics/resources/medium.png -------------------------------------------------------------------------------- /physics/resources/small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/physics/resources/small.png -------------------------------------------------------------------------------- /physics/resources/wall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/physics/resources/wall.png -------------------------------------------------------------------------------- /physics/spec/main_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Application 'sprite-kit-hello-world'" do 2 | before do 3 | @app = UIApplication.sharedApplication 4 | end 5 | 6 | it "has one window" do 7 | @app.windows.size.should == 1 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /putting-it-together/.gitignore: -------------------------------------------------------------------------------- 1 | .repl_history 2 | build 3 | tags 4 | app/pixate_code.rb 5 | resources/*.nib 6 | resources/*.momd 7 | resources/*.storyboardc 8 | .DS_Store 9 | nbproject 10 | .redcar 11 | #*# 12 | *~ 13 | *.sw[po] 14 | .eprj 15 | .sass-cache 16 | .idea 17 | .dat*.* 18 | -------------------------------------------------------------------------------- /putting-it-together/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'rake' 4 | # Add your dependencies here: 5 | -------------------------------------------------------------------------------- /putting-it-together/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | rake (11.3.0) 5 | 6 | PLATFORMS 7 | ruby 8 | 9 | DEPENDENCIES 10 | rake 11 | 12 | BUNDLED WITH 13 | 1.13.5 14 | -------------------------------------------------------------------------------- /putting-it-together/Rakefile: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | $:.unshift("/Library/RubyMotion/lib") 3 | require 'motion/project/template/ios' 4 | 5 | begin 6 | require 'bundler' 7 | Bundler.require 8 | rescue LoadError 9 | end 10 | 11 | Motion::Project::App.setup do |app| 12 | app.version = '5.3' 13 | app.deployment_target = "8.1" 14 | app.name = 'A Noble Circle' 15 | 16 | app.frameworks = %w(CoreGraphics AVFoundation UIKit QuartzCore SpriteKit Foundation AudioToolbox) 17 | app.identifier = 'com.scratchworkdevelopment.flatland' 18 | 19 | app.interface_orientations = [:landscape_right, :landscape_left] 20 | app.info_plist['UIRequiresFullScreen'] = true 21 | app.info_plist['ITSAppUsesNonExemptEncryption'] = false 22 | 23 | app.device_family = [:iphone, :ipad] 24 | 25 | # development 26 | app.codesign_certificate = 'iPhone Developer: Amirali Rajan' 27 | app.provisioning_profile = './profiles/Development.mobileprovision' 28 | 29 | # test 30 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 31 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 32 | # app.entitlements['beta-reports-active'] = true 33 | 34 | # production 35 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 36 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 37 | end 38 | 39 | namespace :sim do 40 | task :five do 41 | system("rake simulator device_name='iPhone 5'") 42 | end 43 | 44 | task :six do 45 | system("rake simulator device_name='iPhone 6'") 46 | end 47 | 48 | task :plus do 49 | system("rake simulator device_name='iPhone 6 Plus'") 50 | end 51 | 52 | task :ipad do 53 | system("rake simulator device_name='iPad Pro (9.7 inch)'") 54 | end 55 | 56 | task :ipadpro do 57 | system("rake simulator device_name='iPad Pro (12.9 inch)'") 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /putting-it-together/app/.#game_scene.rb: -------------------------------------------------------------------------------- 1 | amiralirajan@Amiralis-MBP.attlocal.net.20540 -------------------------------------------------------------------------------- /putting-it-together/app/app_delegate.rb: -------------------------------------------------------------------------------- 1 | class AppDelegate 2 | def application(application, didFinishLaunchingWithOptions:launchOptions) 3 | @game_view_controller = GameViewController.new 4 | 5 | UIApplication.sharedApplication.setIdleTimerDisabled true 6 | @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds) 7 | @window.rootViewController = @game_view_controller 8 | @window.makeKeyAndVisible 9 | 10 | true 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /putting-it-together/app/arrow.rb: -------------------------------------------------------------------------------- 1 | class Arrow 2 | attr_accessor :node, :x, :y, :floor 3 | 4 | def initialize x, y, vx, vy, floor 5 | @x = x 6 | @y = y 7 | @dx = vx 8 | @dy = vy 9 | @floor = floor 10 | end 11 | 12 | def gravity 13 | -1 14 | end 15 | 16 | def bottom_of_arrow 17 | @floor + 30 18 | end 19 | 20 | def update 21 | if(@y > bottom_of_arrow) 22 | @x += @dx 23 | @y += @dy 24 | @dy += gravity 25 | @y = bottom_of_arrow if @y < bottom_of_arrow 26 | node.position = CGPointMake(@x, @y) 27 | else 28 | node.position = CGPointMake(@x, bottom_of_arrow) 29 | end 30 | end 31 | 32 | def create_node parent 33 | return @node if @node 34 | 35 | @node = add_sprite(parent, 36 | @x, 37 | @y, 38 | 'ball.png', 39 | 'circle') 40 | 41 | @node.physicsBody = SKPhysicsBody.bodyWithCircleOfRadius(20) 42 | @node.physicsBody.dynamic = true 43 | @node.physicsBody.categoryBitMask = 2 44 | @node.physicsBody.contactTestBitMask = 4 45 | @node.physicsBody.collisionBitMask = 0 46 | end 47 | 48 | def add_sprite parent, x, y, path, name 49 | texture = SKTexture.textureWithImageNamed path 50 | sprite = SKSpriteNode.spriteNodeWithTexture texture 51 | sprite.position = CGPointMake x, y 52 | sprite.name = name 53 | parent.addChild sprite 54 | sprite 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /putting-it-together/app/game_scene.rb: -------------------------------------------------------------------------------- 1 | class GameScene < SKScene 2 | include ScreenSizes 3 | 4 | def shoot_arrow vx, vy 5 | arrow = Arrow.new(20, device_screen_height * 0.8, vx, vy, floor) 6 | arrow.create_node self 7 | @arrows << arrow 8 | end 9 | 10 | def didMoveToView view 11 | $self = self 12 | @arrows = [] 13 | self.scaleMode = SKSceneScaleModeAspectFit 14 | self.backgroundColor = UIColor.whiteColor 15 | self.physicsWorld.gravity = CGVectorMake(0, 0) 16 | self.physicsWorld.contactDelegate = self 17 | self.view.showsPhysics = true 18 | 19 | @wall = add_sprite(device_screen_width.fdiv(2), 20 | floor, 21 | 'wall.png', 22 | 'wall') 23 | end 24 | 25 | def add_sprite x, y, path, name 26 | texture = SKTexture.textureWithImageNamed path 27 | sprite = SKSpriteNode.spriteNodeWithTexture texture 28 | sprite.position = CGPointMake x, y 29 | sprite.name = name 30 | addChild sprite 31 | sprite 32 | end 33 | 34 | def update currentTime 35 | @arrows.each do |a| 36 | a.update 37 | end 38 | end 39 | 40 | def floor 41 | 35 42 | end 43 | 44 | def touchesBegan touches, withEvent: _ 45 | @begin_touch = touches.allObjects.first.locationInNode(self) 46 | end 47 | 48 | def touchesEnded touches, withEvent: _ 49 | @end_touch = touches.allObjects.first.locationInNode(self) 50 | vx = @begin_touch.x - @end_touch.x 51 | vy = @begin_touch.y - @end_touch.y 52 | shoot_arrow(vx * 0.10, vy * 0.10) 53 | end 54 | 55 | def didBeginContact _ 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /putting-it-together/app/game_view_controller.rb: -------------------------------------------------------------------------------- 1 | class GameViewController < UIViewController 2 | include ScreenSizes 3 | 4 | def viewDidLoad 5 | super 6 | 7 | self.view = sk_view 8 | 9 | @scene = GameScene.sceneWithSize(sk_view.frame.size) 10 | sk_view.presentScene @scene 11 | end 12 | 13 | def sk_view 14 | @sk_view ||= SKView.alloc.initWithFrame screen_rect 15 | end 16 | 17 | def prefersStatusBarHidden 18 | true 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /putting-it-together/app/screen_sizes.rb: -------------------------------------------------------------------------------- 1 | module ScreenSizes 2 | def device_screen_width 3 | UIScreen.mainScreen.bounds.size.width 4 | end 5 | 6 | def device_screen_height 7 | UIScreen.mainScreen.bounds.size.height 8 | end 9 | 10 | def screen_rect 11 | CGRectMake(0, 0, device_screen_width, device_screen_height) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /putting-it-together/readme.md: -------------------------------------------------------------------------------- 1 | # Putting it Together 2 | 3 | This sample app shows a simple game. Built from the concepts in the 4 | sample apps. 5 | 6 | To run the application: 7 | 8 | `rake` will run the app in the iPhone 6 simulator. 9 | 10 | Here's what it looks like: 11 | 12 | TODO 13 | -------------------------------------------------------------------------------- /putting-it-together/resources/Default-375w-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/putting-it-together/resources/Default-375w-667h@2x.png -------------------------------------------------------------------------------- /putting-it-together/resources/Default-414w-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/putting-it-together/resources/Default-414w-736h@3x.png -------------------------------------------------------------------------------- /putting-it-together/resources/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/putting-it-together/resources/Default-568h@2x.png -------------------------------------------------------------------------------- /putting-it-together/resources/Default-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/putting-it-together/resources/Default-667h@2x.png -------------------------------------------------------------------------------- /putting-it-together/resources/Default-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/putting-it-together/resources/Default-736h@3x.png -------------------------------------------------------------------------------- /putting-it-together/resources/ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/putting-it-together/resources/ball.png -------------------------------------------------------------------------------- /putting-it-together/resources/explosion_particle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/putting-it-together/resources/explosion_particle.png -------------------------------------------------------------------------------- /putting-it-together/resources/large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/putting-it-together/resources/large.png -------------------------------------------------------------------------------- /putting-it-together/resources/medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/putting-it-together/resources/medium.png -------------------------------------------------------------------------------- /putting-it-together/resources/small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/putting-it-together/resources/small.png -------------------------------------------------------------------------------- /putting-it-together/resources/wall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/putting-it-together/resources/wall.png -------------------------------------------------------------------------------- /putting-it-together/spec/main_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Application 'sprite-kit-hello-world'" do 2 | before do 3 | @app = UIApplication.sharedApplication 4 | end 5 | 6 | it "has one window" do 7 | @app.windows.size.should == 1 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Mobile Game Development in Ruby # 2 | 3 | Game development is fun! 4 | 5 | Here are some sample apps that will help you build games for iOS using... _drumroll_ 6 | 7 | Ruby :-) (specifically using [RubyMotion](http://rubymotion.com)). 8 | 9 | Steps to get started with RubyMotion: 10 | 11 | - You need a mac. 12 | - Download the RubyMotion Starter Pack from the [RubyMotion](http://rubymotion.com) website. 13 | - You need to be on the El Cap OS (at least). 14 | - You need to download XCode (you can get it from the AppStore). 15 | - You need to then open XCode and accept the license. 16 | - You need to install XCode command line tools by running `xcode-select --install`. 17 | - You need Ruby installed, preferablly version `2.3.1p112` or 18 | later. Use [`rbenv`](https://github.com/rbenv/rbenv) for managing Ruby 19 | versions. 20 | 21 | ## Overview of Sample Projects ## 22 | 23 | You'll want to go through the projects in the following order: 24 | 25 | - [hello-world](/hello-world): This sample app shows how to set up a scene, get a 26 | label on the page, and have it update within the game loop. 27 | - [create-sprite](/create-sprite): This sample app shows how to create a single sprite 28 | and put it on the screen. Within the game loop, the sprite's angle 29 | is updated so that it spins. 30 | - [touch-event](/touch-event): This sample app shows how to accept a simple tap 31 | event from the player. 32 | - [particle-effects](/particle-effects): This sample app shows how to create particle 33 | effects programatically. 34 | - [collision-detection](/collision-detection): This sample app shows how to do collision 35 | detection using SpriteKit's physics engine. 36 | - [physics](/physics): This sample app shows how to use SpriteKit's physic 37 | engine to apply gravity to sprites. 38 | - [actions](/actions): This sample app shows how to use SpriteKit's declarative 39 | animations to create a camera shake. 40 | - [animated-sprite](/animated-sprite): This sample app shows how to 41 | chain frame by frame sprite drawings together to create a moving character. 42 | - [Space Invaders](/SpaceInvaders): This sample app takes a lot of 43 | things learned from the sample apps above and makes a Space Invaders game. 44 | 45 | ## ObjectiveC to Ruby ## 46 | 47 | Answers on StackOverflow for iOS are usually in ObjectiveC. There's no 48 | denying that. This section goes into how you can translate ObjectiveC 49 | to Ruby. It's surprisingly simple, even if you've never written a line 50 | of ObjectiveC. If you're gun shy about using Ruby, you'll still get a 51 | great overview of how to read ObjectiveC and Java code contextualized 52 | through Ruby lenses. So let's get started. You can also 53 | read [Learn Ruby the Hard Way](https://learnrubythehardway.org/book/) 54 | to learn more about the language (independent of a framework). 55 | 56 | Here is how a `Person` class would be created in ObjectiveC. There are 57 | two properties `firstName` and `lastName`, and an instance method 58 | called `sayHello` that returns a string. Instance methods in 59 | ObjectiveC are denoted by the `-` sign preceeding the function name: 60 | 61 | ### Class Construction ### 62 | 63 | ```objectivec 64 | //Person.h 65 | @interface Person : NSObject 66 | @property NSString *firstName; 67 | @property NSString *lastName; 68 | - (NSString*)sayHello; 69 | @end 70 | 71 | //Person.m 72 | #import "Person.h" 73 | @implementation Person 74 | - (NSString*)sayHello { 75 | return [NSString stringWithFormat:@"Hello, %@ %@.", 76 | _firstName, 77 | _lastName]; 78 | } 79 | @end 80 | ``` 81 | 82 | Here is how you would instanciate an instance of `Person` and call the 83 | `sayHello` function. 84 | 85 | ```objectivec 86 | Person *person = [[Person alloc] init]; 87 | person.firstName = @"Amir"; 88 | person.lastName = @"Rajan"; 89 | NSLog([person sayHello]); 90 | ``` 91 | 92 | Let's break this down: 93 | 94 | Method invocation in ObjectiveC is done through 95 | paired brackets `[]`. So instead of `person.sayHello()` you have 96 | `[person sayHello]`. All ObjectiveC classes have an `alloc` class 97 | method, and an `init` instance method. The `alloc` class method 98 | creates a memory space for the instance of the class, and the `init` 99 | method initializes it (essentially a constructor). 100 | 101 | Properties are accessed using the `.` operator (as opposed to the `[]`). 102 | 103 | String literals must be preceded by an `@` sign. This is required for 104 | backwards compatability with C (all C code is valid ObjectiveC 105 | code... ObjectiveC is a superset of C). 106 | 107 | `NSLog` is essentially `puts`. It's a global C method so is available anywhere. 108 | 109 | Here is the same `Person` class and usage, but in Ruby. 110 | 111 | ```ruby 112 | class Person 113 | attr_accessor :firstName, :lastName 114 | 115 | def sayHello 116 | "Hello, #{@firstName} #{@lastName}" 117 | end 118 | end 119 | ``` 120 | 121 | The usage should be pretty straight forward. It's important to 122 | interalize the _mechancial_ aspect of converting ObjectiveC to 123 | Ruby. Basically, you remove the `[]` and replace it with `.`. We'll 124 | have more examples later. 125 | 126 | ```ruby 127 | person = Person.alloc.init 128 | person.firstName = "Amir" 129 | person.lastName = "Rajan" 130 | NSLog(person.sayHello) 131 | ``` 132 | 133 | Also, in Ruby, you _can_ use `Person.alloc.init`, but `Person.new` is 134 | also available to you and does the same thing. 135 | 136 | ### Method Anatomy ### 137 | 138 | Generally speaking, all APIs in iOS use named parameters (and by 139 | extension, most iOS developers follow suit with their own 140 | classes). Here is an example how you would declare a method in ObjectiveC. 141 | 142 | ```objectivec 143 | - (void)setDobWithMonth:(NSInteger)month 144 | withDay:(NSInteger)day 145 | withYear:(NSInteger)year { 146 | 147 | } 148 | ``` 149 | 150 | This was really weird the first time I saw it too. So let's break down 151 | the code above. First, the `-` sign preceeding the method name denotes 152 | that this is an instance method (a `+` sign denotes that it's a class 153 | method... more on that later). The next token `(void)` denotes the 154 | return type. 155 | 156 | Now for the fun part. The method name _includes_ the name of the first 157 | parameter (usually the method name is seperated from the parameter 158 | name using the word `With` as a delimeter). The `setDobWithMonth`, 159 | `withDay`, `withYear` are the _public_ names or the parameters. This 160 | is what users of the method will see when autocompletion pops up. 161 | 162 | The tokens `month`, `day`, `year` are what the public names are bound 163 | to _within_ the method body. This is crazy/weird I know. Take a moment 164 | to internalize this. In short, a method's name includes its named 165 | parameters, and each parameter has a outward facing name and an 166 | internal binding. 167 | 168 | Here is how you would call the method. 169 | 170 | ```objectivec 171 | [person setDobWithMonth:1 withDay:1 withYear:2013]; 172 | ``` 173 | 174 | If you were to tell a teammate to call this method you would say. 175 | 176 | >Call the `setDobWithMonth:withDay:withYear` method. 177 | 178 | Now that you understand the anatomy of a ObjectiveC function. Here is 179 | how you would do exact same thing in Ruby. 180 | 181 | ```ruby 182 | def setDobWithMonth(month, 183 | withDay, 184 | withYear) 185 | 186 | end 187 | ``` 188 | 189 | And here is the invocation: 190 | 191 | ```ruby 192 | person.setDobWithMonth(1, withDay: 1, withYear: 2013) 193 | ``` 194 | 195 | Now, of course, you can nix the public names of the methods if you 196 | wish, and simply have: 197 | 198 | 199 | ```ruby 200 | def setDobWithMonth(month, day, year) 201 | 202 | end 203 | 204 | person.setDobWithMonth(1, 1, 2013) 205 | ``` 206 | 207 | But it's important to know how to call methods with named parameters, 208 | because all iOS APIs are built that way. 209 | 210 | ### Blocks ### 211 | 212 | There is a reason why 213 | [Fucking Block Syntax](http://fuckingblocksyntax.com/) exists. It's 214 | because it's terrifying. Let's break down the next piece of code, 215 | which does an `POST (HTTP)`, passing a dictionary, to a url, and 216 | providing a callback on success. 217 | 218 | ```objectivec 219 | - (void) 220 | post:(NSDictionary *)objectToPost 221 | toUrl:(NSString *)toUrl 222 | success:(void (^)(RKMappingResult *mappingResult))success { } 223 | ``` 224 | 225 | Building upon what we learned in the previous section. The name of 226 | this method is `post:toUrl:success` (a more idiomatic name would 227 | probably be `postWithObject:withUrl:success`... but I digress). 228 | 229 | The block is denoted by the `^` token. The full type signature for the 230 | block is `void (^)(RKMappingResult) (╯°□°)╯︵ ┻━┻`. 231 | 232 | Here is how you would invoke the `post:toUrl:success` method: 233 | 234 | ```objectivec 235 | [client post: @{ @"firstName": @"Amir", @"lastName": @"Rajan" } 236 | toUrl: @"http://localhost/people" 237 | success:^(RKMappingResult *result) { 238 | //callback code here 239 | }]; 240 | ``` 241 | 242 | Again, method invocation is denoted by using `[]`. For backward 243 | compatability with C, dictionary literals must be prefixed with the 244 | `@`, and of course, strings must also be prefixed with the `@` sign. I 245 | call it the bloody stump character, because after you've typed a good 246 | 100 times, your fingers will end up being bloody stumps. 247 | 248 | The callback `success` is denoted with the `^`, plus the typed 249 | parameters, plus the callback method body. Here's how you would write 250 | and invoke the same thing in Ruby: 251 | 252 | ```ruby 253 | def post(objectToPost, toUrl: toUrl, success: success) 254 | 255 | end 256 | 257 | client post({ firstName: "Amir", lastName: "Rajan" }, 258 | toUrl: "http://localhost/people", 259 | success: lambda { |result| 260 | #callback code here 261 | }) 262 | ``` 263 | 264 | With what you've read so far, you should be able to translate the 265 | ObjectiveC code to Ruby. This was taken from an actual StackOverflow answer: 266 | 267 | ```objectivec 268 | _label.layer.backgroundColor = [UIColor whiteColor].CGColor; 269 | 270 | [UIView animateWithDuration:2.0 animations:^{ 271 | _label.layer.backgroundColor = [UIColor greenColor].CGColor; 272 | } completion:NULL]; 273 | ``` 274 | 275 | Don't look, below until you think you've got the translation figured out. 276 | 277 | ```ruby 278 | @label.layer.backgroundColor = UIColor.whiteColor.CGColor 279 | 280 | UIView.animateWithDuration(2.0, animations: lambda { 281 | @label.layer.backgroundColor = UIColor.greenColor.CGColor 282 | }, completion: nil) 283 | ``` 284 | 285 | ### Categories vs Mixins ### 286 | 287 | To extend a sealed/third party classes, ObjectiveC has the concept of 288 | a `Category`. Let's say we want to take the animation logic from the 289 | StackOverflow question above, and make it a part of `UIView` (a class 290 | within iOS's `UIKit` library). Here is how you would do it in 291 | ObjectiveC. 292 | 293 | First we define the preprocessor directive (method with named 294 | parameters, blocks, and bloody stump characters): 295 | 296 | ```objectivec 297 | @interface UIView (UIViewExtensions) 298 | - (void)animate:(double)duration block:(void (^)(void))block; 299 | - (void)animate:(void (^)(void))block; 300 | @end 301 | ``` 302 | 303 | ObjectiveC has method overloading, so we provide two implementations 304 | of the function, one that takes in a duration and another that has a 305 | default value. 306 | 307 | ```objectivec 308 | @implementation UIView (UIViewExtensions) 309 | - (void)animate:(void (^)(void))block { 310 | [self animate:0.5 block:block]; 311 | } 312 | 313 | - (void)animate:(double)duration block:(void (^)(void))block { 314 | [UIView beginAnimations:NULL context:NULL]; 315 | [UIView setAnimationDuration:duration]; 316 | block(); 317 | [UIView commitAnimations]; 318 | } 319 | @end 320 | ``` 321 | 322 | This is the usage: 323 | 324 | ```objectivec 325 | [label setAlpha:0]; 326 | [label animate:1 block:^{ [label setAlpha:1]; }]; 327 | ``` 328 | 329 | In Ruby, we simply open the class/use a mixin. For berevity, I've just 330 | opened the class \#yolo. 331 | 332 | ```ruby 333 | class UIView 334 | def animate duration = 0.5, &block 335 | UIView.beginAnimations(nil, context:nil) 336 | UIView.setAnimationDuration(duration) 337 | instance_eval &block 338 | UIView.commitAnimations 339 | end 340 | end 341 | 342 | def animate duration = 0.5, &block 343 | UIView.beginAnimations(nil, context:nil) 344 | UIView.setAnimationDuration(duration) 345 | instance_eval &block 346 | UIView.commitAnimations 347 | end 348 | end 349 | ``` 350 | 351 | Here is how you would invoke that function. 352 | 353 | ```ruby 354 | label.setAlpha 0 355 | label.animate 1 { label.setAlpha 1 } 356 | ``` 357 | 358 | ### Benefit of Class Macros ### 359 | 360 | Ruby class macros are great, and significantly increase 361 | readability. Here is a class from my game A Dark Room, which describes 362 | an encounter with an enemy. 363 | 364 | ```ruby 365 | class SnarlingBeastEvent < EncounterEvent 366 | title "a snarling beast" 367 | text "a snarling beast leaps out of the underbrush." 368 | damage 1 369 | 370 | def loot 371 | { 372 | fur: { min: 3, max: 7, chance: 1.0 } 373 | } 374 | end 375 | end 376 | ``` 377 | 378 | Here is the definition of the class macro. 379 | 380 | ```ruby 381 | class EncounterEvent 382 | def self.title title 383 | define_method("title") { title } 384 | end 385 | 386 | def self.text text 387 | define_method("text") { text } 388 | end 389 | 390 | def self.health health 391 | define_method("health") { health } 392 | end 393 | end 394 | ``` 395 | 396 | Given that ObjectiveC: 397 | 398 | - Doesn't have class macros. 399 | - Makes you use the bloody stump character. 400 | - Doesn't have the concept of a symbol. 401 | - Forces you to explicitly box and unbox value types from 402 | dictionaries. 403 | 404 | You get a death by 1000 paper cuts. Here is the ObjectiveC code that 405 | accomplishes the same thing as the Ruby code with class macros. 406 | 407 | Define the preprocessor directive. One class method `initNew`, and one 408 | instance method `loot`: 409 | 410 | ```objectivec 411 | @interface SnarlingBeastEvent : EncounterEvent 412 | + (id)initNew; 413 | - (NSDictionary *)loot; 414 | @end 415 | ``` 416 | 417 | Call parent constructor with specific attributes. Override `loot` 418 | method. The dictionary literal contstruction, and boxing/unboxing apis 419 | are horrid: 420 | 421 | ```objectivec 422 | @implementation SnarlingBeastEvent 423 | + (id)initNew { 424 | return [super initWithAttributes: @{ 425 | @"health": [[NSNumber alloc]initWithInt: 1], 426 | @"title": @"a snarling beast", 427 | @"text": @"a snarling beast leaps out of the underbrush." 428 | }]; 429 | } 430 | 431 | - (NSDictionary *)loot { 432 | return @{ 433 | @"fur": @{ 434 | @"min": [[NSNumber alloc]initWithDouble:3.0], 435 | @"max": [[NSNumber alloc]initWithDouble:7.0], 436 | @"chance": [[NSNumber alloc]initWithDouble:1.0] 437 | } 438 | }; 439 | } 440 | @end 441 | ``` 442 | Base class implementation. Preprocessor directive, plus 443 | implementation. The dictionary boxing/unboxing apis are horrid: 444 | 445 | ```objectivec 446 | @interface EncounterEvent : NSObject 447 | @property NSString *title; 448 | @property NSString *text; 449 | @property NSInteger health; 450 | + (id)initWithAttributes:(NSDictionary *)attributes; 451 | @end 452 | 453 | @implementation EncounterEvent 454 | + (id)initWithAttributes:(NSDictionary *)attributes { 455 | EncounterEvent *e = [[EncounterEvent alloc] init]; 456 | e.title = [attributes valueForKey:@"title"]; 457 | e.text = [attributes valueForKey:@"text"]; 458 | NSNumber *num = [attributes valueForKey:@"health"]; 459 | e.health = [num integerValue]; 460 | return e; 461 | } 462 | @end 463 | ``` 464 | 465 | Congratulations! You can now read and translate ObjectiveC to Ruby. 466 | -------------------------------------------------------------------------------- /touch-event/.gitignore: -------------------------------------------------------------------------------- 1 | .repl_history 2 | build 3 | tags 4 | app/pixate_code.rb 5 | resources/*.nib 6 | resources/*.momd 7 | resources/*.storyboardc 8 | .DS_Store 9 | nbproject 10 | .redcar 11 | #*# 12 | *~ 13 | *.sw[po] 14 | .eprj 15 | .sass-cache 16 | .idea 17 | .dat*.* 18 | -------------------------------------------------------------------------------- /touch-event/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'rake' 4 | # Add your dependencies here: 5 | -------------------------------------------------------------------------------- /touch-event/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | rake (11.3.0) 5 | 6 | PLATFORMS 7 | ruby 8 | 9 | DEPENDENCIES 10 | rake 11 | 12 | BUNDLED WITH 13 | 1.13.5 14 | -------------------------------------------------------------------------------- /touch-event/Rakefile: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | $:.unshift("/Library/RubyMotion/lib") 3 | require 'motion/project/template/ios' 4 | 5 | begin 6 | require 'bundler' 7 | Bundler.require 8 | rescue LoadError 9 | end 10 | 11 | Motion::Project::App.setup do |app| 12 | app.name = 'touch-event' 13 | app.frameworks = %w(CoreGraphics AVFoundation UIKit QuartzCore SpriteKit Foundation AudioToolbox) 14 | app.info_plist['UIRequiresFullScreen'] = true 15 | app.device_family = [:iphone, :ipad] 16 | app.icons = ['large', 'medium', 'small'] 17 | 18 | # development 19 | app.codesign_certificate = 'iPhone Developer: Amirali Rajan' 20 | app.provisioning_profile = './profiles/Development.mobileprovision' 21 | 22 | # test 23 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 24 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 25 | # app.entitlements['beta-reports-active'] = true 26 | 27 | # production 28 | # app.codesign_certificate = "iPhone Distribution: Amirali Rajan" 29 | # app.provisioning_profile = './profiles/Distribution.mobileprovision' 30 | end 31 | 32 | namespace :sim do 33 | task :five do 34 | system("rake simulator device_name='iPhone 5'") 35 | end 36 | 37 | task :six do 38 | system("rake simulator device_name='iPhone 6'") 39 | end 40 | 41 | task :plus do 42 | system("rake simulator device_name='iPhone 6 Plus'") 43 | end 44 | 45 | task :ipad do 46 | system("rake simulator device_name='iPad Pro (9.7 inch)'") 47 | end 48 | 49 | task :ipadpro do 50 | system("rake simulator device_name='iPad Pro (12.9 inch)'") 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /touch-event/app/app_delegate.rb: -------------------------------------------------------------------------------- 1 | class AppDelegate 2 | def application(application, didFinishLaunchingWithOptions:launchOptions) 3 | @game_view_controller = GameViewController.new 4 | 5 | UIApplication.sharedApplication.setIdleTimerDisabled true 6 | @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds) 7 | @window.rootViewController = @game_view_controller 8 | @window.makeKeyAndVisible 9 | 10 | true 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /touch-event/app/game_scene.rb: -------------------------------------------------------------------------------- 1 | class GameScene < SKScene 2 | include ScreenSizes 3 | 4 | def didMoveToView view 5 | self.scaleMode = SKSceneScaleModeAspectFit 6 | self.backgroundColor = UIColor.whiteColor 7 | self.view.multipleTouchEnabled = true 8 | @squares = [] 9 | end 10 | 11 | def touchesBegan touches, withEvent: _ 12 | touches.allObjects.each do |t| 13 | @squares << add_sprite(t.locationInNode(self).x, 14 | t.locationInNode(self).y, 15 | 'square.png') 16 | end 17 | end 18 | 19 | def add_sprite x, y, path 20 | texture = SKTexture.textureWithImageNamed path 21 | sprite = SKSpriteNode.spriteNodeWithTexture texture 22 | sprite.position = CGPointMake x, y 23 | addChild sprite 24 | sprite 25 | end 26 | 27 | def update currentTime 28 | @squares.each { |s| s.zRotation += 0.1 } 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /touch-event/app/game_view_controller.rb: -------------------------------------------------------------------------------- 1 | class GameViewController < UIViewController 2 | include ScreenSizes 3 | 4 | def viewDidLoad 5 | super 6 | 7 | self.view = sk_view 8 | 9 | @scene = GameScene.sceneWithSize(sk_view.frame.size) 10 | sk_view.presentScene @scene 11 | end 12 | 13 | def sk_view 14 | @sk_view ||= SKView.alloc.initWithFrame screen_rect 15 | end 16 | 17 | def prefersStatusBarHidden 18 | true 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /touch-event/app/screen_sizes.rb: -------------------------------------------------------------------------------- 1 | module ScreenSizes 2 | def device_screen_width 3 | UIScreen.mainScreen.bounds.size.width 4 | end 5 | 6 | def device_screen_height 7 | UIScreen.mainScreen.bounds.size.height 8 | end 9 | 10 | def screen_rect 11 | CGRectMake(0, 0, device_screen_width, device_screen_height) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /touch-event/readme.md: -------------------------------------------------------------------------------- 1 | # Create Sprite at Point Touched 2 | 3 | This sample app shows how to create sprites at touch locations. 4 | 5 | To run the application: 6 | 7 | `rake` will run the app in the iPhone 6 simulator. 8 | 9 | Here's what it looks like: 10 | 11 |

12 | 13 |

14 | 15 | High level structure: 16 | 17 | - In the `didMoveToView` method, `view.multipleTouchEnabled` is set to 18 | `true`. 19 | - Whenever a touch occurs the `touchesBegan` method is invoked. 20 | - The `touches.allObjects` is enumerated to create a sprite at each 21 | touch location. 22 | - Each sprite is enumerated within the `update` method to get rotated 23 | via the `zRotation` property. 24 | -------------------------------------------------------------------------------- /touch-event/resources/Default-375w-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/touch-event/resources/Default-375w-667h@2x.png -------------------------------------------------------------------------------- /touch-event/resources/Default-414w-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/touch-event/resources/Default-414w-736h@3x.png -------------------------------------------------------------------------------- /touch-event/resources/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/touch-event/resources/Default-568h@2x.png -------------------------------------------------------------------------------- /touch-event/resources/Default-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/touch-event/resources/Default-667h@2x.png -------------------------------------------------------------------------------- /touch-event/resources/Default-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/touch-event/resources/Default-736h@3x.png -------------------------------------------------------------------------------- /touch-event/resources/large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/touch-event/resources/large.png -------------------------------------------------------------------------------- /touch-event/resources/medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/touch-event/resources/medium.png -------------------------------------------------------------------------------- /touch-event/resources/small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/touch-event/resources/small.png -------------------------------------------------------------------------------- /touch-event/resources/square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/touch-event/resources/square.png -------------------------------------------------------------------------------- /touch-event/spec/main_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Application 'sprite-kit-hello-world'" do 2 | before do 3 | @app = UIApplication.sharedApplication 4 | end 5 | 6 | it "has one window" do 7 | @app.windows.size.should == 1 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /touch-event/touch-event.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amirrajan/ios-ruby-game-dev/a11f66a8980b8a638ec44b4712b0eb3f9212a7f0/touch-event/touch-event.gif --------------------------------------------------------------------------------