Categories
Uncategorized

Once again, IDC’s quarterly tablet tracker numbers, nicely formatted and graphed and Excel-ified for you!

venturebeat

VentureBeat have posted their report on IDC’s quarterly tablet sales tracker, and like Business Insider before them, they were content to simply publish screen shots of IDC’s tables.

Here at Global Nerdy, we like to do a little more to help you better understand the numbers. So here are:

  • Some nicely-formatted versions of IDC’s tables
  • The data from those tables turned into graphs
  • A downloadable spreadsheet so that you can play with IDC’s numbers.

Enjoy!

Top Five Tablet Vendors, Shipments, Market Share, and Change, Fourth Quarter 2015

Shipments are in millions of units:

4Q14 Unit Shipments 4Q14 Market Share 4Q15 Unit Shipments 4Q15 Market Share Year-Over-Year Change
Apple 21.4 28.0% 16.1 24.4% -24.8%
Samsung 11.0 14.4% 9.0 13.7% -18.1%
Amazon 1.9 2.5% 5.2 7.9% 175.7%
Lenovo 3.7 4.8% 3.2 4.9% -13.5%
Huawei 1.0 1.3% 2.2 3.3% 124.6%
Others 37.4 49.0% 30.2 45.8% -19.2%
Total 76.4 100.0% 65.9 100.0% -13.7%

top tablet vendors 1

Top Five Tablet Vendors, Shipments, Market Share, and Change, 2015

Shipments are in millions of units:

2014 Unit Shipments 2014 Market Share 2015 Unit Shipments 2015 Market Share Year-Over-Year Change
Apple 63.4 27.6% 49.6 24.0% -21.8%
Samsung 39.8 17.3% 33.4 16.1% -16.1%
Lenovo 11.2 4.9% 11.2 5.4% 0.4%
ASUS 11.8 5.1% 7.1 3.4% -39.9%
Huawei 3.0 1.3% 6.5 3.1% 116.6%
Others 100.9 43.9% 99.1 47.9% -1.8%
 Total 230.1 100.0% 206.9 100.0% -10.1%

top tablet vendors 2

download excel spreadsheet Click here to download the spreadsheet with IDC’s numbers.

Categories
Uncategorized

Writing iOS games with Swift and Sprite Kit, part 2: Responding to touches

touching ipad screen

In the previous article in this series, we looked using actions to create complex sprite movements with very few lines of code. As this series progresses, we’ll work our way towards building complete games.

In this article, we’ll look at responding to user’s touches on the screen.

Set up a new project

It’s time to do the File → New → Project… dance again! Open up Xcode and create a new Game project:

new project

When it comes time to name the project, give it an appropriate name like RespondingToTouches (that’s the name I gave my project).

Once again, we’ll set the game to that it’s landscape-only. The simplest way to restrict our app’s orientation to landscape is by checking and unchecking the appropriate Device Orientation checkboxes in the app’s properties. Make sure that:

  • Portrait is unchecked
  • Landscape Left and Landscape Right are checked

uncheck portrait

Click the screenshot to see it at full size.

You can confirm that the app is landscape-only by running it. It should look like the video below, with spinning spaceships appearing wherever you tap the screen. It shouldn’t switch to portrait mode when you rotate the phone to a portrait orientation:

Making the spaceship go to where you touch the screen

It’s time to make our own interactivity. Let’s make an app that puts the spaceship sprite in the center of the screen, and then has the spaceship sprite immediately go to wherever the user touches the screen.

Open Gamescene.swift and replace its code with this:

import SpriteKit

class GameScene: SKScene {

  override func didMoveToView(view: SKView) {

  }
  
  override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

  }

}

