From 2d iOS, we learn how to make entities using components and display them on the scene. This includes in some cases making some entities children of others. I gave this a go and after a while found it not too hard to do. Taking it up a notch I wonder how to join entities and where the best place is to do that in the code.
My Example: You create two entities that have sprite components. I’m imagining maybe a car as the parent node and a wheel as the child entity. Once you get this working you could conceivably reuse the code to do another wheel or several if you want a big truck!
Once you make a VehicleEntity and a TireEntity as its child, (I learned this right out of the book) you give them physicsbodies, set their rotation and gravity properties. Then you are left with the decision of where to create the jointPin. I chose to make it part of the Component that makes the TireEntity a child of the VehicleEntity. Now it just has to be added to the scene somehow and that is where I got stuck.
My Work!
- Creating the VehicleEntity
- Creating the TireEntity
- Creating an AxleComponent to bring them together.
1.
Creating my VehicleEntity just like in the book:
import GameplayKit
import SpriteKit
enum VehicleType: String {
case SportsCar = “SportsCar”
//room for more cars later
//some variables to help locate the position the wheels need to be placed
var frontAxleVector: CGFloat {
switch self {
case SportsCar: return 50.0
}
}
var rearAxleVector: CGFloat {
switch self {
case SportsCar: return 50.0
}
}
}
class VehicleEntity: GKEntity {
let veclType: VehicleType
var spriteComponent: SpriteComponent!
init(veclType: VehicleType) {
self.veclType = veclType
super.init()
let size: CGSize
switch veclType {
case .SportsCar:
size = CGSizeMake(200, 75)
//add more vehicles for fun here later
}
let textureAtlas = SKTextureAtlas(named: veclType.rawValue)
let defaultTexture = textureAtlas.textureNamed(“Driving__01.png”)
spriteComponent = SpriteComponent(entity: self, texture: defaultTexture, size: size)
addComponent(spriteComponent)
let vehiclePhysicsBody = SKPhysicsBody(rectangleOfSize: size)
vehiclePhysicsBody.dynamic = true
vehiclePhysicsBody.allowsRotation = true
//add categorybitmask here see page 592
spriteComponent.node.physicsBody = vehiclePhysicsBody
axleComponent = AxleComponent(veclType: veclType, parentNode: spriteComponent.node)
addComponent(axleComponent)
}
2.
Now for the TireEnitity: Again just like in the book with the addition of physicsbodies
import SpriteKit
import GameplayKit
class TireEntity: GKEntity {
var spriteComponent: SpriteComponent!
init(veclType: VehicleType) {
super.init()
//let testSize = CGSize(width: 100, height: 100)
let texture = SKTexture(imageNamed: "\(veclType.rawValue)Wheel")
spriteComponent = SpriteComponent(entity: self, texture: texture, size: texture.size())
addComponent(spriteComponent)
let physicsBody = SKPhysicsBody(circleOfRadius: texture.size().width/2)
physicsBody.dynamic = true
physicsBody.allowsRotation = true
physicsBody.affectedByGravity = true
spriteComponent.node.physicsBody = physicsBody
}
}
3.
And now an AxleComponent to help bring the VehicleEntity and the TireEntity together and create the pinJoint:
import SpriteKit
import GameplayKit
class AxleComponent: GKComponent {
let veclType: VehicleType
let parentNode: SKNode
let rearAxle: SKPhysicsJointPin
init(veclType: VehicleType, parentNode: SKNode) {
self.veclType = veclType
self.parentNode = parentNode
let wheel = TireEntity(veclType: veclType)
let wheelNode = wheel.spriteComponent.node
wheelNode.position = CGPointMake(-50.0, 0.0)
/*at some point I will ave to go back and do the vector math and use the variables I saved in the vehicle entity to calculate the wheelNode.position correctly… pythagorean fun here I come! */
wheelNode.zPosition = 1
parentNode.addChild(wheelNode)
let wheelPhysicsBody = wheelNode.physicsBody
let vehicle = VehicleEntity(veclType: veclType)
let vehicleNode = vehicle.spriteComponent.node
let vehiclePhysicsBody = vehicleNode.physicsBody
let anchorPoint = CGPointZero
let rearAxle = SKPhysicsJointPin.jointWithBodyA(vehiclePhysicsBody!, bodyB: wheelPhysicsBody!, anchor: anchorPoint)
//rinse and repeat for the frontAxle
}
}
So that’s it, I just don’t know where and how to call the addJoint(rearAxle). Normally you just call scene.physicsWorld.addJoint(rearAxle) but its not that straight forward here, or I’ve gotten so wrapped up in the details that I’ve forgotten something obvious. What do you think?