Als Zeichenfläche benutze ich ein JLabel. In der paintComponent Methode wird dann lediglich ein BufferedImage gezeichnet, welches in einem anderen Thread gezeichnet wird, nach der Idee von KonradN.
Die Test.jar habe ich mir angeschaut, der Code dahinter ist nirgends zu finden.
Ok, für ein 2D Spiel wird das schon reichen, persönlich würde ich da eher zu AWT greifen als zu Swing.
Hab mal testweise für meine Software eine 3D-Darstellung mit Java3D eingebaut und es gab einmal die Möglichkeit, das per JCanvas zu machen oder Canvas (AWT) zu verwenden. Obwohl der Renderer selbst bei beiden der Selbe war, war der effektive Geschwindigkeitsunterschied enorm. Swing führt noch einen Riesenbatzen an Prüfungen durch, erlaubt Popupmenüs usw. Verwendet man hingegen ein AWT-Canvas entfällt das alles, die Rechteckfläche wird gezeichnet und fertig. Der Vorteil des Swing-Elements war natürlich, dass ich Buttons einfach darüber legen und verwenden konnte anstatt das über rechteckige Flächen im Render mit Abfrage der Mausposition zu machen.
In jedem Fall brauchst du 2 BufferedImages: Eines für allein den Hintergrund und eines mit dem fertigen zu zeichnenden Bild inklusive Spielfiguren.
(1) immer dann neu erstellt, wenn sich etwas am Hintergrund ändert (Blöcke haben z.B. statische Positionen, können als Hintergrund behandelt werden). (2) ist das, welches in das Label gezeichnet wird und wird bei jeder Änderung von egal was neu befüllt. Zuerst wird darauf der Hintgrund (1) reinkopiert, dann die Sprites. Vielleicht gibt es eine effiziente Methode, um alle Pixels eines Images auf ein anderes gleicher Größe zu übertragen, aber drawImage sollte eigentlich reichen.
Edit: Es geht natürlich auch ohne das Hintergrundbild (1), wenn du selbigen für die Erstellung von (2) jedesmal neu erstellen lassen willst.
Aber wenn sich der Hintergrund nur vergleichsweise selten ändert (nicht so oft, wie Figuren bewegt werden), bietet es sich an, selbigen zu cachen.
Falls du Flimmern verhindern willst (kann passieren, wenn (2) durch die repaint-Methode neu gezeichnet werden soll, während es noch erstellt wird), dann brauchst du noch ein drittes Image. (2) und (3) wechseln sich dann ab. Je eins von beiden wird ins JLabel gezeichnet, während das andere neu berechnet wird.
Wenn du mal so was wie Parallax-Scrolling implementierst, brauchst du natürlich mehrere Hintergrundebenen mit Transparenz. Das Prinzip ist aber immer das Gleiche. Ein Element "entfernt" man nicht einfach, sondern zeichnet an der Stelle (oder dank massig Rechenpower seit Mitte der 90er überall) den Hintergrund neu.