First task: drawing the spaceship sprite in the center of the screen. Before you look at the code, see if you can do it yourself. There’s enough information in the previous article to help you do this, or you can follow these hints:

  • A sprite is an instance of the SKSpriteNode class, and given the name of an image, you can instantiate one by using SKSpriteNode‘s init(imageNamed:) method.
  • A game scene’s didMoveToView method is called when the scene is first presented, and it’s the perfect place to do things like setting sprites in their initial locations.
  • A sprite’s location onscreen can be set using its position property, which is of type CGPoint, a struct that holds 2 Floats: one for the x-coordinate, and another for the y-coordinate.
  • The frame of a scene is the rectangle — a CGRect — that determines its bounds. You can get its width and height through the properties bearing those names.
  • You might want to scale down the spaceship sprite to one-third of its size. The setScale method will do that.
  • To display a sprite in a scene, you need to use the addChild method.

Your code should look something like this…

import SpriteKit

class GameScene: SKScene {
  
  let spaceshipSprite = SKSpriteNode(imageNamed: "Spaceship")
  

  override func didMoveToView(view: SKView) {
    spaceshipSprite.position = CGPoint(x: frame.width / 2,
                                       y: frame.height / 2)
    spaceshipSprite.setScale(0.33)
    addChild(spaceshipSprite)
  }
  
  override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

  }

}

…and when you run it, it should look like this:

spaceship in the middle of the screen

If you were to touch the screen, nothing would happen. That’s because there’s no code to respond to touches on the screen…yet! We’ll start by adding code to the touchesBegan method.

touchesBegan is called when the user puts a finger on the screen. It provides information about that touch action in its touches<c/ode> argument, a Set of touch objects, which are instances of the UITouch class. One of the properties of UITouch is locationInNode, which is a CGPoint. Given that sprites have a position property that is also a CGPoint, you've probably already guessed what we're about to code.

The default setting for multitouch in an app is “off”. We want to keep things simple for now, so we’ll just go with the default, which means that the app will register only one touch at a time, which in turn means that touchesBegan‘s touches argument will only contain a single touch object. We’ll retrieve that object from touches by using Set‘s first property.

Try coding it yourself before looking at the code below:

import SpriteKit

class GameScene: SKScene {
  
  let spaceshipSprite = SKSpriteNode(imageNamed: "Spaceship")
  

  override func didMoveToView(view: SKView) {
    spaceshipSprite.position = CGPoint(x: frame.width / 2,
                                       y: frame.height / 2)
    spaceshipSprite.setScale(0.33)
    addChild(spaceshipSprite)
  }
  
  override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    let touch = touches.first!
    spaceshipSprite.position = touch.locationInNode(self)
  }
 
}

If you run the app, you’ll see that the spaceship jumps to wherever you put down your finger:

Making the spaceship go to where you released your finger

You’ll notice that if you hold your finger on the screen and move it about, the ship doesn’t follow your finger. It just stays where you first touched the screen and doesn’t move until you remove your finger and touch some other point.

The name touchesBegan implies that it has a counterpart method for when the user releases his/her finger from the screen. That method is called touchesEnded, and it takes the same arguments as touchesBegan.

Start typing touchesEnded into GameScene, and Xcode’s autocompletion should make it simple for you to set up a touchesEnded method. Cut the code from touchesBegan and paste it into touchesEnded, like so:

import SpriteKit

class GameScene: SKScene {
  
  let spaceshipSprite = SKSpriteNode(imageNamed: "Spaceship")
  

  override func didMoveToView(view: SKView) {
    spaceshipSprite.position = CGPoint(x: frame.width / 2,
                                       y: frame.height / 2)
    spaceshipSprite.setScale(0.33)
    addChild(spaceshipSprite)
  }
  
  override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

  }
  
  override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
    let touch = touches.first!
    spaceshipSprite.position = touch.locationInNode(self)
  }
 
}

Note what happens: the spaceship doesn’t move when you touch the screen until you remove your finger. Only when you release your finger does it move, and it jumps to the location where you released your finger from the screen. Try touching the screen, moving your finger to another location on the screen, and then releasing your finger.

What if we put the same code into both the touchesBegan and touchesEnded methods, like this?

import SpriteKit

class GameScene: SKScene {
  
  let spaceshipSprite = SKSpriteNode(imageNamed: "Spaceship")
  

