Im programmatically using SKTileMapNode. The code is C# (Xamarin.iOS) but should be readable by every Swift/ObjC developer.The problem is that the sorting of tiles in isometric projection seems to be incorrect and I cannot see why. To test, the map has 1 row and 5 columns. See the screenshot:https://dl.dropboxusercontent.com/u/111612273/SVhjD.pngThe tiles at 0|0 and 2|0 are in front of the others. The pyramid styled tile at 4|0 however, is drawn correctly in front of the one at 3|0.I'm using two simple tiles: The first one has a resolution of 133x83px and the second one is 132x131px:https://dl.dropboxusercontent.com/u/111612273/bcIvP.pngandhttps://dl.dropboxusercontent.com/u/111612273/wzCZV.pngThis is what it looks like in Tiled and what I am trying to reproduce: https://dl.dropboxusercontent.com/u/111612273/66G6p.pngThe tile map is setup and added to the scene using the following code:var tileDef1 = new SKTileDefinition (SKTexture.FromImageNamed ("landscapeTiles_014"));
var tileDef2 = new SKTileDefinition (SKTexture.FromImageNamed ("landscapeTiles_036"));
var tileGroup1 = new SKTileGroup (tileDef1);
var tileGroup2 = new SKTileGroup (tileDef2);
var tileSet = new SKTileSet (new [] { tileGroup1, tileGroup2 }, SKTileSetType.Isometric);
var tileMap = SKTileMapNode.Create(tileSet, 5, 2, new CGSize (128, 64));
tileMap.Position = new CGPoint (0, 0);
tileMap.SetTileGroup (tileGroup1, 0, 0);
tileMap.SetTileGroup (tileGroup2, 1, 0);
tileMap.SetTileGroup (tileGroup1, 2, 0);
tileMap.SetTileGroup (tileGroup2, 3, 0);
tileMap.SetTileGroup (tileGroup2, 4, 0);
tileMap.AnchorPoint = new CGPoint (0, 0);
Add (tileMap);The tile size used to initialise the tile map (128|64) looks strange to me. It really hasn't anything to do with the texture size of the tiles and unlike everywhere else in SpriteKit it doesn't seem to be using "points". However, this is the size where Tiled is giving me nicely aligned tiles and also SpriteKit is looking good, besides the sorting issue.What am I doing wrong or where am I thinking wrong?
SpriteKit
RSS for tagDrawing shapes, particles, text, images, and video in two dimensions using SpriteKit.
Post
Replies
Boosts
Views
Activity
I built a simple Swift game in SpriteKit. I have audio on the simulator but no audio or sound effects on the device. Any suggestions?
GCVirtualController isn't displaying when used with SKScene class. The Virtual controllers appear but then it seems that they are obscured by the SKScene itself!? The documentation says that calling connect() will display the virtual controllers but I seem to be missing how to add the controllers to the SKScene?
class GameScene: SKScene {
private var _virtualController: Any?
@available(iOS 15.0, *)
public var virtualController: GCVirtualController? {
get { return self._virtualController as? GCVirtualController }
set { self._virtualController = newValue }
}
override func didMove(to view: SKView) {
let background = SKSpriteNode(imageNamed: ".jpg")
background.zPosition = -1
addChild(background)
let virtualConfig = GCVirtualController.Configuration()
virtualConfig.elements = [GCInputLeftThumbstick, GCInputRightThumbstick, GCInputButtonA, GCInputButtonB]
virtualController = GCVirtualController(configuration: virtualConfig)
virtualController?.connect()
}
}
I've also tried adding the virtual controllers in the UIViewController but this doesn't work either.
I've an app I've been working on for quite some time now. It uses SpriteKit. The windows with the scenes in them are generated programmatically. All of a sudden, when it's up and running through XCode, the console throws out a continuous stream of errors - probably in the order of 1 per second. The main one that makes up this stream is:
2022-03-07 20:07:38.765930+0000 My*App[8461:465673] [] CurrentVBLDelta returned 0 for display 1 -- ignoring unreasonable value
But others that appear slightly less frequently are:
2022-03-07 20:07:38.447800+0000 My*App[8461:465143] Metal GPU Frame Capture Enabled 2022-03-07 20:07:38.448070+0000 My*App[8461:465143] Metal API Validation Enabled 2022-03-07 20:07:38.613097+0000 My*App[8461:465640] [] [0x7f9596053820] CVCGDisplayLink::setCurrentDisplay: 1 2022-03-07 20:07:38.613415+0000 My*App[8461:465640] [] [0x7f9596053820] Bad CurrentVBLDelta for display 1 is zero. defaulting to 60Hz. 2022-03-07 20:07:38.613442+0000 My*App[8461:465640] [] [0x7f9596053800] CVDisplayLinkCreateWithCGDisplays count: 1 [displayID[0]: 0x1] [CVCGDisplayLink: 0x7f9596053820] 2022-03-07 20:07:38.613467+0000 My*App[8461:465640] [] [0x7f9596053800] CVDisplayLinkStart 2022-03-07 20:07:38.613487+0000 My*App[8461:465640] [] [0x7f9596053820] CVDisplayLink::start 2022-03-07 20:07:38.613541+0000 My*App[8461:465640] [] [0x7f9596053800] CVDisplayLinkStart 2022-03-07 20:07:38.613575+0000 My*App[8461:465640] [] [0x7f9596053820] CVDisplayLink::start 2022-03-07 20:07:38.613634+0000 My*App[8461:465671] [] [0x600000c09f10] CVXTime::reset 2022-03-07 20:07:38.613718+0000 My*App[8461:465671] [] CurrentVBLDelta returned 0 for display 1 -- ignoring unreasonable value 2022-03-07 20:07:38.639810+0000 My*App[8461:465671] [] CurrentVBLDelta returned 0 for display 1 -- ignoring unreasonable value 2022-03-07 20:07:38.639887+0000 My*App[8461:465671] [] [0x7f9596053820] CVCGDisplayLink::getDisplayTimes display: 1 -- SLSDisplayGetCurrentVBLDelta returned 0 => generating fake times 2022-03-07 20:07:38.673702+0000 My*App[8461:465653] [] [0x7f9596053820] CVCGDisplayLink::setCurrentDisplay: 1 2022-03-07 20:07:38.673748+0000 My*App[8461:465653] [] [0x7f9596053820] CVDisplayLink::stop 2022-03-07 20:07:38.673862+0000 My*App[8461:465653] [] [0x7f9596053820] Bad CurrentVBLDelta for display 1 is zero. defaulting to 60Hz. 2022-03-07 20:07:38.673883+0000 My*App[8461:465653] [] [0x7f9596053820] CVDisplayLink::start
I really don't know how else to describe this. I can only imagine having to hand over the entire project as lately I've only been working on the storyboard file so how would this affect it? To be honest the only change I can see is my upgrade to OSX 12.2.1. It's definitely something to do with SpriteKit since not initialising a window with a scene in it stops the errors from showing.
Hello there 👋
I've noticed a different behavior between iOS 15 and iOS 16 using CIFilter and SpriteKit.
Here is a sample code where I want to display a text and apply a blurry effect on the same text in the back of it.
Here is the expected behavior (iOS 15):
And the broken behavior on iOS 16:
It looks like the text is rotated around the x-axis and way too deep.
Here is the sample code:
import UIKit
import SpriteKit
class ViewController: UIViewController {
var skView: SKView?
var scene: SKScene?
override func viewDidLoad() {
super.viewDidLoad()
skView = SKView(frame: view.frame)
scene = SKScene(size: skView?.bounds.size ?? .zero)
scene?.backgroundColor = UIColor.red
view.addSubview(skView!)
skView!.presentScene(scene)
let neonNode = SKNode()
let glowNode = SKEffectNode()
glowNode.shouldEnableEffects = true
glowNode.shouldRasterize = true
let blurFilter = CIFilter(name: "CIGaussianBlur")
blurFilter?.setValue(20, forKey: kCIInputRadiusKey)
glowNode.filter = blurFilter
glowNode.blendMode = .alpha
let labelNode = SKLabelNode(text: "MOJO")
labelNode.fontName = "HelveticaNeue-Medium"
labelNode.fontSize = 60
let labelNodeCopy = labelNode.copy() as! SKLabelNode
glowNode.addChild(labelNode)
neonNode.addChild(glowNode)
neonNode.addChild(labelNodeCopy)
neonNode.position = CGPoint(x: 200, y: 200)
scene?.addChild(neonNode)
}
}
I have multiple images that at various times I need to replace a target image for a SKSpriteNode.
Each of these multiple images has a different size.
The target SKSpriteNode has a fixed frame that I want to stay fixed.
This target is created via:
myTarget = SKSpriteNode(imageNamed: “target”)
myTarget.size = CGSize(…)
myTarget.physicsBody = SKPhysicsBody(rectangleOf: myTarget.size)
How do I resize each of the multiple images so that each fills up the target frame (expand or contract)?
Pretend the target is a shoebox and each image is a balloon that expands or contracts to fill the shoebox.
I have tried the following that fails, that is, it changes the size of the target to fit the new image .. in short, it does the exact opposite of what I want.
let newTexture = SKTexture(imageNamed: newImage)
let changeImgAction = SKAction.setTexture(newTexture, resize: true)
myTarget.run(changeImgAction)
Again, keep frame of myTarget fixed and change size of newTexture to fit the above frame ..
Mac Studio won't show scene in canvas assist
Hi,
I'm creating a SF Symbols image like this:
var img = UIImage(systemName: "x.circle" ,withConfiguration: symbolConfig)!.withTintColor(.red)
In the debugger the image is really red.
and I'm using this image to create a SKTexture:
let shuffleTexture = SKTexture(image: img)
The texture image is ALWAYS black and I have no idea how to change it's color. Nothing I've tried so far works.
Any ideas how to solve this?
Thank you!
Best Regards,
Frank
I'm trying to animate a shape (e.g. a circle) to follow a custom path, and struggling to find the best way of doing this.
I've had a look at the animation options from SwiftUI, UIKit and SpriteKit and all seem very limited in what paths you can provide. Given the complexity of my path, I was hoping there'd be a way of providing a set of coordinates in some input file and have the shape follow that, but maybe that's too ambitious.
I was wondering if this were even possible, and assuming not, if there were other options I could consider.
I have a sprite kit scene with an edge loop physics body set programmatically with the category bit mask set to a custom Physics Category called Edge. Through the scene editor, I've added several sprite nodes with varying physics body types and various category masks and collision masks.
The collision mask for a particular sprite node includes the Edge category. Initially, I have this node partially off the screen on the scene editor but when I run the program, it appears completely inside the edge loop.
Is it possible to have a sprite node be positioned partially inside the edge loop and partially outside the edge loop?
[SKCropNode setMaskNode:] crash, any idea? Help!
Crashed: com.apple.main-thread
EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x000000012e8067b0
0 SpriteKit 0x62d2c SKCCropNode::setMaskNode(SKCNode*) + 8
1 SpriteKit 0xa0854 -[SKCropNode setMaskNode:] + 88
Hi all
So I'm quite new into GameDev and am struggling a bit with the Tilemap
All my elements have the size of 64x64. As you can see in my screenshot there is some gap between the street and the water. It might be simple but what's the best way to fix that gap? I could increase the width of the left and right edge png but then I will sooner or later run into other problems as it then is not fitting with the rest.
Thanks for your help
Cheers from Switzerland
All our custom Playground Books using SpriteKit stopped working after upgrading to SwiftPlaygrounds version 4.4
To reproduce the issue, simply create a new book by clicking the top right hand icon and in the book add two lines of code.
import SpriteKit
let circle = SKShapeNode(circleOfRadius: 100.0)
The second line produces an error. I tried with other classes. SKAction seems to work. SKSpriteNode, SKTexture etc have the same issue. Please help. Our students are stuck!
I have a ProRes 4444 format video with an alpha channel.
The circle in the middle of the video is completely opaque, while the rest is fully transparent. Everything looks normal in iMovie, as I can see the background through the surrounding parts.
However, when I play it using AVPlayer, the parts that are supposed to be fully transparent appear somewhat opaque, as shown in the image below:
I used the official project provided by Apple named 'using_hevc_video_with_alpha', but I only replaced the HEVC with alpha format file with a ProRes 4444 format video file. Below is the main code.
import Cocoa
import SpriteKit
import AVFoundation
class ViewController: NSViewController {
@IBOutlet var skView: SKView!
var videoPlayer: AVPlayer!
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.skView {
// Load the SKScene from 'backgroundScene.sks'
guard let scene = SKScene(fileNamed: "backgroundScene") else {
print ("Could not create a background scene")
return
}
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
// Present the scene
view.presentScene(scene)
// Add the video node
guard let alphaMovieURL = Bundle.main.url(forResource: "xuewang", withExtension: "mov") else {
print("Failed to overlay alpha movie on the background")
return
}
videoPlayer = AVPlayer(url: alphaMovieURL)
let video = SKVideoNode(avPlayer: videoPlayer)
video.size = CGSize(width: view.frame.width, height: view.frame.height)
print( "Video size is %f x %f", video.size.width, video.size.height)
scene.addChild(video)
// Play video
videoPlayer.play()
}
}
}
I need to associate sound with the movement of a sprite. Movement can be as a result of physics, not as a result of an SKAction. When the object is sliding thee should be sliding sound throughout the time when it is sliding, and then a different sound when it bumps into a rock and goes up in the air. When the object is airborne, there is no sound, till it falls again - a falling sound, and then slides down with a sliding sound. The sounds associated with the collision ( rock, ground and so on ) are straightforward and work fine. But am having difficulty associating the sound with movement.
The closest result I have is to check the velocity of the sprite's physics body every update cycle and play or stop the sound based on whether the velocity is greater than zero. I tried SKAction.playSoundFileNamed first - the sound kept going even when the object was not moving. I tried adding an SKAudioNode with Play and Stop, with no better result. I finally tried using AVAudioPlayer to play and Pause , which yielded the best results, but the sliding sound still played past the sliding action.
What is the best way to do this?
My code for playing the sound is as follows:
var blockSliding = false
for block in gameBlocks {
if (block.physicsBody?.velocity.dx ?? 0) + (ball.physicsBody?.velocity.dy ?? 0) > 0.05 {
blockSliding = true
break
}
}
if slideSound.isPlaying {
if !blockSliding {
slideSound.pause()
}
} else {
if blockSliding {
slideSound.play()
}
}
I have setup slideSound earlier loading the appropriate sound file into an AVAudioPlayer
Background:
This is a question asking for a good example of SpriteKit from a very new iOS developer who is investigating for starting an iOS 2D game project.
As I explored in the official apple development doc, to dev a 2D game SpriteKit is the very framework I am looking for.
There have been some clear and succinct words for any API and class documented in the reference spec when I started a project in Xcode. However I haven't been able to finish the project as having no any general idea about what is always needed of a typical game using the framework.
Question:
As an experienced Java Spring programmer I believe that I am needed a brief example to get started with the SpriteKit framework which provides me an idea of necessary steps for a 2D game.
Hello everyone
I am porting my existing 2d game writing by spritekit to visionOS
and I am creating a SpriteView in WindowGroup
let currentScene = BattleScene.newGameScene(gameMode: "endless", dataContext: dataController.container.viewContext)
SpriteView(scene: currentScene)
.ignoresSafeArea(.all)
.frame(width: currentScene.frame.width, height: currentScene.frame.height, alignment: .center)
.onReceive(NotificationCenter.default.publisher(for: GameoverNotification)) { _ in
stopAllAudio()
}
.onTapGesture { location in
let viewPosition = location
let touchLocation = CGPoint(x: viewPosition.x, y: viewPosition.y)
print("touch on vision window: ", touchLocation.x, touchLocation.y)
}
.glassBackgroundEffect()
//WindowGameView()
// .environment(\.managedObjectContext, dataController.container.viewContext)
// .environment(model)
// .environment(pressedKeys)
}
.windowStyle(.automatic)
.defaultSize(width: 0.5, height: 1.0, depth: 0.0, in: .meters)
run it and it turns out the scene can't receive tap event.
but it works normal if I run it with my ios target (vision Os designd for ipad)
is there anything I missed?
I have implemented auto renewable subscriptions in my app, as well as promo codes. Purchase of subscriptions both monthly and annual; work correctly. What I don't know is what to "listen for" instead of product, when the user uses a promo code to purchase the product. am I looking for a different product code? or product identifier when the offer code is used to subscribe?
I am using the following code to create a texture atlas at runtime using a single .png image sprite sheet:
func createSpriteTextureAtlas(atlasNumber atlas:Int, forWorld world:Int) {
//load the png file
let image = UIImage(named: "world\(world)_spritesheet\(atlas)_2048x2048.png")
//create the dictonary
var imageDictionary = [String: UIImage]()
//iterate through all rows and columns and get the subimage
var imageIndex = 0
for row in 0...7 {
for column in 0...7 {
let sourceRect = CGRect(x:column * 256, y:row * 256, width:256, height:256)
let sourceImage = image?.cgImage!.cropping(to: sourceRect)
let subImage = UIImage(cgImage: sourceImage!)
//add the sub image and name to the dictionary
imageDictionary["\(imageIndex)"] = subImage
imageIndex = imageIndex + 1
}
}
//create the texture atlas using the dictionary
spriteTextureAtlas[atlas] = SKTextureAtlas(dictionary: imageDictionary)
}
I have a different sprite sheet for every world. I made all the sprite sheets myself using the same tool. This code works 100% of the time for most images.
For some images however, the program crashes at: SKTextureAtlas(dictionary: imageDictionary) with the error: Thread 4: EXC_BAD_ACCESS (code=1, address=0x105ff2000). The stack trace says it is crashing inside: #0 0x00000002178e2d34 in -[SKTextureAtlasPacker isFullyOpaque:] ().
The crash does not happen every time and only happens for some images. The crash never happens on the simulator.
Did I make a mistake inside createSpriteTextureAtlas or is this a SpriteKit bug?
P.S. I already know that I can let Xcode make the texture atlas for me by using a folder with a .atlas extension but this is not what i want to do.
How do I change a UIBezierPath.currentPoint to a SKSpriteNode.position?
Here are the appropriate code snippets:
func createTrainPath() {
let startX = -tracksWidth/2,
startY = tracksPosY
savedTrainPosition = CGPoint(x: startX, y: startY!)
trackRect = CGRect(x: savedTrainPosition.x,
y: savedTrainPosition.y,
width: tracksWidth,
height: tracksHeight)
trainPath = UIBezierPath(ovalIn: trackRect)
trainPath = trainPath.reversing() // makes myTrain move CW
} // createTrainPath
Followed by:
func startFollowTrainPath() {
let theSpeed = Double(5*thisSpeed)
var trainAction = SKAction.follow(
trainPath.cgPath,
asOffset: false,
orientToPath: true,
speed: theSpeed)
trainAction = SKAction.repeatForever(trainAction)
createPivotNodeFor(myTrain)
myTrain.run(trainAction, withKey: runTrainKey)
} // startFollowTrainPath
So far, so good (I think?) ...
Within other places in my code, I call:
return trainPath.currentPoint
I need to convert trainPath.currentPoint to myTrain.position ...
When I insert the appropriate print statements, I see for example:
myTrain.position = (0.0, -295.05999755859375)
trainPath.currentPoint = (392.0, -385.0)
which obviously disqualifies a simple = , as in:
myTrain.position = trainPath.currentPoint
Since this = is not correct, what is ?
After more investigation, my guess is that .currentPoint is in SKSpriteNode coordinates and .position is in SKScene coordinates.