0% found this document useful (0 votes)
16 views81 pages

Development Cookbook 1st Edition Jonathon Manning

Uploaded by

neisyjakie
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
16 views81 pages

Development Cookbook 1st Edition Jonathon Manning

Uploaded by

neisyjakie
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 81

Download the full version of the ebook at

https://ebookultra.com

iOS Game Development Cookbook 1st Edition


Jonathon Manning

https://ebookultra.com/download/ios-game-
development-cookbook-1st-edition-jonathon-manning/

Explore and download more ebook at https://ebookultra.com


Recommended digital products (PDF, EPUB, MOBI) that
you can download immediately if you are interested.

Beginning iOS Game Development 1st Edition Patrick Alessi

https://ebookultra.com/download/beginning-ios-game-development-1st-
edition-patrick-alessi/

ebookultra.com

Beginning iOS 7 Development Exploring the iOS SDK 1st


Edition Jack Nutting

https://ebookultra.com/download/beginning-ios-7-development-exploring-
the-ios-sdk-1st-edition-jack-nutting/

ebookultra.com

Beginning iOS 5 Games Development 1st Edition Lucas Jordan

https://ebookultra.com/download/beginning-ios-5-games-development-1st-
edition-lucas-jordan/

ebookultra.com

Learn Design for iOS Development 1st Edition Sian Morson


(Auth.)

https://ebookultra.com/download/learn-design-for-ios-development-1st-
edition-sian-morson-auth/

ebookultra.com
Beginning iOS 3D Unreal Games Development 1st Edition
Robert Chin

https://ebookultra.com/download/beginning-ios-3d-unreal-games-
development-1st-edition-robert-chin/

ebookultra.com

Learn iOS 8 App Development Second Edition James Bucanek


(Auth.)

https://ebookultra.com/download/learn-ios-8-app-development-second-
edition-james-bucanek-auth/

ebookultra.com

HTML5 Mobile Development Cookbook 1st Edition Shi Chuan

https://ebookultra.com/download/html5-mobile-development-cookbook-1st-
edition-shi-chuan/

ebookultra.com

Lua Game Development Cookbook Over 70 recipes that will


help you master the elements and best practices required
to build a modern game engine using Lua 1st Edition Kasuba
https://ebookultra.com/download/lua-game-development-cookbook-
over-70-recipes-that-will-help-you-master-the-elements-and-best-
practices-required-to-build-a-modern-game-engine-using-lua-1st-
edition-kasuba/
ebookultra.com

Beginning Game Level Design Premier Press Game Development


1st Edition John Harold Feil

https://ebookultra.com/download/beginning-game-level-design-premier-
press-game-development-1st-edition-john-harold-feil/

ebookultra.com
iOS Game Development Cookbook 1st Edition Jonathon
Manning Digital Instant Download
Author(s): Jonathon Manning, Paris Buttfield-Addison
ISBN(s): 9781449368760, 144936876X
Edition: 1
File Details: PDF, 16.82 MB
Year: 2014
Language: english
iOS Game Development Cookbook

Jonathon Manning and Paris Buttfield-Addison