  override func didMoveToView(view: SKView) {
    spaceshipSprite.position = CGPoint(x: frame.width / 2,
                                       y: frame.height / 2)
    spaceshipSprite.setScale(0.33)
    addChild(spaceshipSprite)
  }
  
  override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    let touch = touches.first!
    spaceshipSprite.position = touch.locationInNode(self)
  }
  
  override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
    let touch = touches.first!
    spaceshipSprite.position = touch.locationInNode(self)
  }
 
}

If you run the app, the spaceship now jumps to the location where you made initial contact with the screen, and again to the location where you released your finger.

Making the spaceship follow your finger as you move it

You’re probably wondering if there’s a method that responds to changes that occur between the touchesBegan and touchesEnded events, something that lets you track the movements of the user’s finger as it moves on the screen. There is, and it’s called touchesMoved. It takes the same arguments as touchesBegan and touchesEnded, which means that it should respond to the code that we put into those two methods. Copy and paste the code from either touchesBegan and touchesEnded and paste it into touchesMoved. Your code should look like the following:

import SpriteKit

class GameScene: SKScene {
  
  let spaceshipSprite = SKSpriteNode(imageNamed: "Spaceship")
  

  override func didMoveToView(view: SKView) {
    spaceshipSprite.position = CGPoint(x: frame.width / 2,
                                       y: frame.height / 2)
    spaceshipSprite.setScale(0.33)
    addChild(spaceshipSprite)
  }
  
  override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    let touch = touches.first!
    spaceshipSprite.position = touch.locationInNode(self)
  }
  
  override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
    let touch = touches.first!
    spaceshipSprite.position = touch.locationInNode(self)
  }
  
  override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
    let touch = touches.first!
    spaceshipSprite.position = touch.locationInNode(self)
  }
 
}

Run the app. It should look like this:

You’ll find that the spaceship jumps to the location where you touched the screen and as long as you keep your finger on the screen, you can drag it around. When you release your finger from the screen, the ship stays at the location where you released your finger.

Let’s refactor the duplicate code in touchesBegan, touchesMoved, and touchesEnded into its own method, handleTouch. The code will now look like this:

import SpriteKit

class GameScene: SKScene {
  
  let spaceshipSprite = SKSpriteNode(imageNamed: "Spaceship")
  

  override func didMoveToView(view: SKView) {
    spaceshipSprite.position = CGPoint(x: frame.width / 2,
                                       y: frame.height / 2)
    spaceshipSprite.setScale(0.33)
    addChild(spaceshipSprite)
  }
  
  override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    handleTouch(touches.first!)
  }
  
  override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
    handleTouch(touches.first!)
  }
  
  override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
    handleTouch(touches.first!)
  }

  func handleTouch(touch: UITouch) {
    spaceshipSprite.position = touch.locationInNode(self)
  }

}

Experimenting with actions

Let’s combine this article’s lessons with the ones from the last one. Can you create some actions that make the spaceship pulsate as long as the user presses on the screen, as shown below?

Before you look at my solution below, see if you can’t code it yourself first:

import SpriteKit

class GameScene: SKScene {
  
  let spaceshipSprite = SKSpriteNode(imageNamed: "Spaceship")
  

  override func didMoveToView(view: SKView) {
    spaceshipSprite.position = CGPoint(x: frame.width / 2,
                                       y: frame.height / 2)
    spaceshipSprite.setScale(0.33)
    addChild(spaceshipSprite)
  }
  
  override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    let expandAction = SKAction.scaleTo(0.5, duration: 0.33)
    let contractAction = SKAction.scaleTo(0.33, duration: 0.33)
    let pulsateAction = SKAction.repeatActionForever(
      SKAction.sequence([expandAction, contractAction]))
    spaceshipSprite.runAction(pulsateAction)
    handleTouch(touches.first!)
  }
  
  override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
    handleTouch(touches.first!)
  }
  
  override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
    handleTouch(touches.first!)
    spaceshipSprite.removeAllActions()
    let restoreScaleAction = SKAction.scaleTo(0.33, duration: 0.1)
    spaceshipSprite.runAction(restoreScaleAction)
  }

  func handleTouch(touch: UITouch) {
    spaceshipSprite.position = touch.locationInNode(self)
  }

}

