I came across the Ebook "Swift Development with Cocoa: Developing for Mac and iOS App" by "Jonathan Manning, Paris Buttfield" in Amazon, and downloaded its sample to my Kindle (Original version) Ereader 6".
As I started reading the sample this weekend, I tried out the instructions in the first chapter about Xcode, and started an empty game project in Xcode with Swift language. Here are the details about that game snippet.
Since I work with C++ mainly, most of my technical knowledge is based off of C++ standards. So I might find myself using C++ jargons automatically. I will try my best to stick to Swift jargons, and add comparison with C++ standards wherever possible. Also I am assuming you have a fairly good knowledge about C++ language and a decent knowledge about Xcode IDE. Focus of this blog is mainly on Swift Programming Language and comparisons with C++
P.S:
I am writing these blogs to help anyone else who might be looking for similar explanations, and to deepen my understanding of the language. Hence I have provided as many explanations and code snippets as possible.
P.S:
I am writing these blogs to help anyone else who might be looking for similar explanations, and to deepen my understanding of the language. Hence I have provided as many explanations and code snippets as possible.
Also I got this idea of code jam a week from Jayenkai and Adriel Wallace, hence I would like to contribute this blog series to their brilliant and dedicated "games a week" idea. I am naming this blog code jam a week, because the game snippets I think will be done each week are not complete games. But parts of the game, that will build up to be a complete game(s).
About the Game:
Its a simple one, where spaceships arrive on the screen at random coordinates, and when user touches a spaceship, his/her score increases.
I used iOS simulator, setting the game up for iPhone 5.
ScreenShots:
Game Mechanics:
- Enemy spaceships appear randomly on screen
- They move to random destinations
- User has to touch them to destroy them
- Each spaceship destroyed, increases score by 1.
There are no:
- Time limits
- no poof during spaceship destruction
- no transparent transition or other animations during appearance or disappearance
This game is as simple as a "hello world" example.
Implementation Details
Now lets get to the main part. Since I am new to swift, I will try to explain as much as I can. Feel free to correct me if I am wrong in any of the technicalities.
Create a Project:
- Create a new Xcode project : iOS -> Application -> Game. Provide Product Name, chose Swift as language, SpriteKit as Game Technology and other details, and save it to a convenient location on your device.
-SpriteKit is a framework to render animated sprites on screen. They are the easiest and fastest way to bring animated 2d objects on screen.
-Swift is a iOS and OS X programming language introduced by Apple of course, in 2014. It aims at providing an enhanced language, to shift from Objective C, and works at eliminating Objective C's demerits like null pointers, etc.
Now that we have covered the definitions, lets move to actual code. More information on these two topics are available online in abundant quantities.
Make a spaceship appear on the screen at random location:
class - class GameScene : SKScene
// C++ derived class is called as subclass in Swift. There are many differences and similarities between them. I am currently not going into those comparisons. Might do that later. but not in this introduction blog.
// Every parent class member that has the same signature needs to be overridden using the keyword "override" . I believe it is similar to C++ "virtual" keyword.
Question for the knowledgeable readers:
//func is the keyword used to indicate that this is a function. Not sure why we have to use "func" explicitly. I am guessing it is to avoid conflicts with some other declarations. If anyone knows answer to why swift needs functions to be declared explicitly with "func" keyword, kindly let me know. I am curious to know the reason.
//update has a parameter of name currentTime belonging to CFTimeInterval type. Similar to C++ function parameter of signature (Type name). If this is written in C++ , it would be (CFTimeInterval currentTime). This function does not return any values.
function - override func update(currentTime: CFTimeInterval) {
Question for the knowledgeable readers:
//func is the keyword used to indicate that this is a function. Not sure why we have to use "func" explicitly. I am guessing it is to avoid conflicts with some other declarations. If anyone knows answer to why swift needs functions to be declared explicitly with "func" keyword, kindly let me know. I am curious to know the reason.
//update has a parameter of name currentTime belonging to CFTimeInterval type. Similar to C++ function parameter of signature (Type name). If this is written in C++ , it would be (CFTimeInterval currentTime). This function does not return any values.
function - override func update(currentTime: CFTimeInterval) {
//let keyword is a little bit like a const pointer in C. You can change the values of the object, but that variable cannot be assigned to a different object. ( C : SKSpriteNode * const sprite = &object ). It can be thought of as "static single assignment" form (reference: compiler design), where each variable is assigned only once, and it should be defined before its first use.
//Also let keyword usage means the value is immutable. If you use let keyword to access an array or dictionary, then its values/elements/key-value pairs cannot be changed. But if you use let keyword to access an instance of a class, then the members of the class are editable, at the same time, the let value cannot be assigned to a different instance of the same class.
//for e.g let a = 5
// a = 6 // error
// let x = SKSpriteNode(imageNamed: "Spaceship")
// x.memberFunction() // allowed
// x = SKNode() // error
// x = SKSpriteNode(imageNamed: "Boss") //error
// Before Xcode 6, Beta 3, arrays had values and references, and using "let" keyword enabled edits to the array elements. But that feature has been removed.
//I believe in this line, sprite is an instance of the class SKSpriteNode, and not a pointer.
//I believe code in C++ would be like : SKSpriteNode sprite("Spaceship")
let sprite = SKSpriteNode(imageNamed: "Spaceship")
// Set values of members of class SKSpriteNode
// If Float is not explicitly stated, value is taken to be a double (64 bit float)
// . operator is used to access the members just like in C++
sprite.xScale = 0.15
sprite.yScale = 0.15
// position is set to be an instance of type CGPoint (struct) in CoreGraphics framework's CGGeometry
//function parameters are passed in, with format: x: value, y: value
//value is a random one generated between 0 - 1000 using arc4random_uniform(). 1000 is the upper bound. The argument is of type Uint32 or u_int32_t, and returns value of same type. Hence we have to convert it to Int type because CGPoint constructor expects either Int or Double type values.
//X and Y 's upper bound values (1000 and 700) was chosen using Trial and Error method.
//Goal is to make the enemy spaceships appear at random locations.
sprite.position = CGPoint(x: Int(arc4random_uniform(1000)), y: Int(arc4random_uniform(700)))
//Declare a variable(mutable) array of name SpriteActionArray. The array has elements of type SKAction.
//This looks similar to C++ std::vector declaration. Where vector is a template, that holds elements of type specified in <Type> when declaring the vector. As per the source code, Array is an efficient, tail growable ( elements added to end of list ), random access ( Can access N th element in the list directly from an array of M elements ) collection of arbitrary elements ( Can hold homogenous elements of same type. The type can be an user defined type or a primitive one)
// You can also write a short form of the Array declaration like this :
var SpriteActionArray: [SKAction] or var s1 = [String]() where empty array of strings is created. Note that to create an empty array = sign is used, but to declare an Array : sign is used.
or var list1: [String] = ["xx", "yy"] where initial values are being set in the same line.
// Normally shorthand method of using [] is preferred. But since this is my first Swift program, I am using Array<> to be more explicit.
// Note: I am using "list" word interchangeably with array to denote an array of elements.
var SpriteActionArray = Array<SKAction>()
// Here I am appending (C++ : push_back() of std::vector) SKActions to the array. The first appended action is instructing the sprite to move to a destination. The destination is a random location of range x : 0 -1000 , y: 0 - 1000 . Random numbers obtained from previous Brute force method results.
//moveTo is a function that moves the node/sprite to a destination point. First argument is the location to move to, second argument is the duration of the movement. Here the spaceship is expected to keep moving for 60 seconds before it disappears from the screen.
Question for the knowledgeable readers:
//I am not sure how moveTo function can be invoked by using . dot operator. In C++ the SKAction would have to be an object. Static functions can be called using :: operator. But it looks like in Swift SKAction is a class. If anyone knows the answer to the question, how . operator is used to access the member function moveTo of the class SKAction, kindly enlighten us Swift beginners. Thanks in advance.
SpriteActionArray.append(SKAction.moveTo(CGPoint(x: Int(arc4random_uniform(1000), y: Int(arc4random_uniform(1000))), duration: 60)
// Create a sequence of the SKAction array elements. As per the official iOS developer library documentation: A Sequence is a set of actions that are run consecutively one after the other. i.e when one action completes, next one starts immediately. When the last action completes, the sequence is considered complete.
//A sequence is an overkill for just one action, but since I will be experimenting with more animation effects for the spaceship, I am keeping it a sequence to begin with . You can also call runAction with just one SKAction as its argument.
// This line creates a seq object using let keyword(immutable assignment)
let seq = SKAction. sequence(spriteActionArray)
// This calls runAction method that runs the actions specified in an orderly fashion(because we are using Sequence) for the sprite (Spaceship)
sprite.runAction(seq)
//GameScene is a subclass of SKNode, hence the sprite object has to be added as a child object in order for the class to process it during every update and render operations.
//As per official Apple docs: addChild adds a node to the end of the receiver's list of child nodes
self.addChild(sprite)
//Then I add sprite to my own array, which will be processed later to figure out if the touch was made on each spaceship or not.
//Enemies is an Array in the class GameScene declared like so: var Enemies = [SKSpriteNode]()
// This declaration as mentioned above, creates an empty array of SKSpriteNode type elements.
// Objects of type SKSpriteNode are added to the end of the list (tail growable array) by using append() function
Enemies.append(sprite)
End of Part 1.
Par 2 of this series will have implementation details about keeping the spaceship population under control, verifying if the touch collides with spaceships, incrementing score count, displaying the score on the screen using SKLabelNode.
This is the code jam of the week starting with Jan 12 2015
// Set values of members of class SKSpriteNode
// If Float is not explicitly stated, value is taken to be a double (64 bit float)
// . operator is used to access the members just like in C++
sprite.xScale = 0.15
sprite.yScale = 0.15
// position is set to be an instance of type CGPoint (struct) in CoreGraphics framework's CGGeometry
//function parameters are passed in, with format: x: value, y: value
//value is a random one generated between 0 - 1000 using arc4random_uniform(). 1000 is the upper bound. The argument is of type Uint32 or u_int32_t, and returns value of same type. Hence we have to convert it to Int type because CGPoint constructor expects either Int or Double type values.
//X and Y 's upper bound values (1000 and 700) was chosen using Trial and Error method.
//Goal is to make the enemy spaceships appear at random locations.
sprite.position = CGPoint(x: Int(arc4random_uniform(1000)), y: Int(arc4random_uniform(700)))
//Declare a variable(mutable) array of name SpriteActionArray. The array has elements of type SKAction.
//This looks similar to C++ std::vector declaration. Where vector is a template, that holds elements of type specified in <Type> when declaring the vector. As per the source code, Array is an efficient, tail growable ( elements added to end of list ), random access ( Can access N th element in the list directly from an array of M elements ) collection of arbitrary elements ( Can hold homogenous elements of same type. The type can be an user defined type or a primitive one)
// You can also write a short form of the Array declaration like this :
var SpriteActionArray: [SKAction] or var s1 = [String]() where empty array of strings is created. Note that to create an empty array = sign is used, but to declare an Array : sign is used.
or var list1: [String] = ["xx", "yy"] where initial values are being set in the same line.
// Normally shorthand method of using [] is preferred. But since this is my first Swift program, I am using Array<> to be more explicit.
// Note: I am using "list" word interchangeably with array to denote an array of elements.
var SpriteActionArray = Array<SKAction>()
// Here I am appending (C++ : push_back() of std::vector) SKActions to the array. The first appended action is instructing the sprite to move to a destination. The destination is a random location of range x : 0 -1000 , y: 0 - 1000 . Random numbers obtained from previous Brute force method results.
//moveTo is a function that moves the node/sprite to a destination point. First argument is the location to move to, second argument is the duration of the movement. Here the spaceship is expected to keep moving for 60 seconds before it disappears from the screen.
Question for the knowledgeable readers:
//I am not sure how moveTo function can be invoked by using . dot operator. In C++ the SKAction would have to be an object. Static functions can be called using :: operator. But it looks like in Swift SKAction is a class. If anyone knows the answer to the question, how . operator is used to access the member function moveTo of the class SKAction, kindly enlighten us Swift beginners. Thanks in advance.
SpriteActionArray.append(SKAction.moveTo(CGPoint(x: Int(arc4random_uniform(1000), y: Int(arc4random_uniform(1000))), duration: 60)
// Create a sequence of the SKAction array elements. As per the official iOS developer library documentation: A Sequence is a set of actions that are run consecutively one after the other. i.e when one action completes, next one starts immediately. When the last action completes, the sequence is considered complete.
//A sequence is an overkill for just one action, but since I will be experimenting with more animation effects for the spaceship, I am keeping it a sequence to begin with . You can also call runAction with just one SKAction as its argument.
// This line creates a seq object using let keyword(immutable assignment)
let seq = SKAction. sequence(spriteActionArray)
// This calls runAction method that runs the actions specified in an orderly fashion(because we are using Sequence) for the sprite (Spaceship)
sprite.runAction(seq)
//GameScene is a subclass of SKNode, hence the sprite object has to be added as a child object in order for the class to process it during every update and render operations.
//As per official Apple docs: addChild adds a node to the end of the receiver's list of child nodes
self.addChild(sprite)
//Then I add sprite to my own array, which will be processed later to figure out if the touch was made on each spaceship or not.
//Enemies is an Array in the class GameScene declared like so: var Enemies = [SKSpriteNode]()
// This declaration as mentioned above, creates an empty array of SKSpriteNode type elements.
// Objects of type SKSpriteNode are added to the end of the list (tail growable array) by using append() function
Enemies.append(sprite)
End of Part 1.
Par 2 of this series will have implementation details about keeping the spaceship population under control, verifying if the touch collides with spaceships, incrementing score count, displaying the score on the screen using SKLabelNode.
This is the code jam of the week starting with Jan 12 2015



No comments:
Post a Comment