PyObjC SpriteKit Framework
PyObjC provides Python bindings for Objective-C frameworks on macOS, enabling Python developers to interact with Apple's system APIs. `pyobjc-framework-spritekit` offers wrappers for the SpriteKit framework, which is Apple's high-performance 2D graphics framework used for games and other graphics-intensive applications. The library is currently at version 12.1 and maintains an active release cadence, typically aligning with new macOS SDK and Python version updates.
Warnings
- breaking PyObjC frequently drops support for older Python versions to align with active Python maintenance. PyObjC 12.0 dropped Python 3.9, and PyObjC 11.0 dropped Python 3.8. Always check the `requires_python` metadata or release notes to ensure compatibility with your Python environment.
- breaking PyObjC 11.1 aligned its core bridge with `clang`'s Automatic Reference Counting (ARC) documentation for initializer methods. Methods in the 'init' family now correctly steal a reference to `self` and return a new reference. This changed behavior for `[NSObject alloc]` proxies and can affect custom `init` implementations in Python subclasses, potentially leading to crashes if old reference counting patterns are assumed.
- gotcha PyObjC 10.3 initially broke `__init__` usage for Python subclasses of Objective-C classes, particularly when a user implemented `__new__` or when relying on PyObjC's `__new__` behavior. This was partially reverted in 10.3.1 to reintroduce `__init__` support when a user explicitly implements `__new__`. Code relying on PyObjC's provided `__new__` still cannot use `__init__` as before.
- gotcha PyObjC 11.0 introduced experimental support for free-threading (PEP 703) with Python 3.13+. While PyObjC protects its own implementation, Apple's Cocoa and SpriteKit frameworks are not inherently thread-safe. Concurrent updates to GUI elements or non-atomic properties from multiple Python threads can lead to undefined behavior or crashes.
- gotcha PyObjC provides bindings to macOS frameworks, but it does not provide explicit documentation for every Objective-C API. Developers must refer to Apple's official SpriteKit and Cocoa documentation for detailed API usage, paying attention to how PyObjC translates Objective-C conventions (e.g., `someMethod:withArg:` becomes `someMethod_withArg_` in Python).
Install
-
pip install pyobjc-framework-spritekit
Imports
- SpriteKit
import SpriteKit
- AppKit
import AppKit
- AppHelper
from PyObjCTools import AppHelper
Quickstart
import AppKit
import SpriteKit
from PyObjCTools import AppHelper
# Define a simple SpriteKit scene
class MyScene(SpriteKit.SKScene):
def didMoveToView_(self, view):
if not self.contentCreated:
self.createSceneContents()
self.contentCreated = True
def createSceneContents(self):
self.backgroundColor = SpriteKit.SKColor.redColor()
self.scaleMode = SpriteKit.SKSceneScaleMode.aspectFit
helloNode = SpriteKit.SKLabelNode.labelNodeWithFontNamed_('Chalkduster')
helloNode.text = 'Hello, PyObjC SpriteKit!'
helloNode.fontSize = 24
helloNode.position = AppKit.CGPointMake(self.frame().size.width / 2, self.frame().size.height / 2)
self.addChild_(helloNode)
# Define an Application Delegate to set up the window and scene
class AppDelegate(AppKit.NSObject):
def applicationDidFinishLaunching_(self, notification):
rect = AppKit.NSMakeRect(0, 0, 800, 600)
self.window = AppKit.NSWindow.alloc().initWithContentRect_styleMask_backing_defer_(
rect,
AppKit.NSWindowStyleMaskTitled | AppKit.NSWindowStyleMaskClosable | AppKit.NSWindowStyleMaskMiniaturizable | AppKit.NSWindowStyleMaskResizable,
AppKit.NSBackingStoreBuffered,
False
)
self.window.center()
self.window.setTitle_('PyObjC SpriteKit Example')
# Create an SKView and set it as the window's content view
skView = SpriteKit.SKView.alloc().initWithFrame_(rect)
self.window.setContentView_(skView)
# Create and present the scene
scene = MyScene.sceneWithSize_(skView.bounds().size)
skView.presentScene_(scene)
skView.setShowsFPS_(True)
skView.setShowsNodeCount_(True)
self.window.makeKeyAndOrderFront_(None)
def applicationShouldTerminateAfterLastWindowClosed_(self, sender):
return True
# Start the Cocoa application
if __name__ == '__main__':
app = AppKit.NSApplication.sharedApplication()
delegate = AppDelegate.alloc().init()
app.setDelegate_(delegate)
AppHelper.runEventLoop()