iOS Game Development Cookbook
by Jonathon Manning and Paris Buttfield-Addison
Copyright © 2014 Jonathon Manning and Paris Buttfield-Addison. All rights reserved.
Printed in the United States of America.
Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472.
O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are
also available for most titles (http://my.safaribooksonline.com). For more information, contact our corporate/
institutional sales department: 800-998-9938 or [email protected].
Editor: Rachel Roumeliotis Indexer: Ellen Troutman-Zaig
Production Editor: Melanie Yarbrough Cover Designer: Karen Montgomery
Copyeditor: Rachel Head Interior Designer: David Futato
Proofreader: Jasmine Kwityn Illustrator: Rebecca Demarest

April 2014: First Edition

Revision History for the First Edition:


2014-04-09: First release

See http://oreilly.com/catalog/errata.csp?isbn=9781449368760 for release details.

Nutshell Handbook, the Nutshell Handbook logo, and the O’Reilly logo are registered trademarks of O’Reilly
Media, Inc. iOS Game Development Cookbook, the image of a queen triggerfish, and related trade dress are
trademarks of O’Reilly Media, Inc.
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 O’Reilly Media, Inc. was aware of a trademark
claim, the designations have been printed in caps or initial caps.
While every precaution has been taken in the preparation of this book, the publisher and authors assume
no responsibility for errors or omissions, or for damages resulting from the use of the information contained
herein.

ISBN: 978-1-449-36876-0
[LSI]
Table of Contents

Preface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix

1. Laying Out a Game. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1


1.1. Laying Out Your Engine 1
1.2. Creating an Inheritance-Based Game Layout 2
1.3. Creating a Component-Based Game Layout 4
1.4. Calculating Delta Times 7
1.5. Detecting When the User Enters and Exits Your Game 8
1.6. Updating Based on a Timer 10
1.7. Updating Based on When the Screen Updates 11
1.8. Pausing a Game 13
1.9. Calculating Time Elapsed Since the Game Start 13
1.10. Working with Blocks 14
1.11. Writing a Method That Calls a Block 18
1.12. Working with Operation Queues 19
1.13. Performing a Task in the Future 21
1.14. Storing Blocks in Objects 22
1.15. Using a Timer 25
1.16. Making Operations Depend on Each Other 26
1.17. Filtering an Array with Blocks 27
1.18. Loading New Assets During Gameplay 28
1.19. Adding Unit Tests to Your Game 29
1.20. 2D Grids 32

2. Views and Menus. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37


2.1. Working with Storyboards 38
2.2. Creating View Controllers 43
2.3. Using Segues to Move Between Screens 50
2.4. Using Constraints to Lay Out Views 53

iii
2.5. Adding Images to Your Project 55
2.6. Slicing Images for Use in Buttons 56
2.7. Using UI Dynamics to Make Animated Views 58
2.8. Moving an Image with Core Animation 60
2.9. Rotating an Image 62
2.10. Animating a Popping Effect on a View 63
2.11. Theming UI Elements with UIAppearance 65
2.12. Rotating a UIView in 3D 66
2.13. Overlaying Menus on Top of Game Content 68
2.14. Designing Effective Game Menus 69

3. Input. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
3.1. Detecting When a View Is Touched 72
3.2. Responding to Tap Gestures 73
3.3. Dragging an Image Around the Screen 74
3.4. Detecting Rotation Gestures 76
3.5. Detecting Pinching Gestures 78
3.6. Creating Custom Gestures 79
3.7. Receiving Touches in Custom Areas of a View 84
3.8. Detecting Shakes 84
3.9. Detecting Device Tilt 85
3.10. Getting the Compass Heading 89
3.11. Accessing the User’s Location 90
3.12. Calculating the User’s Speed 93
3.13. Pinpointing the User’s Proximity to Landmarks 94
3.14. Receiving Notifications When the User Changes Location 95
3.15. Looking Up GPS Coordinates for a Street Address 99
3.16. Looking Up Street Addresses from the User’s Location 100
3.17. Using the Device as a Steering Wheel 101
3.18. Detecting Magnets 102
3.19. Utilizing Inputs to Improve Game Design 104

4. Sound. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
4.1. Playing Sound with AVAudioPlayer 105
4.2. Recording Sound with AVAudioRecorder 108
4.3. Working with Multiple Audio Players 110
4.4. Cross-Fading Between Tracks 112
4.5. Synthesizing Speech 114
4.6. Getting Information About What the iPod Is Playing 115
4.7. Detecting When the Currently Playing Track Changes 117
4.8. Controlling iPod Playback 118
4.9. Allowing the User to Select Music 119

iv | Table of Contents
4.10. Cooperating with Other Applications’ Audio 122
4.11. Determining How to Best Use Sound in Your Game Design 123

5. Data Storage. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125


5.1. Saving the State of Your Game 125
5.2. Storing High Scores Locally 128
5.3. Using iCloud to Save Games 129
5.4. Using the iCloud Key/Value Store 132
5.5. Loading Structured Information 134
5.6. Deciding When to Use Files or a Database 136
5.7. Using SQLite for Storage 137
5.8. Managing a Collection of Assets 139
5.9. Storing Information in NSUserDefaults 142
5.10. Implementing the Best Data Storage Strategy 144
5.11. In-Game Currency 144

6. 2D Graphics and Sprite Kit. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147


6.1. Getting Familiar with 2D Math 147
6.2. Creating a Sprite Kit View 152
6.3. Creating a Scene 154
6.4. Adding a Sprite 156
6.5. Adding a Text Sprite 157
6.6. Determining Available Fonts 159
6.7. Including Custom Fonts 160
6.8. Transitioning Between Scenes 160
6.9. Moving Sprites and Labels Around 162
6.10. Adding a Texture Sprite 165
6.11. Creating Texture Atlases 165
6.12. Using Shape Nodes 166
6.13. Using Blending Modes 167
6.14. Using Image Effects to Change the Way that Sprites Are Drawn 169
6.15. Using Bézier Paths 170
6.16. Creating Smoke, Fire, and Other Particle Effects 171
6.17. Shaking the Screen 172
6.18. Animating a Sprite 174
6.19. Parallax Scrolling 175
6.20. Creating Images Using Perlin Noise 182

7. Physics. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
7.1. Reviewing Physics Terms and Definitions 191
7.2. Adding Physics to Sprites 193
7.3. Creating Static and Dynamic Objects 194

Table of Contents | v
7.4. Defining Collider Shapes 195
7.5. Setting Velocities 197
7.6. Working with Mass, Size, and Density 198
7.7. Creating Walls in Your Scene 199
7.8. Controlling Gravity 201
7.9. Keeping Objects from Falling Over 202
7.10. Controlling Time in Your Physics Simulation 202
7.11. Detecting Collisions 203
7.12. Finding Objects 204
7.13. Working with Joints 206
7.14. Working with Forces 207
7.15. Adding Thrusters to Objects 208
7.16. Creating Explosions 209
7.17. Using Device Orientation to Control Gravity 211
7.18. Dragging Objects Around 212
7.19. Creating a Car 215

8. 3D Graphics. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
8.1. Working with 3D Math 219
8.2. Creating a GLKit Context 223
8.3. Drawing a Square Using OpenGL 225
8.4. Loading a Texture 233
8.5. Drawing a Cube 235
8.6. Rotating a Cube 238
8.7. Moving the Camera in 3D Space 239

9. Intermediate 3D Graphics. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241


9.1. Loading a Mesh 241
9.2. Parenting Objects 248
9.3. Animating a Mesh 252
9.4. Batching Draw Calls 255
9.5. Creating a Movable Camera Object 256

10. Advanced 3D Graphics. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261


10.1. Understanding Shaders 261
10.2. Working with Materials 265
10.3. Texturing with Shaders 271
10.4. Lighting a Scene 272
10.5. Using Normal Mapping 275
10.6. Making Objects Transparent 277
10.7. Adding Specular Highlights 278

vi | Table of Contents
10.8. Adding Toon Shading 280

11. Artificial Intelligence and Behavior. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283


11.1. Making an Object Move Toward a Position 283
11.2. Making Things Follow a Path 285
11.3. Making an Object Intercept a Moving Target 286
11.4. Making an Object Flee When It’s in Trouble 287
11.5. Making an Object Decide on a Target 288
11.6. Making an Object Steer Toward a Point 289
11.7. Making an Object Know Where to Take Cover 290
11.8. Calculating a Path for an Object to Take 291
11.9. Finding the Next Best Move for a Puzzle Game 296
11.10. Determining if an Object Can See Another Object 297
11.11. Using AI to Enhance Your Game Design 299

12. Networking and Social Media. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301


12.1. Using Game Center 301
12.2. Getting Information About the Logged-in Player 305
12.3. Getting Information About Other Players 305
12.4. Making Leaderboards and Challenges with Game Center 306
12.5. Finding People to Play with Using Game Center 310
12.6. Using Bluetooth to Detect Nearby Game Players with the Multipeer
Connectivity Framework 312
12.7. Making Real-Time Gameplay Work with Game Kit and the Multipeer
Connectivity Framework 315
12.8. Creating, Destroying, and Synchronizing Objects on the Network 317
12.9. Interpolating Object State 318
12.10. Handling When a Player Disconnects and Rejoins 320
12.11. Making Turn-Based Gameplay Work with GameKit 321
12.12. Sharing Text and Images to Social Media Sites 324
12.13. Implementing iOS Networking Effectively 325
12.14. Implementing Social Networks Effectively 326

13. Game Controllers and External Screens. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327


13.1. Detecting Controllers 329
13.2. Getting Input from a Game Controller 331
13.3. Showing Content via AirPlay 332
13.4. Using External Screens 333
13.5. Designing Effective Graphics for Different Screens 335
13.6. Dragging and Dropping 338

14. Performance and Debugging. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345

Table of Contents | vii


14.1. Improving Your Frame Rate 345
14.2. Making Levels Load Quickly 348
14.3. Dealing with Low-Memory Issues 349
14.4. Tracking Down a Crash 351
14.5. Working with Compressed Textures 352
14.6. Working with Watchpoints 355
14.7. Logging Effectively 356
14.8. Creating Breakpoints That Use Speech 358

Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361

viii | Table of Contents


Preface

Games rule mobile devices. The iPhone, iPad, and iPod touch are all phenomenally
powerful gaming platforms, and making amazing games that your players can access at
a moment’s notice has never been easier. The iTunes App Store category with the most
apps is Games; it includes games ranging from simple one-minute puzzle games to in-
depth, long-form adventures. The time to jump in and make your own games has never
been better. We say this having been in iOS game development since the App Store
opened: Our first iOS game, in 2008, a little strategy puzzler named Culture, led us to
working on a hundreds of other awesome projects, ranging from a digital board game
for museums to educational children’s games, and everything in between! The possi‐
bilities for games on this platform are only becoming wider and wider.
This book provides you with simple, direct solutions to common problems found in
iOS game programming. If you’re stuck figuring out how to give objects physical motion,
how to handle Game Center, or just want a refresher on common gaming-related math
problems, you’ll find simple, straightforward answers, explanations, and sample
projects. This book is designed as part-way between a series of tutorials and a reference
work: it’s something you’ll want to keep handy for quick reference, as well as browse
through to get new ideas about what’s possible.

Audience
We assume that you’re a reasonably capable programmer, and assume that you know at
least a little bit about developing for iOS: what Xcode is and how to get around in it,
how to use the iOS Simulator, and the basics of the Objective-C programming language.
We also assume you know how to use an iOS device. We don’t assume any existing
knowledge of game development on any platform, but we’re guessing that you’re reading
this book with a vague idea about the kind of game you’d like to make.
This book isn’t based on any particular genre of games—you’ll find the recipes in it
applicable to all kinds of games, though some will suit some genres more than others.

ix
Organization of This Book
Each chapter of this book contains recipes: short solutions to common problems found
in game development. The book is designed to be read in any order; you don’t need to
read it cover-to-cover, and you don’t need to read any chapter from start to finish. (Of
course, we encourage doing that, since you’ll probably pick up on stuff you didn’t realize
you wanted to know.)
Each recipe is structured like this: the problem being addressed is presented, followed
by the solution, which explains the technique of solving the problem (or implementing
the feature, and so on). Following the solution, the recipe contains a discussion that
goes into more detail on the solution, which gives you more information about what
the solution does, what other things to watch out for, and other useful knowledge.
Here is a concise breakdown of the material each chapter covers:
Chapter 1, Laying Out a Game
This chapter discusses different ways to design the architecture and code layout of
your game, how to work with timers in a variety of different ways, and how blocks
work in iOS. You’ll also learn how to schedule work to be performed in the future
using blocks and operation queues, and how to add unit tests to your project.
Chapter 2, Views and Menus
This chapter focuses on interface design, and working with UIKit, the built-in sys‐
tem for displaying user interface graphics. In addition to providing common objects
like buttons and text fields, UIKit can be customised to suit your needs—for some
kinds of games, you might not need to use any more complex graphical tools than
it.
Chapter 3, Input
In this chapter, you’ll learn how to get input from the user so that you can apply it
to your game. This includes touching the screen, detecting different types of ges‐
tures (such as tapping, swiping and pinching), as well as other kinds of input like
the user’s current position on the planet, or motion information from the variety
of built-in sensors in the device.
Chapter 4, Sound
This chapter discusses how to work with sound effects and music. You’ll learn how
to load and play audio files, how to work with the user’s built-in music library, and
how to make your game’s sound work well when the user wants to listen to their
music while playing your game.
Chapter 5, Data Storage
This chapter is all about storing information for later use. The information that
games need to save ranges from the very small (such as high scores), to medium
(saved games), all the way up to very large (collections of game assets). In this

x | Preface
chapter, you’ll learn about the many different ways that information can be stored
and accessed, and which of these is best suited for what you want to do.
Chapter 6, 2D Graphics and Sprite Kit
This chapter discusses Sprite Kit, the 2D graphics system built into iOS. Sprite Kit
is both powerful and very easy to use; in this chapter, you’ll learn how to create a
scene, how to animate sprites, and how to work with textures and images. This
chapter also provides you with info you can use to brush up on your 2D math skills.
Chapter 7, Physics
In this chapter, you’ll learn how to use the two-dimensional physics simulation that’s
provided as part of Sprite Kit. Physics simulation is a great way to make your game’s
movements feel more realistic, and you can use it to get a lot of great-feeling game
for very little programmer effort. You’ll learn how to work with physics bodies,
joints and forces, as well as how to take user input and make it control your game’s
physical simulation.
Chapter 8, 3D Graphics
This chapter and the two that follow it provide a tutorial on OpenGL ES 2, the 3D
graphics system used on iOS. These three chapters follow a slightly different struc‐
ture to the rest of the book, because it’s not quite as easy to explain parts of OpenGL
in isolation. Instead, these chapters follow a more linear approach, and we recom‐
mend that you read the recipes in order, so that you can get the best use out of them.
Chapter 8 introduces the basics of OpenGL, and shows you how to draw simple
shapes on the screen; at the same time, the math behind the graphics is explained.
Chapter 9, Intermediate 3D Graphics
This chapter is designed to follow on from the previous, and discusses more ad‐
vanced techniques in 3D graphics. You’ll learn how to load a 3D object from a file,
how to animate objects, and how to make a camera that moves around in 3D space.
Chapter 10, Advanced 3D Graphics
This chapter follows on from the previous two, and focuses on shaders, which give
you a tremendous amout of control over how objects in your game look. You’ll learn
how to write shader code, how to create different shading effects (including diffiuse
and specular lighting, cartoon shading, and more), and how to make objects trans‐
parent.
Chapter 11, Artificial Intelligence and Behavior
This chapter discusses how to make objects in your game behave on their own, and
react to the player. You’ll learn how to make an object chase another, make objects
flee from something, and how to work out a path from one point to another while
avoiding obstacles.

Preface | xi
Chapter 12, Networking and Social Media
In this chapter, you’ll learn about Game Center, the social network and match-
making system built into iOS. You’ll learn how to get information about the player’s
profile, as well as let the player connect to their friends. On top of this, you’ll also
learn how to connect to nearby devices using Bluetooth. Finally, you’ll learn how
to share text, pictures and other content to social media sites like Twitter and Face‐
book.
Chapter 13, Game Controllers and External Screens
This chapter discusses the things that players can connect to their device: external
displays, like televisions and monitors, and game controllers that provide additional
input methods like thumbsticks and physical buttons. You’ll learn how to detect,
use and design your game to take advantage of additional hardware where it’s
present.
Chapter 14, Performance and Debugging
The last chapter of the book looks at improving your game’s performance and sta‐
bility. You’ll learn how to take advantage of advanced Xcode debugging features,
how to use compressed textures to save memory, and how to make your game load
faster.

Additional Resources
You can download, or fork using GitHub, the code samples from this book at https://
github.com/thesecretlab/iOSGameDevCookbook1stEd.
O’Reilly has a number of other excellent books on game development and software
development (both generally, and related to iOS) available that can help you on your
iOS game development journey, including:

• Physics for Game Developers


• Learning Cocoa with Objective-C (by us!)
• Programming iOS 7

We strongly recommend that you add Gamasutra to your regular reading list, due to
the high quality of their coverage of game industry news.
Game designer Marc LeBlanc’s website is where he collects various presentations, notes,
and essays. We’ve found him to be a tremendous inspiration.
Finally, we’d be remiss if we didn’t link to our own blog.

xii | Preface
Conventions Used in This Book
The following typographical conventions are used in this book:
Italic
Indicates new terms, URLs, email addresses, filenames, and file extensions.
Constant width
Used for program listings, as well as within paragraphs to refer to program elements
such as variable or function names, databases, data types, environment variables,
statements, and keywords.
Constant width bold
Shows commands or other text that should be typed literally by the user.
Constant width italic
Shows text that should be replaced with user-supplied values or by values deter‐
mined by context.

This element signifies a tip or suggestion.

This element signifies a general note.

This element indicates a warning or caution.

Using Code Examples


Supplemental material (code examples, exercises, etc.) is available for download at
https://github.com/thesecretlab/iOSGameDevCookbook1stEd.
This book is here to help you get your job done. In general, if example code is offered
with this book, you may use it in your programs and documentation. You do not need
to contact us for permission unless you’re reproducing a significant portion of the code.
For example, writing a program that uses several chunks of code from this book does

Preface | xiii
not require permission. Selling or distributing a CD-ROM of examples from O’Reilly
books does require permission. Answering a question by citing this book and quoting
example code does not require permission. Incorporating a significant amount of ex‐
ample code from this book into your product’s documentation does require permission.
We appreciate, but do not require, attribution. An attribution usually includes the title,
author, publisher, and ISBN. For example: “iOS Game Development Cookbook by Jon‐
athan Manning and Paris Buttfield-Addison (O’Reilly). Copyright 2014 Jonathon Man‐
ning and Paris Buttfield-Addison, 978-1-449-36876-0.”
If you feel your use of code examples falls outside fair use or the permission given above,
feel free to contact us at [email protected].

Safari® Books Online


Safari Books Online is an on-demand digital library that
delivers expert content in both book and video form from
the world’s leading authors in technology and business.
Technology professionals, software developers, web designers, and business and crea‐
tive professionals use Safari Books Online as their primary resource for research, prob‐
lem solving, learning, and certification training.
Safari Books Online offers a range of product mixes and pricing programs for organi‐
zations, government agencies, and individuals. Subscribers have access to thousands of
books, training videos, and prepublication manuscripts in one fully searchable database
from publishers like O’Reilly Media, Prentice Hall Professional, Addison-Wesley Pro‐
fessional, Microsoft Press, Sams, Que, Peachpit Press, Focal Press, Cisco Press, John
Wiley & Sons, Syngress, Morgan Kaufmann, IBM Redbooks, Packt, Adobe Press, FT
Press, Apress, Manning, New Riders, McGraw-Hill, Jones & Bartlett, Course Technol‐
ogy, and dozens more. For more information about Safari Books Online, please visit us
online.

How to Contact Us
Please address comments and questions concerning this book to the publisher:

O’Reilly Media, Inc.


1005 Gravenstein Highway North
Sebastopol, CA 95472
800-998-9938 (in the United States or Canada)
707-829-0515 (international or local)
707-829-0104 (fax)

xiv | Preface
We have a web page for this book, where we list errata, examples, and any additional
information. You can access this page at http://oreil.ly/ios_game_dev_cookbook.
To comment or ask technical questions about this book, send email to bookques
[email protected].
For more information about our books, courses, conferences, and news, see our website
at http://www.oreilly.com.
Find us on Facebook: http://facebook.com/oreilly
Follow us on Twitter: http://twitter.com/oreillymedia
Watch us on YouTube: http://www.youtube.com/oreillymedia

Acknowledgement
Jon thanks his mother, father, and the rest of his weirdly extended family for their tre‐
mendous support.
Paris thanks his mother, whose credit card bankrolled literally hundreds of mobile de‐
vices through his childhood—an addiction that, in all likelihood, created the gadget-
obsessed monster he is today. He can’t wait to read her upcoming novel.
Thank you to our editor, Rachel Roumeliotis, who kept the book under control and
provided a ton of useful advice on content. We know it was a ton because we measured
it. Likewise, all the O’Reilly Media staff and contractors we’ve worked with over the
course of writing the book have been absolutely fantastic, and every one of them made
this book better for having had them work on it. Thank you also to Brian Jepson, our
first editor at O’Reilly.
A huge thank you to Tony Gray and the AUC for the monumental boost they gave us
and many others listed on this page. We wouldn’t be working in this industry, let alone
writing this book, if it wasn’t for Tony and the AUC community.
Thanks also to Neal Goldstein, who richly deserves all of the credit and/or blame for
getting both of us into the whole book-writing racket.
We’d like to thank the support of the goons at Maclab, who know who they are and
continue to stand watch for Admiral Dolphin’s inevitable apotheosis, as well as Professor
Christopher Lueg, Dr Leonie Ellis, and the rest of the staff at the University of Tasmania
for putting up with us.
Additional thanks to Tim N, Nic W, Andrew B, Jess L, and Rex S for a wide variety of
reasons. Thanks also to Ash Johnson, for general support.
Finally, very special thanks to Steve Jobs, without whom this book (and many others
like it) would not have reason to exist.

Preface | xv
CHAPTER 1
Laying Out a Game

Games are software, and the best software has had some thought put into it regarding
how it’s going to work. When you’re writing a game, you need to keep in mind how
you’re going to handle the individual tasks that the game needs to perform, such as
rendering graphics, updating artificial intelligence (AI), handling input, and the hun‐
dreds of other small tasks that your game will need to deal with.
In this chapter, you’ll learn about ways you can lay out the structure of your game that
will make development easier. You’ll also learn how to organize the contents of your
game so that adding more content and gameplay elements is easier, and find out how
to make your game do multiple things at once.

1.1. Laying Out Your Engine


Problem
You want to determine the best way to lay out the architecture of your game.

Solution
The biggest thing to consider when you’re thinking about how to best lay out your game
is how the game will be updated. There are three main things that can cause the state of
the game to change:
Input from the user
The game may change state when the user provides some input, such as tapping a
button or typing some text. Turn-based games are often driven by user input (e.g.,
in a game of chess, the game state might only be updated when the user finishes
moving a piece).

1
Timers
The game state may change every time a timer goes off. The delay between timer
updates might be very long (some web-based strategy games have turns that update
only once a day), or very short (such as going off every time the screen finishes
drawing). Most real-time games, like shooters or real-time strategy games, use very
short-duration timers.
Input from outside
The game state may change when information from outside the game arrives. The
most common example of this is some information arriving from the network, but
it can also include data arriving from built-in sensors, such as the accelerometer.
Sometimes, this kind of updating is actually a specific type of timer-based update,
because some networks or sensors need to be periodically checked to see if new
information has arrived.

Discussion
None of these methods are mutually exclusive. You can, for example, run your game on
a timer to animate content, and await user input to move from one state to the next.
Updating every frame is the least efficient option, but it lets you change state often,
which makes the game look smooth.

1.2. Creating an Inheritance-Based Game Layout


Problem
You want to use an inheritance-based (i.e., a hierarchy-based) architecture for your
game, which is simpler to implement.

Solution
First, define a class called GameObject:
@interface GameObject : NSObject {
}

- (void) update:(float)deltaTime;

@end

@implementation GameObject

- (void) update:(float)deltaTime {
// Do some updating
}

2 | Chapter 1: Laying Out a Game


@end

When you want to create a new kind of game object, you create a subclass of the Game
Object class, which inherits all of the behavior of its parent class and can be customized:
@interface Monster : GameObject {
}

@property (assign) float hitPoints; // num of times it can be hit without dying
@property (weak) GameObject* targetObject; // try to kill this object

@end

@implementation Monster

- (void) update:(float)deltaTime {
[super update:deltaTime];

// Do some monster-specific updating


}

@end

Discussion
In an inheritance-based layout, as seen in Figure 1-1, you define a single base class for
your game object (often called GameObject), which knows about general tasks like being
updated, and then create subclasses for each specific type of game object. This hierarchy
of subclasses can be multiple levels deep (e.g., you might subclass the GameObject class
to make the Monster subclass, and then subclass that to create the Goblin and Dragon
classes, each of which has its own different kinds of monster-like behavior).

1.2. Creating an Inheritance-Based Game Layout | 3


Figure 1-1. An inheritance-based layout

The advantage of a hierarchy-based layout is that each object is able to stand alone: if
you have a Dragon object, you know that all of its behavior is contained inside that single
object, and it doesn’t rely on other objects to work. The downside is that you can often
end up with a very deep hierarchy of different game object types, which can be tricky
to keep in your head as you program.

1.3. Creating a Component-Based Game Layout


Problem
You want to use a component-based architecture for your game, which allows for greater
flexibility.

Solution
First, define a Component class. This class represents components that are attached to
game objects—it is a very simple class that, at least initially, only has a single method
and a single property:
@class GameObject;
@interface Component : NSObject

- (void) update:(float)deltaTime;

@property (weak) GameObject* gameObject;


@end

Next, define a GameObject class. This class represents game objects:

4 | Chapter 1: Laying Out a Game


#import "Component.h"

@interface GameObject : NSObject

@property (strong) NSSet* components;

- (void) addComponent:(Component*)component;
- (void) removeComponent:(Component*)component;

- (void)update:(float)deltaTime;

- (id)componentWithType:(Class)componentType;
- (NSArray*)componentsWithType:(Class)componentType;
@end
The implementation for this class looks like this:
#import "GameObject.h"

@implementation GameObject {
NSMutableSet* _components;
}

@synthesize components = _components;

- (id)init {
self = [super init];

if (self) {
_components = [NSMutableSet set];
}

return self;
}

- (void)addComponent:(Component *)component {
[_components addObject:component];
component.gameObject = self;
}

- (void)removeComponent:(Component *)component {
[_components removeObject:component];
component.gameObject = nil;
}

- (void)update:(float)deltaTime {
for (Component* component in _components) {
[component update:deltaTime];
}
}

- (id)componentWithType:(Class)componentType {
// Helper function that just returns the first component with a given type

1.3. Creating a Component-Based Game Layout | 5


return [[self componentsWithType:componentType] firstObject];
}

- (NSArray*)componentsWithType:(Class)componentType {
// Return nil if the class isn't actually a type of component
if ([componentType isSubclassOfClass:[Component class]] == NO)
return nil;

// Work out which components match the component type, and return them all
return [[_components objectsPassingTest:^BOOL(id obj, BOOL *stop) {
return [obj isKindOfClass:componentType];
}] allObjects];
}
@end
Using these objects looks like this:
// Make a new game object
GameObject gameObject = [[GameObject alloc] init];

// Add some components


Component* component = [[Component alloc] init];
[gameObject addComponent:component];

// When the game needs to update, send all game objects the "update" message
// This makes all components get updated as well
[gameObject update];

Discussion
In a component-based architecture, as seen in Figure 1-2, each game object is made up
of multiple components. Compare this to an inheritance-based architecture, where each
game object is a subclass of some more general class (see Recipe 1.2).
A component-based layout means you can be more flexible with your design and not
worry about inheritance issues. For example, if you’ve got a bunch of monsters, and you
want one specific monster to have some new behavior (such as, say, exploding every
five seconds), you just write a new component and add it to that monster. If you later
decide that you want other monsters to also have that behavior, you can add that be‐
havior to them too.
In a component-based architecture, each game object has a list of components. In this
recipe, we’re using an NSMutableSet, which means that if you add the same component
more than once, the list will only contain one copy of the component. When something
happens to an object—for example, the game updates, or the object is added to or re‐
moved from the game—the object goes through each one of its components and notifies
them. This gives them the opportunity to respond in their own way.

6 | Chapter 1: Laying Out a Game


Figure 1-2. A component-based layout

The main problem with component-based architectures is that it’s more laborious to
create multiple copies of an object, because you have to create and add the same set of
components every time you want a new copy.

1.4. Calculating Delta Times


Problem
You want to know how many seconds have elapsed since the last time the game updated.

Solution
First, decide which object should be used to keep track of time. This may be a view
controller, an SKScene, a GLKViewController, or something entirely custom.
Create an instance variable inside that object:
@interface MyTimeKeepingObject {
double lastFrameTime;
}
Then, each time your game is updated, get the current time in milliseconds, and subtract
lastFrameTime from that. This gives you the amount of time that has elapsed since the
last update.

1.4. Calculating Delta Times | 7


When you want to make something happen at a certain rate—for example, moving at
3 meters per second—multiply the rate by the delta time:
- (void)update:(double)currentTime {

double deltaTime = currentTime - lastFrameTime;

// Move at 3 units per second


float movementSpeed = 3;
[someObject moveAtSpeed:movementSpeed * deltaTime];

lastFrameTime = currentTime;
}

Discussion
“Delta time” means “change in time.” Delta times are useful to keep track of how much
time has elapsed from one point in time to another—in games, this means the time from
one frame to the next. Because the game content changes frame by frame, the amount
of time between frames becomes important.
Additionally, the amount of time between frames might change a little. You should
always be aiming for a constant frame rate of 60 frames per second (i.e., a delta time of
16 milliseconds: 1÷60 = 0.0166); however, this may not always be achievable, depending
on how much work needs to be done in each frame. This means that delta time might
vary slightly, so calculating the delta time between each frame becomes necessary if you
want rates of change to appear constant.
Some engines give you the delta time directly. For example, CADisplayLink gives you
a duration property (see Recipe 1.7), and GLKViewController gives you timeSince
LastUpdate (see Recipe 8.6).
Some engines give you just the current time, from which you can calculate the delta
time. For example, the SKScene class passes the currentTime parameter to the update:
method (discussed further in Recipe 7.15).
In other cases (e.g., if you’re doing the main loop yourself), you won’t have easy access
to either. In these cases, you need to get the current time yourself:
double currentTime = [NSDate timeIntervalSinceReferenceDate];

1.5. Detecting When the User Enters and Exits Your Game
Problem
You want to detect when the user leaves your game, so that you can pause the game. You
also want to know when the user comes back.

8 | Chapter 1: Laying Out a Game


Solution
To get notified when the user enters and exits your game, you register to receive noti‐
fications from an NSNotificationCenter. The specific notifications that you want to
receive are UIApplicationDidBecomeActiveNotification, UIApplicationWillEnter
ForegroundNotification, UIApplicationWillResignActiveNotification, and UIAp
plicationDidEnterBackgroundNotification:
- (void)viewDidAppear:(BOOL)animated {
// Called when the application becomes the active one
// (i.e., when nothing's covering it up)
[[NSNotificationCenter defaultCenter]
addObserver:self selector:@selector(applicationDidBecomeActive:)
name:UIApplicationDidBecomeActiveNotification object:nil];

// Called when the application will enter the foreground (i.e.,


// when the user has left another app and entered this one)
[[NSNotificationCenter defaultCenter]
addObserver:self selector:@selector(applicationWillEnterForeground:)
name:UIApplicationWillEnterForegroundNotification object:nil];

// Called when the application will resign active (i.e., when something's
// covering it up, like the notification tray or a phone call)
[[NSNotificationCenter defaultCenter]
addObserver:self selector:@selector(applicationWillResignActive:)
name:UIApplicationWillResignActiveNotification object:nil];

// Called when the application enters the background


// (i.e., when the user has left it)
[[NSNotificationCenter defaultCenter]
addObserver:self selector:@selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification object:nil];

- (void)viewDidDisappear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void) applicationDidBecomeActive:(NSNotification*)notification {
NSLog(@"Application did become active!");
}

- (void) applicationWillResignActive:(NSNotification*)notification {
NSLog(@"Application will resign active!");
}

- (void) applicationDidEnterBackground:(NSNotification*)notification {
NSLog(@"Application did enter background!");
}

1.5. Detecting When the User Enters and Exits Your Game | 9
- (void) applicationWillEnterForeground:(NSNotification*)notification {
NSLog(@"Application will enter foreground!");
}

Discussion
On iOS, only one app can be the “active” application (i.e., the app that is taking up the
screen and that the user is interacting with). This means that apps need to know when
they become the active one, and when they stop being active.
When your game is no longer the active application, the player can’t interact with it.
This means that the game should pause (see Recipe 1.8). When the game resumes being
the active application, the player should see a pause screen.

Pausing, of course, only makes sense in real-time games, such as


shooters, driving games, arcade games, and so on. In a turn-based
game, like a strategy or puzzle game, you don’t really need to worry
about the game being paused or not.

In addition to being the active application, an application can be in the foreground or


the background. When an application is in the foreground, it’s being shown on the
screen. When it’s in the background, it isn’t visible at all. Apps that are in the background
become suspended after a short period of time, to save battery power. Apps that enter
the background should reduce their memory consumption as much as possible; if your
app consumes a large amount of memory while it is in the background, it is more likely
to be terminated by iOS.

1.6. Updating Based on a Timer


Problem
You want to update your game after a fixed amount of time.

Solution
Use an NSTimer to receive a message after a certain amount of time, or to receive an
update on a fixed schedule.
First, add an instance variable to your view controller:
NSTimer* timer;

Next, add a method that takes an NSTimer parameter:


- (void) updateWithTimer:(NSTimer*) timer {
// The timer's gone off; update the game

10 | Chapter 1: Laying Out a Game


NSLog(@"Updated from timer!");
}
Finally, when you want to start the timer:
timer = [NSTimer scheduledTimerWithTimeInterval:0.5
target:self selector:@selector(updateWithTimer:) userInfo:nil repeats:YES];
To stop the timer:
[timer invalidate];
timer = nil;

Discussion
An NSTimer waits for a specified number of seconds, and then calls a method on an
object that you specify. You can change the number of seconds by changing the time‐
Interval parameter:
// Wait 2 seconds
[NSTimer scheduledTimerWithTimeInterval:2
target:self selector:@selector(updateWithTimer:) userInfo:nil repeats:YES];

// Wait 0.1 seconds (100 milliseconds)


[NSTimer scheduledTimerWithTimeInterval:0.1
target:self selector:@selector(updateWithTimer:) userInfo:nil repeats:YES];
You can also make a timer either fire only once or repeat forever, by changing the
repeats parameter to NO or YES, respectively.

1.7. Updating Based on When the Screen Updates


Problem
You want to update your game every time the screen redraws.

Solution
Use a CADisplayLink, which sends a message every time the screen is redrawn.
First, add an instance variable to your view controller:
@interface ViewController () {
CADisplayLink* displayLink;
}

Next, add a method that takes a single parameter (a CADisplayLink):


- (void) update:(CADisplayLink*)displayLink {
// The screen's just updated; update the game
NSLog(@"Updated from display link!");
}

1.7. Updating Based on When the Screen Updates | 11


Finally, add this code when you want to begin receiving updates:
// Create the CADisplayLink; "self" will receive the updateWithDisplayLink:
// message every time the screen updates
displayLink = [CADisplayLink
displayLinkWithTarget:self selector:@selector(update:)];

// Add the display link and start receiving updates


[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];

When you want to pause receiving updates, set the paused property of the CADisplay
Link to YES:
displayLink.paused = YES;

When you want to stop receiving updates, call invalidate on the CADisplayLink:
[displayLink invalidate];
displayLink = nil;

Discussion
When we talk about “real-time” games, what comes to mind is objects like the player,
vehicles, and other things moving around the screen, looking like they’re in continuous
motion. This isn’t actually what happens, however—what’s really going on is that the
screen is redrawing itself every 1/60th of a second, and every time it does this, the
locations of some or all of the objects on the screen change slightly. If this is done fast
enough, the human eye is fooled into thinking that everything’s moving continuously.

In fact, you don’t technically need to update as quickly as every 1/60th


of a second—anything moving faster than 25 frames per second (in
other words, one update every 1/25th of a second) will look like mo‐
tion. However, faster updates yield smoother-looking movement, and
you should always aim for 60 frames per second.

You’ll get the best results if you update your game at the same rate as the screen. You
can achieve this with a CADisplayLink, which uses the Core Animation system to figure
out when the screen has updated. Every time this happens, the CADisplayLink sends
its target a message, which you specify.
It’s worth mentioning that you can have as many CADisplayLink objects as you like,
though they’ll all update at the same time.

12 | Chapter 1: Laying Out a Game


1.8. Pausing a Game
Problem
You want to be able to pause parts of your game, but still have other parts continue to
run.

Solution
Keep track of the game’s “paused” state in a BOOL variable. Then, divide your game objects
into two categories—ones that run while paused, and ones that don’t run while paused:
// This is just pseudocode--your game will likely look slightly different
for (GameObject* gameObject in gameObjects) {
if (paused == NO || gameObject.shouldPause == NO) {
[gameObject update];
}
}

Discussion
The simplest possible way to pause the game is to keep track of a pause state; every time
the game updates, you check to see if the pause state is set to YES, and if it is, you don’t
update any game objects.
However, you often don’t want every single thing in the game to freeze. For example:

• The user interface may need to continue to animate.


• The network may need to keep communicating with other computers, rather than
stopping entirely.

In these cases, having special objects that never get paused makes more sense.

1.9. Calculating Time Elapsed Since the Game Start


Problem
You want to find out how much time has elapsed since the game started.

Solution
When the game starts, create an NSDate object and store it:
// In your class's @interface:
@property (strong) NSDate* gameStartDate;

1.8. Pausing a Game | 13


// When the game starts:
self.gameStartDate = [NSDate date];
When you want to find out how much time has elapsed since the game started, create
a second NSDate and use the timeIntervalSinceDate: method to calculate the time:
NSDate* now = [NSDate date];

NSTimeInterval timeSinceGameStart =
[self.gameStartDate timeIntervalSinceDate:self.gameStartDate];

NSLog(@"The game started %.2f seconds ago", timeSinceGameStart);

Discussion
NSDate objects represent moments in time. They’re the go-to object for representing
any instant of time that you want to be able to refer to again later, such as when your
game starts. NSDate objects can refer to practically any date in the past or future and are
very precise.
When you create an NSDate with the [NSDate date] method, you get back an NSDate
object that refers to the current time (i.e., the instant when the NSDate object was cre‐
ated).
To determine the interval between two dates, you use timeIntervalSinceDate:. This
method returns an NSTimeInterval, which is actually another term for a floating-point
number. These values are represented in seconds, so it’s up to your code to do things
like determine the number of hours and minutes:
NSTimeInterval timeElapsed = ... // an NSTimeInterval from somewhere

float minutes = timeElapsed / 60.0; // 60 seconds per minute


float hours = timeElapsed / 3600.0; // 3600 seconds per hour
float seconds = fmodf(timeElapsed, 60.0); // get the remainder

NSLog(@"Time elapsed:%.0f:%.0f:%.2f", hours, minutes, seconds);

1.10. Working with Blocks


Problem
You want to store some code in a variable, for later execution.

Solution
Blocks are ideal for this:
void(^onCollision)(void);

14 | Chapter 1: Laying Out a Game


onCollision = ^(void) {
NSLog(@"Character collided with something!");
};

// Later, when a collision happens:


onCollision();

Discussion
Blocks are a language feature in Objective-C that allow you to store chunks of code in
variables, which can then be worked with like any other variable.
Here’s an example of a simple block:
void(^MyBlock)(void);
MyBlock = ^(void) {
NSLog(@"Hello from the block!");
};
MyBlock();

This is how you define a block. In this case, the block returns void, is named
MyBlock, and accepts no parameters.
Just like any other variable, once a block is defined, it needs to be given a value.
In this case, we’re providing a block that takes no parameters and returns
nothing, just like the block variable’s definition.
Calling a block works just like calling any other function.

How blocks work


So far, this just seems like a very roundabout way to call a function. However, the real
power of blocks comes from two facts:

• Blocks capture the state of any other variables their code references.
• Blocks are objects, and they stay around until you need them. If you store a block,
you can call it however often you like.

Let’s talk about the first point. Say you had a block like this:
int i = 1;

void(^MyBlock)(void) = ^(void) {
NSLog(@"i = %i", i);
};

MyBlock();

As you’d expect, running this code would print i = 1 to the console. But watch what
happens when you change the value of i after creating the block, like this:

1.10. Working with Blocks | 15


int i = 1;

void(^MyBlock)(void) = ^(void) {
NSLog(@"i = %i", i);
};

i = 5;

MyBlock();
This code will print the following to the console:
i = 1
That’s right—running this code produces the same result as the first version. Even
though the i variable has been modified, the console will still print i = 1. This is because
i had the value of 1 at the moment the block was created—the fact that i was later
changed to 5 doesn’t affect the block’s copy of that variable.
This is extremely powerful, because it means that your game doesn’t need to carefully
store values for later use; if a block needs a value, it automatically keeps it.
The syntax for creating blocks is a little messy, with carets (^) and parentheses all over
the place. An easier way to do it is to define a block type, which is just a simple type
definition of a block. For example, here’s a block type for the preceding examples:
typedef void(^ExampleBlock)(void);
This allows you to declare variables with nicer syntax, and with significantly fewer
parentheses and carets:
ExampleBlock myBlock = ^(void) {
NSLog(@"i SPILL my DRINK!");
};
So far, we’ve talked entirely about blocks that don’t have parameters or return types.
These are easy to define, though. For example, here’s a block that returns a BOOL and
takes two parameters, one NSString and one int:
typedef BOOL(^ParameterBlock)(NSString* string, int number);
The syntax to create this block is very similar to the earlier examples:
ParameterBlock paramBlock = ^(NSString* string, int number) {
NSLog(@"I received a string %@, and a number %i!", string, number);

return YES;
};

paramBlock(@"Hello", 1337);
If your block doesn’t take any parameters, you can actually skip the parameter list en‐
tirely:

16 | Chapter 1: Laying Out a Game


typedef void(^ExampleBlock)(void);

[...]

ExampleBlock aBlock = ^{
NSLog(@"Whoa!");
};

Blocks and other objects


When a block is created, the compiler looks at all of the variables that the block is
referencing. If a variable is a simple value, like an int or a float, that value is simply
copied. However, if the variable is an Objective-C object, it can’t be copied, because it
could potentially be very large. Instead, the object is retained by the block. When a block
is freed, any objects retained by the block are released.
This means that if you have a block that references another object, that block will keep
the other object around.
For example, say you have code that looks like this:
NSString* aString = [NSString stringWithFormat:@"One = %i", 1];

void(^MyBlock)(void) = ^(void) {
NSLog(@"The string is %@", aString);
};

aString = nil;

// aString is still in memory, because MyBlock is keeping it around!

The block MyBlock, because it references the aString object, will maintain an owning
reference to aString. This means that even if all other references to aString go away,
the string is kept in memory, and it will only be released when MyBlock goes away. (This
example only makes sense if you’re using automatic reference counting, or ARC—which
you should be.)
This is usually what you want, since it would be annoying to have to remember to keep
the variables referenced by blocks in memory. However, sometimes that’s not what you
want.
One example is when you want a block to run in two seconds’ time that causes an enemy
object to run an attack animation. However, between the time you schedule the block
and the time the block runs, the enemy is removed from the game. If the block has a
strong reference to the enemy, the enemy isn’t actually removed from memory until the
block is scheduled to run, which could have unintended side effects.
To get around this problem, you use weak references. A weak reference is a reference
that does not keep an object in memory; additionally, if the object that is being referred

1.10. Working with Blocks | 17


to is removed (because all owning references to it have gone away), the weak reference
will automatically be set to nil.
You create a weak reference by prepending the keyword __weak to a variable declaration,
like so:
__weak NSString* weakString = aString;

This makes weakString into a weak reference to aString. Now, when aString is re‐
moved from memory, the weakString reference will automatically point to nil instead.
Using weak references, the previous example code looks like this:
NSString* aString = [NSString stringWithFormat:@"One = %i", 1];

__weak NSString* weakString = aString;

void(^MyBlock)(void) = ^(void) {
NSLog(@"The string is %@", weakString);
};

aString = nil;

// aString is no longer in memory, and calling MyBlock will print


// "The string is (null)"

1.11. Writing a Method That Calls a Block


Problem
You want to write a method that, after performing its work, calls a block to indicate that
the work is complete.
For example, you want to tell a character to start moving to a destination, and then run
a block when the character finishes moving.

Solution
To create a method that takes a block as a parameter, you just do this:
- (void) moveToPosition:(CGPoint)position
completionBlock:(void (^)(void))completion {

// Do the actual work, which might take place over several frames
[...]

// Call the completion block


if (completion != nil) {
completion();

18 | Chapter 1: Laying Out a Game


}
}
And to pass the block to the method, you do this:
CGPoint destination = ...
[someObject moveToPosition:destination completionBlock:^{
NSLog(@"Finished moving!");
}];

Discussion
Methods that take a block as a parameter are useful for when you’re writing code that
starts off a long-running process, and you want to run some code at the conclusion of
that process but want to keep that conclusion code close to the original call itself.
Before blocks were added to the Objective-C language, the usual technique was to write
two methods: one where you started the long-running process, and one that would be
called when the process completed. This separates the various parts of the code, which
decreases the readability of your code; additionally, passing around variables between
these two methods is more complicated (because you need to manually store them in a
temporary variable at the start, and retrieve them at the end; with blocks, you just use
the variables without any additional work).

1.12. Working with Operation Queues


Problem
You want to put chunks of work in a queue, so that they’re run when the operating
system has a moment to do them.

Solution
Use an NSOperationQueue to schedule blocks to be run in the background without
interfering with more time-critical tasks like rendering or accepting user input:
NSOperationQueue* concurrentQueue = [[NSOperationQueue alloc] init];
concurrentQueue.maxConcurrentOperationCount = 10;

[concurrentQueue addOperationWithBlock:^{
UploadHighScores();
}];

[concurrentQueue addOperationWithBlock:^{
SaveGame();
}];

[concurrentQueue addOperationWithBlock:^{

1.12. Working with Operation Queues | 19


DownloadMaps();
}];

Discussion
An operation queue is a tool for running chunks of work. Every application has an
operation queue called the main queue. The main queue is the queue that normal ap‐
plication tasks (e.g., handling touches, redrawing the screen, etc.) are run on.

Many tasks can only be run on the main queue, including updating any‐
thing run by UIKit. It’s also a good idea to only have a single operation
queue that’s in charge of sending OpenGL instructions.
The main queue is a specific NSOperationQueue, which you can access
using the mainQueue method:
NSOperationQueue* mainQueue = [NSOperationQueue mainQueue];

[mainQueue addOperationWithBlock:^{
ProcessPlayerInput();
}];
It’s often the case that you want to do something in the background (i.e.,
on another operation queue), and then alert the user when it’s finished.
However, as we’ve already mentioned, you can only do UIKit or Open‐
GL tasks (e.g., displaying an alert box) on the main queue
To address this, you can put tasks on the main queue from inside a back‐
ground queue:
NSOperationQueue* backgroundQueue = [[NSOperationQueue alloc] init];

[backgroundQueue addOperationWithBlock:^{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"This is run on the main queue");
}];
}];

