diff --git a/ios/Escape/LICENSE b/ios/Escape/LICENSE new file mode 100644 index 0000000..95df743 --- /dev/null +++ b/ios/Escape/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Mateus + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/ios/Escape/README.md b/ios/Escape/README.md new file mode 100644 index 0000000..2dd4154 --- /dev/null +++ b/ios/Escape/README.md @@ -0,0 +1,21 @@ +Rubymotion Escape +====== + +Rubymotion Game developed in SpriteKit for iOS7, Apple's new game and physics engine. based on [@StevenVeshkini](https://github.com/StevenVeshkini/) Escape + +# + +While playing around with some ideas for [Coderdojo Cologne](http://zen.coderdojo.com/dojo/385) lessons, +I found [this post](http://www.reddit.com/r/iOSProgramming/comments/1wc0yi/made_a_small_game_with_spritekit_this_is_my_code/) by [@StevenVeshkini](https://github.com/StevenVeshkini/). +So I decided to port it to [Rubymotion](http://www.rubymotion.com) iOS and Mac OS X. At the end I hope to write this or similar games with the kids and +our next [Coderdojo Cologne](http://zen.coderdojo.com/dojo/385). + +Thanks to [Steven Veshkini](https://github.com/StevenVeshkini/) for giving his code for free to ALL. + +This code is under __I don't owe you nothing license__ and MIT. + + +![GameOver](ios_game_over_scene.PNG?raw=true "iOS Gameover Scene" =250x) +![GameScene](ios_game_scene.PNG?raw=true "iOS Game Scene" =250x) +![OSX](osx_game_scene.PNG?raw=true "OS X Game Scene" =250x) +![Start](osx_start_scene.PNG?raw=true "OS X Start A Game Scene" =250x) \ No newline at end of file diff --git a/ios/Escape/app/helpers/constants.rb b/ios/Escape/app/helpers/constants.rb new file mode 100644 index 0000000..0216c26 --- /dev/null +++ b/ios/Escape/app/helpers/constants.rb @@ -0,0 +1,33 @@ +module Escape + + SCREEN_FRAME = CGRect.new([0, 0], [380, 678]) + + unless defined?(SKColor) + SKColor = if defined?(UIColor) + UIColor + elsif defined?(NSColor) + NSColor + end + end + + GAME_SCREEN_COLOR = SKColor.colorWithRed(0.15, green:0.15, blue:0.3, alpha:1.0) + # SKColor.colorWithRed(0.345, green:0.329, blue:0.314, alpha:1.0) + + LEFT_RIGHT_WALL_WIDTH = 10 + TOP_BOTTOM_WALL_HEIGHT = 10 + + module Wall + LEFT = 'leftWall' + RIGHT = 'rightWall' + TOP = 'topWall' + BOTTOM = 'bottomWall' + end + + module Category + WALL = 1 + MONSTER = 2 + PLAYER = 4 + PROJECTILE = 8 + end + +end \ No newline at end of file diff --git a/ios/Escape/app/helpers/vector.rb b/ios/Escape/app/helpers/vector.rb new file mode 100644 index 0000000..f5d2647 --- /dev/null +++ b/ios/Escape/app/helpers/vector.rb @@ -0,0 +1,28 @@ +module Escape # Vector + module Vector + + module_function + + def add(a, b) + CGPoint.new(a.x + b.x, a.y + b.y) + end + + def subtract(a, b) + CGPoint.new(a.x - b.x, a.y - b.y) + end + + def resultantLength(a) + Math.sqrt(a.x * a.x + a.y * a.y) + end + + def multiply(a, withScalar:scalar) + CGPoint.new(a.x * scalar, a.y * scalar) + end + + def normalize(a) + length = resultantLength(a) + CGPoint.new(a.x / length, a.y / length) + end + + end +end \ No newline at end of file diff --git a/ios/Escape/app/models/monster.rb b/ios/Escape/app/models/monster.rb new file mode 100644 index 0000000..ab4dbd5 --- /dev/null +++ b/ios/Escape/app/models/monster.rb @@ -0,0 +1,115 @@ +module Escape # Monster + + # states => :idle | :walking | :seek | :throw + class Monster < SKSpriteNode + + def initWithImageNamed(name) + super.tap do + @score = 0 + @currentState = :idle + end + end + + def moveToSpriteNode(target, withTimeInterval:time) + if @currentState == :idle + targetVector = Vector.subtract(target.position, self.position) + + unitizedVector = Vector.normalize(targetVector) + + shootAmt = Vector.multiply(unitizedVector, withScalar:self.screenSize.height + self.screenSize.width) + + actualDistance = Vector.add(shootAmt, self.position) + + moveAction = SKAction.moveTo(actualDistance, duration:time) + + self.runAction(moveAction) + + @currentState = :seek + end + end + + + def endSeek + self.removeAllActions + self.chooseNextAction + end + + + def chooseNextAction + if randomizer(1..3) <= 1 # 67 % chance to walk + @currentState = :walk + self.monsterWalk + else + if self.score >= 0 && Random.rand(1).zero? # 100% chance to throw projectile (33% overall) + self.shootProjectile + end + end + end + + + def resetState + @currentState = :idle + end + + + def shootProjectile + @currentState = :throw + end + + + def monsterWalk + multiplier = 1.5 + if @currentState == :walk + randomInterval = Random.rand * multiplier # Time between 0 and 1.5s + + # Decide magnitude of walk + walkDistance = randomizer(-80..80) + + # Decide direction of walk depending on the current wall + if self.wallIdentifier == Wall::LEFT || self.wallIdentifier == Wall::RIGHT + wallVertical = SKAction.moveByX(0, y:walkDistance, duration:randomInterval) + resetState = SKAction.performSelector(:resetState, onTarget:self) + self.runAction SKAction.sequence([wallVertical, resetState]) + + elsif self.wallIdentifier == Wall::BOTTOM || self.wallIdentifier == Wall::TOP + walkHorizontal = SKAction.moveByX(walkDistance, y:0, duration:randomInterval) + resetState = SKAction.performSelector(:resetState, onTarget:self) + self.runAction SKAction.sequence([walkHorizontal, resetState]) + end + end + end + + + def updateWithTimeSinceLastUpdate(timeSinceLast) + if self.score >= 100 + time = if self.score <= 1000 + Random.rand + 2.0 + elsif self.score.between?(1000, 3000) + Random.rand + 1.5 + elsif self.score.between?(3000, 5000) + Random.rand + 1.0 + else + Random.rand + 0.7 + end + + if @currentState == :idle + self.moveToSpriteNode(self.target, withTimeInterval:time) + end + + end + end + + + attr_accessor :screenSize, :target, :score, :wallIdentifier + attr_reader :currentState + + + private + + def randomizer(range) + @randomizer ||= Random.new + @randomizer.rand(range) + end + end + +end diff --git a/ios/Escape/app/models/projectile.rb b/ios/Escape/app/models/projectile.rb new file mode 100644 index 0000000..22a82bc --- /dev/null +++ b/ios/Escape/app/models/projectile.rb @@ -0,0 +1,33 @@ +module Escape # Projectile + + class Projectile < SKSpriteNode + + def moveToSpriteNode(target) + # Get vector from projectile to target + targetVector = Vector.subtract(target.position, self.position) + + # Add a random x and y coordinate to the projectile path in order + # to confuse the user and end their game faster + randomizer = Random.new + + x = 8 * randomizer.rand(-25..51) + y = 5 * randomizer.rand(-25..51) + + randomVector = CGPoint.new(targetVector.x + x, targetVector.y + y) + + # make unit vector + direction = Vector.normalize(randomVector) + + # May cause glitches + shootAmount = Vector.multiply(direction, withScalar:self.scene.size.height + self.scene.size.width) + actualDistance = Vector.add(shootAmount, self.position) + + velocity = 200.0 / 1.0 + time = self.scene.size.width / velocity + + actionMove = SKAction.moveTo(actualDistance, duration:time) + self.runAction(actionMove) + end + + end +end diff --git a/ios/Escape/app/scenes/common_scene.rb b/ios/Escape/app/scenes/common_scene.rb new file mode 100644 index 0000000..8497b8a --- /dev/null +++ b/ios/Escape/app/scenes/common_scene.rb @@ -0,0 +1,17 @@ +module Escape # CommonScene + class CommonScene < SKScene + + def didMoveToView(view) + unless @_contentCreated + createSceneContents + @_contentCreated = true + end + end + + + # you better override this :-) + def createSceneContents + end + + end +end \ No newline at end of file diff --git a/ios/Escape/app/scenes/game_over_scene.rb b/ios/Escape/app/scenes/game_over_scene.rb new file mode 100644 index 0000000..b288fae --- /dev/null +++ b/ios/Escape/app/scenes/game_over_scene.rb @@ -0,0 +1,86 @@ +module Escape # GameOverScene + class GameOverScene < CommonScene + + def initWithSize(sceneSize, userData:userData) + initWithSize(sceneSize).tap do |newScene| + self.userData = userData + @_didTap = false + end + end + + attr_accessor :score + + def touchesBegan(touches, withEvent:event) + unless @_didTap # Called when user taps screen + presentMainScene = SKAction.runBlock(-> { + @_didTap = true + gameScene = MainGameScene.sceneWithSize(self.size) + transition = SKTransition.pushWithDirection(SKTransitionDirectionUp, duration:1.0) + backgroundMusicPlayer.stop + transition.pausesIncomingScene = true + self.scene.view.presentScene(gameScene, transition:transition) + }) + + self.runAction(presentMainScene) + end + end + + + def backgroundMusicPlayer + @backgroundMusicPlayer ||= begin + error = Pointer.new(:object) + musicURL = NSBundle.mainBundle.URLForResource('8-bit loop (loop)', withExtension:'mp3') + audioPlayer = AVAudioPlayer.alloc.initWithContentsOfURL(musicURL, error:error) + audioPlayer.volume = 0.2 + audioPlayer.numberOfLoops = -1 + audioPlayer.prepareToPlay + audioPlayer + end + end + + + private + + + def createSceneContents + # Start background music + backgroundMusicPlayer.play + + # Configure background color + self.backgroundColor = GAME_SCREEN_COLOR + self.scaleMode = SKSceneScaleModeAspectFit + + # Display labels + self.score = self.userData[:score] + + labelPosition = CGPoint.new(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) + 200) + firstLabel = createLabel('GAME OVER', fontSize:42, position:labelPosition) + # firstLabel.fontColor = SKColor.blackColor + + labelPosition = CGPoint.new(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) + 35) + secondLabel = createLabel('SCORE:', fontSize:28, position:labelPosition) + + labelPosition = CGPoint.new(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) - 175) + thirdLabel = createLabel('TAP TO PLAY AGAIN!', fontSize:16, position:labelPosition) + + labelPosition = CGPoint.new(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)) + fourthLabel = createLabel("#{self.score}", fontSize:36, position:labelPosition) + + self.addChild(firstLabel) + self.addChild(secondLabel) + self.addChild(thirdLabel) + self.addChild(fourthLabel) + end + + + def createLabel(text, fontSize:fontSize, position:position) + SKLabelNode.labelNodeWithFontNamed('BankGothicBold').tap do |label| + label.text = text + label.name = text + label.fontSize = fontSize + label.position = position + end + end + + end +end diff --git a/ios/Escape/app/scenes/main_game_scene.rb b/ios/Escape/app/scenes/main_game_scene.rb new file mode 100644 index 0000000..76b2c0e --- /dev/null +++ b/ios/Escape/app/scenes/main_game_scene.rb @@ -0,0 +1,283 @@ +module Escape # GameScreen + class MainGameScene < CommonScene + + attr_accessor :score + + def initWithSize(size) + super + end + + # Create and configure monster sprite + def monster + @monster ||= Monster.spriteNodeWithImageNamed('blockerMad').tap do |mo| + mo.position = CGPoint.new(CGRectGetMidX(self.frame), CGRectGetMinY(self.frame)+mo.size.height/2) + mo.physicsBody = SKPhysicsBody.bodyWithRectangleOfSize(mo.size) + mo.physicsBody.categoryBitMask = Category::MONSTER + mo.physicsBody.contactTestBitMask = Category::WALL | Category::PLAYER + mo.physicsBody.collisionBitMask = Category::WALL + end + end + + # Create and configure player sprite + def player + @player ||= SKSpriteNode.spriteNodeWithImageNamed('hud_p1_opt').tap do |pl| + pl.position = CGPoint.new(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)) + pl.physicsBody = SKPhysicsBody.bodyWithRectangleOfSize(pl.size) + pl.physicsBody.categoryBitMask = Category::PLAYER + pl.physicsBody.contactTestBitMask = Category::WALL | Category::MONSTER + pl.physicsBody.collisionBitMask = Category::WALL + pl.physicsBody.dynamic = true + pl.physicsBody.usesPreciseCollisionDetection = true + pl.physicsBody.velocity = CGVector.new(0, 0) + end + end + + # Create and configure wall boundaries + def leftWall + wallNamed(Wall::LEFT, ofSize:CGSize.new(10, @screenWindow.size.height)) do |wall| + wall.position = CGPoint.new(CGRectGetMinX(self.frame), (wall.size.height/2)) + end + end + + def rightWall + wallNamed(Wall::RIGHT, ofSize:CGSize.new(10, @screenWindow.size.height)) do |wall| + wall.position = CGPoint.new(CGRectGetMaxX(self.frame), (wall.size.height/2)) + end + end + + def topWall + wallNamed(Wall::TOP, ofSize:CGSize.new(@screenWindow.size.width, 10)) do |wall| + wall.position = CGPoint.new(wall.size.width/2, CGRectGetMaxY(self.frame)) + end + end + + def bottomWall + wallNamed(Wall::BOTTOM, ofSize:CGSize.new(@screenWindow.size.width, 10)) do |wall| + wall.position = CGPoint.new(wall.size.width/2, CGRectGetMinY(self.frame)*2) + end + end + + def scoreLabel + @scoreLabel ||= SKLabelNode.labelNodeWithFontNamed('BankGothicBold').tap do |lb| + # lb.fontColor = SKColor.blackColor + lb.fontSize = 14; + lb.text = "Score: #@score" + lb.name = "Score" + lb.position = CGPoint.new(CGRectGetMaxX(self.frame) - lb.frame.size.width, CGRectGetMinY(self.frame) + lb.frame.size.height) + end + end + + # Configure and run background music + def backgroundMusicPlayer + @backgroundMusicPlayer ||= begin + error = Pointer.new(:object) + musicURL = NSBundle.mainBundle.URLForResource('Endless Sand', withExtension:'mp3') + audioPlayer = AVAudioPlayer.alloc.initWithContentsOfURL(musicURL, error:error) + audioPlayer.volume = 0.2 + audioPlayer.numberOfLoops = -1 + audioPlayer.prepareToPlay + audioPlayer + end + end + + def dragPlayer(gesture) + if gesture.state == UIGestureRecognizerStateChanged + # Get the (x,y) translation coordinate + translation = gesture.translationInView(self.view) + + # Move by -y because moving positive is right and down, we want right and up + # so that we can match the user's drag location (SKView rectangle y is opp UIView) + newLocation = CGPoint.new(self.player.position.x + translation.x, self.player.position.y - translation.y) + + # Check if location is in bounds of screen + self.player.position = checkBounds(newLocation) + + # Reset the translation point to the origin so that translation does not accumulate + gesture.setTranslation(CGPoint.new, inView:self.view) + end + end + + def updateWithTimeSinceLastUpdate(timeSinceLast) + @lastMoveTimeInterval += timeSinceLast + @lastMoveTimeInterval = 0 if @lastMoveTimeInterval > 1 + + # Update score + self.score += 1 + self.scoreLabel.text = "Score: #@score" + self.monster.score = self.score + + # Update the monster's state + self.monster.updateWithTimeSinceLastUpdate(timeSinceLast) + + # Handle projectile throwing + if self.score > 100 && self.monster.currentState == :throw + self.shootProjectile + end + end + + def update(currentTime) + + timeSinceLast = currentTime - @lastUpdateTimeInterval + @lastUpdateTimeInterval = currentTime + + # more than a second since last update + if timeSinceLast > 1 + timeSinceLast = 1.0 / 60.0 + @lastUpdateTimeInterval = currentTime # ????? + end + + self.updateWithTimeSinceLastUpdate(timeSinceLast) + end + + def didBeginContact(contact) + if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask + firstBody, secondBody = contact.bodyA, contact.bodyB + else + firstBody, secondBody = contact.bodyB, contact.bodyA + end + + # wall and Monster + if firstBody.categoryBitMask & Category::WALL != 0 && secondBody.categoryBitMask & Category::MONSTER != 0 + self.monster.wallIdentifier = firstBody.node.name + self.monster.endSeek + end + + # Wall and Player + if firstBody.categoryBitMask & Category::WALL != 0 && secondBody.categoryBitMask & Category::PLAYER != 0 + self.score = 0 + end + + # Monster and Player + if firstBody.categoryBitMask & Category::MONSTER != 0 && secondBody.categoryBitMask & Category::PLAYER != 0 + self.removeAllActions + self.gameOver + end + + # Wall and Projectile + if firstBody.categoryBitMask & Category::WALL != 0 && secondBody.categoryBitMask & Category::PROJECTILE != 0 + secondBody.node.removeFromParent + end + + # Player and Projectile + if firstBody.categoryBitMask & Category::PLAYER != 0 && secondBody.categoryBitMask & Category::PROJECTILE != 0 + self.removeAllActions + self.gameOver + end + + end + + def shootProjectile + # Create and configure a projectile + projectile = Projectile.spriteNodeWithImageNamed('blockerBodySmall').tap do |proj| + proj.position = self.monster.position; + proj.physicsBody = SKPhysicsBody.bodyWithRectangleOfSize(proj.size) + proj.physicsBody.dynamic = true + proj.physicsBody.usesPreciseCollisionDetection = true + proj.physicsBody.categoryBitMask = Category::PROJECTILE + proj.physicsBody.contactTestBitMask = Category::WALL | Category::PLAYER + proj.physicsBody.collisionBitMask = 0 + end + + self.addChild(projectile) + + # Fire the projectile + projectile.moveToSpriteNode(self.player) + + action = SKAction.rotateByAngle(380, duration: 0.2) + finalAction = SKAction.repeatActionForever(action) + projectile.runAction(finalAction) + + self.monster.resetState + end + + def gameOver + # Save the score and pass it to the game over screen + self.userData = { score: self.score } + gameOverScreen = GameOverScene.alloc.initWithSize(self.size, userData: self.userData) + self.backgroundMusicPlayer.stop + + # Transition to new view + transition = SKTransition.pushWithDirection(SKTransitionDirectionUp, duration:1.0) + transition.pausesOutgoingScene = true + self.view.presentScene(gameOverScreen, transition:transition) + end + + private + + def checkBounds(newLocation) + # This method will make sure the object is not outside of the bounds of the screen + screenSize = self.size + retValue = newLocation + retValue.x = [retValue.x, LEFT_RIGHT_WALL_WIDTH].max + retValue.x = [retValue.x, screenSize.width - LEFT_RIGHT_WALL_WIDTH].min + retValue.y = [retValue.y, TOP_BOTTOM_WALL_HEIGHT].max + retValue.y = [retValue.y, screenSize.height - TOP_BOTTOM_WALL_HEIGHT].min + retValue + end + + def createSceneContents + @lastMoveTimeInterval = 0 + @lastUpdateTimeInterval = 0 + self.score = 0 + + # Separate method to configure all of the scene to reduce overhead upon initialization + # Set up physics world and background + self.backgroundColor = GAME_SCREEN_COLOR + self.scaleMode = SKSceneScaleModeAspectFit + self.physicsWorld.contactDelegate = self + self.anchorPoint = CGPoint.new(0.0, 0.0) + self.physicsWorld.gravity = CGVector.new(0.0, 0.0) # No gravity + + # set monster target to player + self.monster.target = self.player + + # Get bounds of device screen + # to get it running on OSX and iOS + if defined?(UIScreen) + @screenWindow = UIScreen.mainScreen.bounds + elsif defined?(NSApplication) + @screenWindow = NSApplication.sharedApplication.delegate.window.contentView.bounds + end + + self.monster.screenSize = @screenWindow.size + + # Add nodes to scene + self.addChild(self.monster) + self.addChild(self.player) + self.addChild(self.leftWall) + self.addChild(self.topWall) + self.addChild(self.rightWall) + self.addChild(self.bottomWall) + self.addChild(self.scoreLabel) + + # Configure the pan gesture (dragging finger across the screen) + # to track and drag the player sprite accordingly + @panGesture ||= UIPanGestureRecognizer.alloc.initWithTarget(self, action:'dragPlayer:').tap do |gesture| + gesture.minimumNumberOfTouches = 1 + gesture.delegate = self + self.view.addGestureRecognizer(gesture) + end if defined?(UIPanGestureRecognizer) + + # Configure and run background music + self.backgroundMusicPlayer.play + end + + def wallNamed(wallName, ofSize:size) + var_name = wallName[0].downcase + wallName[1, wallName.length - 1].gsub(/\s/, '') + instance_variable_get("@#{var_name}") || + instance_variable_set("@#{var_name}", SKSpriteNode.spriteNodeWithColor(SKColor.blackColor, size:size)).tap do |wall| + + yield(wall) if block_given? + + wall.physicsBody = SKPhysicsBody.bodyWithRectangleOfSize(wall.size) + wall.physicsBody.categoryBitMask = Category::WALL + wall.physicsBody.contactTestBitMask = Category::MONSTER | Category::PLAYER + wall.physicsBody.collisionBitMask = Category::PLAYER + wall.physicsBody.dynamic = false + wall.physicsBody.resting = true + wall.name = wallName + end + end + + end +end \ No newline at end of file diff --git a/ios/Escape/app/scenes/start_scene.rb b/ios/Escape/app/scenes/start_scene.rb new file mode 100644 index 0000000..94b3818 --- /dev/null +++ b/ios/Escape/app/scenes/start_scene.rb @@ -0,0 +1,71 @@ +module Escape + class StartScene < CommonScene + + def touchesBegan(touches, withEvent:event) + unless @_didTap + presentMainScene = SKAction.runBlock(-> { + @_didTap = true + gameScene = MainGameScene.sceneWithSize(self.size) + # transition = SKTransition.pushWithDirection(SKTransitionDirectionUp, duration:1.0) + doors = SKTransition.doorsOpenHorizontalWithDuration(1.0) + # transition.pausesIncomingScene = true + doors.pausesIncomingScene = true + self.scene.view.presentScene(gameScene, transition:doors) + }) + + button = self.childNodeWithName('Start Button') + if button + moveSequence = animateStartbutton(button) + button.runAction(moveSequence, completion:-> { + self.runAction(presentMainScene) + }) + else + self.runAction(presentMainScene) + end + + end + end + + + def update(currentTime) + end + + + private + + def createSceneContents + @_didTap = false + + self.backgroundColor = GAME_SCREEN_COLOR + self.scaleMode = SKSceneScaleModeAspectFit + + gameNameLabel = SKLabelNode.labelNodeWithFontNamed('BankGothicBold').tap do |label| + label.text = 'ESCAPE' + label.name = 'Escape' + label.fontSize = 42 + label.position = CGPoint.new(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)+100) + end + + startLabel = SKLabelNode.labelNodeWithFontNamed('BankGothicBold').tap do |label| + label.text = 'TAP TO START!' + label.name = 'Start Button' + label.fontSize = 20 + label.position = CGPoint.new(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)-100) + end + + self.addChild(gameNameLabel) + self.addChild(startLabel) + end + + def animateStartbutton(startButton) + startButton.name = nil + SKAction.sequence([ + SKAction.moveByX(0, y:100.0, duration:0.2), + SKAction.scaleTo(0.5, duration:0.2), + SKAction.waitForDuration(0.1), + SKAction.fadeOutWithDuration(0.1), + SKAction.removeFromParent, + ]) + end + end +end diff --git a/ios/Escape/ios/.gitignore b/ios/Escape/ios/.gitignore new file mode 100644 index 0000000..c357662 --- /dev/null +++ b/ios/Escape/ios/.gitignore @@ -0,0 +1,16 @@ +.repl_history +build +tags +app/pixate_code.rb +resources/*.nib +resources/*.momd +resources/*.storyboardc +.DS_Store +nbproject +.redcar +#*# +*~ +*.sw[po] +.eprj +.sass-cache +.idea diff --git a/ios/Escape/ios/Gemfile b/ios/Escape/ios/Gemfile new file mode 100644 index 0000000..764be63 --- /dev/null +++ b/ios/Escape/ios/Gemfile @@ -0,0 +1,4 @@ +source 'https://rubygems.org' + +gem 'rake' +# Add your dependencies here: diff --git a/ios/Escape/ios/Gemfile.lock b/ios/Escape/ios/Gemfile.lock new file mode 100644 index 0000000..8051ba8 --- /dev/null +++ b/ios/Escape/ios/Gemfile.lock @@ -0,0 +1,10 @@ +GEM + remote: https://rubygems.org/ + specs: + rake (10.1.0) + +PLATFORMS + ruby + +DEPENDENCIES + rake diff --git a/ios/Escape/ios/Rakefile b/ios/Escape/ios/Rakefile new file mode 100644 index 0000000..4df2e64 --- /dev/null +++ b/ios/Escape/ios/Rakefile @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +$:.unshift("/Library/RubyMotion/lib") +require 'motion/project/template/ios' + +begin + require 'bundler' + Bundler.require +rescue LoadError +end + +Motion::Project::App.setup do |app| + # Use `rake config' to see complete project settings. + # app.delegate_class = 'Escape::AppDelegate' + app.name = 'Escape' + app.frameworks += %W{SpriteKit} + app.files += Dir.glob(File.join(File.dirname(__FILE__), '../app/**/*.rb')) + app.resources_dirs << '../resources' + + app.info_plist['UIStatusBarHidden'] = true + + app.info_plist['UISupportedInterfaceOrientations~ipad'] = [ + 'UIInterfaceOrientationPortrait', + 'UIInterfaceOrientationPortraitUpsideDown', + 'UIInterfaceOrientationLandscapeLeft', + 'UIInterfaceOrientationLandscapeRight', + ] + + app.info_plist['UISupportedInterfaceOrientations'] = [ + 'UIInterfaceOrientationPortrait', + 'UIInterfaceOrientationPortraitUpsideDown', + ] + + app.info_plist['UIViewControllerBasedStatusBarAppearance'] = false +end diff --git a/ios/Escape/ios/app/app_delegate.rb b/ios/Escape/ios/app/app_delegate.rb new file mode 100644 index 0000000..e1d7996 --- /dev/null +++ b/ios/Escape/ios/app/app_delegate.rb @@ -0,0 +1,22 @@ +module Escape + class AppDelegate + def application(application, willFinishLaunchingWithOptions:launchOptions) + true + end + + def application(application, didFinishLaunchingWithOptions:launchOptions) + UIApplication.sharedApplication.setStatusBarHidden true + mainViewController = MainViewController.alloc.init + # mainViewController.edgesForExtendedLayout = UIRectEdgeNone + mainViewController.wantsFullScreenLayout = true + self.window.rootViewController = mainViewController + self.window.makeKeyAndVisible + true + end + + def window + @_window ||= UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds) + end + + end +end diff --git a/ios/Escape/ios/app/controllers/main_view_controller.rb b/ios/Escape/ios/app/controllers/main_view_controller.rb new file mode 100644 index 0000000..2f20137 --- /dev/null +++ b/ios/Escape/ios/app/controllers/main_view_controller.rb @@ -0,0 +1,44 @@ +module Escape + + class MainViewController < UIViewController + + def loadView + self.view = SKView.alloc.initWithFrame(UIScreen.mainScreen.bounds) + self.view.accessibilityLabel = 'Game View' + end + + def viewDidLoad + super + ## FOR DEBUGGING pretty handy + # self.view.showsDrawCount = true + # self.view.showsNodeCount = true + # self.view.showsFPS = true + end + + + def viewWillAppear(animated) + # Configure the view + scene = StartScene.sceneWithSize(self.view.bounds.size) + scene.scaleMode = SKSceneScaleModeAspectFill + + # Present the scene. + self.view.presentScene(scene) + end + + + def prefersStatusBarHidden + true + end + + + def shouldAutorotate + true + end + + + def supportedInterfaceOrientations + Device.iphone? ? UIInterfaceOrientationMaskAllButUpsideDown : UIInterfaceOrientationMaskAll + end + end + +end diff --git a/ios/Escape/ios/app/helpers/device.rb b/ios/Escape/ios/app/helpers/device.rb new file mode 100644 index 0000000..b591cc6 --- /dev/null +++ b/ios/Escape/ios/app/helpers/device.rb @@ -0,0 +1,11 @@ +module Escape + module Device + module_function + # Verifies that the device running the app is an iPhone. + # @return [TrueClass, FalseClass] true will be returned if the device is an iPhone, false otherwise. + # copied from BubbleWrap + def iphone?(idiom=UIDevice.currentDevice.userInterfaceIdiom) + idiom == UIUserInterfaceIdiomPhone + end + end +end diff --git a/ios/Escape/ios/resources/Default-568h@2x.png b/ios/Escape/ios/resources/Default-568h@2x.png new file mode 100644 index 0000000..87de555 Binary files /dev/null and b/ios/Escape/ios/resources/Default-568h@2x.png differ diff --git a/ios/Escape/ios/spec/main_spec.rb b/ios/Escape/ios/spec/main_spec.rb new file mode 100644 index 0000000..237e688 --- /dev/null +++ b/ios/Escape/ios/spec/main_spec.rb @@ -0,0 +1,9 @@ +describe "Application 'Escape'" do + before do + @app = UIApplication.sharedApplication + end + + it "has one window" do + @app.windows.size.should == 1 + end +end diff --git a/ios/Escape/ios/spec/main_view_controller_spec.rb b/ios/Escape/ios/spec/main_view_controller_spec.rb new file mode 100644 index 0000000..80be2f9 --- /dev/null +++ b/ios/Escape/ios/spec/main_view_controller_spec.rb @@ -0,0 +1,30 @@ +describe Escape::MainViewController do + + tests Escape::MainViewController + + def instance_of?(klass) + lambda { |obj| obj.class == klass } + end + + it 'the view is a spriteKit view [SKView]' do + controller.view.should.be.a instance_of?(SKView) + end + + it 'shows the start [Game scene]' do + controller.view.scene.should.be.a instance_of?(Escape::StartScene) + end + + it 'after a tap should move to [Main Game scene]' do + tap 'Game View' + wait 2.0 do + controller.view.scene.should.be.a instance_of?(Escape::MainGameScene) + end + end + + it 'once killed should move to [Game Over scene]' do + tap 'Game View' + wait 3.5 do + controller.view.scene.should.be.a instance_of?(Escape::GameOverScene) + end + end +end \ No newline at end of file diff --git a/ios/Escape/ios/spec/scenes/0_shared_scene_spec.rb b/ios/Escape/ios/spec/scenes/0_shared_scene_spec.rb new file mode 100644 index 0000000..bc5b172 --- /dev/null +++ b/ios/Escape/ios/spec/scenes/0_shared_scene_spec.rb @@ -0,0 +1,7 @@ +shared 'Scene' do + + def have_child_named?(name) + lambda { |obj| !obj.childNodeWithName(name).nil? } + end + +end diff --git a/ios/Escape/ios/spec/scenes/game_over_scene_spec.rb b/ios/Escape/ios/spec/scenes/game_over_scene_spec.rb new file mode 100644 index 0000000..54ec2e5 --- /dev/null +++ b/ios/Escape/ios/spec/scenes/game_over_scene_spec.rb @@ -0,0 +1,35 @@ +describe Escape::GameOverScene do + + behaves_like 'Scene' + + before do + @view = SKView.alloc.initWithFrame(UIScreen.mainScreen.bounds) + @scene = Escape::GameOverScene.alloc.initWithSize(@view.bounds.size, userData: {score: 10}) + @view.presentScene(@scene) + end + + it 'First Scene should have 4 Nodes' do + @scene.children.count.should == 4 + end + + it "should have a Node named 'GAME OVER'" do + @scene.should have_child_named?('GAME OVER') + end + + it "should have a Node named 'SCORE:'" do + @scene.should have_child_named?('SCORE:') + end + + it "should have a Node named 'TAP TO PLAY AGAIN!'" do + @scene.should have_child_named?('TAP TO PLAY AGAIN!') + end + + it "should have a Node named [Score=10]" do + @scene.should have_child_named?('10') + end + + it 'should play background music' do + @scene.backgroundMusicPlayer.playing?.should.be == true + end + +end \ No newline at end of file diff --git a/ios/Escape/ios/spec/scenes/main_game_scene_spec.rb b/ios/Escape/ios/spec/scenes/main_game_scene_spec.rb new file mode 100644 index 0000000..d875a84 --- /dev/null +++ b/ios/Escape/ios/spec/scenes/main_game_scene_spec.rb @@ -0,0 +1,39 @@ +describe Escape::MainGameScene do + + behaves_like 'Scene' + + before do + @view = SKView.alloc.initWithFrame(UIScreen.mainScreen.bounds) + @scene = Escape::MainGameScene.sceneWithSize(@view.bounds.size) + @view.presentScene(@scene) + end + + it 'First Scene should have 7 Nodes' do + @scene.children.count.should == 7 + end + + it "should have a Node named #{Escape::Wall::LEFT}" do + @scene.should have_child_named?(Escape::Wall::LEFT) + end + + it "should have a Node named #{Escape::Wall::RIGHT}" do + @scene.should have_child_named?(Escape::Wall::RIGHT) + end + + it "should have a Node named #{Escape::Wall::TOP}" do + @scene.should have_child_named?(Escape::Wall::TOP) + end + + it "should have a Node named #{Escape::Wall::BOTTOM}" do + @scene.should have_child_named?(Escape::Wall::BOTTOM) + end + + it "should have a Node named Score" do + @scene.should have_child_named?('Score') + end + + it 'should play background music' do + @scene.backgroundMusicPlayer.playing?.should.be == true + end + +end \ No newline at end of file diff --git a/ios/Escape/ios/spec/scenes/start_scene_spec.rb b/ios/Escape/ios/spec/scenes/start_scene_spec.rb new file mode 100644 index 0000000..909d0e0 --- /dev/null +++ b/ios/Escape/ios/spec/scenes/start_scene_spec.rb @@ -0,0 +1,24 @@ +describe Escape::StartScene do + + behaves_like 'Scene' + + before do + @view = SKView.alloc.initWithFrame(UIScreen.mainScreen.bounds) + @scene = Escape::StartScene.sceneWithSize(@view.bounds.size) + @view.presentScene(@scene) + end + + + it 'First Scene should have 2 Nodes' do + @scene.children.count.should == 2 + end + + it 'should have a Title Node ESCAPE,' do + @scene.should have_child_named?('Escape') + end + + it 'should have a Start Button Node' do + @scene.should have_child_named?('Start Button') + end + +end \ No newline at end of file diff --git a/ios/Escape/ios/spec/vector_spec.rb b/ios/Escape/ios/spec/vector_spec.rb new file mode 100644 index 0000000..1ded481 --- /dev/null +++ b/ios/Escape/ios/spec/vector_spec.rb @@ -0,0 +1,28 @@ +describe Escape::Vector do + before do + @firstPoint = CGPoint.new(10, 10); + @secondPoint = CGPoint.new(20, 20); + end + + it '::normalize' do + normalized = Escape::Vector.normalize(@firstPoint) + normalized.x.should.be.close? 0.70, 0.71 + normalized.y.should.be.close? 0.70, 0.71 + normalized.should == CGPoint.new(0.70710678118654746, 0.70710678118654746) + end + + it '::multiply:withScalar:' do + multiply = Escape::Vector.multiply(@firstPoint, withScalar:10.0) + multiply.should == CGPoint.new(100, 100) + end + + it '::subtract' do + subtraction = Escape::Vector.subtract(@firstPoint, @secondPoint) + subtraction.should == CGPoint.new(-10, -10) + end + + it '::add' do + addition = Escape::Vector.add(@firstPoint, @secondPoint) + addition.should == CGPoint.new(30, 30) + end +end diff --git a/ios/Escape/ios_game_over_scene.PNG b/ios/Escape/ios_game_over_scene.PNG new file mode 100644 index 0000000..41c636a Binary files /dev/null and b/ios/Escape/ios_game_over_scene.PNG differ diff --git a/ios/Escape/ios_game_scene.PNG b/ios/Escape/ios_game_scene.PNG new file mode 100644 index 0000000..6d122db Binary files /dev/null and b/ios/Escape/ios_game_scene.PNG differ diff --git a/ios/Escape/osx/.gitignore b/ios/Escape/osx/.gitignore new file mode 100644 index 0000000..c357662 --- /dev/null +++ b/ios/Escape/osx/.gitignore @@ -0,0 +1,16 @@ +.repl_history +build +tags +app/pixate_code.rb +resources/*.nib +resources/*.momd +resources/*.storyboardc +.DS_Store +nbproject +.redcar +#*# +*~ +*.sw[po] +.eprj +.sass-cache +.idea diff --git a/ios/Escape/osx/Gemfile b/ios/Escape/osx/Gemfile new file mode 100644 index 0000000..764be63 --- /dev/null +++ b/ios/Escape/osx/Gemfile @@ -0,0 +1,4 @@ +source 'https://rubygems.org' + +gem 'rake' +# Add your dependencies here: diff --git a/ios/Escape/osx/Gemfile.lock b/ios/Escape/osx/Gemfile.lock new file mode 100644 index 0000000..8051ba8 --- /dev/null +++ b/ios/Escape/osx/Gemfile.lock @@ -0,0 +1,10 @@ +GEM + remote: https://rubygems.org/ + specs: + rake (10.1.0) + +PLATFORMS + ruby + +DEPENDENCIES + rake diff --git a/ios/Escape/osx/Rakefile b/ios/Escape/osx/Rakefile new file mode 100644 index 0000000..fce5c31 --- /dev/null +++ b/ios/Escape/osx/Rakefile @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +$:.unshift("/Library/RubyMotion/lib") +require 'motion/project/template/osx' + +begin + require 'bundler' + Bundler.require +rescue LoadError +end + +Motion::Project::App.setup do |app| + # Use `rake config' to see complete project settings. + app.name = 'Escape' + app.files += Dir.glob(File.join(File.dirname(__FILE__), '../app/**/*.rb')) + app.resources_dirs << '../resources' + app.frameworks += %W{SpriteKit} +end diff --git a/ios/Escape/osx/app/app_delegate.rb b/ios/Escape/osx/app/app_delegate.rb new file mode 100644 index 0000000..129d6fc --- /dev/null +++ b/ios/Escape/osx/app/app_delegate.rb @@ -0,0 +1,23 @@ +class AppDelegate + def applicationDidFinishLaunching(notification) + buildMenu + buildWindow + mainViewController = Escape::MainViewController.new + mainViewController.view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable + self.window.contentView.addSubview(mainViewController.view) + self.window.acceptsMouseMovedEvents = true + self.window.makeFirstResponder(mainViewController.view.scene) + end + + def buildWindow + window.title = NSBundle.mainBundle.infoDictionary['CFBundleName'] + window.orderFrontRegardless + end + + def window + @_window ||= NSWindow.alloc.initWithContentRect([[240, 180], Escape::SCREEN_FRAME.size], + styleMask: NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask, + backing: NSBackingStoreBuffered, + defer: false) + end +end diff --git a/ios/Escape/osx/app/controllers/main_view_controller.rb b/ios/Escape/osx/app/controllers/main_view_controller.rb new file mode 100644 index 0000000..25a41f1 --- /dev/null +++ b/ios/Escape/osx/app/controllers/main_view_controller.rb @@ -0,0 +1,24 @@ +module Escape + class MainViewController < NSViewController + + def loadView + self.view = SKView.alloc.initWithFrame(SCREEN_FRAME) + viewDidLoad + end + + def viewDidLoad + ## FOR DEBUGGING pretty handy + # self.view.showsDrawCount = true + # self.view.showsNodeCount = true + # self.view.showsFPS = true + + # Configure the view + scene = StartScene.sceneWithSize(self.view.bounds.size) + scene.scaleMode = SKSceneScaleModeAspectFill + + # Present the scene. + self.view.presentScene(scene) + end + + end +end diff --git a/ios/Escape/osx/app/menu.rb b/ios/Escape/osx/app/menu.rb new file mode 100644 index 0000000..3c02b24 --- /dev/null +++ b/ios/Escape/osx/app/menu.rb @@ -0,0 +1,110 @@ +class AppDelegate + def buildMenu + @mainMenu = NSMenu.new + + appName = NSBundle.mainBundle.infoDictionary['CFBundleName'] + addMenu(appName) do + addItemWithTitle("About #{appName}", action: 'orderFrontStandardAboutPanel:', keyEquivalent: '') + addItem(NSMenuItem.separatorItem) + addItemWithTitle('Preferences', action: 'openPreferences:', keyEquivalent: ',') + addItem(NSMenuItem.separatorItem) + servicesItem = addItemWithTitle('Services', action: nil, keyEquivalent: '') + NSApp.servicesMenu = servicesItem.submenu = NSMenu.new + addItem(NSMenuItem.separatorItem) + addItemWithTitle("Hide #{appName}", action: 'hide:', keyEquivalent: 'h') + item = addItemWithTitle('Hide Others', action: 'hideOtherApplications:', keyEquivalent: 'H') + item.keyEquivalentModifierMask = NSCommandKeyMask|NSAlternateKeyMask + addItemWithTitle('Show All', action: 'unhideAllApplications:', keyEquivalent: '') + addItem(NSMenuItem.separatorItem) + addItemWithTitle("Quit #{appName}", action: 'terminate:', keyEquivalent: 'q') + end + + addMenu('File') do + addItemWithTitle('New', action: 'newDocument:', keyEquivalent: 'n') + addItemWithTitle('Open…', action: 'openDocument:', keyEquivalent: 'o') + addItem(NSMenuItem.separatorItem) + addItemWithTitle('Close', action: 'performClose:', keyEquivalent: 'w') + addItemWithTitle('Save…', action: 'saveDocument:', keyEquivalent: 's') + addItemWithTitle('Revert to Saved', action: 'revertDocumentToSaved:', keyEquivalent: '') + addItem(NSMenuItem.separatorItem) + addItemWithTitle('Page Setup…', action: 'runPageLayout:', keyEquivalent: 'P') + addItemWithTitle('Print…', action: 'printDocument:', keyEquivalent: 'p') + end + + addMenu('Edit') do + addItemWithTitle('Undo', action: 'undo:', keyEquivalent: 'z') + addItemWithTitle('Redo', action: 'redo:', keyEquivalent: 'Z') + addItem(NSMenuItem.separatorItem) + addItemWithTitle('Cut', action: 'cut:', keyEquivalent: 'x') + addItemWithTitle('Copy', action: 'copy:', keyEquivalent: 'c') + addItemWithTitle('Paste', action: 'paste:', keyEquivalent: 'v') + item = addItemWithTitle('Paste and Match Style', action: 'pasteAsPlainText:', keyEquivalent: 'V') + item.keyEquivalentModifierMask = NSCommandKeyMask|NSAlternateKeyMask + addItemWithTitle('Delete', action: 'delete:', keyEquivalent: '') + addItemWithTitle('Select All', action: 'selectAll:', keyEquivalent: 'a') + end + + fontMenu = createMenu('Font') do + addItemWithTitle('Show Fonts', action: 'orderFrontFontPanel:', keyEquivalent: 't') + addItemWithTitle('Bold', action: 'addFontTrait:', keyEquivalent: 'b') + addItemWithTitle('Italic', action: 'addFontTrait:', keyEquivalent: 'i') + addItemWithTitle('Underline', action: 'underline:', keyEquivalent: 'u') + addItem(NSMenuItem.separatorItem) + addItemWithTitle('Bigger', action: 'modifyFont:', keyEquivalent: '+') + addItemWithTitle('Smaller', action: 'modifyFont:', keyEquivalent: '-') + end + + textMenu = createMenu('Text') do + addItemWithTitle('Align Left', action: 'alignLeft:', keyEquivalent: '{') + addItemWithTitle('Center', action: 'alignCenter:', keyEquivalent: '|') + addItemWithTitle('Justify', action: 'alignJustified:', keyEquivalent: '') + addItemWithTitle('Align Right', action: 'alignRight:', keyEquivalent: '}') + addItem(NSMenuItem.separatorItem) + addItemWithTitle('Show Ruler', action: 'toggleRuler:', keyEquivalent: '') + item = addItemWithTitle('Copy Ruler', action: 'copyRuler:', keyEquivalent: 'c') + item.keyEquivalentModifierMask = NSCommandKeyMask|NSControlKeyMask + item = addItemWithTitle('Paste Ruler', action: 'pasteRuler:', keyEquivalent: 'v') + item.keyEquivalentModifierMask = NSCommandKeyMask|NSControlKeyMask + end + + addMenu('Format') do + addItem fontMenu + addItem textMenu + end + + addMenu('View') do + item = addItemWithTitle('Show Toolbar', action: 'toggleToolbarShown:', keyEquivalent: 't') + item.keyEquivalentModifierMask = NSCommandKeyMask|NSAlternateKeyMask + addItemWithTitle('Customize Toolbar…', action: 'runToolbarCustomizationPalette:', keyEquivalent: '') + end + + NSApp.windowsMenu = addMenu('Window') do + addItemWithTitle('Minimize', action: 'performMiniaturize:', keyEquivalent: 'm') + addItemWithTitle('Zoom', action: 'performZoom:', keyEquivalent: '') + addItem(NSMenuItem.separatorItem) + addItemWithTitle('Bring All To Front', action: 'arrangeInFront:', keyEquivalent: '') + end.menu + + NSApp.helpMenu = addMenu('Help') do + addItemWithTitle("#{appName} Help", action: 'showHelp:', keyEquivalent: '?') + end.menu + + NSApp.mainMenu = @mainMenu + end + + private + + def addMenu(title, &b) + item = createMenu(title, &b) + @mainMenu.addItem item + item + end + + def createMenu(title, &b) + menu = NSMenu.alloc.initWithTitle(title) + menu.instance_eval(&b) if b + item = NSMenuItem.alloc.initWithTitle(title, action: nil, keyEquivalent: '') + item.submenu = menu + item + end +end diff --git a/ios/Escape/osx/app/scenes/game_over_scene.rb b/ios/Escape/osx/app/scenes/game_over_scene.rb new file mode 100644 index 0000000..cd27981 --- /dev/null +++ b/ios/Escape/osx/app/scenes/game_over_scene.rb @@ -0,0 +1,9 @@ +module Escape # GameOverScene + class GameOverScene < CommonScene + + def mouseUp(event) + touchesBegan(nil, withEvent:event) + end + + end +end diff --git a/ios/Escape/osx/app/scenes/main_game_scene.rb b/ios/Escape/osx/app/scenes/main_game_scene.rb new file mode 100644 index 0000000..16ffadc --- /dev/null +++ b/ios/Escape/osx/app/scenes/main_game_scene.rb @@ -0,0 +1,23 @@ +module Escape # GameScreen + class MainGameScene < CommonScene + + def acceptsFirstMouse(event) + true + end + + def didMoveToView(view) + # without this, dragging the player wouldn't work + NSApp.delegate.window.makeFirstResponder(self) + super + end + + def mouseDragged(event) + dragPlayer(event) + end + + def dragPlayer(event) + newLocation = self.convertPointToView(event.locationInWindow) + self.player.position = checkBounds(newLocation) + end + end +end \ No newline at end of file diff --git a/ios/Escape/osx/app/scenes/start_scene.rb b/ios/Escape/osx/app/scenes/start_scene.rb new file mode 100644 index 0000000..b8788f6 --- /dev/null +++ b/ios/Escape/osx/app/scenes/start_scene.rb @@ -0,0 +1,9 @@ +module Escape + class StartScene < CommonScene + + def mouseUp(event) + touchesBegan(nil, withEvent:event) + end + + end +end diff --git a/ios/Escape/osx/resources/Credits.rtf b/ios/Escape/osx/resources/Credits.rtf new file mode 100644 index 0000000..46576ef --- /dev/null +++ b/ios/Escape/osx/resources/Credits.rtf @@ -0,0 +1,29 @@ +{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} +{\colortbl;\red255\green255\blue255;} +\paperw9840\paperh8400 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\f0\b\fs24 \cf0 Engineering: +\b0 \ + Some people\ +\ + +\b Human Interface Design: +\b0 \ + Some other people\ +\ + +\b Testing: +\b0 \ + Hopefully not nobody\ +\ + +\b Documentation: +\b0 \ + Whoever\ +\ + +\b With special thanks to: +\b0 \ + Mom\ +} diff --git a/ios/Escape/osx/spec/main_spec.rb b/ios/Escape/osx/spec/main_spec.rb new file mode 100644 index 0000000..d4654b7 --- /dev/null +++ b/ios/Escape/osx/spec/main_spec.rb @@ -0,0 +1,9 @@ +describe "Application 'OSXEscape'" do + before do + @app = NSApplication.sharedApplication + end + + it "has one window" do + @app.windows.size.should == 1 + end +end diff --git a/ios/Escape/osx_game_scene.PNG b/ios/Escape/osx_game_scene.PNG new file mode 100644 index 0000000..994873c Binary files /dev/null and b/ios/Escape/osx_game_scene.PNG differ diff --git a/ios/Escape/osx_start_scene.PNG b/ios/Escape/osx_start_scene.PNG new file mode 100644 index 0000000..50e1f0f Binary files /dev/null and b/ios/Escape/osx_start_scene.PNG differ diff --git a/ios/Escape/resources/8-bit loop (loop).mp3 b/ios/Escape/resources/8-bit loop (loop).mp3 new file mode 100644 index 0000000..bd2103f Binary files /dev/null and b/ios/Escape/resources/8-bit loop (loop).mp3 differ diff --git a/ios/Escape/resources/BankGothicBold.ttf b/ios/Escape/resources/BankGothicBold.ttf new file mode 100644 index 0000000..4235b55 Binary files /dev/null and b/ios/Escape/resources/BankGothicBold.ttf differ diff --git a/ios/Escape/resources/Default-568h@2x.png b/ios/Escape/resources/Default-568h@2x.png new file mode 100644 index 0000000..87de555 Binary files /dev/null and b/ios/Escape/resources/Default-568h@2x.png differ diff --git a/ios/Escape/resources/Endless Sand.mp3 b/ios/Escape/resources/Endless Sand.mp3 new file mode 100644 index 0000000..bcb13a0 Binary files /dev/null and b/ios/Escape/resources/Endless Sand.mp3 differ diff --git a/ios/Escape/resources/blockerBodySmall.png b/ios/Escape/resources/blockerBodySmall.png new file mode 100644 index 0000000..e5f3ece Binary files /dev/null and b/ios/Escape/resources/blockerBodySmall.png differ diff --git a/ios/Escape/resources/blockerBodySmall@2x.png b/ios/Escape/resources/blockerBodySmall@2x.png new file mode 100644 index 0000000..e1acc85 Binary files /dev/null and b/ios/Escape/resources/blockerBodySmall@2x.png differ diff --git a/ios/Escape/resources/blockerMad.png b/ios/Escape/resources/blockerMad.png new file mode 100755 index 0000000..1ac459b Binary files /dev/null and b/ios/Escape/resources/blockerMad.png differ diff --git a/ios/Escape/resources/blockerMad@2x.png b/ios/Escape/resources/blockerMad@2x.png new file mode 100644 index 0000000..3ba4a1f Binary files /dev/null and b/ios/Escape/resources/blockerMad@2x.png differ diff --git a/ios/Escape/resources/hud_p1_opt.png b/ios/Escape/resources/hud_p1_opt.png new file mode 100644 index 0000000..b7ecae3 Binary files /dev/null and b/ios/Escape/resources/hud_p1_opt.png differ diff --git a/osx/Escape b/osx/Escape new file mode 120000 index 0000000..19b2d1a --- /dev/null +++ b/osx/Escape @@ -0,0 +1 @@ +../ios/Escape \ No newline at end of file