You may have noticed that in the touchesEnded method, the spaceship sprite is restored to its normal scale with an action rather than by simply setting its scale using the setScale method. I found that simply setting the spaceship back to its normal scale with setScale a little too abrupt; restoreScaleAction makes the transition very smooth.

What we just covered

In this article, we covered:

  • A recap of:
    • Starting a new Game project in Xcode
    • Restricting an app’s orientation to landscape-only
    • Drawing sprites at a specified location on the screen
  • Responding to the event where the user touches the screen with the touchesBegan method
  • Responding to the event where the user stops touching the screen with the touchesEnded method
  • Responding to the event where the user moves his/her finger while touching the screen with the touchesMoved method
  • Combining actions with touch events for interesting visual effects.

In the next article in this series, we’ll look at moving player characters around the screen.

Previous articles in this series

  1. Writing iOS games with Swift and Sprite Kit, part 1: The power of actions
Categories
Uncategorized

The story hidden inside Business Insider’s “More iPad Pros sold in 6 weeks than Surfaces sold in 3 months” story

business insider ipad pro 1

Here’s the story: Business Insider has posted a story with the lengthy title Apple’s gigantic iPad Pro outsold Microsoft’s entire Surface lineup last quarter — and it was only on sale for 6 weeks. They report that with a November 11 release date, Apple had only 6 weeks of the fourth quarter of 2015 in which to sell the iPad Pro, and in that time, they sold over 2 million units. In twice the time, Microsoft managed to sell fewer units of their entire Surface line: 1.6 million of them over the entire fourth quarter.

Here’s the story hidden inside that story: Like most online news outlets, Business Insider tries to squeeze a few more clicks and pageviews out of you by providing links to related stories also on their site. For this story, here are the articles they linked to:

business insider ipad pro 2

…and here are the IDC numbers they cited. Because Business Insider is really in the clicks-for-money business and not the “informing you” business, they made do with a crappy screenshot of IDC’s table of 4Q 2015 tablet sales:

screen shot 2016-02-01 at 1.22.28 pm

But because Global Nerdy is just Yours Truly sharing information because I can’t live any other way, I searched for the IDC news release that Business Insider refused to provide a link to (which I just did), and I took both their tables and turned them into these graphs:

top tablet vendors 1

Click the graph to see the information source.

top tablet vendors 2

Click the graph to see the information source.

Business Insider‘s reporting on the shrinking tablet market is correct. From 2014 to 2015, tablet sales shrank by 10.1%, with Huawei as the only top 5 vendor seeing growth. As for their prediction of the iPad’s Pro’s impending doom: if this is doom, I’d like some of that action, please!

Categories
Uncategorized

T-shirt of the day

internet went skawee reweert

For those of you who miss the SKAWEE REWEERT sound, here it is, with annotations! It works best when viewed in full-screen mode on a large screen:

And for those of you who always thought that the sound of dial-up could be turned into music, here’s 56K by RAC:

Categories
Uncategorized

Your guide to software developer job ads

software developer advertisements

Courtesy of George Takei’s Facebook page — an ever-reliable source nerd humor — here’s a handy guide that should prove useful to people looking at software job site’s descriptions of available positions. As with many things, it’s funny because it’s true.

Categories
Uncategorized

Privacy joke of the day

difference between usa and usb

It’s Hump Day, and what better way to start it than with a privacy joke, courtesy of @alfiedotwtf?

Categories
Uncategorized

Better to be roughly right than precisely wrong: Rounding numbers with Swift

ludicrous trek accuracy

Update (December 19, 2016): The code in this article was updated for Swift 3.0.

The 1960s Star Trek TV series wasn’t written by engineers, scientists, or mathematicians, which is why one of their tricks for showing you that Mr. Spock was an intellectual badass was having make calculations to a ridiculous degree of preciseness, a dramatic device that TV Tropes calls ludicrous precision.