An operation queue runs as many operations as it can simultaneously. The number of


concurrent operations that can be run depends on a number of conditions, including
the number of processor cores available, and the different priorities that other opera‐
tions may have.
By default, an operation queue determines the number of operations that it can run at
the same time on its own. However, you can specify a maximum number of concurrent
operations by using the maxConcurrentOperationCount property:
NSOperationQueue* aQueue = [[NSOperationQueue alloc] init];
aQueue.maxConcurrentOperationCount = 2;

20 | Chapter 1: Laying Out a Game


1.13. Performing a Task in the Future
Problem
You want to run some code, but you want it to happen a couple of seconds from now.

Solution
Use dispatch_after to schedule a block of code to run in the future:
// Place a bomb, but make it explode in 10 seconds
PlaceBomb();

double timeToWait = 10.0;


dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(timeToWait * NSEC_PER_SEC));

dispatch_queue_t queue = dispatch_get_main_queue();

dispatch_after(delayTime, queue, ^(void){


// Time's up. Kaboom.
ExplodeBomb();
});

Discussion
NSOperationQueue is actually a higher-level wrapper around the lower-level features
provided by the C-based Grand Central Dispatch API. Grand Central Dispatch, or GCD,
works mostly with objects called “dispatch queues,” which are basically NSOperation
Queues. You do work with GCD by putting blocks onto a queue, which runs the blocks.
Just as with NSOperationQueue, there can be many queues operating at the same time,
and they can be serial or concurrent queues.
GCD provides a function called dispatch_after that runs a block on an operation
queue at a given time. To use the function, you first need to figure out the time when
the block should be run. GCD doesn’t actually work in seconds, or even in nanoseconds,
but rather with time units called dispatch_time_t, which Apple’s documentation de‐
scribes as “a somewhat abstract representation of time.”
To work with dispatch_time_t, you use the function dispatch_time, which takes two
parameters: a base time and an amount of time to be added on top, measured in nano‐
seconds.
Therefore, to get a dispatch_time_t that represents 1 second in the future, you would
use this:

1.13. Performing a Task in the Future | 21


double timeToWait = 1.0;
dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(timeToWait * NSEC_PER_SEC));
Once you have a time for the block to run at, you need to get a reference to a GCD
dispatch_queue. You can create your own, but you generally only want the main queue,
which you can get using dispatch_get_main_queue:
dispatch_queue_t queue = dispatch_get_main_queue();
Finally, you instruct GCD to run the block:
dispatch_after(delayTime, queue, ^(void){
NSLog(@"Delayed block");
});

1.14. Storing Blocks in Objects


Problem
You want to store a block in an object, so that the object can call it later.

Solution
Blocks can be stored as properties in objects. For example:
typedef void(^CallbackBlock)(void);

@interface Monster : NSObject

@property (copy) CallbackBlock onDeathBlock;


@property (copy) CallbackBlock onHitBlock;

@end

[...]

// In the Monster class:


- (void) die {
self.onDeathBlock();
}

- (void) hit {
self.onHitBlock();
}

[...]

Monster* monster = ...

monster.onDeathBlock = ^{

22 | Chapter 1: Laying Out a Game


NSLog(@"Monster died!");
};

monster.onHitBlock = ^{
NSLog(@"Monster hit something")!
};

Note that the property settings for the aBlock copy in this example indicate that the
block should be copied. This is important—if you don’t do this, then your application
will crash when you try to call it.
The reason for this is that when a block is created, it’s created on the stack. When the
function that it’s created in returns, the block is destroyed.
Copying a block moves the block from the stack to the heap, which means that the block
stays around after the function that created it returns. It also means that the block needs
to be explicitly freed (though ARC handles this for you, either when you set the property
that contains the block to nil or when the object is freed).

