Angepinnt Einfache Spieleentwicklung am Beispiel :-)

  • Garbage? Sollte nicht sein :)
    Welche Version von x64 benutzt Du?
    Naja, das GBA reversen ist ja nicht zwingend Teil der Spieleentwicklung. Daher ging ich darauf auch nicht weiter ein und statt dessen basiert das Testlevel auf der sehr groben Preview-GFX ;)
    Vielleicht doch mal kurz etwas Code damit man sieht wie einfach das sein kann:

    Quellcode

    1. import sys
    2. from PIL import Image
    3. img = Image.open(sys.argv[1])
    4. colors=[1,3,3,1,2,2,3,2,1,1,0]
    5. # 0 1 2 3 4 5 6 7 8 9 a
    6. for y in range(img.size[1]):
    7. print "\n.byte ",
    8. for x in range(img.size[0]):
    9. col=img.getpixel((x,y))
    10. col=colors[col]
    11. print "$%02x" % col,
    12. if x < (img.size[0]-1):
    13. print ",",
    Alles anzeigen


    Das ist bereits der vollstaendige Konverter fuer Preview.png -> Leveldaten.
    (wenn das PNG als indexed color vorliegt).
    Oben ein kurzer Array mit dem ich die 10 Farben des Previews auf meine 4 mappe.
    Dann zwei FOR-Schleifen ueber Y und X.
    Das print-Gebastel ist nur um immer eine Zeile ".byte $00, $01, ..." auszugeben.
    Ich mag da immer PRINT fuer so einfache Tools und leite die Ausgabe direkt in eine Datei um.
    Ein sauber formatiertes file.write() ist netter, aber so gehts ruckizucki.
  • uU liegt es sogar tatsaechlich an Vice ;)
    Ich untersuche das mal genauer. Am Exomizer sehr sicher nicht.
    Hier jetzt eine weitere Version.
    Es geht voran :)
    neu:
    - Rotor aus 3 Segmenten (wie man leider auch noch sieht ;)
    - Rotor hat jetzt sehr genau die Laenge UND Geschwindigkeit des Originals am GBA.

    Das Level ist allerdings nun etwas schwerer als am Original weil ja der Rand mit 2x2 chars voll dazuzaehlt. Wenn das eine 'Bande' draus wird, ragen die Ecken ja nicht mehr so in die Bahn versteht sich...


    Edit:
    jetzt auch ohne seltenen Timing-bug :)
    Bilder
    • shot06.png

      19,85 kB, 768×272, 146 mal angesehen
    Dateien
    • rotor.prg

      (2,09 kB, 14 mal heruntergeladen, zuletzt: )
  • [offtopic]

    enthusi schrieb:

    Die 128x128 Map ist uebrigens 16KB gross. Das passt recht gut, aber es koennte ratsam sein, dass am C64 in Tiles zu verschachteln. Also eine Map mit 64x64 aus 2x2 Tiles z.B. Sehr viele Spiele mit wiederkehrenden Elementen machen soetwas (GianaSisters, Turrican, ...).

    Giana Sisters benutzt Tiles in verschiedenen Größen (wie Katakis) und die Map wird vor jedem Level vollständig in den Speicher geschrieben.[/offtopic]
  • Es gibt etwas Neues :)
    Und zwar ist Erfolg zu vermelden was das Reversen des GBA-codes angeht.
    Kniffeliger als ich erst dachte. Die Maps sind in der Tat gepackt im ROM, aber ich kann jetzt alle extrahieren.
    Die Rohdaten sind teils etwas obskur, aber jetzt liegt alles in echter Tileaufloesung vor.
    Ich habe mal eben das eine Testlevel von vorher neu aufgesetzt.
    Mit dabei ein Rotor in Originalgroesse und -geschwindigkeit.
    Ebenfalls eine recht nette Kollisionskontrolle die noch amok laeuft wenn man in Waende faehrt.
    Die lohnt es sich aber erst feinzujustieren/debuggen wenn man auch pixelweises Scrolling hat.
    8-directional Scoftscrolling und bessere Levelaufbereitung/extrahierung stehen jetzt auf dem Plan erstmal.
    Danach bessere Kollision die DANN auch doch auf charebene wird laufen muessen (bisher nicht :) damit man die Federn abfangen kann.
    Ebenfalls geht es dann auch an die Scrollgeschwindigkeit die variabel ist...
    Bilder
    • shot.png

      1,5 kB, 504×312, 95 mal angesehen
    Dateien
    • level.prg

      (2,25 kB, 35 mal heruntergeladen, zuletzt: )
  • Und ein grosser Schritt ist getan ;)
    Das Projekt hat seinen ersten Speicherplan bekommen:

    Brainfuck-Quellcode

    1. ;------------------------------
    2. ;new memory mapping
    3. ;------------------------------
    4. ;VIC bank $4000-$7fff
    5. ;charset $5800
    6. ;sprites $6000
    7. ;screenram $7800, $7c00 ;double buffer
    8. ;map $8000-$bfff ;128x128 tiles
    9. ;code/SID area
    10. ;c000-ffff
    11. ;0800-3fff
    Alles anzeigen


    das erschien mir erstmal ganz zweckmaessig.
    Und auch das etwas laestige Softscrolling ist drin.
    8-Wege Softscroller mit Doublebuffer (bisher ohne color RAM!).
    Aktuell nur 20 Zeilen wie im GBA Original. Ob ich das auf 30x20 einschraenken sollte?
    Man gewinnt CPU-Zeit, verliert aber ein Sprite und natuerlich schraenkt es die Sichtbarkeit ein.
    Das gilt es also abzuwaegen.
    (Man verliert ein Sprite weil man (fast) nur mit einem Sprite den flackernden Softscroll-Rand verdecken kann. Bei 40 Zeichen Breite sorgt ja der 30 Spalten-Mode dafuer).
    Der Hardscroll ist schon recht fix und passiert sogar in einem Rutsch!
    Dadurch gibt es weniger Aerger mit dem Softscroll und der Vorhersagbarkeit der noetigen Richtung.
    Darauf gehe ich bei Bedarf gerne nochmal genauer ein.
    Der Code benutzt "halben Speedcode", also lda source,x - sta destination,x Serien.
    Und zwar fuer jede der 8 Richtungen und beide Buffer. Also 16 insgesamt.
    Aktuell scrollt es fix mit 2 pix pro Schritt aber das ist auf jeden beliebigen Wert aenderbar mit dieser Methode.
    Das Original erlaubt auch verschiedene Geschwindigkeiten.
    Das muss noch 'vermessen' werden.
    Das Kollisionshandling liefert jetzt auch schon recht brauchbare Ergebnisse auch wenn es nach sehr einfachen Regeln arbeitet und dazu neigt im wahrsten Sinne des Wortes durchzudrehen ;)
    Viel Spass, es ist so quasi schon spielbar :)
    Dateien
    • softscroll.prg

      (3,53 kB, 29 mal heruntergeladen, zuletzt: )
  • Gefällt mir auch :thumbup: .

    enthusi schrieb:

    Der Code benutzt "halben Speedcode", also lda source,x - sta destination,x Serien.
    Und zwar fuer jede der 8 Richtungen und beide Buffer. Also 16 insgesamt.

    enthusi schrieb:

    Darauf gehe ich bei Bedarf gerne nochmal genauer ein.

    Mach mal bitte :dafuer: .

    enthusi schrieb:

    (Man verliert ein Sprite weil man (fast) nur mit einem Sprite den flackernden Softscroll-Rand verdecken kann. Bei 40 Zeichen Breite sorgt ja der 30 Spalten-Mode dafuer).

    Wieso nur EIN Sprite?

    Der Rotor 'zuckt' optisch irgendwie, wenn er waagerecht oder senkrecht steht (beim waagerechten Zucken liegt es scheinbar daran, das sich der Rotor 'ausdehnt'; beim senkrechten an diesem einen 'Knick' im Rotor). Das macht mich nervös :D .
    Read'n'Blast my jump'n'stop-text-sprite-scroller Select A Move

    Ex-TLI (The Level 99 Industries) & Ex-TNP (The New Patriots) & Ex-TEA (The East Agents) & ?
  • Ah! Es liest hier also doch jemand mit ;)
    Per Hardwareregister kann man immer nur die volle Bildschirmbreite scrollen (0-7 Pixel).
    Das kann man auch nicht IN einer Zeile aendern. Selbst wenn ich nur z.B. die linke Haelfte oder um bei Kuru zu bleiben 30 chars scrollen moechte, wackeln die rechten 10 dann trotzem fies hin und her.
    Genauer gesagt bewegt sich alles per Hardscroll in eine Richung und springt dann zurueck.
    Es gibt da 4 Loesungen die mir grade einfallen.

    1) man laesst den Teil der nicht mitscrollen soll schwarz.
    Problem: Trotzdem eiert der Rand dann dumm rum.
    Loesung dazu: man legt ein (hier schwarzes) Sprite an die Stelle an der man den Rand haben will. Prioritaet dann ueber der Bitmap (und ueber allen anderen Sprites).
    Wieso nur ein Sprite? Man kann es ja Problemlos immer wieder nach unten verschieben sobald es dargestellt wurde. Nach unten schieben geht sogar immer, so dass das Timing kaum eine Rolle spielt.
    In dieser 'gecrackten' Proof-of-concept Engine von mir hab ich das z.B. so gemacht:
    csdb.dk/release/?id=114516
    Das ist die einfachste Variante obwohl es in dem Beispiel da oben etwas kniffeliger war, weil der Multiplexer das beruecksichtigen musste, dass immer das Sprite mit der hoechsten Prioritaet an der Stelle bleibt.

    2) Man macht das wie bei 1) moechte aber Text oder sowas darstellen am Rand. Den plottet man dann in (z.B. weisse) Sprites. Damit es leserlich wird, verliert man aber nochmal 1-3 Sprites pro Zeile.

    3) wie 1) aber statt Sprites nimmt man chars fuer den Text. ABER die scrollen ja mit?! Also erstellt man die Grafik fuer den Rand so, dass sie fuer jeden Scrollschritt entgegengesetzt scrollt. Wenn da 'A' stehen soll und das Spiel immer in 2 Pixelschritten scrollt, braucht man also 8 chars.
    zwei Nebeneinander und das A scrollt in 4 schritten von links nach rechts entgegen dem Rest des Screens. Das sieht man meist nur bei Scrollern mit 4 oder 2 Pixeln pro Scrollschritt, da man sonst einfach zuviele der 256 chars verliert.
    Ich habe hier ein Projekt mit 1 Pixelscroll rumliegen, dass das macht ;) Beruehmtes Beispiel ist Operation Wolf und Co.

    4) Man kann auch ALLE Levelgrafiken so designen, dass jedes Char in mehreren Scrollstufen vorliegt. Dann kann man ganz ohne VIC-Scroll auskommen. Das braucht aber sehr viele chars, so dass die Grafik sehr limitiert ist.
    Vor allem wenn man nicht nur links-rechts scrollen will. Es gibt einige wenige Beispiele aber. Auf meiner Festplatte :) und mal in der 64er irgendwann auf jeden Fall.

    Im Prinzip entsprechen 3) und 4) einer echten Parallax-Scrolliung-Engine, aber statt einige wenige Zeichen so zu behandeln, besteht eben sehr viel mehr Grafik daraus.
    Siehe auch Fluglevel bei Turrican 3, Flimbos Quest, Hawkeye 2.
    Bei diesen 3 koennte man die Hintergrundgrafik nehmen und daraus einen Scroller basteln, der OHNE Hardwarescroll auskommt.
    (und dann auch nicht Bildschirmbreit sein muss natuerlich).

    Bei _diesem_ Spiel hier wollen wir aber schon viele Chars fuer die Levelgrafik verwenden.
    Ich ueberlege noch ob man es auch auf 30x20 begrenzen sollte.
    Vorteile:
    - die Level funktionieren wie im Original (was man sieht und nicht sieht).
    - mehr CPU-Zeit fuer Farbscrolling (evtl. ist es am Ende sogar noetig deswegen)

    Nachteile:
    - entweder kleineres Bild, oder man opfert Sprites fuer Leben/Score-Anzeige die dann im schwarzen Bereich neben dem Hauptschirm liegen wuerden.

    Edit:
    - Der Rotor benutzt 3 Sprites. +1 fuer die Kugel in der Mitte. gerne haette ich fuer die beiden 'Arme' noch ein Overlaysprite. Das sind dann schon 6 + 2 fuer Randabdeckung:
    Score/Leben koennte also nur ueber oder unter dem Rotor rechts stehen. Das passt aber auch noch locker.


    Vielleicht gibt es dazu ja Meinungen?
    Ich tendiere zu 30x20 momentan...
  • Hexworx schrieb:

    Das macht mich nervös


    Mich auch ;)
    Ich bin eher erstaunt, dass es ueberhaupt SO gut aussieht.
    Das obliegt am Ende einem Zusammenspiel von Grafiker und mir jeden Animationsschritt sauber auszurichten.
    Das jetzt von Hand zu machen waere nur vertane Zeit.
    Das hier ist uebrigens der (schlampige!) Pythoncode fuer die Korrektur-Tables der beiden aeusseren Rotorsprites:

    Quellcode

    1. from math import *
    2. pi=3.14159265359
    3. Rx=23-3
    4. Ry=23-3
    5. R=23-3
    6. offset=55+2
    7. offset2=51-3
    8. prg = True
    9. if prg: print "table0"
    10. for i in range(60,0,-1):
    11. phi=2*pi/360* i*3
    12. x=(int(sin(phi)*R+0.5)-Rx+offset2)
    13. y=(int(cos(phi)*R+0.5)-Ry+offset2)
    14. if prg: print ".byte $%02x ;x\n" % x ,
    15. if prg: print ".byte $%02x ;y\n" % y ,
    16. else: print x,y
    17. print
    18. print
    19. if prg: print "table1"
    20. for i in range(60,0,-1):
    21. phi=2*pi/360* i*3
    22. x=offset- (int(sin(phi)*R+0.0)-Rx+offset2)
    23. y=offset- (int(cos(phi)*R+0.0)-Ry+offset2)
    24. if prg: print ".byte $%02x ;x\n" % x ,
    25. if prg: print ".byte $%02x ;y\n" % y ,
    26. else: print x,y
    Alles anzeigen


    Das ist beim Testen etwas gewachsen und liesse sich enorm verkuerzen/verschoenern. Wie immer ist Zeit knapp ;)
    per "prg = False" kann ich die Koordinaten direkt ausgeben und dann durch Gnuplot jagen zum testen.
    Rx und Ry separat sowie das bisschen Tuning +/- sind einfach noch uebrig geblieben als ich etwas ganz anderes ausprobiert habe ;)
  • Endurion schrieb:

    Würde man den Spielausschnitt mit 30x20 nicht fast besser horizontal zentrieren? Dadurch geht vermutlich noch ein Sprite flöten, aber nach links gequetscht sieht doch komisch aus.
    Als Bonus hat man dann das X-Extend-Bit an der Backe


    klar, das waere dann zentriert bei diesem Spiel natuerlich, das mit dem 1 Sprite war eher fuer das Prinzip ;)
    MSB der X-Koordinate stoert mich nicht.
    Ich glaube nichtmal dass man in den Bereich > 255 kommt? Selbst wenn: das ist ja immer bekannt wann welches Sprite wo ist beim Rotor - das ist ja das schoene wenn der Scroller pixelexakt ist ;)
  • enthusi schrieb:

    Ah! Es liest hier also doch jemand mit ;)
    Aber natürlich! Ich find's richtig klasse und sehr gut und verständlich beschrieben.

    enthusi schrieb:

    Per Hardwareregister kann man immer nur die volle Bildschirmbreite scrollen (0-7 Pixel).
    Das kann man auch nicht IN einer Zeile aendern. Selbst wenn ich nur z.B. die linke Haelfte oder um bei Kuru zu bleiben 30 chars scrollen moechte, wackeln die rechten 10 dann trotzem fies hin und her.
    OK, hier muss ich der Vollständigkeit halber anmerken: Doch, man kann das Hardwareregister $D016 auch mitten in der Zeile ändern und die Änderung wird sofort wirksam. Wenn man also in jeder Rasterzeile das Hardwarescrollregister $D016 zweimal beschreiben würde, könnte man damit theoretisch auch die linken 30 Chars soft scrollen und die 10 rechten Chars fest stehen lassen. Das kostet aber so viel Rechenzeit, dass es in einem Spiel nicht sinnvoll nutzbar ist.
  • enthusi schrieb:

    - Der Rotor benutzt 3 Sprites. +1 fuer die Kugel in der Mitte.

    Hatte ich noch gar nicht geblickt, dass das drei und nicht zwei sind (hab doch die Pixel nicht nachgezählt... :rotwerd: )

    enthusi schrieb:

    per "prg = False" kann ich die Koordinaten direkt ausgeben und dann durch Gnuplot jagen zum testen.
    Rx und Ry separat sowie das bisschen Tuning +/- sind einfach noch uebrig geblieben als ich etwas ganz anderes ausprobiert habe ;)

    Das ist mir jetzt grad etwas zu hoch..., hab's aber halbwegs durchblickt. Für alles mit irgendwelchen Sinus-Kurven & Co. (Intros/Demos) musste bei mir damals immer BASIC herhalten und hat dafür auch ausgereicht. Deine Routine ließe sich vermutlich in BASIC auch nachstellen. Laufzeit: :nixwiss:

    Wurde der 'innere' Rotor auch damit gemacht?

    enthusi schrieb:

    Wieso nur ein Sprite? Man kann es ja Problemlos immer wieder nach unten verschieben sobald es dargestellt wurde. Nach unten schieben geht sogar immer, so dass das Timing kaum eine Rolle spielt.
    In dieser 'gecrackten' Proof-of-concept Engine von mir hab ich das z.B. so gemacht:
    csdb.dk/release/?id=114516

    :respect:

    Eine ungefähre Vorstellung habe ich (Char/Sprites/Border), aber sicher wohl nicht ganz ohne :prost:

    Bei solchen Sachen denke ich immer: Wenn man Commodore 1983/84 hätte zeigen können, was das 'C64-Monster' so kann... :freude :schreck!: :platsch:



    Was ist denn eigentlich aus 'Mario' geworden :roll: ?
    Read'n'Blast my jump'n'stop-text-sprite-scroller Select A Move

    Ex-TLI (The Level 99 Industries) & Ex-TNP (The New Patriots) & Ex-TEA (The East Agents) & ?