You don’t want your apps to be as annoying as Spock could sometimes be, which is why rounding is an important operation.

Rounding is useful for things like:

  • The limits of your input precision. Suppose you’re calculating the average of the daily high temperatures over the past week, each of which is accurate to the nearest degree. Because of the way an average (or more technically, the mean) is calculated, the result may contain a decimal point. However, the result you report shouldn’t be more precise than the data it’s based on, so you’ll want to round it to the nearest degree.
  • The limits of usefulness. If you’re displaying directions for a short trip, you probably wouldn’t want to report the total distance with more than a 1/4 mile or 1/2 kilometer precision, and you’d probably want to state the trip time rounded to the nearest minute. On the other hand, for a trip covering the width of the United States or Canada, anything more precise than rounding the total distance to the nearest 10 miles and the trip time to the nearest half-hour isn’t generally helpful.
  • Practical considerations. When performing financial calculations, especially when dealing with cash, you’ll want to round your result to the nearest penny. In countries like Canada, where they’ve phased out the penny, you’ll want to round cash calculations to the nearest nickel.

Swift’s built-in rounding functions

Swift comes built-in with most of the rounding functions in C’s math library. The ones you’re most likely to use are round, floor, and ceil:

round(_:) Given a number n, this returns n rounded to the nearest whole number. For example:

  • round(2.0) returns 2.0
  • round(2.2) returns 2.0
  • round(2.5) returns 3.0
  • round(2.9) returns 3.0

With negative numbers, a fractional value of 0.5 or higher rounds the number down, and lower fractional values round the number up:

  • round(-2.0) returns –2.0
  • round(-2.2) returns –2.0
  • round(-2.5) returns –3.0
  • round(-2.9) returns –3.0
floor(_:) Given a number n, this returns n rounded down to the nearest whole number. For example:

  • floor(2.0) returns 2.0
  • floor(2.2) returns 2.0
  • floor(2.5) returns 2.0
  • floor(2.9) returns 2.0
  • floor(-2.0) returns -2.0
  • floor(-2.2) returns -3.0
  • floor(-2.5) returns -3.0
  • floor(-2.9) returns -3.0
ceil(_:) Given a number n, this returns n rounded up to the nearest whole number (you’ve probably guessed that ceil is short for ceiling). For example:

  • ceil(2.0) returns 2.0
  • ceil(2.2) returns 3.0
  • ceil(2.5) returns 3.0
  • ceil(2.9) returns 3.0
  • ceil(-2.0) returns -2.0
  • ceil(-2.2) returns -2.0
  • ceil(-2.5) returns -2.0
  • ceil(-2.9) returns -2.0

round, floor, and ceil each come in two versions:

  • A version that accepts a Double argument and returns a Double result (Doubles are 64-bit numbers and have a precision of at least 15 decimal digits), and
  • a version that accepts a Float argument and returns a Float result (Floats are 32-bit numbers and have a precision of as little as 6 decimal digits).

Rounding n to the nearest multiple of x

rounding coaster

round, floor, and ceil work well when you’re trying to round to nearest whole number, but they’re not as useful if you’re facing one of these rounding scenarios:

  • Rounding a number to the nearest 10 (as demonstrated in the “Rounding Coaster” shown above), 100, 1000, etc.
  • Rounding a number to the nearest .1, .01, .001, etc.
  • Rounding a dollar value to the nearest penny
  • In Canada, which has eliminated the penny (because it costs more than a penny to manufacture one), you calculate change by rounding to the nearest nickel
  • Rounding a number to the nearest multiple of x

For situations like the ones listed above, you’ll find these Swift functions handy:

// Given a value to round and a factor to round to,
// round the value to the nearest multiple of that factor.
func round(_ value: Double, toNearest: Double) -> Double {
  return round(value / toNearest) * toNearest
}

// Given a value to round and a factor to round to,
// round the value DOWN to the largest previous multiple
// of that factor.
func roundDown(_ value: Double, toNearest: Double) -> Double {
  return floor(value / toNearest) * toNearest
}