Discussion
A block stored as a property can be accessed just like any other variable, and called like
all blocks are:
- (void) doSomething {
self.aBlock();
}

If you call a block that’s set to nil, your app will crash. For example:
ExampleBlock aBlock = nil;
aBlock(); // CRASH!
You need to do explicit checking if you want to be safe:
if (aBlock != nil) {
aBlock();
}

When you store a block as a property of an object, it’s important to remember that blocks
can retain objects. If an object is retaining a block, and that block is retaining the object
as well, you have a retain cycle.
Say you have a block that looks like this:
void(^MyBlock)(void) = ^(void) {
NSLog(@"I am %@", self); // block now retains self
};

self.aBlock = MyBlock; // self now retains block; retain cycle!

1.14. Storing Blocks in Objects | 23


Note how MyBlock references the self object. The compiler notices this, and will make
the block retain the self object in memory (because in order for the block to function,
it needs to be able to use that variable, which means that the object that that variable
points to needs to be kept around). See Figure 1-3.

Figure 1-3. Retain cycles

However, if you store that block in a property in self, the block and the object will be
retaining each other. This prevents the object from being removed from memory when
all other strong references to it have gone away, as shown in Figure 1-4.

Figure 1-4. A fixed retain cycle

To prevent this from happening, you should always use weak references to self by
declaring the variable with the __weak keyword:
__weak id weakSelf = self;

void(^MyBlock)(void) = ^(void) {
NSLog(@"I am %@", weakSelf); // block does NOT retain self
};

self.aBlock = MyBlock; // self now retains block; no retain cycle

24 | Chapter 1: Laying Out a Game


1.15. Using a Timer
Problem
You want to create a timer that repeatedly calls a block.

Solution
First, create an instance variable to store the timer:
@interface ViewController () {
dispatch_source_t timer;
}

@end
Then, create the timer like so:
// Get the queue to run the blocks on
dispatch_queue_t queue = dispatch_get_main_queue();

// Create a dispatch source, and make it into a timer that goes off every second
timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);

dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0);

// When the timer goes off, heal the player


dispatch_source_set_event_handler(timer, ^{
GivePlayerHitPoints();
});

// Dispatch sources start out paused, so start the timer by resuming it


dispatch_resume(timer);

To cancel the timer, just set the timer variable to nil:


timer = nil;

Discussion
In addition to dispatch queues, GCD has a concept called a dispatch source, which is
something that triggers work to be done. Dispatch sources can be created for things like
file I/O where you can run a block when data is available to be read, and timers, where
you run a block at a fixed interval.
To create a dispatch timer, you first create a dispatch_source_t, and then configure it
to be a timer. As part of setting it up, you also give it a dispatch_queue_t for it to run
its code on:

1.15. Using a Timer | 25


dispatch_queue_t queue = dispatch_get_main_queue();

timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);


