Ett SpriteKit-spel utan en enda bild- eller ljudfil: så byggde vi Street Legends

Street Legends levereras utan en enda bild- eller ljudfil. Varje tröja, boll, plan och visselpipa skapas i kod. Så här gjorde vi, och därför kanske du vill göra likadant.

Mustafa GüderGrundare, GuderTech4 min läsning
spritekit-game-without-asset-files.md

Street Legends är vårt snabba gatufotbollsspel fem mot fem för iPhone, med en liga att klättra i, en trupp på nio spelare och tröjor att låsa upp. Öppnar du apppaketet hittar du inte en enda PNG- eller ljudfil. Varje bild och varje ljud skapas i Swift medan spelet körs.

Varför bygga ett spel så här?

  • Liten nedladdning: inga texturatlaser eller ljudpaket, så appen installeras på sekunder
  • Skarpt i alla storlekar: formerna ritas för just den skärmen, från minsta iPhone till iPad
  • Oändliga varianter: en ny tröja är några färger, inte en ny uppsättning bilder
  • Snabb iteration: ändra en siffra så uppdateras hela spelet, utan exportsteg

Priset är att du inte kan lämna över en fil till en illustratör. Det passar stiliserad, geometrisk grafik, precis den stil vi ville ha.

Rita sprites med Core Graphics

Att rita komplexa former med SKShapeNode i varje bildruta är dyrt. I stället ritar vi en gång till en bild med UIGraphicsImageRenderer och gör om den till en textur:

import SpriteKit
import UIKit

func ballTexture(diameter: CGFloat) -> SKTexture {
    let size = CGSize(width: diameter, height: diameter)
    let image = UIGraphicsImageRenderer(size: size).image { context in
        let rect = CGRect(origin: .zero, size: size)
        UIColor.white.setFill()
        context.cgContext.fillEllipse(in: rect)

        UIColor.black.setFill()
        let patch = rect.insetBy(dx: diameter * 0.34, dy: diameter * 0.34)
        context.cgContext.fillEllipse(in: patch)
    }
    return SKTexture(image: image)
}

let ball = SKSpriteNode(texture: ballTexture(diameter: 28))

Texturer cachas utifrån sina parametrar, så varje textur ritas en gång och återanvänds av alla noder som behöver den. Tröjor fungerar likadant: en tröjform fylld med lagets färger och ett nummer ritat ovanpå.

Syntetisera ljud med AVAudioEngine

Ljudeffekter är korta vågformer med en envelope. Med AVAudioSourceNode kan du skriva samplingar direkt:

import AVFoundation

final class Synth {
    private let engine = AVAudioEngine()
    private var phase = 0.0
    private var frequency = 0.0
    private var amplitude = 0.0

    init() {
        let sampleRate = engine.outputNode.inputFormat(forBus: 0).sampleRate
        let source = AVAudioSourceNode { [unowned self] _, _, frameCount, bufferList -> OSStatus in
            let buffers = UnsafeMutableAudioBufferListPointer(bufferList)
            for frame in 0..<Int(frameCount) {
                let sample = Float(sin(phase) * amplitude)
                phase += 2 * .pi * frequency / sampleRate
                if phase > 2 * .pi { phase -= 2 * .pi }
                amplitude *= 0.9993 // quick decay, like a plucked sound
                for buffer in buffers {
                    buffer.mData?.assumingMemoryBound(to: Float.self)[frame] = sample
                }
            }
            return noErr
        }
        let format = AVAudioFormat(standardFormatWithSampleRate: sampleRate, channels: 1)
        engine.attach(source)
        engine.connect(source, to: engine.mainMixerNode, format: format)
        try? engine.start()
    }

    func kick() {
        frequency = 90
        amplitude = 0.7
    }
}

En spark är en låg ton som faller snabbt. En visselpipa är en hög ton med lite vibrato. Publikljud är filtrerat slumpbrus som sväller efter ett mål. Att kombinera en handfull sådana generatorer täcker alla ljud i spelet.

Håll det snabbt

  • Rita texturer en gång vid laddning, aldrig inuti update(_:)
  • Återanvänd noder för upprepade effekter i stället för att skapa nya
  • Använd SpriteKits fysikkroppar med enkla former, cirklar för spelarna och bollen
  • Profilera på den äldsta enheten du stöder, inte på den nyaste

När procedurell grafik är rätt val

Den glänser i arkadspel, pusselspel och stiliserade världar där geometrin är estetiken. För målerisk eller figurtung grafik är en konstnär och en texturatlas fortfarande det bättre verktyget; vårt match-3-spel Paw & Home är ett bra exempel på den sidan.

Vill du få ett spel byggt? Berätta om det. Vi bygger i SpriteKit, SceneKit och Unity.

Vanliga frågor

Är SpriteKit fortfarande ett bra val för iOS-spel 2026?

Ja, för 2D-spel på Apples plattformar. Det är lätt, inbyggt och väl integrerat med Game Center och StoreKit. För spel på flera plattformar eller med mycket 3D passar Unity oftast bättre.

Låter procedurellt ljud sämre än inspelat?

För korta effekter som sparkar, klick och visslingar kan det låta utmärkt och tar nästan ingen plats. För musik och röster är inspelningar fortfarande bättre.

Gör texturgenerering att appen startar långsammare?

Bara om du ritar dem i varje bildruta. Ritade en gång vid start och cachade tar enkla texturer millisekunder.

Hur litet kan ett SpriteKit-spel vara?

Utan bild- och ljudfiler kan ett komplett spel vara bara några megabyte, där det mesta är kompilerad kod.

DelaXLinkedInWhatsApp
Mustafa Güder

Om skribenten

Mustafa Güder

Mustafa Güder är grundare av GuderTech och iOS-utvecklare. Efter två års studier i Australien flyttade han hem till Adana och byggde Scevia, Paw & Home och Street Legends.

Studier i Australien, 2 år Adana, Turkiet

Alla artiklar