Write a ninja game with Swift and Spritekit

Source: Internet
Author: User
Tags addchild spritekit


This article of the game uses Spritekit and swift language to complete.

Spritekit is Apple's own game engine that fits the underlying API of the iOS system, but architecture and implementation mimic cocos2d. So the use of the fact that the difference is not small, just spritekit more lightweight.


Program entry
The main function, like OC, points the entry to Appdelegate, and the cocoa touch frame is almost like OC, just rewritten with Swift.


These templates come with a method that doesn't differ from the OC project ...
Start writing a game
Let's say you know ccnode,ccsprite,ccscene and so it looks like spritekit almost no matter what.
    Override Func Viewwilllayoutsubviews () {        super.viewwilllayoutsubviews ()                var skview:skview = Self.view As Skview        if!skview.scene {            //debug            Skview.showsfps = True            Skview.showsnodecount = True                        var scene: Skscene = Gamescene.scenewithsize (skView.bounds.size)            Scene.scalemode =. Aspectfill                        skview.presentscene (Scene)        }    }


Because when the Viewdidload method is called, Skview has not been added to the view hierarchy, so it does not have a corresponding orientation and layout change. So Skview's Bounds property is not the correct value at this time, but the default vertical screen corresponding value, it seems this time is not a good time to initialize the scene. So we need to move this part of the code into the method that will layout the child view.

Play background music
Here we use Avaudioplayer to play music. The controller declares an attribute var backgroundmusicplayer:avaudioplayer?

Func Setupmedia () {                var error:nserror?        Let Backgroundmusicurl:nsurl = Nsbundle.mainbundle (). Urlforresource (Bg_music_name, withextension: "CAF")        Backgroundmusicplayer = Avaudioplayer (contentsofurl: Backgroundmusicurl, Error: &error)        if error {            println ("Load background music error: \ (Error)")        } else { c6/>backgroundmusicplayer!. Numberofloops =-1            backgroundmusicplayer!. Preparetoplay ()            backgroundmusicplayer!. Play ()        }    }

    Override Func Viewdidload () {        super.viewdidload ()        Setupmedia ()    }

Starts playing when the view loading is complete.

Game scene
We have built a Skscene subclass for game display and logic writing. Class Gamescene:skscene

Victory failure Scenario
Class Gameoverscene:skscene {convenience init (size:cgsize, Won:bool) {self.init (size:size) sel        F.backgroundcolor = Skcolor (red:1.0, green:1.0, blue:1.0, alpha:1.0) Self.setupmsglabel (Iswon:won) Self.directoraction ()} func Setupmsglabel (Iswon won:bool) {var msg:string = won?        "Yow won!": "You Lose: [" var msglabel = Sklabelnode (fontnamed: "Chalkduster") Msglabel.text = Msg Msglabel.fontsize = Msglabel.fontcolor = Skcolor.blackcolor () msglabel.position = Cgpointmake (self . SIZE.WIDTH/2, SELF.SIZE.HEIGHT/2) Self.addchild (Msglabel)} func directoraction () {var actions: anyobject[] = [Skaction.waitforduration (3.0), Skaction.runblock ({var reveal = Sktransition.fliphorizontalwith Duration (0.5) var gamescene = Gamescene (size:self.size) self.view.presentScene (Gamescene, Transitio N:reveal)})] Var sequence = skaction.sequence (Actions) self.runaction (sequence)}} 

A simple page that shows the game wins and fails, with just a label and some action.
Initialization
    var player:skspritenode!  Hero Elf    var lastspawntimeinterval:nstimeinterval!//Record last time and update time    var lastupdatetimeinterval:nstimeinterval!    var monstersdestroyed:int! Record the number of monsters that have been wiped out


    Init (size:cgsize) {        super.init (size:size)                Self.backgroundcolor = Skcolor (red:1.0, green:1.0, blue:1.0, Alpha : 1.0)        player = Skspritenode (imagenamed: "Player")        player.position = Cgpointmake (SELF.PLAYER.SIZE.WIDTH/2, SELF.FRAME.SIZE.HEIGHT/2)        self.addchild (player)                monstersdestroyed = 0        lastspawntimeinterval = 0        Lastupdatetimeinterval = 0                gamelevel.nextlevel ()                //physics        self.physicsWorld.gravity = Cgvectormake ( 0, 0)        self.physicsWorld.contactDelegate = self    }


Some properties are declared and are assigned during construction. Instantiate the Hero Wizard. The primary physical engine properties are set.

Add Monsters

Func Addmonster () {var monster = Skspritenode (imagenamed: "Monster")//location var miny = m        ONSTER.SIZE.HEIGHT/2 var maxy = self.frame.size.height-monster.size.height/2 var rangey = Maxy-miny var actualy = arc4random ()% rangey + miny monster.position = cgpointmake (Self.frame.size.width + monste R.SIZE.WIDTH/2, actualy) Self.addchild (monster)//physics monster.physicsbody = Skphysicsbody (rectangleOfSize:monster.size) Monster.physicsBody.dynamic = True Monster.physicsBody.categoryBitMask = Mon Stercategory Monster.physicsBody.contactTestBitMask = projectilecategory Monster.physicsBody.collisionBitMas k = 0//speed var minduration = 2.0 var maxduration = 4.0 var rangeduration = Maxdurat ion-minduration var actualduration = arc4random ()% rangeduration + minduration var actionmove = S Kaction.moveto (CgpointmaKe (-MONSTER.SIZE.WIDTH/2, actualy), duration:actualduration) var actionmovedone = Skaction.removefromparent () var loseaction = Skaction.runblock ({var reveal = sktransition.fliphorizontalwithduration (0.5) VA R gameoverscene = Gameoverscene (size:self.size, Won:false) self.view.presentScene (gameoverscene, Transition: Reveal)}) Monster.runaction (Skaction.sequence ([Actionmove, Loseaction, Actionmovedone])}

The monsters were initialized, physically configured, and the speed was set and allowed to act, assuming that beyond the left bounds the game failed, assuming that the ninja-sent darts would be destroyed, partly by collision detection, which will be mentioned later.

Join Darts
When we click the end of the screen, we need to launch a dart to attack.
The system has its own monitoring method, as in Uikit.
Override Func touchesended (touches:nsset!, withevent event:uievent!) {        //Get touch        var touch = Touches.anyobject () as Uitouch        var location = Touch.locationinnode (self)                // Bullet Action        self.addprojectile (location:location)    }

And then a bullet-adding method.
    Func addprojectile (#location: cgpoint) {var projectile = Skspritenode (imagenamed: "Projectile") projecti Le.position = player.position//physics projectile.physicsbody = Skphysicsbody (circleofradius:proje CTILE.SIZE.WIDTH/2) Projectile.physicsBody.dynamic = True Projectile.physicsBody.categoryBitMask = Projectil Ecategory Projectile.physicsBody.contactTestBitMask = monstercategory Projectile.physicsBody.collisionBitMas K = 0 Projectile.physicsBody.usesPreciseCollisionDetection = true var offset = nisub (location, Proje ctile.position) If Offset.x < 0 {return} self.addchild (projectile)/direct unit vector var direction = ninormalize (offset)//to screen ' s edge var shootamount = Nimult (direction, 100 0)//now loc var realdest = Niadd (Shootamount, projectile.position)//action var veloc ity = 480.0/1.0 VAr realmoveduration = Double (self.size.width)/velocity var actionmove = Skaction.moveto (Realdest, Duratio n:realmoveduration) var actionmovedone = skaction.removefromparent () var sequence = Skaction.sequence ([acti OnMove, Actionmovedone]) projectile.runaction (sequence) self.runaction (skaction.playsoundfilenamed (" PEW-PEW-LEI.CAF ", Waitforcompletion:false))}

Like monsters, we initialize the dart, configure the physical state, and then determine its vector direction based on the location of the click and the location of the hero, so that he can start moving. Then let him move up in that direction.
Game assist in determining the direction of movement we used some of our own definition of closure functions, and because Swift is a type-safe language, very often we can not directly operate on different types of numeric values, so as in C + +, Swift can also do operator overloading.
Overload@infix func% (Lhs:uint32, rhs:float), float {    return float (LHS)% float (RHS)} @infix func% (lhs:uint (rhs:double), double {    return double (LHS)% double (RHS)}let Niadd = {(A:cgpoint, b:cgpoint), Cgpoint I N Cgpointmake (a.x + b.x, A.Y + b.y)}let nisub = {(A:cgpoint, b:cgpoint)-Cgpoint in Cgpointmake (a.x-b.x, A.y-b. Y)}let Nimult = {(A:cgpoint, b:float), Cgpoint in Cgpointmake (a.x * b, a.y * b)}let nilength = {(A:cgpoint) CGFloat in CGFloat (sqrt (Double (a.x * a.x + a.y * a.y))}
Unit Vectorlet ninormalize = {(A:cgpoint), cgpoint in    var length = Nilength (a)    return Cgpointmake (a.x/ Length, A.y/length)}


The right time to join the monster
It is noted that we have not previously called the method of adding monsters, the number of frames per second in the iOS system is 60, while in Skscene, the refresh frame will have the default method update to write the game logic.
Override func Update (currenttime:nstimeinterval) {        var timesincelast:cftimeinterval = currenttime- Lastspawntimeinterval        lastupdatetimeinterval = currenttime        If timesincelast > 1 {            timesincelast = Double (Gamelevel.toraw ())/60.0            lastupdatetimeinterval = currenttime        }                Self.updatewithtimesincelastupdate (timesincelast:timesincelast)    }

Then we'll be able to join the beast.
    Func updatewithtimesincelastupdate (#timeSinceLast: cftimeinterval) {        Lastspawntimeinterval = Lastspawntimeinterval + timesincelast        if Lastspawntimeinterval > 1 {            lastspawntimeinterval = 0            Self.addmonster ()        }    }

Collision detection
Finally, the collision logic needs to be defined.
There is a proxy method callback when the physical model is connected.
    Func didbegincontact (contact:skphysicscontact) {        var firstbody:skphysicsbody!        var secondbody:skphysicsbody!                if (Contact.bodyA.categoryBitMask < Contact.bodyB.categoryBitMask)        {            firstbody = Contact.bodya;            Secondbody = Contact.bodyb;        }        else        {            firstbody = Contact.bodyb;            Secondbody = Contact.bodya;        }                if (Firstbody.categorybitmask & projectilecategory)! = 0 && (Secondbody.categorybitmask & monstercategory)! = 0 {            self.didcollide (projectile:firstBody.node as Skspritenode, Monster:secondBody.node as Skspritenode)        }    }

At this point we want to make the following logic when monsters and darts collide
    Func didcollide (#projectile: Skspritenode, Monster:skspritenode) {        projectile.removefromparent ()        Monster.removefromparent ()                monstersdestroyed = monstersdestroyed + 1        if monstersdestroyed > {            var reveal = Sktransition.fliphorizontalwithduration (0.5)            var gameoverscene = Gameoverscene (Size:self.size, Won:true )            Self.view.presentScene (Gameoverscene, transition:reveal)        }    }

So the whole Ninja Dart monster game is over.
Here are the Games:




Game code: Click to open the link

The above is all the content of this blog post. Welcome to correct and discuss.

Write a ninja game with Swift and Spritekit

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.