The next step is to tell the timer how often it should be fired. This is defined in nano‐
seconds:
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0);
Finally, you provide the timer with the block that should be run every time the timer
goes off. Dispatch sources start out paused, so you also need to unpause the timer by
calling dispatch_resume:
dispatch_source_set_event_handler(timer, ^{
GivePlayerHitPoints();
});

dispatch_resume(timer);

When you want to stop the timer, you just set it to nil. ARC knows about GCD objects,
so setting it to nil will cause it to be cleaned up properly.

1.16. Making Operations Depend on Each Other


Problem
You want to run some operations, but they need to run only after certain other opera‐
tions are done.

Solution
To make an operation wait for another operation to complete, store each individual
operation in a variable, and then use the addDependency: method to indicate which
operations need to complete before a given operation begins:
NSBlockOperation* firstOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"First operation");
}];

NSBlockOperation* secondOperation = [NSBlockOperation blockOperationWithBlock:^{


NSLog(@"Second operation (depends on third operation and first operation)");
}];

NSBlockOperation* thirdOperation = [NSBlockOperation blockOperationWithBlock:^{


NSLog(@"Third operation");
}];

[secondOperation addDependency:thirdOperation];
[secondOperation addDependency:firstOperation];

26 | Chapter 1: Laying Out a Game


[[NSOperationQueue mainQueue] addOperations:@[firstOperation, secondOperation,
thirdOperation] waitUntilFinished:NO];

Discussion
You can add an operation to another operation as a dependency. This is useful for cases
where you want one block to run only after one or more operations have completed.
To add a dependency to an operation, you use the addDependency: method. Doing this
doesn’t run the operation, but just links the two together.
Once the operation dependencies have been set up, you can add the operations to the
queue in any order that you like; operations will not run until all of their dependencies
have finished running.

1.17. Filtering an Array with Blocks


Problem
You have an array, and you want to filter it with your own custom logic.

Solution
Use the filteredArrayUsingPredicate method to create an array that only contains
objects that meet certain conditions:
NSArray* array = @[@"One", @"Two", @"Three", @"Four", @"Five"];

NSLog(@"Original array: %@", array);

array = [array filteredArrayUsingPredicate:


[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject,
NSDictionary *bindings) {

NSString* string = evaluatedObject;

// Search for an "e" in the string


if ([string rangeOfString:@"e"].location != NSNotFound)
return YES;
else
return NO;

}]];

NSLog(@"Filtered array: %@", array);

1.17. Filtering an Array with Blocks | 27


Exploring the Variety of Random
Documents with Different Content
The Project Gutenberg eBook of
A Life Unveiled, by a Child of the Drumlins
This ebook is for the use of anyone anywhere in the United
States and most other parts of the world at no cost and with
almost no restrictions whatsoever. You may copy it, give it away
or re-use it under the terms of the Project Gutenberg License
included with this ebook or online at www.gutenberg.org. If you
are not located in the United States, you will have to check the
laws of the country where you are located before using this
eBook.

Title: A Life Unveiled, by a Child of the Drumlins

Author: Anonymous

Author of introduction, etc.: John Burroughs

Release date: November 12, 2021 [eBook #66717]

Language: English

Credits: Martin Pettit and the Online Distributed Proofreading


Team at https://www.pgdp.net (This file was produced
from images generously made available by The
Internet Archive/American Libraries.)

*** START OF THE PROJECT GUTENBERG EBOOK A LIFE


UNVEILED, BY A CHILD OF THE DRUMLINS ***
Transcriber’s Note:

Obvious typographic errors have been


corrected.

A LIFE UNVEILED
A LIFE UNVEILED
BY

A CHILD OF THE DRUMLINS


WITH AN INTRODUCTION
BY
JOHN BURROUGHS

Ce livre est toute ma jeunesse; je


l’ai fait sans presque y songer.
—De Musset

GARDEN CITY NEW YORK


DOUBLEDAY, PAGE & COMPANY
1922

COPYRIGHT, 1922, BY
DOUBLEDAY, PAGE & COMPANY
ALL RIGHTS RESERVED, INCLUDING THAT OF TRANSLATION
INTO FOREIGN LANGUAGES, INCLUDING THE SCANDINAVIAN
PRINTED IN THE UNITED STATES
AT
THE COUNTRY LIFE PRESS, GARDEN CITY, N. Y.
First Edition
CONTENTS
PAGE
Introduction by John Burroughs vii
To the Reader xi
CHAPTER
I. The Family Tree 1
II. The Roof-Tree 14
III. “A Child Went Forth” 42
IV. In the Old Paths 71
V. “As Twig Is Bent” 94
VI. “Bred in the Bone” 119
VII. School Days 134
VIII. The “Medic” 172
IX. The “Medic” (Continued) 229
X. The “Medic” (Concluded) 245
XI. Through the Gate of Dreams 273
INTRODUCTION
I fancy that this “Child of the Drumlins” did not know she was living
amid drumlins when she passed her youth there. She knew them
only as the long, smooth, loaf-shaped hills that were scattered over
her native landscape, upon which she saw cattle grazing and grain
ripening, and upon which she roamed and played in the freedom of
childhood.
These curious-looking hills are found in certain parts of New
England, and in a large section of the central and western parts of
New York state. They would suggest artificial mounds were they not
so large as to preclude all idea of their being the work of man. They
were indeed made, but not by human hands. They are the work of
the great continental ice-sheet which tens of thousands of years ago
crept slowly over a large part of the Northern hemisphere, giving to
the landscape, among many other strange new features, these long,
low, rounded hills, called by the geologists drumlins, amid which the
“Child” passed her early life. Carpeted with grass and often dotted
with trees, these peaceful pastoral elevations are seldom more than
a quarter of a mile long, and perhaps a hundred feet high. Their
trend is in one direction, from northeast to southwest—the general
course the ice-flood took. They are simply huge heaps of clay and
water-worn boulders shovelled together by the gods of the Ice Age,
though just how it all came about the geologists are not clear. But
there they stand, making a marked feature in the landscape.
To the Land of the Drumlins, rich in its early associations, the writer
of this narrative turns, giving a moving record of real life which to
me makes fiction insipid. It presents the natural history of an
American girl in the last quarter of the nineteenth century. (And why
should we not have such a history, as well as that of much less
interesting animals?) Herein we see pictured typical and
representative conditions and individuals which contributed to the
development of a dreaming, aspiring girl into a woman of serious
purpose and substantial achievement in a strenuous and useful
career. A notable piece of work of permanent literary and
psychological value, it sweeps one along by its intrinsic interest, its
candour, its playfulness, and its seriousness. Childhood memories,
trivial and signal events, portraiture, incidents, form a picture of real
life convincing as only real things can convince. Through it we look
into a heart and a life. It is life. One sees the writer from her
forebears up. With what admirable art she brings certain scenes
before us! One is present, sees and feels them all, and shares her
inmost thoughts and emotions. One’s tears stand trembling at the
doorway; smiles and laughter are irresistibly evoked. The feeling
with which the writer has invested the narrative is the principal
source of its charm and value; it is that which makes us a sharer in
all her life. The book does not appear to be written, but rather an
unveiling of memories, with an entire absence of literary
consciousness. Her mind seems transparent; her life like an open
book before her where she can trace every passage. Does she forget
nothing? Few persons can see themselves objectively and at the
same time achieve such self-analysis.
One is carried along by the rush and spontaneity of the record, as
the author evidently was in writing it. In her passionate confession,
faults and errors are courageously set down. One rejoices to know
that there were imps in the girl who shows at the same time such a
serious, earnest nature, such a vibrant, susceptible personality. One
likes her for her pranks and her naughtiness, her stubbornness, her
primness, and her deep attachments. She piques one and leads one
on, a willing sharer in all her experiences. One comes to see that he
is always to expect the unexpected from this demure, enigmatic
creature who, though preserving her own individuality, is so like all
girls of her time and race. And it is this universal appeal which gives
the record its value: other girls and women, other youths and men
as well, will see themselves in this “Child of the Drumlins” who
summons her past before us so vividly that we, too, live over again
the days of our own youth.
TO THE READER
Have you ever reached a time in your life when all that had gone
before seemed cut off from the present; when you felt an imperious
need to review whatever had gone to the making of the You; when
the preceding years, full as they had seemed, were barren of that
which made the present so vital; when, because of that barrenness,
they seemed to have belonged rather to the life of one you knew
than to your own? If you have, you will understand the motive that
sometimes leads one to deliberate self-study and self-delineation.
He who honestly undertakes such study is pledged to candour at all
costs. Beginning by reviewing his ancestry and environment, he also
tries to recapture some of those earliest, evanescent sense
experiences and memories of childhood. He peers into that
mysterious borderland between childhood and youth; surveys the
formative influences, the outstanding events, the proclivities,
longings, aspirations, achievements, struggles, temptations,
successes, defeats—reviews them all, tries to estimate their
influence, and to recognize their possible reappearance, in other
guises perhaps, in his present self. The dawning of religious
emotion, sex consciousness, the gradual transition from the
receptiveness and naïve simplicity of childhood to the wilful caprice
of adolescence (with its blind gropings, its heightened emotional life,
its contradictory moods, its evolution of self-consciousness and social
consciousness)—all these phases he passes in review and weighs,
hoping to form a just estimate as to their effect upon his personality
as he alone knows it.
One cannot compass this survey until one has passed beyond the
seething period of adolescence which merges so insensibly into that
of maturity. Immaturity, maturity—the difference is only of degree;
the child is father to the man; the psychology we trace in child life is
fundamentally the same that obtains when the individual achieves
that self-control and balance, that steadiness of aim, that
harmonious union of bodily and mental powers which characterize
maturity. Until we understand this merging and blending of
experiences that make up a life history, we may regard as trivial the
fleeting events and memories of childhood which the psychologist
knows are significant and far-reaching.
In the rapid setting down of what comes crowding into the
consciousness as the canvas of one’s life unrolls before him, one is
not especially concerned with the orderly sequence of events;
mental associations are intractable forces to deal with; a certain
looseness of exterior matters is inevitable; the eye cannot look both
in and out at the same time. What really matters is that one
accurately read one’s own consciousness, without mistakes, without
self-deception, without wilful deceit. Unless this is achieved, one
cheats one’s self.
Perhaps the record is made for self alone; perhaps for another; in
any case not for the public; and yet as the years pass, and the
events recorded have become so remote as to seem dissociated
from the present self, it may happen that the question of sharing the
record with others arises—a question which gives pause to the
autobiographer with scant claim on the public.
“Who is this,” he imagines the reader inquiring, “who so confidently
asks us to share all these details of her life?” And then there comes
to mind that statement of Carlyle’s: that the humblest life, if
truthfully presented, would be of absorbing interest; that a true
delineation of the smallest man and his scene of pilgrimage
throughout life, is capable of interesting the greatest men, since all
men are brothers, and since human portraits, faithfully drawn, must
be of all pictures the welcomest on human walls.
And so the story goes forth. If it faithfully depict the psychology of
child life, of adolescence, of dawning maturity, devoid though it be
of plot and, as a whole, of dramatic interest, it may yet, as a typical
human portrait, justify itself; may aid the young to a better
understanding of their own natures, and help those no longer young
to a keener remembrance, a deeper sympathy, and a broader
tolerance concerning the struggles, problems, and complexities that
beset the young lives around them.
This book of my childhood and youth, written many years ago, is as
sincere as such a thing can well be, and this constitutes its only
excuse for being. Unless I have told the naked, unblushing truth,
why pretend to unveil my life?[1] If I have concealed faults and
follies, what is there in common with your life as you alone know it?
Doubtless you yourself would shrink from the deliberate self-analysis
and self-revelation I have made, and yet may find herein natural
human reactions which tally with your own inarticulate experiences.
L’Innommée.

