Build ios Games with Sprite Kit

Similar documents
Programming Clojure. Extracted from: Second Edition. The Pragmatic Bookshelf

Pragmatic Guide to Sass

Distributed and Parallel Computing with Ruby

Practical Programming, Third Edition

Developing Android on Android

Pragmatic Guide to Git

Practical Programming, 2nd Edition

Node.js the Right Way

Java by Comparison. Extracted from: Become a Java Craftsman in 70 Examples. The Pragmatic Bookshelf

Automate with Grunt. Extracted from: The Build Tool for JavaScript. The Pragmatic Bookshelf

Reactive Programming with RxJS

Reactive Programming with RxJS 5

Java By Comparison. Extracted from: Become a Java Craftsman in 70 Examples. The Pragmatic Bookshelf

Practical Vim, Second Edition

Learn Functional Programming with Elixir

Agile Web Development with Rails 5.1

Dart for Hipsters. Extracted from: The Pragmatic Bookshelf

Practical Vim, Second Edition

Build Database Apps in Elixir for Scalability and Performance

Complex Network Analysis in Python

ios 9 SDK Development

ios 8 SDK Development

SQL Antipatterns. Extracted from: Avoiding the Pitfalls of Database Programming. The Pragmatic Bookshelf

Agile Web Development with Rails 5

Node.js 8 the Right Way

Agile Web Development with Rails 5

Modern Vim. Extracted from: Craft Your Development Environment with Vim 8 and Neovim. The Pragmatic Bookshelf

Build Safe and Maintainable Front-End Applications

Deploying with JRuby 9k

Cocoa Programming A Quick-Start Guide for Developers

Effective Testing with RSpec 3

iphone SDK Development

Beginning Mac Programming

Copyright 2009 The Pragmatic Programmers, LLC.

Pragmatic Guide to Sass 3

Build Reactive Websites with RxJS

ios 8 SDK Development

Web Design for Developers A Programmer s Guide to Design Tools and Techniques

Programming Google Glass, Second Edition

Web Design for Developers A Programmer s Guide to Design Tools and Techniques

Design It! Extracted from: From Programmer to Software Architect. The Pragmatic Bookshelf

Mastering Clojure Macros

Programming Clojure, Third Edition

Python Companion to Data Science

SPRITES Moving Two At the Same Using Game State

Docker for Rails Developers

Release It! Second Edition

Programming Kotlin. Extracted from: Creating Elegant, Expressive, and Performant JVM and Android Applications. The Pragmatic Bookshelf

Complex Network Analysis in Python

How to Make a Book Interior File

Getting Started with Processing by Casey Reas and Ben Fry

The ThoughtWorks Anthology 2

Creating an Animated Navigation Bar in InDesign*

2SKILL. Variables Lesson 6. Remembering numbers (and other stuff)...

Shadows in the graphics pipeline

Excel Basics Rice Digital Media Commons Guide Written for Microsoft Excel 2010 Windows Edition by Eric Miller

Functional Programming in Java

Pong in Unity a basic Intro

CSCI 1100L: Topics in Computing Lab Lab 11: Programming with Scratch

Things You Should Know

SNOWFLAKES PHOTO BORDER - PHOTOSHOP CS6 / CC

[ the academy_of_code] Senior Beginners

Mobile Application Programming. Controls

What is OneNote? The first time you start OneNote, it asks you to sign in. Sign in with your personal Microsoft account.

Real World Kanban Do Less Accomplish More With Lean Thinking

The great primary-key debate

two using your LensbAby

SQL. Draft Version. Head First. A Brain-Friendly Guide. Lynn Beighley. A learner s companion to database programming using SQL

UNIVERSITY OF CALIFORNIA, SANTA CRUZ BOARD OF STUDIES IN COMPUTER ENGINEERING

Polygons and Angles: Student Guide

Mailman Max. The postcode is a great way to work out the next sorting office a letter should go to, so you ll use that.

Smoother Graphics Taking Control of Painting the Screen

Copyright 2006The Pragmatic Programmers, LLC.

Add Photo Mounts To A Photo With Photoshop Part 1

Objective-C. Stanford CS193p Fall 2013

Getting the most out of Microsoft Edge

VISUAL QUICKSTART GUIDE QUICKTIME PRO 4. Judith Stern Robert Lettieri. Peachpit Press

4.7 Approximate Integration

Stanford CS193p. Developing Applications for ios Fall Stanford CS193p. Fall 2013