// Given a value to round and a factor to round to,
// round the value DOWN to the largest previous multiple
// of that factor.
func roundUp(_ value: Double, toNearest: Double) -> Double {
  return ceil(value / toNearest) * toNearest
}

Here’s the round(_:toNearest:) function in action:

round(52.376, toNearest: 0.01) // 52.38
round(52.376, toNearest: 0.1)  // 52.4
round(52.376, toNearest: 0.25) // 52.5
round(52.376, toNearest: 0.5)  // 52.5
round(52.376, toNearest: 1)    // 52
round(52.376, toNearest: 10)   // 50
round(52.376, toNearest: 100)  // 100
round(52.376, toNearest: 1000) // 0

Here’s the roundDown(_:toNearest:) function in action:

roundDown(52.376, toNearest: 0.01) // 52.37
roundDown(52.376, toNearest: 0.1)  // 52.3
roundDown(52.376, toNearest: 0.25) // 52.25
roundDown(52.376, toNearest: 0.5)  // 52
roundDown(52.376, toNearest: 1)    // 52
roundDown(52.376, toNearest: 10)   // 50
roundDown(52.376, toNearest: 100)  // 0
roundDown(52.376, toNearest: 1000) // 0

Here’s the roundUp(_:toNearest:) function in action:

roundUp(52.376, toNearest: 0.01) // 52.38
roundUp(52.376, toNearest: 0.1)  // 52.4
roundUp(52.376, toNearest: 0.25) // 52.5
roundUp(52.376, toNearest: 0.5)  // 52.5
roundUp(52.376, toNearest: 1)    // 53
roundUp(52.376, toNearest: 5)    // 55
roundUp(52.376, toNearest: 10)   // 60
roundUp(52.376, toNearest: 100)  // 100
roundUp(52.376, toNearest: 1000) // 1000

Rounding to a specified number of decimal places

price break

Photo from Consumerist. Click to see the source.

If you want to round a value to a specific number of decimal places, try this function:

// Round the given value to a specified number
// of decimal places
func round(_ value: Double, toDecimalPlaces places: Int) -> Double {
  let divisor = pow(10.0, Double(places))
  return round(value * divisor) / divisor
}

Here’s roundToPlaces(_:decimalPlaces:) in action:

round(52.3761, toDecimalPlaces: 3) // 52.376
round(52.3761, toDecimalPlaces: 2) // 52.38
round(52.3761, toDecimalPlaces: 1) // 52.4
round(52.3761, toDecimalPlaces: 0) // 52.0

// If we put a negative number n into decimalPlaces,
// roundToPlaces rounds to the nearest multiple of 
// 10^abs(n):
round(52.3761, toDecimalPlaces: -1) // 50.0 (rounding to nearest multiple of 10)
round(52.3761, toDecimalPlaces: -2) // 100.0 (rounding to nearest multiple of 100)
round(52.3761, toDecimalPlaces: -3) // 0 (rounding to nearest multiple of 1000))

Removing the fractional part of a number

seamus levine from family guy

“Seamus” from Family Guy is rather truncated.

Sometimes, you just want to lop off anything after the decimal point. That’s what trunc (short for truncate) is for:

trunc(52.376)  // 52.0
trunc(52.576)  // 52.0
trunc(-52.376) // -52.0
trunc(-52.576) // -52.0

Displaying rounded values

There are times when you want to store a precise value but display a rounded one. Use the String class’ init(format:arguments:) method and C’s format strings for printf to display numbers as strings representing rounded values. Here it is in action:

// Remember, these are *string* values!
String(format: "%.3f", 52.3761) // "52.376"
String(format: "%.2f", 52.3761) // "52.38"
String(format: "%.1f", 52.3761) // "52.4"
String(format: "%.0f", 52.3761) // "52"
String(format: "%.0f", 52.5761) // "53"

Happy rounding!

Thanks to John Maynard Keynes for the title of this article!