FOOTNOTE:
[1] The names in the narrative are, of course, fictitious.
A LIFE UNVEILED

I once wandered in a beautiful garden. It had high walls which made


one feel safe and sheltered. There were many flower-bordered
paths, and some that were stony and rough. There were broad open
spaces, dark, wooded corners, cosy nooks, and friendly trees.
Openings in the wall gave glimpses that made one’s heart beat
faster and that filled one with queer restless feelings, half pleasure,
half pain.
There came a day when I left the garden and started on a long
journey. I have never been back. Sometimes I have wanted to go
back, but the great gate can never open from the outside.
When we lose our Edens, you and I, is it any wonder that we
sometimes pause in the journey, and long to recapture the days
when we played in the enchanted enclosure? What if, some day, one
creeps back close to the wall, holding up the magic mirror he
brought away with him? What if he gets glimpses that help him to
continue on the way? What if he lets you peep into the mirror, too—
the mirror which will reflect the garden you played in, the paths you
trod, the flowers you gathered, the playmates you knew?

A LIFE UNVEILED
CHAPTER I
The Family Tree

I seem always to have lived a life apart from the obvious one, seeing
the strange contrasts, the incongruities, the dramatic moments,
though always these things were unexpressed. Those about me had
no inkling of what was passing in my mind. Perhaps it is so with all
children. One can only know one’s self, and that so vaguely.
I was born near the foot of a drumlin. Their smooth level crests
broke the horizon line of my native village. Amid the drumlins I
shared in all the little world they bounded. On the summit of a
drumlin my kindred lie buried, and back to the drumlins I shall one
day turn—back to the commonplace little village where my life
began. The village has not grown in all the years, either in
population or importance; on the contrary, it seems to have
dwindled to tiny dimensions. Whenever I go back there now, the
houses and the prominent buildings look smaller, the drumlins lower,
and all the distances are lessened to a surprising degree. I look at
the one handsome residence the village boasts and ask, Is that the
house I used to think so imposing? Are those the grounds so
illimitable to my childish eyes? And is this the same hill near
Grandfather’s barn that was so steep when three happy children
clambered over it in search of sorrel leaves? What a paltry patch of
ground Grandmother’s garden now is! yet there was a time when,
engaged in one of the tasks of my childhood (that of picking
Grandma’s raspberries and currants), her garden bounded my little
world which then did not seem little at all. Nor was it; for while
moving among the currant bushes, my fingers busy, my thoughts
roamed far afield—out past the hop vines in the rear; out past the
clump of big red “pineys” in front, and the corner where the
smallage grew; past the snowball bush, even past the oxheart cherry
tree; through the little blue gate, and out into the big wonderful
world beyond. No, it was not a little garden; it was a very big garden
then; some unkind trickery has been at work these later years to
make it the poor cramped little enclosure which I viewed last
summer through blinding tears.
And Grandma’s old house, too. How low the rooms are now! There
was a time when, caught up in the arms of an uncle, and seated on
his shoulder, the laughing faces below me seemed remote indeed to
my half-pleased, half-frightened eyes. How tall I feel, almost stately,
as I enter the rooms now; and what a chill and gloom strike to the
marrow of my being to find no longer the dear old wrinkled face to
greet me! To see the same paper on the walls, the same clock on
the mantel, the same familiar things at every turn, worn and faded,
but still there, while that cherished face, and those beneficent, toil-
worn hands, and the tired, pain-racked heart are gone forever!
No one was ever so hospitable as Grandpa and Grandma. “Just sit
by and have a bite of something,” Grandma would urge, unaware
that she was dispensing a blessing instead of asking a boon. Their
meals were frugal—no recollection of bounty comes to me, except at
Thanksgiving or other family reunions; but Grandma’s bread and
butter, her warmed-up potatoes, and her sugar cookies (with
caraway seeds in them), touched the spot as no other food ever did
or can. Then she used to place a cup of tea (green tea, it always
was) slyly by my plate, saying: “I guess your Ma won’t care this time
if you take a little.” I can see the little brown tea-pot now as she
brings it from the back of the stove; the silver lustre sugar-bowl with
its ribbed sides, and the nick on the knob of the cover; the blue
dishes; the Britannia spoons—no one but Grandma had Britannia
spoons—and the thin, pointed silver ones; the yellow-handled
knives; and the funny little two-tined fork that Grandma herself used
—the rest of us had forks with three tines.
There’s the Boston rocker in which Grandpa sat of a winter evening
and peeled apples for drying. I wonder where his little old “shoe-
knife” is. “What makes your hands tremble so, Grandpa?” Sister
would ask; but in spite of the tremor he peeled a heaping pile of an
evening.
“Eunice, fetch me a bigger pan,” he would call to Grandma, busy in
kitchen or buttery; and how testy he got if she didn’t understand, or
brought the wrong pan! I shuddered when he spoke that way to her,
and wondered why it was; and her meek face and humble silence
made me love and pity her the more. I never learned not to mind
Grandpa’s angry tones. It was “his way” with her. His voice, as I
remember it, was almost always harsh to her, but never to me,
never to me. He was always indulgent with me, and with all of us
children—except when we hung around the barn at milking-time—
then he would forget himself, and one would have thought he was
shouting to Grandma or to the cows instead. We learned not to put
his temper to this strain very often—his hospitality did not extend
that far. I don’t know how much an incident of my babyhood
engendered this feeling: Grandpa had a white cow, a gentle, well-
behaved “critter,” but one day when they took her calf away,
maddened, she made a dash at me, playing near; caught me on her
horns, and ran up the bank of the tow-path, while Mother looked on
paralyzed with fear. As Grandpa and a neighbour ran up the bank,
the cow ran faster, then tossed me wildly in the air.
“I didn’t know whether you would fall in the water or on her horns,”
Mother used to say; “I expected to see you drowned in the canal or
horribly wounded; but Mr. Mintline caught you in his arms—Grandpa
sold the cow the next day.” Mother’s voice always trembled in
recounting the incident.
Since then I have always been afraid of cows. If the peaceable
creatures come slowly toward me, try as I will I cannot walk slowly
away. I breathe freely only when the fence is between them and me.
By some childish twist of the imagination, so vivid was the
impression made upon me by hearing of being caught on the horns
of that old white cow, I believed myself to have been injured by the
act, and was quite a big child before I learned that certain
anatomical mark on my body—the little deep dimple in the abdomen
—was not made by the horns of that angry cow. It needed the
confirmation given by seeing my sister’s and other children’s bodies
similarly marked to disabuse my mind of that belief.
I remember when in my early ’teens I would meet that neighbour—
Mintline—an unkempt man, who had long since forgotten his share
in my life, I would think, “He caught you in his arms,” and would
smile to myself at the incongruity as, fluttering past him on the
street in my pretty muslin gown, I was acutely conscious of the
contrast with his rough, untidy clothes. Turning and looking after
him I would say under my breath, “You don’t know, but I do, and
I’m grateful to you, even if you have forgotten it all.”
Grandpa, as I have said, was impatient and irascible; he was easily
moved to profanity; but he was a man of probity of life and
character and a hater of shams. His sense of humour was keen, also
his sense of justice. He was a mason by trade; had built the brick
church in the town, the old Academy, and a few other fine old brick
buildings standing there to-day. I used to look upon these with
pride, saying to myself, “Grandpa built that—and that”; though, since
my earliest recollection, he had not worked at his trade. He led an
active life up to his eighty-sixth year about his village farm, with his
cows and his pigs, and his haying in the low-lying meadows. I can
see him now riding his black horse, straight and sturdy, on his way
to the pasture with the cows. Often they were wayward and the
boys in the street would annoy him. I used to feel chagrined beyond
words when I heard him swearing at the cows, or at the boys, and
saw him brandishing his whip in the air. Mother felt the same. I
could detect a look of relief on her face those days when Grandpa
rode peaceably by with the cows.
Grandma was not pious, she was a saint. Though a church member,
she seldom went to church. Toiling from morning till night, she
endured hardship, harshness, and pain with a sweet reasonableness
that endeared her to all. Grandpa’s impatience and shouting never
provoked complaints from her. She seemed to think his quick temper
and deafness excused him.
In contrast to her hard workaday life I was always dreaming of the
romance of Grandma’s early days. Filling in related facts with
fancies, I pored over her early picture with its quaint arrangement of
gown and hair, rejoicing in traces of her girlish beauty. I liked her
quaint name, Eunice (a cousin of hers, a courtly old gentleman, used
to call her Eu-ni’-ce—that was beautiful, but Grandpa
uncompromisingly pronounced it Eu’-nis); I liked the names of her
sisters, too—Thankful, Peace, and Nancy.
In retrospect I mourned with my great-grandfather Albro when he
lost his young wife and had to scatter his baby girls among their
relatives. Near neighbours, John Gear and wife, had begged for little
Eunice, then less than two years old. Though he let them take her,
he had refused their repeated requests to adopt her. But one
morning the neighbours were astonished to find the Gear house
dismantled and deserted, the couple having stolen away in the night.
They were bound to have that child. No trace of them could be
obtained. That was in 1813. They easily escaped detection, though
for years the poor father inquired diligently of chance strangers and
travellers for news of the fugitives.
The Gears journeyed to a distant county. Eunice was reared in
ignorance of her real parentage. Even when she married, her foster
parents were loth to let her leave them. Her own home and children
soon claimed all her thoughts, and she lived on unaware of the
tragedy in the life of her father.
There was a certain youth, Otis Sprague, to whom Grandma had
been attached before marrying Grandpa; at least, she went to
parties with him. (I can’t tell just how much of this is my own
romancing, but I convinced myself he was a disappointed suitor.) He
left home in the early years after Grandma’s marriage, journeying to
Washington county, the home of his ancestors. (I used to make
believe he left because he could not bear to see Grandma the wife of
another.) Visiting among his kindred, he came upon his uncle, my
great-grandfather. As usual, the old man inquired of the traveller
what parts he had come from, and then ventured, “Did you ever
chance to meet a man, Gear—John Gear?”
“John Gear? Why, yes—there’s a John Gear lives in our place. I know
him well.”
I could see the old man trembling with joy—the long-expected
answer come at last! Faltering as he tried to frame the next
question, he hesitated so long the young man thought him a little
daft:
“And did you—has he—is there—did you ever hear tell of Eunice—a
child with big blue eyes and”—then he broke off, afraid to question
further—she might be dead, or, if living, must be a woman now.
Otis had his own reasons, I was confident, for remembering Eunice.
He knew just how those wistful blue eyes looked, and how the soft
brown hair waved over her forehead. Seeing at once that this meant
more to the old man than he could express, Otis answered the
unasked questions; told him there had been a Eunice Gear, eldest
daughter of John Gear (for the childless couple had later had
children born to them). She had married a young mason a few years
ago—Crandall by name—quick tempered, but a good fellow; they
had two babies when he came away, and he guessed there was
another one a-coming. Yes, he went to school with her—took her to
a party once.
Then I saw the scene that followed—the broken explanations of the
joyous father—questions, answers, hurriedly uttered, and the
growing eagerness of both men as they supplemented for each
other the missing information about the lost-and-found Eunice.
Enraged at the Gears, on his return home Otis told Grandma the
story of her abduction, and gave her the messages from her father
and sisters.
After that, one hope dominated Grandma’s life—to save enough
money to go to her father. Loving the Gears, her heart yet yearned
for the father and sisters she had never known. But her children
came near together; money was scarce; means of travel were
difficult and uncertain; two children sickened and died; and the
years went by with her hope unfulfilled, an infrequent and laboured
correspondence being the only link between them.
After many years of careful saving, the little hoard was thought
sufficient for the trip. The children were old enough to be left with
Otis’s sister, and Grandma set out on her long journey.
There were no railroads then. She went on the canal “packet.” This
scene was very real to me. I could see her starting, loth to leave her
little family, yet eager to go; timid at the thought of the enterprise,
but impatient at the slow-moving boat. I’m sure she often walked on
the towpath to relieve excitement and suspense. I wonder how long
it took that snail boat to make the trip. Parts of the journey were
made by stagecoach.
On reaching her old home she found her sisters, but her father had
moved to Warren County. More than that, he had had one or two
strokes of apoplexy and could no longer converse; he would, as the
sisters said, “say one word when he meant another.” Her money was
not sufficient to meet the additional expenses; the extra time it
would take was a serious drawback to the anxious mother; then
there was her father’s inability to talk with her; so, torn between
conflicting interests, hampered, anxious, and sore beset, she
abandoned the quest, renounced her long-cherished hope of reunion
with her father, and turned her face toward home and family, drawn
by a half-defined fear lest they get scattered, too.
During Grandma’s last years her sister Thankful came and lived with
her—two feeble old women, united in infancy, separated throughout
their long lives, reunited just before the end! We children called her
Aunt Unthankful: her presence added much to Grandma’s burdens,
but no murmur passed the patient lips; nor would she suffer
criticism of the poor soul who had found refuge in her home and
heart.
As a girl I was keenly alive to the pathos of my great-grandfather’s
life, and to the deferred, then all-but-accomplished hope in
Grandma’s. My own mother’s cherished hope of one day taking
Grandma to her childhood home was also doomed to unfulfilment;
and with a curious prescience I used to ask, “Will the dearest hope
that sleeps against my own heart meet a like rebuff?” Had the tired,
saddened woman found her father at the last, I wonder if his failing
mind could have grasped the truth. Perhaps he would have turned
away in bitter disappointment when they had tried to make him
understand; unable to articulate, but thinking, “That is not my baby
Eunice that John Gear stole from me.” Perhaps he died hoping,
believing, that his little Eunice would still come back.
As a child I remember being gathered into Grandma’s arms,
conscious of an infinite tenderness, inarticulate but encompassing. I
used to look up into her pale, weary face and wonder why she had
to work so hard. I loved to stroke her soft cheeks; was mystified by
the wrinkled flesh that hung beneath her chin; and her poor hands
with their enlarged joints and crooked fingers—it seemed as though
they must hurt to be so bent; vainly I tried to straighten them. It
was such a puzzle, too—the contrast between age and youth as I
saw and felt it in Grandma and myself when patting her face with
my chubby hand. I looked and marvelled and questioned, then gave
up questioning, and rested my head on her breast, content to be
folded in her arms.
There was a pink china teapot with a broken spout high on
Grandma’s pantry shelf. I never saw inside it, but a delightful jingle
came from its capacious depths. In it Grandma kept pennies, nickels,
half-dimes and dimes, and those tiny, three-cent coins I haven’t seen
since childhood; yes, and there were the large three-cent pieces and
the two-cent coppers that one sees no more. Grandma had a way of
urging us children: “Now take a nickel for all your trouble,” just as
she had of urging us to help her empty the old brown cookie jar.
Although there were no injunctions concerning a reasonable amount
of cookies, we were taught at home that we must not accept
Grandma’s nickels (her milk and yeast money) for the errands we
did; and to our credit, be it said, we refused them as a rule, even
when we had to summon all our strength to refuse. I can see now
three pairs of red-mittened hands quickly drawn away as Grandma
would press the tempting coins, first on one, then the other, of her
little helpers. Sometimes the nickel would fall into the pail, and we
would fumble to get it out, while Grandma’s siren tones would urge:
“There, run along home like good children and mind Grandma, just
this once.” Ah, Grandma! many an enticing temptation of yours did
our childish strength withstand! Would that the forbidden sweets
and glittering coins Life has proffered had oftener met a like
renunciation! And yet, can one ever really say that he would change
anything that has become a part of him, of his experience—that, if
he could, he would blot it out, make it as though it had never been?
So used to serving was she, instead of being served, Grandma
seemed always to ask aid under protest; her gratitude was out of all
proportion to the service rendered: “You poor child, when will you
get paid for all you do for Grandma?” was the burden of her talk,
though the “poor child” fairly doted on running errands for her. “Four
pounds of white sugar, two of light brown, half a pound of green
tea, and a ball of Babbitt’s concentrated lye”—this refrain I would
con over and over on my way to the village, lest I forget it while
loitering to watch the boats crawl under the canal bridge.
How many hours I have spent down in her cool sweet cellar over the
little red churn, the dasher going up and down, up and down, while
I said aloud my favourite poems—after Grandma had gone upstairs.
Many a pat of butter has gathered under the dasher while I
rehearsed the winning of Juliet, Othello’s speech to the senate,
Portia’s speech to Shylock—extracts from Cathcart’s Literary Reader,
which was my first introduction to real literature.
Men do not gather grapes from thorns, or figs from thistles. As
Grandma’s life had been one of service, so her daughter, my mother,
was untiring in devotion to her mother; and so, too, I am glad to
say, Mother’s children have tried to emulate the filial examples set
them. By way of contrast I am reminded of a story illustrating
hereditary tendencies: A boy was arrested for beating his father; the
injured father defended his boy thus, “He can’t help beating me: I
beat my father; my father beat his father; and my son’s son will beat
him—it runs in our family.” I am glad it runs in our family to love and
revere our parents. Yet, there was Grandpa with his habit of
profanity, the son of a Baptist clergyman! Mother used to marvel
how he could have grown up that way, since his father, who used to
take boys to tutor in his own home, was said to have given him and
them a very strict up-bringing. His mother, Katrina Klincke, born in
Alsace, was an inexorable housekeeper. Her exacting ways have
cropped out in full force in one of our aunts; and in later years I’m
not sure but this great-grandmother wields an influence over my
sister and me—we cannot be comfortable in disorder or slack
housekeeping, nor—more’s the pity!—can we let any one else be.
My paternal ancestry is French and, probably, Scottish. Father used
to say we were descended on his father’s side from one of the
celebrated French Revolutionists, an intimate of Napoleon’s and
Josephine’s; but my grandparents and great-grandparents were born
in the Land of the Drumlins. When, some years ago, the memoirs of
our reputed French ancestor were published, bringing to light his
brilliant but unscrupulous career, I took a mischievous pleasure in
sending Father the particularly scathing comments concerning “our
ancestor.”
My father was the fifth child in a family of ten; his father died in
early adult life, presumably of tuberculosis, though Father would
never admit it. Two of his sisters had the same disease, and,
because of my resemblance to one of them, and my not robust
health in childhood, I was something of an object of solicitude in
early girlhood, though all fears on that score vanished long ago. I
have heard that my paternal grandfather drank to excess, and know
that one of his sons did, which may largely account for my father’s
life-long zeal for the Temperance Cause. His mother, of Scottish
descent, left with a large family, was brave, strong, and resourceful
to an unusual degree. Their little log-house being miles away from a
neighbour, once during a big snow-storm lasting several days they
had nothing in the house to eat but potatoes and salt. “But we ate
them and were glad to get them,” said Father, who added, “We can
never know how much inward anxiety Mother felt at such times, but
whatever it was, none but herself ever knew.”
We children called her “the other Grandma,” for she then lived “way
out West” (in Michigan), and we never saw her but once. I
remember her serious face, which could look very merry when she
smiled; and her black gown with a purple stripe running through it.
She was at our house on one of my early birthdays and helped us
smoke glass to look at a total eclipse of the sun. When she died, a
cousin came running down the hill waving a yellow paper and saying
breathlessly, “Grandma is dead!” And she smiled when she said it! A
sensitive girl, overcome with the importance of being the bearer of
such news, her smile, I know now, was a purely nervous
manifestation; but I could not judge her leniently then. Moved by
the grief of my parents, I wept to see them weep, but the shadow
passed quickly; not so the resentment I held toward that cousin for
her untimely smile.
As youth passes one longs for fuller knowledge of the lives that
preceded one’s own. We are the result of all that has gone before,
but how often important figures are missing; and even when not,
how inexplicable the sum total is! Lives cut off in our childhood and
youth, or perhaps before we were born, may have endowed us with
this or that constitutional bias, this weakness, that strength—to
which of them do I owe this fault?—is this trait, for which I am
commended, my own, or my great grandmother’s?—insoluble
complexities, yet how we seek an answer, here and there, as we
study our tree of life from the roots up!
CHAPTER II
The Roof-tree