Erasmus+ Project: Yestermorrow Year 1 Maths: Pythagorean Theorem

Beginner OpenGL ES & GLKit Hands-On Challenges

Copyright 2009 The Pragmatic Programmers, LLC.

AN INTRODUCTION TO SCRATCH (2) PROGRAMMING

Table of Contents. 1. Cover Page 2. Quote 3. Calculated Fields 4. Show Values As 5. Multiple Data Values 6. Enroll Today!

Views, Drawing, and Events. Lecture 5

Putting user. experience first A SNEAK PEEK BEHIND THE SCENES OF THE E-WORKBOOK 10 DESIGN JOURNEY

Microsoft. Student Edition. The Richard Stockton College of New Jersey. Computer Courseware

Meet the Cast. The Cosmic Defenders: Gobo, Fabu, and Pele The Cosmic Defenders are transdimensional

Mac Kung Fu. Extracted from: Over 400 Tips, Tricks, Hints, and Hacks for Apple OS X. The Pragmatic Bookshelf

M O T I O N A N D D R A W I N G

Creating animation rigs that solve problems, are fun to use, and don t cause nervous breakdowns.

1 Build Your First App. The way to get started is to quit talking and begin doing. Walt Disney

ITP 342 Mobile App Dev. Connections

Animator Friendly Rigging Part 1

Structuring an App Copyright 2013 Apple Inc. All Rights Reserved.

Section 1.4: Adding and Subtracting Linear and Perpendicular Vectors

Blackfin Online Learning & Development

Installing and Using Trackside Cameras Revised November 2008

Go paperless by using OneNote 2013

On the Web sun.com/aboutsun/comm_invest STAROFFICE 8 DRAW

Transcription:

Extracted from: Build ios Games with Sprite Kit Unleash Your Imagination in Two Dimensions This PDF file contains pages extracted from Build ios Games with Sprite Kit, published by the Pragmatic Bookshelf. For more information or to purchase a paperback or PDF copy, please visit http://www.pragprog.com. Note: This extract contains some colored text (particularly in code listing). This is available only in online versions of the books. The printed versions are black and white. Pagination might vary between the online and printed versions; the content is otherwise identical. Copyright 2014 The Pragmatic Programmers, LLC. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form, or by any means, electronic, mechanical, photocopying, recording, or otherwise, without the prior consent of the publisher. The Pragmatic Bookshelf Dallas, Texas Raleigh, North Carolina

Build ios Games with Sprite Kit Unleash Your Imagination in Two Dimensions Jonathan Penn Josh Smith The Pragmatic Bookshelf Dallas, Texas Raleigh, North Carolina

Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and The Pragmatic Programmers, LLC was aware of a trademark claim, the designations have been printed in initial capital letters or in all capitals. The Pragmatic Starter Kit, The Pragmatic Programmer, Pragmatic Programming, Pragmatic Bookshelf, PragProg and the linking g device are trademarks of The Pragmatic Programmers, LLC. Every precaution was taken in the preparation of this book. However, the publisher assumes no responsibility for errors or omissions, or for damages that may result from the use of information (including program listings) contained herein. Our Pragmatic courses, workshops, and other products can help you and your team create better software and have more fun. For more information, as well as the latest Pragmatic titles, please visit us at http://pragprog.com. The team that produced this book includes: Rebecca Gulick (editor) Potomac Indexing, LLC (indexer) Cathleen Small (copyeditor) David J Kelly (typesetter) Janet Furlow (producer) Ellie Callahan (support) For international rights, please contact rights@pragprog.com. Copyright 2014 The Pragmatic Programmers, LLC. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form, or by any means, electronic, mechanical, photocopying, recording, or otherwise, without the prior consent of the publisher. Printed in the United States of America. ISBN-13: 978-1-94122-210-2 Encoded using the finest acid-free high-entropy binary digits. Book version: P1.0 July 2014

