I'm using Xcode 7 with swift and when I type
class Block {
var Block = SKShapeNode(circleOfRadius: 15)
Block.fillColor = SKColor.redColor() //Error Here
Block.physicsBody = SKPhysicsBody(circleOfRadius: 15)
Block.physicsBody?.affectedByGravity = true
Block.physicsBody?.restitution = 0
Block.physicsbody?.LinearDamping = 0
self.addChild(Block)
It gives me an error that says "expected declaration" (on the line with the comment) and I don't know why
There are some errors:
You have a class and are trying to change class properties outside the scope of a method or an initializer.
The line Block.physicsbody?.LinearDamping = 0 should be Block.physicsBody?.linearDamping = 0; case-sensitivity.
You name your SKShapeNode instance as Block, the same name as your class. By naming convention, class (type) names begin with Capital letters, whereas class properties use small letters in their names.
With these three fixed, we can proceed to looking at your scene.
With help from Leo Dabus (thanks!), we should have enough to set you up with a minimal working example (using your code) of the SKScene:
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
let block = SKShapeNode(circleOfRadius: 15)
// you will also need to set your node initial position
// if you would like your red circle to fall from the middle of the top of your scene you need to use the scene frame midX and maxY (not the view frame). the scene it is not necessarily the same size of your view)
block.position = CGPoint(x: scene!.frame.midX, y: scene!.frame.maxY)
block.fillColor = SKColor.redColor()
block.physicsBody = SKPhysicsBody(circleOfRadius: 15)
block.physicsBody?.affectedByGravity = true
block.physicsBody?.restitution = 0
block.physicsBody?.linearDamping = 0
self.addChild(block)
}
// ...
}
Related
I am making a game in which objects spawn on the map in a certain location and I have multiple functions for different objects and needed a reference so I put my code outside of the function to widen its scope but now I get an error that says
Instance type 'frame' cannot be used on type 'Levelunit'
If i put it back into the function it is completely fine but it seems to have a problem when I put it outside the function. Here is my code:
let yAxisSpawnLocations: [CGFloat] = [0]
let xAxisSpawnLocations: [CGFloat] = {
var spawnLocations:[CGFloat] = [] //Create 5 possible spawn locations
let numberOfNodes = 5
for i in 0...numberOfNodes - 1 {
var xPosition = (frame.maxX) / CGFloat((numberOfNodes - 1)) * CGFloat(i)
xPosition += thePlayer.size.width/2
xPosition -= frame.maxX/1.6
spawnLocations.append( xPosition )
}
return spawnLocations
}()
I looked it up and didn't quite understand the answer given. Could someone tell me what i'm doing wrong please.
BTW, LevelUnit is the name of my class.
You are trying to use self before Levelunit has be fully initialized. For example, this is one place where you use self implicitly:
var xPosition = (frame.maxX) / CGFloat((numberOfNodes - 1)) * CGFloat(i)
it is the same as:
var xPosition = (self.frame.maxX) / CGFloat((numberOfNodes - 1)) * CGFloat(i)
So, what you can do is to initialize this property at Levelunit initializer (which I would skip if you don't want to have a dance with automatic initializer inheritance rules), or to initialize it in didMoveToView, which will work fine. If I am not wrong, Levelunit is probably subclass of a SKScene, right? If so, just do this:
//Define a property of Levelunit like this
var xAxisSpawnLocations:[CGFloat] = []
Then just initialize it inside of didMoveToView:
let numberOfNodes = 5
for i in 0...numberOfNodes - 1 {
var xPosition = (self.frame.maxX) / CGFloat((numberOfNodes - 1)) * CGFloat(i)
xPosition += thePlayer.size.width/2
xPosition -= frame.maxX/1.6
xAxisSpawnLocations.append( xPosition )
}
I am trying to understand how Metal compute shaders work, so I have wrote this code :
class AppDelegate: NSObject, NSApplicationDelegate {
var number:Float!
var buffer:MTLBuffer!
func applicationDidFinishLaunching(aNotification: NSNotification) {
// Insert code here to initialize your application
let metalDevice = MTLCreateSystemDefaultDevice()!
let library = metalDevice.newDefaultLibrary()!
let commandQueue = metalDevice.newCommandQueue()
let commandBuffer = commandQueue.commandBuffer()
let commandEncoder = commandBuffer.computeCommandEncoder()
let pointlessFunction = library.newFunctionWithName("pointless")!
let pipelineState = try! metalDevice.newComputePipelineStateWithFunction(pointlessFunction)
commandEncoder.setComputePipelineState(pipelineState)
number = 12
buffer = metalDevice.newBufferWithBytes(&number, length: sizeof(Float), options: MTLResourceOptions.StorageModeShared)
commandEncoder.setBuffer(buffer, offset: 0, atIndex: 0)
commandEncoder.endEncoding()
commandBuffer.commit()
commandBuffer.waitUntilCompleted()
let data = NSData(bytesNoCopy: buffer.contents(), length: sizeof(Float), freeWhenDone: false)
var newResult:Float = 0
data.getBytes(&newResult, length: sizeof(Float))
print(newResult)
}
By making a buffer with StorageModeShared, I want changes made to the Metal buffer reflected in my Swift code, but when I populate my newResult variable, it looks like the buffer is still the same value than at the beginning (12) while it should be 125 :
#include <metal_stdlib>
using namespace metal;
kernel void pointless (device float* outData [[ buffer(0) ]]) {
*outData = 125.0;
}
What am I doing wrong ?
A kernel function doesn't run unless you dispatch it. I think you're assuming if you have a function, then Metal should run it one time, until you say otherwise, but that won't happen. It will instead not run at all. Add this before endEncoding and you're good to go!
let size = MTLSize(width: 1, height: 1, depth: 1)
commandEncoder.dispatchThreadgroups(size, threadsPerThreadgroup: size)
I'm working in Swift and have created an SKSpriteNode to be the ground in my game. I've set it to the proper position and made the physics body as wide as the screen:
//Ground
var groundTexture = SKTexture(imageNamed: "groundBar")
var groundBar = SKSpriteNode(texture: groundTexture)
groundBar.setScale(2)
groundBar.position = CGPointMake(self.size.width/2, self.size.height/2)
groundBar.hidden = true
self.addChild(groundBar)
var ground = SKNode()
ground.position = CGPointMake(0, groundTexture.size().height)
ground.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(self.frame.size.width, groundTexture.size().height*2))
ground.physicsBody?.dynamic = false
self.addChild(ground)
Then I have another SKSpriteNode that is the character in my game, and when tapped I have this character jump up and to the right:
//Savior character
var saviorTexture = SKTexture(imageNamed: "character")
saviorTexture.filteringMode = SKTextureFilteringMode.Nearest
savior = SKSpriteNode(texture: saviorTexture)
savior.setScale(1)
savior.position = CGPoint(x: self.frame.size.width * 0.5, y: self.frame.size.height * 0.4)
savior.physicsBody = SKPhysicsBody(circleOfRadius: savior.size.height/2)
savior.physicsBody?.dynamic = true
savior.physicsBody?.allowsRotation = false
self.addChild(savior)
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
savior.physicsBody?.velocity = CGVectorMake(0, 0) //pt it returns to?
savior.physicsBody?.applyImpulse(CGVectorMake(5, 30)) //direction/height that it jumps }
Before it is tapped, the character sits on the ground node and therefore doesn't fall off the screen. When tapped, however, the character jumps up and falls off the screen. It's as if it doesn't come in contact with the ground.
I've tried resizing the ground, repositioning the ground, but the character still falls off the screen. Mind you that when the vector is (0,30) and it just jumps straight up, it doesn't fall off the screen.
What is happening here?
In your view controller you can do skView.showsPhysics = true and see if the physics bodies are where you think they are. Also, be sure that their physicsBody.collisionBitMask are not the same.
Is there anything like the UILabel's adjustsFontSizeToFitWidth that can be used with a NSTextField?
In short: no. You have to do some brute force work to determine a string's -sizeWithAttributes: -boundingRectWithSize:options:attributes: with a given font size (set as an NSFont for NSFontAttributeName).
I'd start with a standard system font size and work down or up from there, depending on whether it's smaller or larger than the desired rectangle.
Swift 4 solution:
It will resize one by one until it fits, or until minimumFontSize = 3.
let minimumFontSize = 3
var sizeNotOkay = true
var attempt = 0
while sizeNotOkay || attempt < 15 { // will try 15 times maximun
let expansionRect = textField.expansionFrame(withFrame: textField.frame)
let truncated = !NSEqualRects(NSRect.zero, expansionRect)
if truncated {
if let actualFontSize : CGFloat = textField.font?.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.size) as? CGFloat {
textField.font = NSFont.systemFont(ofSize: actualFontSize - 1)
if actualFontSize < minimumFontSize {
break
}
}
} else {
sizeNotOkay = false
}
attempt += 1
}
I came up with my own solution (its not a good solution!, just in case anyone couldn't find a better solution)
extension NSTextField {
func fontSizeToFit() {
if stringValue.count > 90 {
font = NSFont.systemFont(ofSize: 40)
} else {
font = NSFont.systemFont(ofSize: CGFloat(120 - stringValue.count))
}
}
}
i create a race game using spritkit
well i create button if the user click on it then it will pause the game , well my problem is that the Scene stop from moving but the car will stop slowly like the real car , i want to make stop without gravity
this is my code
physicsWorld.gravity = CGVectorMake(0.0,0.3);
physicsWorld.contactDelegate = self
this is player code
playerNode = SKSpriteNode(imageNamed: "car")
playerNode!.position = CGPoint(x: size.width / 2.0, y: 120.0)
playerNode!.physicsBody =
SKPhysicsBody(circleOfRadius: playerNode!.size.width / 2)
playerNode!.physicsBody!.dynamic = true
playerNode!.physicsBody!.linearDamping = 1.0
playerNode!.physicsBody!.allowsRotation = true
playerNode!.physicsBody!.categoryBitMask = CollisionCategoryPlayer
playerNode!.physicsBody!.contactTestBitMask =
CollisionCategoryPowerUpOrbs
playerNode!.physicsBody!.collisionBitMask = 0
foregroundNode!.addChild(playerNode!)
and finally this is the pause function
if (pasueornot){ // true or false
physicsWorld.gravity = CGVectorMake(0.0,gravitySpeed)
}
else{
physicsWorld.gravity = CGVectorMake(0.0,0.0) // the Scene stop from moving but the car will stop slowly like the real car pasueornot
}