If my father had married a certain sweetheart of his early youth, and


Mother a suitor to whom she almost became engaged, what would
have become of me?

Should I be I, or would it be
One-tenth another to nine-tenths me?

I often asked myself this question. But after each of my parents had
had a preliminary romance, they met at a Methodist prayer-meeting,
and each knew from the start what the outcome would be.
Mother was then a school-teacher, Father a dry-goods clerk. Both
were born in log houses; both reared in the frugal way of their
times; the snow often blew in on their coverlids through chinks in
the logs; they slept in trundle beds; wore homespun clothes and
calf-skin shoes, and had their education at the district schools to
which they walked through the woods following marked trees. Born
amid the drumlins less than fifty miles apart, all their married lives—
more than fifty years together—have been spent in the little village
where they met.
In the early years of their marriage Father had a travelling wagon
called a “Yankee Notion and Boot and Shoe Store.” Brother, several
years my senior, would tell with pride of Papa’s big wagon and the
iron-gray horses. In girlhood I spent hours upstairs, when supposed
to be putting the large closet to rights at the spring housecleaning,
sitting on the floor poring over Father’s letters to Mother, written
during those years. How like a romance to find those letters so full
of solicitude and love!—comments on Brother’s baby ways;
admonitions to the adopted brother; words of love to Mother—
strange to get this glimpse of my parents; to see the young father’s
pride in his boy; and to read these unrestrained expressions of
devotion! For the father I knew, though affectionate and kind, was a
more staid, reserved person than the one in the letters. Now the
baby boy was grown up, the adopted brother scarcely a memory,
and the girl who was not born when the letters were written was
reading eagerly the ardent words that had gladdened her mother’s
young heart!
The circumstances of my brother’s birth strongly appealed to my
imagination: My parents had given up hopes of a child some years
before he came. Father’s health had long been precarious—a
persistent cough and exhausting night sweats were wasting him
rapidly. Mother, at his side day and night, facing his approaching
death, was facing a hidden dread as well—the fear that she was now
to become a mother. As the weeks passed and the fear became a
certainty, she determined to spare Father the knowledge, thinking it
would kill him outright. She almost prayed for his release before the
truth must be apparent. How she dreaded the scrutiny of the Doctor,
and Father’s questioning eyes! How she resorted to evasion, artifice,
and concealment! But one day, suddenly changing her mind, trusting
in God to help him bear it, she told Father that the child they had
hoped for so long was actually to come.
Instantly he became electrified with the glad tidings. Summoning
unknown funds of strength he cried, “I must live, I will live!” It was a
greatly improved patient that the Doctor found the next day, and
recovery, though slow, dated from that time. (It was probably
arrested tuberculosis.)
Many years later Father’s health again seemed precarious—dizziness,
and numbness of the arms, caused the physician to prophesy
approaching paralysis. I remember this as my first sorrow. I was
perhaps fourteen years old. When Mother told me what the Doctor
had said I flung myself on the bed in a paroxysm of grief. My Father
was going to leave me! The utter helplessness and wretchedness of

You might also like