Following the Finger Around To move the ship around, we have to update its position property every time a finger comes in contact with the screen. Thankfully, handling touch events in Sprite Kit scenes is the same as elsewhere in ios. We have all the standard low-level touch event methods. We ll add this method after the -initwithsize: method to move the ship when a touch begins: 01-SpriteIntro/step03/SpaceRun/RCWMyScene.m - (void)touchesbegan:(nsset *)touches withevent:(uievent *)event { UITouch *touch = [touches anyobject]; CGPoint touchpoint = [touch locationinnode:self]; SKNode *ship = [self childnodewithname:@"ship"]; ship.position = touchpoint; In the -touchesbegan:withevent: method, we grab one of the touches out of the set with the anyobject method. Because our game is meant to be played with a single finger, we re going to let the system pick, just in case more than one touch comes in contact with the screen at the same time. We then ask the touch to return coordinates in our scene s coordinate space using the -locationinnode: method and passing in the scene as the parameter. Remember that our RCWMyScene class is a subclass of SKScene, which itself is a subclass of SKNode. It s nodes all the way down to the bottom! Each node s children are positioned within that node s local coordinate space, just like UIView objects in normal UIKit. By calling this method with the scene, we are asking the touch object to convert from screen coordinates to scene coordinates so we have the right location to move the ship as the player expects. Once we have the ship s new coordinates, we re ready to update the position property. But how do we get access to the ship node in this method? Here we re using one of the powerful features of Sprite Kit. We can give nodes names and look them up anywhere in the scene graph. That s what we re doing by calling [self childnodewithname:@"ship"]. In this case, we re just looking for a direct descendant of this scene with that exact name. You ll learn how to find nodes with more flexible queries later. Of course, to make this work we have to give the node the name we re looking for. Update the -initwithsize: method to set the name property. 01-SpriteIntro/step03/SpaceRun/RCWMyScene.m NSString *name = @"Spaceship.png";

2 SKSpriteNode *ship = [SKSpriteNode spritenodewithimagenamed:name]; ship.position = CGPointMake(size.width/2, size.height/2); ship.size = CGSizeMake(40, 40); ship.name = @"ship"; [self addchild:ship]; Now, when we run the game, tapping anywhere on the screen updates the position property, and the ship jumps under the finger. But we don t just want the ship to jump when a finger touches. We want the ship to follow the finger on the screen as it moves. Let s do that next. Making the Ship Glide As our game is now, we have a mechanical problem with our ship. It only moves when a touch begins on the screen, and we want it to move toward where the finger drags around on the screen. Because we get all the standard touch events from ios, we could copy the same code into -touchesmoved:withevent: and update the ship s position property there, but there s a simpler way with Sprite Kit. Let s start with a property that keeps track of the touch that we received until the touch ends. Add this class extension to the top of the RCWMyScene.m file above the @implementation definition: 01-SpriteIntro/step04/SpaceRun/RCWMyScene.m @interface RCWMyScene () @property (nonatomic, weak) UITouch *shiptouch; @end We re declaring the property as weak because we don t want to keep a reference to the object when the system is done with it. UITouch objects live and update themselves for the lifetime of the touch. The touch-handling system releases the objects when the touch is ended. Because our property is weak, it will automatically be set to nil for us. Now let s set that property in -touchesbegan:withevent:. 01-SpriteIntro/step04/SpaceRun/RCWMyScene.m - (void)touchesbegan:(nsset *)touches withevent:(uievent *)event { self.shiptouch = [touches anyobject]; Every time a new touch happens, we ll keep a weak reference to it so we can use it later. Next, we ll update the ship s position every time a frame is drawn by adding this method to the bottom of the RCWMyScene class: 01-SpriteIntro/step04/SpaceRun/RCWMyScene.m - (void)update:(nstimeinterval)currenttime

Making the Ship Glide 3 { if (self.shiptouch) { SKNode *ship = [self childnodewithname:@"ship"]; ship.position = [self.shiptouch locationinnode:self]; The -update: method has special significance on SKScene objects. If Sprite Kit sees this on a scene, it will be called just before every frame is rendered to the screen. This is a great place to update the state of the game, such as making the ship node follow the finger. In this method, we re checking to see whether the shiptouch property is nil. Remember that because this is a weak property, it will be set to nil for us by the touch-handling system when it releases the touches after they are done. If the touch is still there, then we find the ship node by name and update its position property like we did before. Except this time, the position will change on every frame, and the ship will keep up with wherever the finger is on the screen. It s great that our ship can move, but this isn t quite the effect we want. Our game mechanics depend on the ship gliding with a constant speed from where it is now to where the finger is currently on the screen. That makes it more challenging for players so they can t just tap around and cause the ship to jump immediately out of harm s way. Smoothing Out the Motion To create a smooth, gliding effect while the ship follows the finger, we ll want to update the ship s position to move closer to the finger over time, rather than jump right to the finger s coordinates. Because the -update: method receives the value of Sprite Kit s clock in the currenttime parameter, we can use that to calculate how far the ship should move by keeping track of the time between frames. First, we ll add a new property to the class extension of the RCWMyScene object. We ll use this to record the last time we updated the frame. 01-SpriteIntro/step05/SpaceRun/RCWMyScene.m @interface RCWMyScene () @property (nonatomic, weak) UITouch *shiptouch; @property (nonatomic) NSTimeInterval lastupdatetime; @end Then, in the -update: method, we ll subtract the value of that property to calculate the time delta since the last frame.

4 01-SpriteIntro/step05/SpaceRun/RCWMyScene.m - (void)update:(nstimeinterval)currenttime { if (self.lastupdatetime == 0) { self.lastupdatetime = currenttime; NSTimeInterval timedelta = currenttime - self.lastupdatetime; if (self.shiptouch) { [self moveshiptowardpoint:[self.shiptouch locationinnode:self] bytimedelta:timedelta]; self.lastupdatetime = currenttime; We re checking to see whether the lastupdatetime property is zero first, because if it is, that means this is the first frame rendered of this scene. We need to initialize this property before we can get meaningful time-delta calculations, but we don t know what to initialize it to until the first time we are called. Next, we calculate the timedelta value by subtracting the currenttime parameter from the lastupdatetime property. Then, if the shiptouch property holds a touch object, we call a new method to move the ship according to the touch point by how much time has passed. We re asking the UITouch object itself to give us the coordinate of the touch within the scene s local coordinate system. After all the work is done, we set the lastupdatetime property to currenttime so we are ready to calculate the time difference of the next frame. Let s write the -moveshiptowardpoint:bytimedelta: method to nudge the ship by the appropriate amount for this frame. 01-SpriteIntro/step05/SpaceRun/RCWMyScene.m - (void)moveshiptowardpoint:(cgpoint)point bytimedelta:(nstimeinterval)timedelta { CGFloat shipspeed = 130; // points per second SKNode *ship = [self childnodewithname:@"ship"]; CGFloat distanceleft = sqrt(pow(ship.position.x - point.x, 2) + pow(ship.position.y - point.y, 2)); if (distanceleft > 4) { CGFloat distancetotravel = timedelta * shipspeed; CGFloat angle = atan2(point.y - ship.position.y, point.x - ship.position.x); CGFloat yoffset = distancetotravel * sin(angle); CGFloat xoffset = distancetotravel * cos(angle); ship.position = CGPointMake(ship.position.x + xoffset, ship.position.y + yoffset);

Making the Ship Glide 5 Yikes! If you d like to take a moment to write apology notes to your high school trigonometry teacher, go right ahead. We did, too. Game development is a great way to refresh the mind on all the math we thought wouldn t be necessary in real life. Don t worry, we ll break down this code together. Figure 6, Calculating the distance to travel this frame, on page 6 provides a figure to help visualize what s happening: First off, we are setting a shipspeed variable to keep track of how many points per second the ship should travel. We find the ship node and calculate distanceleft using the Pythagorean theorem with the ship s current location and final destination. 4 Before we actually move the ship, we re checking to see whether this distanceleft variable is greater than four points. If not, then we don t want to move the ship anymore. We re close enough. If we kept trying to move the ship anyway, then it s possible that the ship would jitter around the touch point because of the imprecision of the floating-point calculations. Four points is far enough away that any rounding errors won t wiggle the ship around the destination point and close enough that the player will have the impression the ship reached the finger. Assuming we re not close enough, then we calculate the distancetotravel variable by multiplying the timedelta by the shipspeed. This is how far we should move for just this frame. We have to convert that distance back into x- and y-coordinates, so we use the atan2() function and some more basic trigonometry to set the ship node s position property. Now run the game, and the ship will glide at a nice, constant rate to wherever your finger is on the screen. This is an important game mechanic because players will have to think about how to maneuver around obstacles as they approach. No cheating! And that s it for our whirlwind Sprite Kit introduction! You ve learned a little bit about how Sprite Kit draws things to the screen, you ve learned how to track touches and update the ship s position over time, and you ve learned about the frame update loop along the way. This is a great start, but weren t we supposed to be able to shoot and dodge obstacles? Yup, and to do that we ll have to tackle the next topic, Sprite Kit actions! 4. http://en.wikipedia.org/wiki/pythagorean_theorem

6 Figure 6 Calculating the distance to travel this frame