Eigenes Videoformat

Diskussion zum Thema Programmierung unter DOS (Intel x86)
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Eigenes Videoformat

Beitrag von DOSferatu »

zatzen hat geschrieben:Ich antworte später ausführlicher.
Na gut...
zatzen hat geschrieben:Nur schon einmal so viel:
Ich habe etwas experimentiert und ZVID2 für lohnenswert und funktional befunden.
Die Freepascal Routine funktioniert mit clipping an allen Bildschirmseiten und spiegeln, ich muss jetzt nur noch das Format strukturieren,
Ich habe schon mehrmals versucht, Freepascal (auch neuere Versionen) zu benutzen, aber mein Zeug compiliert da nicht. Vielleicht programmiere ich zu seltsam. Ich glaube, die supporten immer noch nicht die mem[] und port[] Dinge - weiß gerade nicht genau, ich glaube, es gab auch noch andere Probleme. Mir vergeht irgendwie die Lust, die Units, die ich in den letzen 25 Jahren geschrieben habe, jetzt auch noch für FreePascal (das angeblich 100% kompatibel zu Borland/Turbo Pascal ist) anzupassen. Aber egal.
zatzen hat geschrieben: und dafür muss ich folgendes klären:
Wenn ich mit getmem Speicher reserviere, in welchem Rahmen wird sich dann das zugeordnete
Offset befinden? Bleibt es unterhalb von 16, unterhalb von 8 oder sogar verlässlich bei 0 ?
Oder kann es sogar passieren, dass es Werte >= 16 annimmt, etwa wenn man nur kleine
Mengen reserviert?
Kann ich nicht genau sagen - aber ein entsprechendes Testprogramm, das viele "krumme" Speichergrößen reserviert und dann den Offset des zugewiesenen Pointers testet/ausgibt, könnte das leicht klären. Es sollte kein Hexenwerk sein, so etwas zu schreiben.
zatzen hat geschrieben:Ich würde das ganze gern im Zweifelsfall so zurechtstutzen beim Laden eine ZV2 Datei, dass ich in der ASM Routine von absoluten Verhältnissen ausgehen kann.
Also bspw. mit getmem den benötigten Speicher + 16 reservieren, und Die Daten
dann an (segment+1:0000) laden.
Klar, mach ich auch immer so - und meine eigene Speicherverwaltung liefert sowieso ausschließlich Pointer mit Offset=0.

Ich habe mal "irgendwo gelesen", daß GetMem immer in minimal 8er-Schritten reserviert - aber ich weiß nicht mehr, wo das war und ob das stimmt - ich verlasse mich da auf nichts.

Aber: Wie Du ja weißt, sind die Segmentanfänge alle 16 Bytes im Speicher, so daß also der Pointer 1234:16 genau auf die gleiche Speicherstelle zeigt, wie der Pointer 1235:0 und der Pointer 1233:32... usw.

Ich mache da immer so etwas, das ich selbst als "Normalisieren des Pointers" bezeichne:

Code: Alles auswählen

procedure PNormalize(var P:Pointer);
var PX:record O,S:word;end absolute P;
begin
with PX do begin inc(P,O shr 4);O:=O and 15;end;
end;
Der Pointer zeigt damit auf die gleiche Adresse, aber sein Offset ist immer nur 0 bis 15.

Jetzt weiß ich nicht, ob FreeMem, bei dem man ja den Pointer angeben muß, GENAU den von GetMem zugewiesenen Pointer braucht, oder auch mit diesem "normalisierten" zurechtkäme. Da kann man sich natürlich auch einen zweiten Pointer machen (vorher in einen anderen kopieren und den normalisieren) ODER man macht das Ganze als Funktion:

Code: Alles auswählen

function GetPNormalize(P:Pointer):Pointer;
var PX:record O,S:word;end absolute P;
begin
with PX do begin inc(P,O shr 4);O:=O and 15;end;
GetPNormalize:=P;
end;
Ja, in Assembler kann man das natürlich mit weniger Geraffel und etwas eleganter machen (wie man - meiner Meinung nach - VIELES in Assembler kürzer und eleganter machen kann als in vielen Hochsprachen - obwohl es ja offiziell angeblich umgekehrt ist), aber es soll hier verdeutlichen, was ich meine/wie es funktioniert.

Falls man sowieso nur ein "Null-Offset-Segment" haben will, braucht man zwar trotzdem auch den Pointer (damit man ihn mit FreeMem wieder freigeben kann), aber da könnte man z.B. das machen:

Code: Alles auswählen

function GetMemSeg(var P:Pointer;SZ:word):word;
var PX:record O,S:word;end absolute P;
begin GetMem(P,SZ+15);
with PX do GetMemSeg:=S+(O shr 4)+ord((O and 15)<>0);
end;
Erklärung (falls nötig) : Man reserviert 15 Bytes mehr als man braucht - für den Fall, daß der Offset an einem "krummen" Wert landet. 15 ist ausreichend, es braucht nicht 16.
Dann weist man dem Segment den "normalisierten" Wert zu. Das ganz letzte (ab "ord") bedeutet: Der Begriff innerhalb ord(), also (O and 15)<>0 ergibt einen Wahrheitswert FALSE oder TRUE und ord() macht daraus 0 oder 1, d.h. falls der Offset trotz Normalisierung "krumm" wäre, daß man dann zum Segment 1 addiert.

Ich hoffe, ich konnte es einigermaßen verständlich ausdrücken. Man kann das Ganze natürlich auch anders darstellen oder machen - aber für jeden, der erst einmal verstanden hat, wie das segmentierte x86-Speichermodell funktioniert, sollte es kein Problem sein, "glatte" Segmente zu reservieren/benutzen.

Man muß natürlich bei o.g. Function dann darauf achten, bei FreeMem die Größe+15 freizugeben. Und außerdem habe ich in o.g. Function auch keine Prüfung drin für den Fall, daß der Speicher nicht reicht oder die gewünschte Größe > 65521 wird - das kriegt man sicher selbst raus, falls man's braucht.
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Eigenes Videoformat

Beitrag von zatzen »

Vielen Dank für die schnelle Antwort!

Sehr elegant das "inc(P,O shr 4)" da bin ich gar nicht drauf gekommen.

Ich muss aber überlegen ob ich nicht doch in der ASM Routine ein paar Takte und Zeilen mehr einbringe (außerhalb innerer
Schleifen), es wäre nämlich auch reizvoll hinsichtlich der Einfachheit, die ZV2's ganz standardmäßig reinzuladen und nicht
mit spezialisierten Routinen.

Was Freepascal angeht, wenn man das in Windows benutzt, dann ist das ja auf Protected Mode und 32 Bit ausgelegt, von
Befehlen wie mem[] oder port wird eindeutig abgeraten. Im Gegensatz zu Turbo Pascal für Dos kann man bei Freepascal
einfach ein Array von z.B. 1 GB anlegen, und so gehe ich dann auch vor wenn ich in Freepascal programmiere. Einfach
Arrays in beliebiger Größe, meistens dynamisch die Größe über setlength festgelegt. Getmem ist wohl möglich, aber
mehr oder weniger unnötig weil man ja 4 GB Speicher hat und somit die Unterscheidung von Codesegment, Datensegment
und Heap gewissermaßen hinfällig wird. Ich programmiere in FPC meist datenverarbeitende Tools, und da kommt es
mir nicht so sehr auf die Performance an, es soll nur möglichst unkompliziert zu programmieren sein und funktionieren.
Freepascal wird nur zu Turbo Pascal kompatibel sein, wenn man ziemlich hardwarefern programmiert, bzw. muss
man einfach das lineare(?) Speichermodell von Freepascal berücksichtigen.
mov ax, 13h
int 10h

while vorne_frei do vor;
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Eigenes Videoformat

Beitrag von DOSferatu »

zatzen hat geschrieben:Sehr elegant das "inc(P,O shr 4)" da bin ich gar nicht drauf gekommen.
Wäre noch eleganter, wenn ich mich nicht verschrieben hätte.
Es muß selbstverständlich heißen:

Code: Alles auswählen

inc(S,O shr 4);
drzeissler
DOS-Gott
Beiträge: 3336
Registriert: Mo 8. Feb 2010, 16:59

Re: Eigenes Videoformat

Beitrag von drzeissler »

Bei YT gibt es einen, der ein FullscreenVideo mit Ton (Beavis&Butthead) auf einem 286/8 oder 10Mhz in VGA laufen lässt. Sowas wäre mal echt interessant. Das wäre ein cooles Feature für ein A2286/8.
CPU: 486 DX2/66 MOBO: SNI-D882 RAM: 3x16MB - FDD: 3,5" 1,44MB HDD: 6,4GB Seagate ISA(1): Audican32Plus PCI(1): 3com TX 905 OS: MsDos622 - Win95a - WinNT 3.51
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Eigenes Videoformat

Beitrag von zatzen »

drzeissler hat geschrieben:Bei YT gibt es einen, der ein FullscreenVideo mit Ton (Beavis&Butthead) auf einem 286/8 oder 10Mhz in VGA laufen lässt. Sowas wäre mal echt interessant. Das wäre ein cooles Feature für ein A2286/8.
Das wäre wirklich mal interessant zu sehen. Ich konnte es leider auf Youtube nicht finden. Gibt so viele Videos...
Und Zusätze wie 286 oder vintage helfen auch nicht. Ich selber könnte das nur unter großem Datenaufkommen
realisieren. Fürs Bild meinetwegen 15 fps und pro Bild im Schnitt 15-25 KB - 320x200 und mit eigener Palette für jedes
Bild, 256 oder 128 Farben, da die Palette für jedes Bild gewechselt werden müsste, immer im Wechsel wenn gerade
nur Farben verwendet werden die nicht geändert werden. Oder man macht Qualitäteinbußen und verwendet
eine generalisierte Palette mit 256 festfarben, dann wäre auch Delta-Kodierung denkbar.
DOSferatu hat geschrieben:Aber es gibt eben Sachen, ohne die das Spiel NICHT funktionieren würde und bevor diese nicht funktionieren/eingebaut sind, kann man sich nicht über die "Zusatzfeatures" hermachen. Wenn die zwar funktionieren, aber für die unbedingt zur Funktion notwendigen Sachen kein Speicher/Rechenzeit/usw. mehr da ist, bekommt man das Programm/Spiel nicht fertig. Deshalb ist es so wichtig, erst sicherzustellen, daß das Grundgerüst, aus dem das Spiel besteht, lauffähig zu bekommen, bevor man überlegt, wieviel Speicher/Rechenzeit usw. man für die "Süßigkeiten" einsetzen will.
Für's erste backe ich kleine Brötchen. D.h. die Grafik wird am Ende vielleicht keine 100 KB füllen (zumindest während
eines Levels), und mit Nutzung von ZVID2 fast nur die Hälfte davon. Zurückblickend auf Kotzman II war der
Programmcode auch nicht so sonderlich groß, naja es ist 24 Jahre her und ich kann mich auch nicht mehr so exakt dran
erinnern. Jedenfalls denke ich dass ich es mir am Ende sogar leisten kann, mehr Sounddaten als Grafikdaten
unterzubringen, einfach weil noch Platz sein wird. Und wenn nicht, dann werden die Sounddaten eben entsprechend
kleiner und kompromittierter, das ist alles kein Problem. Sound kommt am Schluss oder wird zwischendrin angepasst,
wenn's mit dem Speicher eng wird, da ist man flexibel. Und ich bin kein "Pro", habe keinen Wettbewerb zu gewinnen,
daher kann ich einfach mal nach Lust und Laune loslegen und ein Spiel machen das vielleicht etwas sonderbar ist.
Wenn ich denn mal loslege. Ich habe in letzter Zeit mal wieder ein wenig gepixelt und merke dass ich das noch ganz gut
kann, vielleicht sogar besser als früher.
Aber es kommt noch das Prokrastinieren dazu, und ich bin auch mehr abgelenkt als zu Kotzman II Zeiten, weil ich mehr
Hobbys habe als damals.
DOSferatu hat geschrieben:[anm. Stichwort Datenkompression] Wenn man viele Animationsphasen hat, aber wegen Performanceproblemen gar nicht die Framerate erzeugen kann, um diese ruckelfrei darzustellen, sondern deshalb Phasen auslassen muß, wird das Ganze wie eine Schlange, die sich selbst in den Schwanz beißt...
Einerseits hast Du Recht, und ich habe auch schon überlegt ob ich alles was nicht animiert ist, also soetwas wie
Kachelelemente, als simple Bitmaps im Speicher halte und mit einfachen Kopierroutinen in den Puffer haue.
Aber ich finde man muss erstmal sehen wie die Kompression performt.
Im Prinzip kommt die Verlangsamung durch SHR, AND und MOV Befehle und das Vorbereiten von Offset-Registern
Zustande. Das sind durchaus eine handvoll Takte. Allerdings war ich erstaunt, in dem ASM Guide zu lesen, dass STOSB
auch auf einem 486er 5 Takte braucht. Also wenn jemand damit arbeitet, könnte das auch recht langsam werden.
Oder ich übersehe da etwas, dass "MOV ES:[DI], AL ; INC DI" doch nicht schneller (obwohl nur 2 Takte) ist...
Ich musste nur dran denken, weil ich früher oft STOSB verwendete, da es so praktisch ist wenn man das nicht so
ausformulieren muss mit MOV und INC. REP STOSx/MOVSx ist wohl wieder eine andere Sache, was die Performance angeht.
Wie Du schreibst, der Nutzen ergibt sich erst ab einer bestimmten Datenmenge.

Ich werde auch erst einmal versuchen, alle Sprites mit derselben Routine darzustellen, nämlich ZVID2.
Diese enthält praktischerweise ein solides blockweises Clipping, man braucht sich letztlich gar nicht mehr drum
kümmern wo das Sprite auf dem Bildschirm landet, egal ob links, rechts unten oder oben raus oder in einer Ecke,
oder ob es überhaupt noch im sichtbaren Bereich ist, das kann die Routine alles sicher abfangen. Für mich ein kleines
Novum. Ich muss nur ringsherum den Puffer 3 Pixel größer machen als das letztlich sichtbare Bild.
Es wird sich zeigen was letztlich unterm Strich schneller ist - die Grafikobjekte vor Aufruf der Routine auf Sichtbarkeit
prüfen (innerhalb des Screens wenigstens noch ein Stückchen zu sehen), oder einfach alles ungeprüft der Routine
weitergeben, die sich dann bei nicht-Sichtbarkeit nach ein paar handvoll Takten und vielleicht zwei Sprüngen sofort
wieder verabschiedet.
An dieser Stelle wäre noch gut zu wissen um einen Sprung sparen zu können, wenn Du es gerade aus dem
Ärmel schütteln kannst: Mit welchen Assembler-Befehlen kann ich eine Pascal-ASM-Prozedur verlassen?
Oder ist das unklar weil man letztlich nicht sagen kann ob RET oder RETF nötig ist?

Zeichnen/Löschen Methode, nur wenn sich etwas geändert hat: Um in den Puffer zu schreiben ist das ein fummeliges
Unterfangen, aber wenn man sich z.B. ein 1000 Byte (40x25 8x8) Datenfeld anlegt wo man vermerkt ob etwas geändert
wurde... Also nur so ein Gedankenanstoß, ohne die Umsetzung wirklich durchdacht zu haben - dann könnte man
wenigstens beim Kopieren in den Grafikspeicher sparen. Bringt aber spätestens bei Scrollings nichts mehr und ist wohl
auch nur wieder mit mehr Rechenaufwand verbunden. Aber nur so ein Gedanke.
DOSferatu hat geschrieben:Naja, mit 44100 Hz müssen aber doppelt so viele Daten pro Sekunde berechnet werden als mit 22050 Hz - das sollte doch klar sein, oder? Also auch doppelt so viele pro Frame.
Ja, das stimmt. Ich bezog das nur irgendwie auf den Speicherbedarf für die Sounddaten. Und da kann man ja auch
einfach 8 kHz in 44.1 kHz reinmischen. Und ein 2 KB Puffer (ca. 44100 Hz bei 20 fps) tut speichermäßig ja auch keinem
weh, aber klar, es geht Dir um Performance. Aber Mixrate ist bei mir ja verstellbar bis auf 11 kHz runter.

Und ja, Du plädierst für größere Soundpuffer für bessere Performance, und Deine Bild-Ton-Verschiebungstoleranz liegt
bei glaube ich 200 ms, also 1/5tel Sekunde. Ist für mich eben leider nicht akzepabel wenn ich z.B. eine Explosion zuerst
nur sehe und dann erst der Ton verspätet kommt, so als wäre ich hundert Meter davon entfernt.
Es ist einfach so, ich habe einiges mit Video und Ton gemacht. Wenn es dort einen Versatz gibt, selbst nur 50 ms, dann
ist das schon ärgerlich. Und ich möchte mir für ein Spiel einfach diese Präzision ermöglichen.
Ich habe mir letztens Prince Of Persia II angesehen, da ist der Ton punktgenau. Möglicherweise weil sie Adlib verwenden
und den Digisound ohne Puffer realisieren, immer nur ein Sound gleichzeitig durch direkten "DMA Auftrag" im
Hintergrund wenn man so will.

Auch wenn ich beginne, ein variables Timing zu verstehen, werde ich erstmal, auch zugunsten des synchronen Sounds,
das ganze mit dem Interrupt des Soundpuffers timen. Hab ich ja schon oft genug gesagt. Es verschwendet Performance-
Potential, ich muss immer vom Worst-Case ausgehen, was auch dazu führen wird dass das Spiel insgesamt eher
bescheiden ausfallen wird was die Rechenleistung angeht, auch oft gesagt: Ich denke an sowas wie Captain Comic, für
das damals völlig ein 286er ausreichte, und ich würde davon ausgehen dass ein ähnlich geartetes Spiel mit etwas mehr
Framerate und höher auflösendem Scrolling, und meinen extra Features wie ZSM und ZVID auf einem 486er zu realisieren
wäre.

Das mit den Steuerungsbits könnte ich aber übernehmen, wobei da vielleicht auch einfach Boolean Variablen gehen, die
paar Byte kann man ja noch haben, hängt wohl auch davon ab wie es letztlich im Programm interpretiert wird, wenn man
alles in ein Byte packt hat es vielleicht bei Assembler Vorteile.

Danke jedenfalls für die ausführliche Darstellung, ich müsste mir solche Erklärungen mal irgendwo außerhalb des Forums
archivieren, damit ich gezielter und ohne zu suchen darauf zugreifen kann.

ZVID2: Das ist alles nur "because I can" ("...and want").
Richtig sinnvoll wäre es nur für ein Adventure wo es nicht auf Geschwindigkeit aber auf viel Speicher ankommt.
Ich schätze die Kunst, Sprites zu skalieren und zu drehen, aber ich persönlich mag die optischen Resultate meistens
nicht, eine gepixelte Grafik muss für mich ihre Konsistenz bewahren, eher würde ich für Drehungen ein paar Phasen
pixeln. Das alles vielleicht auch, weil ich mit Spielen aufgewachsen bin, in denen nicht gedreht und skaliert wurde (bis
auf manche Momente in Monkey Island z.B). Das "wilde" Skalieren, Stauchen und Drehen erfuhr ich erst bei Duke Nukem
3D, und dieses Spiel hatte für mich nicht mehr den Zauber einer homogenen Pixel-Landschaft, es war alles eher nur noch
zweckmäßig und informativ, voller Aliasing und unförmig aufgeblasenen Pixeln. Dreh- und skalierbar kann ein Segen sein,
wenn man nicht so ein hohes Bedürfnis an die "Integrität" der Pixel hat. Es ist auch eine Stilfrage - spätestens bei
Echtzeit-Vektorgrafik wie bei "Alone In The Dark" braucht man nicht mehr über Aliasing oder soetwas meckern.
Und auch verschiedene Paletten können höchst praktisch sein, das hat auch das gute alte NES ja so gemacht bei einigen
Spielen. Mich haben zu der Zeit als ich begann zu programmieren aber vor allem Adventures geprägt, wo jede Figur ganz
konkret und individuell war. Daher gehe ich so auch an eigene Spiele heran, jeder Figur, jeder Gegner, hat seine
individuellen Sprites - ich hatte also nie den Wunsch etwas anders einzufärben oder auch s.o. zu skalieren oder zu
drehen, daher habe ich mich bislang einfach nur damit beschäftigt, etwas komprimiert zu speichern, damit ich möglichst
viel Grafik bewerkstelligen kann.
Ausreichen würde für meine Zwecke in gewissem Rahmen wohl auch einfach eine RLE Kompression, aber ich bin eben
etwas verspielt. Ich glaube, Datenformate oder Kompressionen zu erfinden fasziniert mich alleine schon genug, siehe
ZSM... Ich hätte ja auch einfach einen abgespeckten MOD-Player schreiben können, aber das wäre mir zu viel sinnlos
das Rad neu erfinden gewesen.
Dein Image-Einpass-Programm nimmt in etwa die Stelle ein, die bei mir der ZVID2 Encoder hat. Natürlich eher schlecht
vergleichbar, aber vom Aufwand her könnte es in etwa hinkommen.
DOSferatu hat geschrieben:Und - so traurig das jetzt vielleicht klingt - auch Du wirst wohl Byte für Byte arbeiten müssen.
Ja, das war schlecht nachgedacht. Selbst wenn ich das bei nicht-Transparenz vielleicht so machen könnte - es bringt
nichts, erst ein 32 Bit Register mit Bytes vollzuschieben um es dann mit einem Rutsch in den Speicher zu knallen.
Das ganze trifft nur für den Fall zu, wenn ein ganzer Block einfarbig und nicht transparent ist.
Dann werde ich das so machen.
DOSferatu hat geschrieben:Ich habe schon öfter mal bereut, manches von meinem alten Zeug "zu dicht komprimiert" zu haben, so daß kein Platz für Erweiterungen mehr da war und habe mich andererseits jedes Mal gefreut, wenn ein altes Format noch Dinge "offen gelassen" hatte, so daß ich es noch weiter verwenden und erweitern konnte.
Mehr oder weniger könnte ich ZSM bereuen, es wäre schwer das Format abwärtskompatibel zu erweitern - denke ich
mal. Aber ich habe auch nicht so viele "Fans" dass das für mich wichtig wäre. Wenn ich für ein Spiel mehr Funktionen
bräuchte, würde ich eine neue Version machen, die dann eben mit dem bisherigen Player nicht mehr kompatibel wäre.
DOSferatu hat geschrieben:Wenn ich heutzutage ein Format benutze, will ich NICHT mehr (wie leider früher manchmal!) alles "um das Format", bzw. "um diese Routine herum" bauen müssen. Da finde ich es inzwischen besser, Zeug so zu machen, daß man es "nur noch einzubauen" braucht und es quasi alles, was es braucht, selbst macht, bzw. "von selbst mitbringt".
Auch deswegen jetzt ZVID2, was neben ein paar Variablen nur aus einer Prozedur bestehen wird. Mal abgesehen von
Initialisierungs-Routinen, die aber auch nur Sachen machen die man auch "zu Fuß" machen könnte. ZVID(1) war eine
ultra-komplizierte Orgie aus Prozeduren und haufenweise Pointern.
DOSferatu hat geschrieben:Naja, daß für "flächige Dinge" (wie Sprites, Rechtecke/Polygone) der fortwährende Zugriff auf eine generalisierte Pixelroutine (die jedes Mal aus Koordinaten die Pixelposition ausrechnet und für den Grafikmode entsprechend die Daten setzt für den Pixel) eine Scheißidee (weil langsam) war, habe ich schon recht schnell herausgefunden.
Ich meine nicht Punkt für Punkt, was in QuickBASIC mit PSET(x, y, color) gemacht wurde. Sondern das Grafik-PUT, man
muss auf ein Integer-Array mit einer Bitmap (für VGA 1 Byte pro Pixel) verweisen und dann die Koordinaten der oberen
linken Ecke. Was PUT macht dürfte etwa das gleiche sein wie rep stosb und das eben für mehrere Zeilen, d.h. es ist
eigentlich sehr schnell. Aber wenn man das auf einem 286er macht, mit einem 32x32 Sprite und es mit nur 1 Pixel
jeweiligen Versatz animiert, dann dauert es schon ein paar Sekunden bis das Ding über den Bildschirm gewandert ist.
Oder es war doch ziemlich schnell und ich habe es mit Sound 0, .1 ausgebremst. Ist fast 30 Jahre her...
DOSferatu hat geschrieben:Um zu merken, daß es wirklich funktioniert, reicht es nicht, zu sehen, ob die Steuerung alleine oder die Grafik alleine oder der Sound alleine funktionieren. Erst, wenn ALLES ZUSAMMEN arbeitet und immer noch funktioniert, DANN wird's ein brauchbares Spiel.
Ich bin relativ optimistisch. Ich habe ja doch ein paar Spiele und Demos programmiert, wenn auch nicht immer die
tollsten. Der Pentium 200 MMX den ich seit 1997 habe hat natürlich alles gefressen.
Das verzerrt die Erwartung an einen 486er ein wenig.
DOSferatu hat geschrieben:Daß ich JETZT so einen "Aufwand" betreibe, einen einigermaßen gescheiten "Rahmen" für Spiele zu schaffen, liegt daran, daß zum Schluß nicht bei jeder neuen Spielidee wieder von Null angefangen werden soll, im Sinne von: Wo krieg ich den ganzen Speicher her? Wie baue ich das Zeug so zusammen, daß es funktioniert ohne abzuschmieren oder rumzuruckeln? Also quasi soll dieser ganze Kram schon so "getestet und für gut befunden" sein, daß man ein Spiel drauf entwickeln kann OHNE jedes Mal komplett neue Routinen bauen zu müssen, die eigentlich das gleiche machen wie die des letzten Spiels.
Ja, da stimme ich Dir absolut zu. Wenn man sich manches klassische NES Spiel ansieht, scheint es auch so, als hätten die
immer wieder die gleiche Engine genommen. Das meine ich absolut nicht negativ, sondern es ist professionell wenn man
sich einen Standard schafft für den man Spiele designen kann. Fast so, als würde man sich dadurch Hardware erschaffen.
Ich wollte ja auch vor ein paar Jahren schon so ein Game-System schaffen, was ich dann während einer
Spieleentwicklung erweitern wollte. Ich habe da aber nicht so klare Vorstellungen wie Du, und bin ersteinmal froh dass
ich einen Sound-Standard habe, und mal sehen wie ZVID2 wird. Letzteres nimmt mir auch die Sorgen ab, wie ich Grafik
in das Spiel bekomme und dabei noch bestmöglich Speicher spare - ich muss sie nur auf den Heap laden und die Routine
mit entsprechenden Parametern aufrufen.
DOSferatu hat geschrieben:Meiner Erfahrung nach scheinen sehr viele (spätere) Coder, vor allem im 3D-Bereich, das so wie ich zu machen: Die FPS-Raten der Spiele sind variabel und hängen davon ab, wie aufwendig gerade berechnet werden muß.
Ich hab ja ne Zeit lang mit ein paar Jungs 3D Spiele gezockt. Ich habe einen Spruch im Kopf: "Framerate is God".
Kennt man vielleicht nicht, hab ich aber irgendwie mal gehört. Bei 3D Ego Shootern sind Framerates von unter 70 schon
nicht mehr tolerabel, und als die ersten LCDs gängig wurden, wurde trotzdem noch an Röhren gespielt, weil die schneller
sind. Und wir haben in 320x200 gespielt, mit Pentiums...

Ich stimme Dir absolut zu, dass das objektiv gesehen besser ist mit variabler Framerate. Für mich ist es nur großes
Neuland zusätzlich dazu dass ich ein Spiel zu bewerkstelligen hätte, und der Trade-Off wäre die Ton-Asynchronität.
Wenn also mein Spiel am Ende auch mit seinen bescheidenen 15-20 fps auf einem 486er ohne Engpässe durchläuft MIT
synchronem Ton, dann ist das für mich sehr zufriedenstellend.
Kotzman II hat technisch sehr viel mehr Rückschläge, ich hätte mir noch gewünscht:
- Sprachausgabe (gescheitert an Unfähigkeit die Soundblasterkarte zu programmieren)
- Musik während der Levels (gescheitert daran, dass ich die Adlib-Kanäle für die Soundeffekte brauchte)
- transparente Sprites (ich konnte kein ASM, geschweige denn innerhalb BASIC)
- jedes Level braucht seine eigene .EXE (in Ermangelung von Heap)
- für die Animationen am Ende eines Levels musste ich mir eine Scriptsprache erfinden, weil die Basic-Befehle nicht
mehr ins Programm passten
Es ist alles sehr improvisiert. Angefangen hat das mit dem Level mit diesem komischen Ding, ich fand es später einfach
so dumm nur Schlüssel zu sammeln und durch ein Labyrinth zu hopsen, dass ich einen Save-State eingebracht habe um
es zu überspringen. Rausnehmen wollte ich es aber auch nicht, weil sonst die Story kaputt gewesen wäre bzw. subjektiv
nimmt man nicht gerne etwas weg woran man länger gesessen hat.
Jedenfalls habe ich unheimlich etwas nachzuholen, wenn ich noch einmal ein Spiel machen werde. Digitaler Sound ist
und war immer etwas das mich fasziniert hat, vielleicht auch weil er bis Anfang/Mitte der 90er so spärlich eingesetzt
wurde.
DOSferatu hat geschrieben:Ich muß aber auch dazu sagen, daß oft mit viel größerer Farbtiefe gearbeitet wird als überhaupt nötig.
Gebe ich Dir absolut recht, dass für Sprites 8 Bit indizierte Palette dick ausreicht, es sei denn die Sprites sind
fotorealistisch und bildschirmfüllend. Es gibt aber einen Bereich, wo man nie genug Farbtiefe haben kann:
Beispielsweise bei der Digitalisierung von Dias. Wenn man da "nur" 24 Bit hat, und ein stark unterbelichtetes Dia,
kann es passieren dass beim Aufhellen Artefakte auftreten, quasi Treppenstufen, weil sich die Helligkeitswerte nur noch
um ein paar Bit drehen. Das ist auch im Audio-Bereich so. Man arbeitet am besten bei der Bearbeitung mit 32 Bit
Floating Point, um es dann am Ende, quasi für den Verbraucher, auf 16 Bit herunterzurechnen, nachdem man es gut
ausgesteuert hat. Unsere Ohren sind offenbar weitaus dynamischer als die Augen: 8 Bit pro Farbkanal reichen
für "True Color", aber 8 Bit für Ton sind mehr schlecht als recht, zumindest aus HiFi-Sicht.

Ja, Max Headroom... Headroom ist auch ein Begriff aus der Audiotechnik, und bei 32 Bit Float hat man praktisch beliebig
viel davon. Das ist auch ein Grund warum man 32 Bit nimmt während der Bearbeitung.


PS: Wird mein Text eigentlich wirr umgebrochen weil ich den Zeilenumbruch selbst mache?
Soll ich das lieber demnächst sein lassen?
mov ax, 13h
int 10h

while vorne_frei do vor;
drzeissler
DOS-Gott
Beiträge: 3336
Registriert: Mo 8. Feb 2010, 16:59

Re: Eigenes Videoformat

Beitrag von drzeissler »

CPU: 486 DX2/66 MOBO: SNI-D882 RAM: 3x16MB - FDD: 3,5" 1,44MB HDD: 6,4GB Seagate ISA(1): Audican32Plus PCI(1): 3com TX 905 OS: MsDos622 - Win95a - WinNT 3.51
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Eigenes Videoformat

Beitrag von DOSferatu »

zatzen hat geschrieben:
drzeissler hat geschrieben:Bei YT gibt es einen, der ein FullscreenVideo mit Ton (Beavis&Butthead) auf einem 286/8 oder 10Mhz in VGA laufen lässt. Sowas wäre mal echt interessant. Das wäre ein cooles Feature für ein A2286/8.
Das wäre wirklich mal interessant zu sehen. Ich konnte es leider auf Youtube nicht finden. Gibt so viele Videos... Und Zusätze wie 286 oder vintage helfen auch nicht.
Zum Glück hat drzeissler den Link noch dreingeschrieben.
zatzen hat geschrieben:Oder man macht Qualitäteinbußen und verwendet eine generalisierte Palette mit 256 festfarben, dann wäre auch Delta-Kodierung denkbar.
Naja - nun ist Beavis and Butt-Head ja klassischer Zeichentrick - was bedeutet: Framerate ist sowieso sehr niedrig und Farbanzahl könnte man hier herunterdampfen.
zatzen hat geschrieben:Für's erste backe ich kleine Brötchen. D.h. die Grafik wird am Ende vielleicht keine 100 KB füllen (zumindest während eines Levels), und mit Nutzung von ZVID2 fast nur die Hälfte davon. Zurückblickend auf Kotzman II war der Programmcode auch nicht so sonderlich groß, naja es ist 24 Jahre her und ich kann mich auch nicht mehr so exakt dran erinnern.
Kommt eben immer drauf an, was für ein Spiel man machen will - und auch WIE. Wie 8-Bit-Guy gezeigt hat, kann man auch ein Spiel für einen XT (4,77 Mhz) komplett in Assembler als monolithisches Teil zusammenbauen. Das "andere Ende" ist, einen generalisierten "Game-Maker" zu benutzen. Und alles, was dazwischenliegt, ist ebenfalls möglich.

Ich persönlich habe mich dazu entschieden, über längere Zeit wiederverwendbare Routinen zu bauen, um meine arg begrenzte Zeit und Energie nicht dazu benutzen zu müssen "immer wieder das Gleiche" zu programmieren (was ich in meinem Leben leider schon oft genug getan habe). Aber persönliche Entscheidungen meinerseits sind natürlich nicht das Maß irgendwelcher Dinge. Inzwischen zweifle ich auch daran, ob ich noch jemals dazu kommen werde, eine meiner Spielideen in ein fertiges Produkt zu gießen. Das mag aber auch daran liegen, daß in den letzten Wochen mein Elan mal wieder einen Tiefpunkt erreicht hat. Das kann sich auch wieder ändern - der Herbst kommt, die Temperaturen sind endlich nicht mehr unerträglich... so etwas kann schon helfen.
zatzen hat geschrieben:Und ich bin kein "Pro", habe keinen Wettbewerb zu gewinnen, daher kann ich einfach mal nach Lust und Laune loslegen und ein Spiel machen das vielleicht etwas sonderbar ist.
Wenn ich denn mal loslege. Ich habe in letzter Zeit mal wieder ein wenig gepixelt und merke dass ich das noch ganz gut kann, vielleicht sogar besser als früher.
Aber es kommt noch das Prokrastinieren dazu, und ich bin auch mehr abgelenkt als zu Kotzman II Zeiten, weil ich mehr Hobbys habe als damals.
Naja, bei mir liegt die Prokrastination eher daran, daß mir derzeit etwas die Freude fehlt. Ich möchte - nach all der Mühe, die ich mir mit den Puzzleteilen für meine Spielengine(s) gegeben habe - jetzt nicht irgendeinen uninspirierten Mist zusammenmurksen.
zatzen hat geschrieben:Einerseits hast Du Recht, und ich habe auch schon überlegt ob ich alles was nicht animiert ist, also soetwas wie Kachelelemente, als simple Bitmaps im Speicher halte und mit einfachen Kopierroutinen in den Puffer haue. Aber ich finde man muss erstmal sehen wie die Kompression performt.
Klar.
zatzen hat geschrieben:...STOSB...
Wie Du schreibst, der Nutzen ergibt sich erst ab einer bestimmten Datenmenge.
Naja, die ganzen MOVSx, LODSx, STOSx sind ja hauptsächlich dazu da, diese Kopierfunktionen zu benutzen (mit REP...). Bei allem, was sowieso "einzeln" passiert, muß man eben "Takte zählen", um zu sehen, ob sich's lohnt. Der kleine Nachteil für mich ist ja immer, daß das Zielregister nicht variabel ist (sondern standardmäßig ES sein muß) und es auch immer nur mit SI/DI funktioniert. Das ist nur dann gut, wenn man diese Register nicht andauernd auch woanders braucht.
Außerdem benutze ich z.B. gern BX, weil das im Gegensatz zu BP/SI/DI "teilbar" ist (in BL/BH) und man dadurch verschiedene andere schicke Tricks anwenden kann.
zatzen hat geschrieben:Ich werde auch erst einmal versuchen, alle Sprites mit derselben Routine darzustellen, nämlich ZVID2.
Diese enthält praktischerweise ein solides blockweises Clipping, man braucht sich letztlich gar nicht mehr drum kümmern wo das Sprite auf dem Bildschirm landet, egal ob links, rechts unten oder oben raus oder in einer Ecke, oder ob es überhaupt noch im sichtbaren Bereich ist, das kann die Routine alles sicher abfangen. Für mich ein kleines Novum. Ich muss nur ringsherum den Puffer 3 Pixel größer machen als das letztlich sichtbare Bild.
Dem entnehme ich, daß die Spriteroutine beim Entpacken 4x4-kachelweise abfragt, ob sich die nächste Kachel innerhalb des sichtbaren Bildausschnitts befindet?

Meine Spriteroutine berechnet vorher die Grenzen (d.h. ein - evtl gedrehtes - "Rechteck") und zeichnet dann nur diesen Bereich - mit entsprechenden "Abschnittkanten" an den Seiten, falls es sich am Rand befindet.

Wenn ich HEUTE eine Spriteroutine programmieren würde (meine sind von 2004), würde ich aber vieles wesentlich eleganter machen. Außerdem würde der geringfügige Pascal-Anteil aus den Routinen verschwinden. Aber ich zwinge mich, das seinzulassen, damit ich endlich mal irgendwann mit einem Spiel anfange.
zatzen hat geschrieben:An dieser Stelle wäre noch gut zu wissen um einen Sprung sparen zu können, wenn Du es gerade aus dem Ärmel schütteln kannst: Mit welchen Assembler-Befehlen kann ich eine Pascal-ASM-Prozedur verlassen?
Oder ist das unklar weil man letztlich nicht sagen kann ob RET oder RETF nötig ist?
Man kann IMMER sagen, ob RET oder RETF nötig ist, weil eine Routine nur ENTWEDER near ODER far compiliert wird, denn danach wird ja entschieden, welchen Return der Compiler selbst ans Ende setzt. Mit Compilerschaltern - oder den Begriffen near; oder far; (nach dem Header) kann man das auch festlegen. In Units wird meines Wissens immer FAR benutzt (kann mich irren) - weil ja die Routinen von überall aufrufbar sein müssen. Könnte aber auch sein, daß es eine Einstellung gibt, die, wenn der Code insgesamt <64kB wird, automatisch alles NEAR setzt.
"Einfachste" Möglichkeit, das im Zweifel rauszufinden: An das Ende der Routine vor das END; schreiben: asm db "Beispiel";end; (also irgendeinen String).
Dieses Programm dann NICHT ausführen! Sondern nur compilieren und dann die EXE mit einem Hex-Editor ansehen und nach dem "Beispiel" suchen und allem, was danach kommt.

ACHTUNG! Sollte die Routine ein sogenanntes "Stack-Frame" einrichten (was immer passiert, wenn man entweder Parameter im Header übergibt ODER Variablen in der Routine deklariert ODER beides) dann muß: 1. am Ende vor dem RET (bzw RETF) noch ein LEAVE stehen und außerdem muß man ein spezielles Return benutzen, nämlich das, bei dem man noch einen Wert danach angeben kann. (Der Wert ist die Anzahl Bytes, die alle Dinge, die man im Header übergeben hat, zusammen brauchen - wobei Byte-Variablen trotzdem 2 Bytes brauchen.)

Wenn man nicht genau weiß, was man tut, ist es hier wohl besser, das obengenannte (mit dem String) zu machen und dann das, was der Hex-Editor bis zum Return bzw Return+Rückgabebytes da hat, 1zu1 auch so zu machen.

Eine andere Möglichkeit ist, einfach ans Ende der Routine zu springen und den normalen Returnprozeß der Routine ausführen zu lassen.
zatzen hat geschrieben:Zeichnen/Löschen Methode, nur wenn sich etwas geändert hat: [...]
Naja, es kommt immer auf den "Trade-Off" an, was man da spart. Wenn die Routine, die das prüft und auswertet, am Ende komplizierter ist (und damit mehr Zeit braucht) als "stupides Kopieren", dann bringt die Mühe nichts. Aber Ausprobieren schadet ja nichts.

Da meine Spiele sowieso auf Scrolling ausgelegt sein werden, habe ich selbst dergleichen noch nie in Erwägung gezogen. Und da ich ja Mode-X (bzw auch Mode-Y) benutze, arbeite ich auch bei Grafik mit Mehrfach-Buffering (3fach/4fach), d.h. ich schreibe immer direkt in den Grafikspeicher, also ohne vorher im Heap-RAM zu puffern. Nachteil bei mir ist, daß ich dadurch einige Pixel mehrfach in die Grafikkarte schreibe (Hintergrund und darüberliegende Sprites), was bei RAM-Puffer nicht passieren würde (da schreibt man nur genauso viele Pixel in die Grafikkarte, wie die Größe des Bildes ist und kann zusätzlich auch mit 32bit-Transfer arbeiten). Dafür schreibe ich nicht in RAM und dann nochmal in die Grafikkarte (und brauche keinen RAM-Puffer). Was nun am Ende besser ist... - ich würde sagen: Kommt drauf an. Hängt auch etwas von der Hardware ab.
zatzen hat geschrieben:
DOSferatu hat geschrieben:Naja, mit 44100 Hz müssen aber doppelt so viele Daten pro Sekunde berechnet werden als mit 22050 Hz - das sollte doch klar sein, oder? Also auch doppelt so viele pro Frame.
Ja, das stimmt. Ich bezog das nur irgendwie auf den Speicherbedarf für die Sounddaten. Und da kann man ja auch einfach 8 kHz in 44.1 kHz reinmischen. Und ein 2 KB Puffer (ca. 44100 Hz bei 20 fps) tut speichermäßig ja auch keinem weh, aber klar, es geht Dir um Performance. Aber Mixrate ist bei mir ja verstellbar bis auf 11 kHz runter.
Naja, Performance hin oder her - mir geht es vor allem darum, daß "alles zusammen" noch funktionieren kann, ohne daß der Sound stottert oder Eingaben des Spielers "verlorengehen". Beides wäre beim Spielen echt ... doof.

Dazu nochmal die Frage: Wenn der IRQ signalisiert: Daten alle/abgespielt und zum neuen Puffer wechselt, WO generierst Du dann die Daten für den alten (nächsten) Puffer? Direkt in der IRQ-Routine oder setzt Du nur ein Flag und generierst in der Hauptschleife (außerhalb des Interrupts)?
zatzen hat geschrieben:Und ja, Du plädierst für größere Soundpuffer für bessere Performance, und Deine Bild-Ton-Verschiebungstoleranz liegt bei glaube ich 200 ms, also 1/5tel Sekunde. Ist für mich eben leider nicht akzepabel wenn ich z.B. eine Explosion zuerst nur sehe und dann erst der Ton verspätet kommt, so als wäre ich hundert Meter davon entfernt.
Bisher habe ich noch nie alles zusammen in Funktion erlebt, wie es am Ende wird, muß ich erstmal sehen.

Nur, wie ich schon mal bemerkt habe: Wenn man am "einen Ende" (Sound) immer genauer dreht, wird es am "anderen Ende" (Grafik) immer ungenauer und umgekehrt. Das ist wie die berühmte Unschärferelation (je genauer man mißt, wo man sich befindet, umso ungenauer kann man seine Geschwindigkeit messen - und umgekehrt).

Will sagen: Wenn man sehr kurze Soundpuffer hat, muß man sehr oft die Routine aufrufen, die den Puffer füllt, braucht also dafür Performance. Wenn man Performance braucht, hat man weniger Performance für den Refresh der Grafik übrig. Wenn die Grafik geringe Framerate hat, dann stellt sich die Frage: Wenn der Sound "synchron" zur Grafilk sein soll, die Grafik dann aber nur 5 FPS hat - zu WAS soll der Sound dann synchron sein? Da würde dann eine 200ms-Synchronität ausreichen, weil öfter ändert sich das Bild ja nicht. Andererseits, wenn man, für volle Framerate die Soundpuffer zu groß macht, so daß der Puffer vielleicht eine Viertelsekunde faßt, dann werden nur alle Viertelsekunde neue Soundeffekte in den Puffer einberechnet und der Knall (oder was auch immer) hat auf der Grafik schon stattgefunden und dann wird der Effekt erst eincodiert - und dann erst im NÄCHSTEN Soundframe ausgeführt (also dann im Worst Case erst eine HALBE Sekunde später als es grafisch zu sehen ist. - Wäre genau so blöd.

Also ist hier der Mittelweg wieder die beste Methode. Die "Besonderheit" des PC ist ja - zumindest bei Digitalsound - daß Sound nie sofort ausgegeben wird, wenn er erzeugt wird, sondern erst in einen Puffer gelegt wird und erst wenn dieser voll ist (und der andere Puffer abgespielt ist) der Sound gespielt wird.

Da stellt sich nun also für mich die Frage, ob/wann ich die Routine aufrufe, die Sound generiert. Bei mir ist es ja so, daß die Berechnung der Grafikanzeige z.B. nichts mit der Steuerung zu tun hat (wird beides nacheinander ausgeführt in der Hauptschleife). Der Plan sah auch vor, daß der Aufruf der Soundgenerator-Routine (ISM) auch in der Hauptschleife erfolgt - und zwar immer dann, wenn der Soundkarten-IRQ ein Flag gesetzt hat (für Puffer leer).

Aber vielleicht ist das die falsche Methode? Bisher habe ich noch nie Spiele mit Digital-Soundeffekten gemacht. Bei Musik wäre es ja egal, die muß in einem Spiel nicht framesynchron zur Grafik sein (und bei einem Film würde man den Zeitversatz einfach mit einplanen). Das ist ja das Problem: Bei einem Spiel kann man den Zeitversatz des Sounds (der durch das Doublebuffering entsteht) nicht voraussehen, weil man ja nicht vorher wissen/planen kann, was der Spieler macht. Da fragt man sich, wie das andere Leute machen.

Wieso ich nicht allzu kleine Puffer will, liegt nur daran, daß noch dazwischen genügend Zeit bleiben muß für den Rest (Grafik, Steuerung) und nicht der (kleine) Soundpuffer schon ZWEIMAL leer ist, bevor man EINMAL die Grafik gezeichnet hat und somit der Sound zu stottern anfinge.

Daher die Frage, ob Du den Soundgenerator im IRQ startest (d.h. zum Neugenerieren des Sounds die Grafik-/Steuerroutinen unterbrichst und das Generieren direkt im Interrupt machst).
zatzen hat geschrieben:Es ist einfach so, ich habe einiges mit Video und Ton gemacht. Wenn es dort einen Versatz gibt, selbst nur 50 ms, dann ist das schon ärgerlich. Und ich möchte mir für ein Spiel einfach diese Präzision ermöglichen.
Ja, wie gesagt, ist es nur (im Gegensatz zu einem Film) schwer, bei etwas Interaktivem (wie einem Spiel), "vorauszusagen", welcher Sound kommen muß, weil das ja davon anhängt, was der Spieler macht. Wenn der Spieler etwas drückt, was im Ergebnis einen bestimmten Sound auslösen würde, muß das ja erst die Steuerroutine durchlaufen, die dann den entsprechenden "hier Sound X abspielen" Befehl in einen Puffer schreibt, damit bei der nächsten Puffergenerierung dies berücksichtigt werden kann - und der Puffer, der diesen Sound enthält wird dann beim übernächsten Mal (nachdem der gerade aktuelle Puffer abgespielt ist), abgespielt.

Das würde zwar für kurze Puffer sprechen - die z.B. auch zur Not so kurz sind, daß sie im Zweifelsfall mehrmals die Grafik- oder Steuerroutine unterbrechen könnten... - ABER: Dabei muß man beachten, daß, während das System im Hauptprogramm die Grafik zeichnet, sowieso keine NEUEN Sounds dazukommen, weil die Grafikroutine keine neuen Sounds aufruft/triggert... Während das System also damit beschäftigt ist, die Grafik zu bauen (und deshalb derzeit keine Steuerung oder andere Dinge ausführt), kommen auch keine NEUEN Sounds dazu...

Alles Dinge, über die ich mir schon so meine Gedanken gemacht habe... Es muß am Ende eine in sich konsistente Hauptschleife entstehen, die nicht sinnloserweise Unterbrechungen für eine "Pseudo-Genauigkeit" erzeugt, die am Ende nur Performance kostet und nichts erreicht.
zatzen hat geschrieben:Ich habe mir letztens Prince Of Persia II angesehen, da ist der Ton punktgenau. Möglicherweise weil sie Adlib verwenden und den Digisound ohne Puffer realisieren, immer nur ein Sound gleichzeitig durch direkten "DMA Auftrag" im Hintergrund wenn man so will.
Genau deswegen. Und aus meiner Erinnerung heraus muß ich sagen, daß ich den Sound in PoP NICHT 100% synchron empfunden habe (die Schritte, das Trinken, die Schwertschläge)
zatzen hat geschrieben:Auch wenn ich beginne, ein variables Timing zu verstehen, werde ich erstmal, auch zugunsten des synchronen Sounds, das ganze mit dem Interrupt des Soundpuffers timen. Hab ich ja schon oft genug gesagt. Es verschwendet Performance-Potential, ich muss immer vom Worst-Case ausgehen, was auch dazu führen wird dass das Spiel insgesamt eher bescheiden ausfallen wird was die Rechenleistung angeht, auch oft gesagt: Ich denke an sowas wie Captain Comic, für das damals völlig ein 286er ausreichte, und ich würde davon ausgehen dass ein ähnlich geartetes Spiel mit etwas mehr Framerate und höher auflösendem Scrolling, und meinen extra Features wie ZSM und ZVID auf einem 486er zu realisieren wäre.
Schauen wir mal. Bei dem Zeug, das ich so da habe, bin ich mir nicht sicher, wie das am Ende insgesamt performen wird - hängt ja von sehr vielen Faktoren ab. Ich befürchte, daß der Riesenklotz von Routinen, die ich hier mitschleppe für Grafik, Sound, Steuerung und "das Leben, das Universum und den ganzen Rest"[tm] am Ende insgesamt die Performance killen wird und am Ende alles unspielbar werden wird. Wie ich ja bereits mal sagte: Nur weil irgend ein "Einzelteil" gut funktioniert (und performt), muß das nicht heißen, daß alle Teile zusammen das auch tun.

Du - als jemand aus der Sound-Ecke - scheinst bei der Spiele-Entwicklung/-planung ziemlich auf den Sound-Anteil fixiert zu sein. Will sagen: Wenn die Grafik klotzig oder ruckelig wird oder in einem verkleinerten Fenster dargestellt werden muß oder das Gameplay eventuell zu "simpel" zu werden könnte, das scheint für Dich alles kein Problem zu sein - solange der Sound dabei in hoher Qualität und Synchronität daherkommt. (Kann ich nicht mit Sicherheit sagen - wirkt aber subjektiv auf mich oft so.)

Ich bin mir nicht sicher, ob das ein geeigneter Ansatz ist, ein Spiel zu entwickeln - andererseits habe ich selbst noch kein wirklich gescheites Spiel gebaut und ich kenne auch keinen der "Großen", die sogar mal so gute Spiele gemacht haben, daß man sie verkaufen (statt nur verschenken) konnte - will sagen: Ich beurteile das auch nur aus meiner reinen Amateur-/Hobby-Schiene.

Wie ich schon öfters erwähnte: Wenn ein Spiel nur 10 FPS hat, dann braucht schon aus rein logischer Sicht die Soundgenauigkeit nicht höher als 100 ms sein und selbst bei knapp 200 ms würde man maximal 1 Grafikframe verpassen. (Soviel zur "Synchronität"...) Außerdem kann der Soundgenerator erst dann "wissen", welchen Effekt er reinmixen soll, wenn das Steuerung das aktiviert hat - und die Steuerung kann das erst wissen, wenn das Spiel weitergelaufen ist und dieser Weiterlauf ist ja kein vorberechneter "Film", sondern ein interaktives Spiel - und hängt ständig von der Eingabe des Spielers ab. Somit ist also jede Reaktion aufeinander immer verzögert.

ABER: Auch der Grafikgenerator (d.h. die Routine, die das Grafikframe erzeugt), hat ja das gleiche "Problem": Auch diese kann erst "wissen", was sie darstellen soll, wenn die Steuerung (die "Spielsituation") vorhanden ist und wird erst angezeigt, nachdem die letzte (vorhergehende) Grafik generiert wurde. Auch dann, wenn man kein eigentliches "Double-Buffering" bei der Grafik macht (wie ich, der dafür direkt in verschiedene "Seiten" des Grafikspeichers schreibt), ist das Generieren der Grafik in einem RAM-Puffer und anschließendes Kopieren in den Grafikspeicher ebenfalls eine Art von "Double-Buffering" mit ähnlicher Wirkweise - und in beiden Fällen dient es dazu, den Spieler nicht den "Zwischen-Aufbau" der Grafik sehen zu lassen, damit es wie eine Bewegung aussieht. Also: Verzögerung auch bei der Grafik.

Was ich damit sagen will, ist, daß sowohl der Sound, als auch die Grafik verzögert ausgegeben werden im Verhältnis zur Spielsituation. Und, wie Mr. Spock sagen würde: "Das ist nur logisch." - denn die Wirkung kann zeitlich nie VOR der Ursache liegen.

Also muß man aufpassen, daß man nicht das ganze Spiel "um die Grafik herum" oder "um den Sound herum" programmiert - denn, wenn man einem Aspekt zu viel Rechenzeit zuteilt, wird alles andere dadurch ausgebremst. (Und übrigens: Speziell die Spiel-STEUERUNG sollte NIE ausgebremst werden - so ein "hakeliges" Spiel würde keiner spielen wollen.)
zatzen hat geschrieben:Das mit den Steuerungsbits könnte ich aber übernehmen, wobei da vielleicht auch einfach Boolean Variablen gehen, die paar Byte kann man ja noch haben, hängt wohl auch davon ab wie es letztlich im Programm interpretiert wird, wenn man alles in ein Byte packt hat es vielleicht bei Assembler Vorteile.
Ja, wie gesagt, ICH hatte mich für Bitmuster entschieden - einfach, weil es mehr als 8, 16, 24 oder 32 (was schon mächtig übertrieben wäre) verschiedene "Tasten"/Steuerelemente wohl nicht in einem Spiel geben wird - und vor allem, weil man dadurch die Steuerbitmuster (z.B. Bytes oer Words) in einen Ringpuffer legen kann, so daß für jeden "Tick" ein Steuerbitmuster vorliegt und man damit eventuelle Unsynchronität ausgleichen kann. Grund: Während Grafik/Sound generiert werden, arbeiten ja die Steuerroutinen gerade nicht. Sollte eines davon zu lange dauern (und deshalb die Steuerroutine mehrmals aufgerufen werden müssen, um wieder zeitlich "hinterherzukommen", sollten auch genauso viele Bitmuster zur Verfügung stehen.

Natürlich könnte man auch OHNE Ringpuffer arbeiten und immer nur ein "allgemeines Bitmuster" irgendwo ablegen (oder eben Boolean-Array) - aber dann entspricht die Genauigkeit der Steuerung nur maximal der Framerate der Grafik und kurze Tastendrücke werden eventuell nicht mehr berücksichtigt. (Erklärung: Wenn Generieren von Sound und/oder Grafik mal etwas länger dauert und der Spieler in dieser Zeit eine Taste drückt UND losläßt, wird das "Tasten-Bit" zwischenzeitlich auf 1 und gleich wieder auf 0 gesetzt und für die Steuerroutine sähe es aus, als wäre gar nichts passiert.)
zatzen hat geschrieben:Danke jedenfalls für die ausführliche Darstellung, ich müsste mir solche Erklärungen mal irgendwo außerhalb des Forums archivieren, damit ich gezielter und ohne zu suchen darauf zugreifen kann.
Naja, ich bin auch kein Experte; und ich weiß auch nicht, wie es die wirklichen Experten machen. Ich gebe nur meine Erfahrungen wider, die ich selbst über die Jahre/Jahrzehnte gesammelt habe und Vorgehensweisen, die bei mir funktioniert haben. Und wenn es funktioniert, kann es ja nicht so falsch sein.
zatzen hat geschrieben:ZVID2: Das ist alles nur "because I can" ("...and want").
Richtig sinnvoll wäre es nur für ein Adventure wo es nicht auf Geschwindigkeit aber auf viel Speicher ankommt. Ich schätze die Kunst, Sprites zu skalieren und zu drehen, aber ich persönlich mag die optischen Resultate meistens nicht, eine gepixelte Grafik muss für mich ihre Konsistenz bewahren, eher würde ich für Drehungen ein paar Phasen pixeln. Das alles vielleicht auch, weil ich mit Spielen aufgewachsen bin, in denen nicht gedreht und skaliert wurde (bis auf manche Momente in Monkey Island z.B).
Ja, kennt man. Die "alten" Spiele (auf alten Konsolen usw.) hatten noch kein Drehen/Skalieren, weil es hardwaremäßig nicht möglich war (und softwaremäßig nicht performt hätte) und diese hatten sogar für 90° Drehungen vorgepixelte/vorgedrehte Sprites. (Wobei bei Drehungen um 90°/180°/270° ja nichts verlorengehen würde.) Ich muß aber sagen, daß ich bei Drehungen um 45° oder 22,5° (Viertel/Achtel) selbst auch nicht viel besser pixeln könnte, als es meine Drehroutinen automatisch machen. Was man bei skalierbaren/drehbaren Sprites generell vermeiden solllte, ist, Farbübergänge selbst zu dither-pixeln. Geditherte Flächen zu drehen sieht nicht gut aus, da entstehen üble Moiré-Effekte. Allerdings geben Sprites, die für Auflösungen von 320x200 und so zwischen 4 und 32 Farben sowieso nicht viel Möglichkeit des Ditherns her, ohne daß es (selbst ungedreht) schon nicht mehr gut aussieht.
zatzen hat geschrieben:Das "wilde" Skalieren, Stauchen und Drehen erfuhr ich erst bei Duke Nukem 3D, und dieses Spiel hatte für mich nicht mehr den Zauber einer homogenen Pixel-Landschaft, es war alles eher nur noch zweckmäßig und informativ, voller Aliasing und unförmig aufgeblasenen Pixeln.
Ja, das bringt die 3D-Geschichte so mit sich - es muß ja quasi ALLES skaliert/gezerrt werden, damit es optisch paßt. Allerdings ist es nun auch so, daß sehr naheliegende Objekte eben dadurch vergrößerte Pixel bekamen. Der Grund ist ganz einfach: Die Größe der Texturen war begrenzt - so ein DOS-Rechner hatte nicht gigabyte-weise Speicher. Wenn man alles bei 50 cm Abstand zum Spieler immer noch "vollgepixelt" (ohne Vergrößerung) hätte haben wollen, hätte man riesige Texturen gebraucht.

Heutzutage wird dem durch Anti-Aliasing und Bump-Mapping entgegengewirkt UND größere Texturen - allerdings erfordert das WESENTLICH mehr Rechenleistung als so ein 486er aufbringen kann und diese Rechenleistung wird selbst auf "modernen" Rechnern nicht von der CPU erbracht, sondern von der GPU in der Grafikkarte.

Nur: Einerseits höchste grafische Qualität wollen - ohne eventuelle "Artefakte" vom Drehen oder Skalieren - andererseits aber zufrieden sein mit ruckeligen 8-10 FPS, evtl. verkleinertem Bildausschnitt und 16-Farb-Grafik... das paßt alles irgendwie nicht zusammen. Einerseits wenig Grafikspeicher wollen und alles zusammenpacken, damit viel Platz für Samples bleibt, andererseits auch gedrehte Phasen einzeln pixeln, was wieder mehr Platz braucht... - Es geht eben nicht alles gleichzeitig.

Ich habe mich längst damit abgefunden, daß ich mit den technischen Mitteln, meinen Fähigkeiten und meiner Zeit niemals das "Spiel des Jahrhunderts" erschaffen können werde - da bin ich froh, mir ein paar Mittel geschaffen zu haben, die einen Teil der Dinge "automatisieren".
zatzen hat geschrieben:Dreh- und skalierbar kann ein Segen sein, wenn man nicht so ein hohes Bedürfnis an die "Integrität" der Pixel hat. Es ist auch eine Stilfrage - spätestens bei Echtzeit-Vektorgrafik wie bei "Alone In The Dark" braucht man nicht mehr über Aliasing oder soetwas meckern.
Meine Routinen haben übrigens eine Option, automatisch zu dithern (NACH dem Drehen/Skalieren!). Weiß nicht, ob Du schon gesehen hast, wie das aussieht, aber vielleicht würde Dir das sogar gefallen. Und das Dither ist nicht nur so 2-stufig (also nur "Schachbrett"), sondern ineinander übergehendes 16-stufiges Dither, d.h. erst ab einer Vergrößerung um über 16-fach gibt es gleiche "Ditherfläche", die man also erst ab mindestens 32-facher Vergrößerung auch optisch wahrnimmt (und so sehr vergrößert man bei 320er Auflösung ohnehin nicht).

D.h. auf Wunsch sieht die Drehung/Skalierung bei mir NICHT aus wie "quadratische Pixelflächen", sondern wie geditherte Übergänge.
zatzen hat geschrieben:Und auch verschiedene Paletten können höchst praktisch sein, das hat auch das gute alte NES ja so gemacht bei einigen Spielen. Mich haben zu der Zeit als ich begann zu programmieren aber vor allem Adventures geprägt, wo jede Figur ganz konkret und individuell war. Daher gehe ich so auch an eigene Spiele heran, jeder Figur, jeder Gegner, hat seine
individuellen Sprites - ich hatte also nie den Wunsch etwas anders einzufärben oder auch s.o. zu skalieren oder zu drehen, daher habe ich mich bislang einfach nur damit beschäftigt, etwas komprimiert zu speichern, damit ich möglichst viel Grafik bewerkstelligen kann.
Ja, die "möglichst viel Grafik" muß auch erstmal jemand pixeln. Und, daß z.B. bei Super Mario die verschiedenfarbigen "Schildkröten" oder "Pilze" alle offenbar das gleiche Spritemuster, nur mit unterschiedlicher Palette haben, finde ich jetzt nicht so störend.

OK - klar könnte man auch jede Figur einzeln pixeln, selbst welche der gleichen "Art", damit die sogar unterschiedliche Gesichter haben... Wäre nett - nur verliert man sich da in Kleinigkeiten, die dem Spieler kaum auffallen werden oder kaum das Erlebnis erhöhen werden, nur weil's keine 2 Figuren gibt, die gleich aussiehen. Wenn man auf 320er Auflösung arbeitet, ergeben sich ohnehin nicht unheimlich viele Möglichkeiten, einer Figur z.B. noch ausreichend "Gesicht" und "Mimik" zu verpassen. - Ist eben meine Meinung dazu.

Ich bin kein Superexperte und kann daher keine Schachcomputer-mäßige KI zustandebringen - daher muß ein Spiel, um herausfordernd zu sein, auch mal mit einer größeren Anzahl Gegner aufwarten können. Aber die pixle ich dann sicher NICHT alle einzeln. Es geht ja auch nicht NUR darum, ob Grafikspeicher gespart wird oder nicht, sondern auch darum, ein Spiel mal in endlicher Zeit fertigzubekommen. Das bedeutet nicht, ob man zu faul wäre, so viel zu pixeln - sondern eher, ob es die Mühe auch wert wäre; aber das muß natürlich auch jeder selbst wissen.
zatzen hat geschrieben:Ausreichen würde für meine Zwecke in gewissem Rahmen wohl auch einfach eine RLE Kompression, aber ich bin eben etwas verspielt. Ich glaube, Datenformate oder Kompressionen zu erfinden fasziniert mich alleine schon genug, siehe ZSM... Ich hätte ja auch einfach einen abgespeckten MOD-Player schreiben können, aber das wäre mir zu viel sinnlos
das Rad neu erfinden gewesen.
Naja, ich habe ja, wie erwähnt, auch schon eine Menge Formate entwickelt - bei mir ergab sich das aber immer eher "aus der Notwendigkeit heraus", nicht nur, "weil ich gern ein Format entwickeln wollte". Bei mir war es auch immer so, daß ich nicht etwas (Format/Protokoll)
entwickelt habe, nur um irgend etwas "um das Format herum" zu bauen, damit das Format "seine Daseinsberechtigung hat", sondern eher immer umgekehrt: Daß ich etwas machen wollte und daher überlegt habe, was ich brauche.

Bei Xpyderz wurde irgendwann der "Sprite-Speicher" knapp und gleichzeitig ergab sich, daß sowieso alle "Elemente" (Hintergrundkacheln, Sprites) kaum mehr als knapp 16 Farben haben - also entstand die Idee, statt verschwenderischem 8bit einfach auf 4bit mit Paletten zu wechseln UND Figuren mit gleichem Image, die nur unterschiedliche Farben haben (z.B. Spinnen) zusammenzufassen - et voilà: über 50% Speicherersparnis ohne Einschränkungen an der bisherigen Grafik und trotzdem wahlfreier Pixelzugriff, Drehbarkeit, Skalierbarkeit beibehalten. D.h. die neuen Routinen wurden entwickelt, um ein bestehendes Problem zu lösen.

GameSys2 ist aus einem ähnlichen Grund entstanden: Irgendwann ist mir aufgefallen, daß ich für Steuerung der Figuren immer wieder gleichen/ähnlichen Code benutze und den Speicher damit vollknalle, ebenfalls die ganze Geschichte mit den Kollisionsabfragen usw., obwohl sich die Bewegungen hauptsächlich nur von Geschwindigkeit, Anzahl Hitpoints usw. unterscheiden. Gleichzeitig hatte ich für die Figuren große homogene Arrays angelegt, obwohl manche Figurentypen gar nicht alle Werte brauchten (also sinnlose Nullen im Speicher) und andere Figurentypen versucht haben, mit den paar Werten auszukommen und am liebsten noch mehr gehabt hätten (was bei den Figuren mit wenigen Werten zu noch mehr "sinnlosen Nullen" geführt hätte).

Weil nun aber die Steuerung und Kollisionsabfrage von 2D-Figuren ja nun eigentlich kein Hexenwerk ist, würde auch ein Art "VM" das erledigen können, die die eigentliche Arbeit in schnellen Assembler-Routinen erledigt und über generalisierte Befehle steuerbar ist. Meine Befürchtung, daß diese indirektere Weise Performance kosten würde, hat sich bisher nicht bestätigt - und zusätzlich erhält nun jeder Figurentyp seinen "Variablenstack", der nur so groß sein muß, wie wirklich benötigt. So können viele kleine Figuren oder "Effekt-Sprites", die einfache Bewegungsmuster haben, ermöglicht werden, die nicht mehr können müssen - und nicht mehr Speicher brauchen - als es nötig ist.

Und auch ISM wurde ja (bekanntlich) nicht deshalb von mir entwickelt, damit ich "irgend etwas habe, um damit Musik zu machen", sondern einzig aus der Vorlage heraus, daß meine Spiele bisher keine Musiken/Klangeffekte hatten und ich diesem Manko Abhilfe schaffen wollte, ohne (wie bisher) für jedes neue Spiel irgendeine Lösung zusammenzukrüppeln.

Das Gleiche ist mit der Abfrage der Steuertasten/Joystick usw. passiert: Irgendwann merkt man, daß es gar nicht so viele Möglichkeiten gibt, das abzufragen und daß man trotzdem für jedes neue Spiel Zeit verschwendet, den Kram einzeln einzubauen.

Und das "SLOT" ist im Prinzip nur dazu da: Es gibt ja gar nicht so viele Möglichkeiten, die ganzen möglichen Subroutinen gemeinsam so zu benutzen, daß alle zusammen als Verbund funktionieren. Also wäre es ja die beste Idee, das Ganze gleich einmal richtig zu machen, zu testen bis es funktioniert und dann zu benutzen, als für jedes neue Projekt herumzuprobieren, wie es am besten gehen könnte. Und da sowieso Spiele in der Art der Konsolenspiele der späten 80er und frühen 90er angedacht waren, wäre es also ganz gut, wenn da alles, was so ein Konsolenspiel braucht und was so Konsolen in Hardware haben (der PC aber nicht), irgendwie "gleich da wäre". Die Konsolen allein haben ja meist gar nichts gemacht - erst, wenn man das Spiel eingelegt/eingesteckt hat in den Modulsteckplatz (Slot) - und genau so ist es mit meinem "Spiel-Rahmen", der nur die theoretische Funktionalität vorgibt, aber ohne Spieldaten kein Spiel ist - und deshalb heißt er auch SLOT.

Also ist in meinem Fall alles so passiert, weil ich schon Spiele gemacht habe, gesehen, was die Schwierigkeiten/Probleme waren und wie es besser lösbar (oder überhaupt lösbar) wäre. Ich habe eher selten (könnte mich jetzt an keinen Fall erinnern, wo es so war) ein Programm oder ein Format "um seiner selbst Willen" entwickelt, um dann "nach irgend etwas zu suchen, wo ich es einbauen/benutzen kann", sondern es war eigentlich immer umgekehrt.

Ich hätte bei dem ganzen Aufwand, den ich inzwischen für den ganzen Kram betrieben habe, schon längst meine Spielideen in direktem Code umgesetzt haben können: Das "Mehrfigur-Jump'n'run", das Raumgleiter-Shoot'em'up, ein Rennspiel... - aber ich habe mich letztendlich dagegen entschieden; ...

... und zwar einzig aus meinen Erfahrungen von Xpyderz heraus: Ich würde ja dann wieder nur 20% Zeug haben, das ich einbauen könnte und den ganzen "Rest" wieder dazucoden - wahrscheinlich "erstmal" in Pascal; und dann würde es auch Pascal bleiben, weil es zu viel Gemurks und "Drumherum-Gecode" wäre, um etwas Gescheites in Assembler daraus zu machen... Und am Ende hätte ich 3-5 Jahre (wie bei Xpyderz) herumgemurkst (obwohl ich da netto nicht mal EIN Jahr gebraucht habe), um einzelne Details "geradezubiegen", in endlosen Test-/Debug-Sessions... Und die ganze schöne Spielidee wäre am Ende nur in einem genauso unfertigen Ding verbraten, wie es bei Xpyderz der Fall ist.

Leider hatte ich unterschätzt, was es mit sich bringt, wenn mal älter wird und den ganzen Tag einen Job zu bewältigen hat: Ich komme kaum noch zum Programmieren. Selbst dann, wenn ich mal Zeit hätte, bin ich oft müde oder einfallslos und uninspiriert - und bei mir liegt es NICHT mal daran, daß ich "so viele andere Hobbys" hätte, denn das ist nicht der Fall. Tja, da sollte man wohl nicht ZU gespannt auf mein nächstes Spiel warten...

Momentan ist eigentlich ALLES fertig, was ich für ein Spiel brauche, ja, dieses Mal wirklich ALLES. Ich muß jetzt nur noch eine möglichst elegante, zeit-und-platz-sparende Methode finden, die ganzen "losen Enden" in SLOT zu einer zusammenhängenden Maschine zusammenzubauen, bei der erstmal KEINE blöden "Workarounds" mehr nötig sind, damit sie läuft.

Es ist so wie oft: Einen laufenden Prozeß kriege ich leichter hin, als die "Vorarbeit, ihn anlaufen zu lassen" - will sagen: Ein gescheites Datenformat für ein "Level" habe ich zwar - aber so richtig gefällt mir das noch nicht - das ist schon wieder viel zu kompliziert gedacht... habe gerade so eine Idee gehabt für ein Level, das aus "internen" und "externen" Daten bestehen kann: eine negative "Position" würde dazu dienen, stattdessen externe Daten zu laden... (Externe Daten = Daten, die von mehreren Levels gleichzeitig benutzt werden können und daher nicht einzeln in jedem Levelfile vorliegen müssen - inklusive Erkennung, ob sie schon geladen sind. Mal sehen...)
zatzen hat geschrieben:Dein Image-Einpass-Programm nimmt in etwa die Stelle ein, die bei mir der ZVID2 Encoder hat. Natürlich eher schlecht vergleichbar, aber vom Aufwand her könnte es in etwa hinkommen.
Naja, das Ding ist ja nur dazu da, damit man das nicht von Hand machen muß. Da werd ich wohl noch mal was Neues bauen, weil das noch einige Dinge hat, die unpraktisch sind. Der Aufwand des "Zusammenbauens" des Spiels soll "so automatisch wie möglich" sein - damit z.B. das Testen des Spiels nicht jedes Mal in ewiges manuelles Gebastel ausartet.
zatzen hat geschrieben:
DOSferatu hat geschrieben:Und - so traurig das jetzt vielleicht klingt - auch Du wirst wohl Byte für Byte arbeiten müssen.
Ja, das war schlecht nachgedacht. Selbst wenn ich das bei nicht-Transparenz vielleicht so machen könnte - es bringt nichts, erst ein 32 Bit Register mit Bytes vollzuschieben um es dann mit einem Rutsch in den Speicher zu knallen.
Das ganze trifft nur für den Fall zu, wenn ein ganzer Block einfarbig und nicht transparent ist.
Dann werde ich das so machen.
Naja, ich will das Ganze nicht schlechtreden und JA - 32bit-Kopieren in den Speicher kann (wenn schlau gemacht) einige Zeitersparnis bringen, ABER:
Selbst dann (bei einfarbigem Block) ist es wahrscheinlich unnötig. Weil:
1. Wie oft kommt das vor?
2. Die Routine, die prüft, ob ein gleichfarbiger Block vorliegt, braucht wahrscheinlich mehr Platz UND Zeit, als es die Sache wert ist.
Oder meinst Du, daß ein ganzer 4x4-Block einfarbig ist? Naja... Einerseits alles handpixeln wollen und bei Skalierungen die klotzigen Flächen monieren (bzw. bei Drehungen die Pixelgenauigkeit) und andererseits große einfarbige Flächen in Sprites wollen... das widerspricht sich ja schon irgendwie.

Ich sag's mal so (persönliche Erfahrung) : Wenn man Sprites für 320er Auflösung macht, kommen so "Flächen" - selbst in 4x4 Größe - in Sprites nur äußerst selten vor und selbst WENN, dann fangen sie vielleicht gerade zufällig NICHT an einer glatten 4er-Position im Sprite an. Meiner bescheidenen Meinung nach sollte man, damit Sprites in so geringer Auflösung noch einigermaßen "schön aussehen", klobige "Umrandungen" oder "Flächen" weitestgehend vermeiden.
zatzen hat geschrieben:
DOSferatu hat geschrieben:Ich habe schon öfter mal bereut, manches von meinem alten Zeug "zu dicht komprimiert" zu haben, so daß kein Platz für Erweiterungen mehr da war und habe mich andererseits jedes Mal gefreut, wenn ein altes Format noch Dinge "offen gelassen" hatte, so daß ich es noch weiter verwenden und erweitern konnte.
Mehr oder weniger könnte ich ZSM bereuen, es wäre schwer das Format abwärtskompatibel zu erweitern - denke ich mal. Aber ich habe auch nicht so viele "Fans" dass das für mich wichtig wäre. Wenn ich für ein Spiel mehr Funktionen bräuchte, würde ich eine neue Version machen, die dann eben mit dem bisherigen Player nicht mehr kompatibel wäre.
Ach naja - dabei geht's mir auch nicht um "Fans" oder so - es gibt derzeit außer mir selbst keine weiteren Leute, die mein Zeug in ihren eigenen Projekten verwenden. Mir geht es dabei mehr um mich selbst: Ich will nicht andauernd auch noch Konverter für meinen Kram schreiben müssen, weil mein Zeug nicht mal zu sich selbst kompatibel ist - ich bin auch mal froh, wenn ich etwas, das ich gemacht habe, auch noch mal weiterverwenden kann.

Das liegt bei mir alles daran, daß ich merke, wie viel Zeit ich damit verbracht habe, immer wieder irgendwelches Zeug zu bauen und wenn ich dann ein Projekt gemacht habe, hatte ich 15 Jahre lang programmiertes Zeug herumliegen, in das viel Mühe gesteckt wurde - und das ich dann NICHT benutzen konnte/wollte, sondern extra für das Projekt dann doch wieder eigenen Code geschrieben habe. Da kommt man sich dann irgendwann schon selber doof vor.
zatzen hat geschrieben:
DOSferatu hat geschrieben:Wenn ich heutzutage ein Format benutze, will ich NICHT mehr (wie leider früher manchmal!) alles "um das Format", bzw. "um diese Routine herum" bauen müssen. Da finde ich es inzwischen besser, Zeug so zu machen, daß man es "nur noch einzubauen" braucht und es quasi alles, was es braucht, selbst macht, bzw. "von selbst mitbringt".
Auch deswegen jetzt ZVID2, was neben ein paar Variablen nur aus einer Prozedur bestehen wird. Mal abgesehen von Initialisierungs-Routinen, die aber auch nur Sachen machen die man auch "zu Fuß" machen könnte. ZVID(1) war eine ultra-komplizierte Orgie aus Prozeduren und haufenweise Pointern.
Tja, wie erwähnt, hatte ich damals auch schon öfter so "Riesenpuzzles" gebaut: Riesige komplizierte Apparate von Subroutinen/Units, in die viel Mühe geflossen ist, die trotz Komplexität funktioniert haben und auf die man (leider zu Unrecht!) stolz war (wegen der ganzen Mühe). Aber, "am Ende des Tages" hat man dann irgendein Teil, was kompliziert, groß und langsam ist, ein ganzes Segment belegt und vielleicht zusätzlich noch riesige Tabellen braucht usw... und das, wo man es einbauen will. braucht kaum eine der "Fähigkeiten" dieser "Superwaffe"...

Inzwischen (wie Du so schön sagst), backe ich eher bei so Routinen "kleinere Brötchen", weil "komplex" mir manchmal schon selbst "ZU komplex" wird und der Nutzen am Ende minimal. Vor allem (kann bei DIr anders sein), war es bei mir IMMER so: Komplexe Subroutinen waren immer schlecht irgendwo einzubauen - sie brauchten vom Hauptprogramm immer auch umfangreiches Init und Datenvorbereitung... Das war dann wie so eine Krake, die das ganze restliche Programm mit seinen "zu befriedigenden Befindlichkeiten" beherrscht.

Inzwischen versuche ich, wie schon in einem meiner letzten Beiträge geschrieben, alles möglichst so zu bauen, daß man es nur noch "einhängen muß" und es funktioniert von alleine - OHNE, daß das Hauptprogramm so ein Ding die ganze Zeit "babysitten" muß, damit es funktioniert.
zatzen hat geschrieben:
DOSferatu hat geschrieben:Naja, daß für "flächige Dinge" (wie Sprites, Rechtecke/Polygone) der fortwährende Zugriff auf eine generalisierte Pixelroutine (die jedes Mal aus Koordinaten die Pixelposition ausrechnet und für den Grafikmode entsprechend die Daten setzt für den Pixel) eine Scheißidee (weil langsam) war, habe ich schon recht schnell herausgefunden.
Ich meine nicht Punkt für Punkt, was in QuickBASIC mit PSET(x, y, color) gemacht wurde. Sondern das Grafik-PUT, man muss auf ein Integer-Array mit einer Bitmap (für VGA 1 Byte pro Pixel) verweisen und dann die Koordinaten der oberen linken Ecke. Was PUT macht dürfte etwa das gleiche sein wie rep stosb und das eben für mehrere Zeilen, d.h. es ist eigentlich sehr schnell.
Achso. Kannte ich gar nicht. Liegt wohl daran, daß ich auf PC nie BASIC programmiert habe (außer mal dieses eine kleine Dings in VB6 unter Windows, zusammen mit einem Kumpel). Aber unter DOS habe ich auf PC gleich mit (Borland) Turbo-Pascal angefangen. Die "Grafikfähigkeiten" von dem, was Borland da mitgeliefert hat, sind aber eher ein Witz. Naja, mag auch daran liegen, wie alt die letzte Version von BP ist. Jedenfalls hatte ich da sehr schnell erkannt: Das ist nix für mich - da muß ich etwas eigenes bauen.
zatzen hat geschrieben:Aber wenn man das auf einem 286er macht, mit einem 32x32 Sprite und es mit nur 1 Pixel jeweiligen Versatz animiert, dann dauert es schon ein paar Sekunden bis das Ding über den Bildschirm gewandert ist. Oder es war doch ziemlich schnell und ich habe es mit Sound 0, .1 ausgebremst. Ist fast 30 Jahre her...
Naja, die "der Spriterahmen löscht das Sprite" Methode habe ich noch nie irgendwo angewendet, deshalb kann ich dazu nichts sagen. Und die Methode, daß das Sprite den Hintergrund löscht und wiederherstellt, habe ich bisher ausschließlich für meine Mauspfeile benutzt. - Bei EINEM Sprite scheint mir das noch vertretbar.
zatzen hat geschrieben:
DOSferatu hat geschrieben:Um zu merken, daß es wirklich funktioniert, reicht es nicht, zu sehen, ob die Steuerung alleine oder die Grafik alleine oder der Sound alleine funktionieren. Erst, wenn ALLES ZUSAMMEN arbeitet und immer noch funktioniert, DANN wird's ein brauchbares Spiel.
Ich bin relativ optimistisch. Ich habe ja doch ein paar Spiele und Demos programmiert, wenn auch nicht immer die tollsten. Der Pentium 200 MMX den ich seit 1997 habe hat natürlich alles gefressen. Das verzerrt die Erwartung an einen 486er ein wenig.
Naja, ich sehe ja, wie wenig schon mein Xpyderz performt (hattest Du ja auch selbst getestet). Und Xpyderz hat noch direktgecodete Steuerung (kein GameSys2) und auch keinerlei Sounds. Da möchte man gar nicht wissen, wie schlimm das jetzt mit allem zusammen (in SLOT) wird - mein Optimismus hält sich da derzeit noch in Grenzen.

Ich muß dazu aber sagen: "Wird schon reichen" war noch nie so mein Credo. Ich denke IMMER: Wenn ich noch ein bißchen mehr spare (Speicher/Rechenzeit), dann bleibt für den Zweifelsfall noch "Luft nach oben". Alles so "gerade so auf Kante" bauen, das wäre mir "zu gefährlich". Und ein Pentium 200 MMX ist nicht gerade mein Zielsystem.
zatzen hat geschrieben:
DOSferatu hat geschrieben:[...]Also quasi soll dieser ganze Kram schon so "getestet und für gut befunden" sein, daß man ein Spiel drauf entwickeln kann OHNE jedes Mal komplett neue Routinen bauen zu müssen, die eigentlich das gleiche machen wie die des letzten Spiels.
Ja, da stimme ich Dir absolut zu. Wenn man sich manches klassische NES Spiel ansieht, scheint es auch so, als hätten die immer wieder die gleiche Engine genommen. Das meine ich absolut nicht negativ, sondern es ist professionell wenn man sich einen Standard schafft für den man Spiele designen kann. Fast so, als würde man sich dadurch Hardware erschaffen.
Ja, das ist die Idee dahinter.
zatzen hat geschrieben:Ich wollte ja auch vor ein paar Jahren schon so ein Game-System schaffen, was ich dann während einer Spieleentwicklung erweitern wollte. Ich habe da aber nicht so klare Vorstellungen wie Du, und bin ersteinmal froh dass ich einen Sound-Standard habe, und mal sehen wie ZVID2 wird. Letzteres nimmt mir auch die Sorgen ab, wie ich Grafik in das Spiel bekomme und dabei noch bestmöglich Speicher spare - ich muss sie nur auf den Heap laden und die Routine
mit entsprechenden Parametern aufrufen.
Ja, wie erwähnt: Selbst das will ich ja schon "automatisieren": Die Steuerung übernimmt GameSys2, die Anzeige passiert in einer Schleife, an der ich für das jeweilige Spiel nichts ändere. Was, ob, wo und wie angezeigt werden soll, wird vom VM-Code in GameSys2 definiert, das hat meine Hauptroutine nicht zu interessieren. Die soll nur das Anzeigen, was in den Daten steht. Früher[tm] habe ich viel weniger "modular" programmiert - nur dann ist man eben dazu verdammt, für jedes Spiel eine eierlegende Wollmilchsau zu bauen, die alles (Anzeige, Steuerung, Kollision, Eingabe/Abfrage, usw...) gleichzeitig macht - und irgendwann wird man es leid, immer wieder das gleiche zu coden, wenn es schonmal funktioniert hat.
zatzen hat geschrieben:
DOSferatu hat geschrieben:Meiner Erfahrung nach scheinen sehr viele (spätere) Coder, vor allem im 3D-Bereich, das so wie ich zu machen: Die FPS-Raten der Spiele sind variabel und hängen davon ab, wie aufwendig gerade berechnet werden muß.
Ich hab ja ne Zeit lang mit ein paar Jungs 3D Spiele gezockt. Ich habe einen Spruch im Kopf: "Framerate is God".
Kennt man vielleicht nicht, hab ich aber irgendwie mal gehört. Bei 3D Ego Shootern sind Framerates von unter 70 schon nicht mehr tolerabel, und als die ersten LCDs gängig wurden, wurde trotzdem noch an Röhren gespielt, weil die schneller sind. Und wir haben in 320x200 gespielt, mit Pentiums...
Ja, verwöhnte KIDS haben diese Einstellung.
Für Singleplayer geht auch weniger. Bei Multiplayer ist natürlich eine geringe Framerate gefährlich - und zwar weniger, weil es "nicht so schön/flüssig aussieht", sondern eher, weil einem bei SEHR ruckeliger Framerate bestimmte Dinge entgehen könnten und man also nicht so schnell/genau auf die Gegner reagieren könnte.

Für MICH zählt alles bis 10 FPS noch immer als "gut spielbar", selbst dann, wenn es gelegentlich zwischendurch auch mal auf 5 FPS einbricht. Aber ich bin ja auch kein verwöhntes Kiddie.

zatzen hat geschrieben:Ich stimme Dir absolut zu, dass das objektiv gesehen besser ist mit variabler Framerate. Für mich ist es nur großes Neuland zusätzlich dazu dass ich ein Spiel zu bewerkstelligen hätte, und der Trade-Off wäre die Ton-Asynchronität.
Wenn also mein Spiel am Ende auch mit seinen bescheidenen 15-20 fps auf einem 486er ohne Engpässe durchläuft MIT synchronem Ton, dann ist das für mich sehr zufriedenstellend.
Naja, wie gesagt: Zur Synchronität habe ich mich ja schon oben ausführlich geäußert. Ich werde mal sehen, wie weit ich mit "meiner Methode" kommen werde und ob mein Zeug dann "zu unsynchron" wird, um noch glaubwürdig spielbar zu sein. Kann ich jetzt leider noch nicht sagen, da noch nicht zusammenhängend getestet. Ich werde aber wohl den "Tonversatz" (also die Puffergröße), genau wie die Ton-Samplerate einstellbar machen, damit auch auf langsamen Rechnern noch gespielt werden kann.

Bei der Grafik wäre alles, was ich einstellbar machen könnte, die Bildauflösung - nur... naja, 320er Auflösung IST ja nun schon nicht gerade "fein" - ob man da dann noch auf 160 gehen sollte (wie bei Xpyderz)? Mal sehen. Genau wie bei Sound, wo es Untergrenzen gibt, die sogar ICH unerträglich finden würde, gibt es das auch bei Grafik. Und verkleinerter Bildausschnitt macht nur bei 3D-Spielen Sinn, wo sowieso alles skaliert wird. Bei 2D weiß ich nicht, ob ich da wirklich in so einem 160x100 oder 80x50 Fenster oder so noch Lust hätte, das zu spielen.
zatzen hat geschrieben:Kotzman II hat technisch sehr viel mehr Rückschläge, ich hätte mir noch gewünscht:
- Sprachausgabe (gescheitert an Unfähigkeit die Soundblasterkarte zu programmieren)
Inwiefern? Für die Zwischensequenzen oder auch im Spielverlauf?
zatzen hat geschrieben:- für die Animationen am Ende eines Levels musste ich mir eine Scriptsprache erfinden, weil die Basic-Befehle nicht mehr ins Programm passten
Das würde ich sowieso so machen, EGAL ob es reinpaßt oder nicht. Animationen als Programm (EXE) "hardcoden" halte ich - zumindest auf PC - für Mega-Schwachsinn.
zatzen hat geschrieben:Digitaler Sound ist und war immer etwas das mich fasziniert hat, vielleicht auch weil er bis Anfang/Mitte der 90er so spärlich eingesetzt wurde.
Ja, ich weiß.
Allerdings fand ich Spiele immer eher öde, die nur "wegen der Effekte" (z.B. Digisound/Sprachausgabe oder Grafik als vorgerenderte Filme) so viel Speicher/Platz brauchten, daß für einen eigentlichen Spielinhalt kein Platz mehr da war. Das waren für mich "Blender", die wegen der Effekthascherei dann leider kaum noch spielbaren Inhalt hatten - das kann man kurz angucken/anhören und bewundern - aber für ein längerfristiges Spielerlebnis hat das kaum je etwas getaugt.

Anfang der 90er kam viel so vorgerenderter Kram raus... Aber nichts davon hat mich irgendwie vom Hocker gerissen, weil der spielerische Aspekt dabei leider immer vernachlässigt wurde. Und das Gleiche wäre es für mich, wenn ein Spiel tolle Soundausgabe (und Sprachausgabe) hätte, aber wegen des ganzen Aufwands und Platz der ganze Rest nur irgendeine uninspirierte Grütze wäre, die nur "um den Sound herum" gebaut wäre.

Wenn ein Spiel nur 4-farbig ist und ein wenig Speaker-Gepiepe hätte, dafür aber eine tolle Spielidee und interessante Umsetzung, würde ich das länger/lieber spielen als eben o.g. "Blender".
zatzen hat geschrieben:
DOSferatu hat geschrieben:Ich muß aber auch dazu sagen, daß oft mit viel größerer Farbtiefe gearbeitet wird als überhaupt nötig.
Gebe ich Dir absolut recht, dass für Sprites 8 Bit indizierte Palette dick ausreicht, es sei denn die Sprites sind fotorealistisch und bildschirmfüllend.
Naja, Sprite-Spiele einerseits und Fotorealismus andererseits sind für mich zwei Dinge, die nichts miteinander zu tun haben.
zatzen hat geschrieben:Es gibt aber einen Bereich, wo man nie genug Farbtiefe haben kann: Beispielsweise bei der Digitalisierung von Dias. Wenn man da "nur" 24 Bit hat, und ein stark unterbelichtetes Dia, kann es passieren dass beim Aufhellen Artefakte auftreten, quasi Treppenstufen, weil sich die Helligkeitswerte nur noch um ein paar Bit drehen.
Ja, ich weiß. Das sind technische Sonderfälle - das hat aber nichts mit Spielen zu tun. Und irgendwelche "Zwischenberechnungs-Stufen" gehören auch dazu. Am Ende wird das Dia dann aber wohl doch als 24bit-Grafik (oder als Foto) vorliegen. Was soll man auch mit einem 48-Bit Grafikformat, das man nirgends anzeigen kann oder das bei der Anzeige sowieso auf 24-Bit runtergerechnet wird? Man braucht Programme, die es anzeigen/runterrechnen können. Man braucht Rechenzeit zum Runterrechnen, man braucht mehr Platz für Daten, die man sowieso nicht sieht...
zatzen hat geschrieben:Das ist auch im Audio-Bereich so. Man arbeitet am besten bei der Bearbeitung mit 32 Bit Floating Point, um es dann am Ende, quasi für den Verbraucher, auf 16 Bit herunterzurechnen, nachdem man es gut ausgesteuert hat. Unsere Ohren sind offenbar weitaus dynamischer als die Augen: 8 Bit pro Farbkanal reichen für "True Color", aber 8 Bit für Ton sind mehr schlecht als recht, zumindest aus HiFi-Sicht.
Vergleiche mal nicht Deine Ohren mit den Ohren aller anderen Leute... - Mir reichen 8 Bit oft dicke aus und mit Fließkomma arbeite ich am liebsten... GAR NICHT.

Andererseits wirft man da natürlich auch mehrere Dinge, die NICHTS miteinander zu tun haben, in den gleichen Topf: Spiele mit Konsolengrafik und Konsolenmusik (Konsole vor 1994) einerseits und Tonbearbeitung für Orchestermusik andererseits haben NIX - aber auch GAR NIX miteinander zu tun und ich werde NIEMALS (ja, NIEMALS!) für Grafiken - selbst für Source-Bearbeitungen - mehr als 24Bit-Bilder benutzen (und auch nur, um sie dann an eine 8-Bit-Palette anzupassen) und für Sound wird es bei mir auch NIEMALS (ja, NIEMALS!) auf Fließkomma hinauslaufen - und wahrscheinlich auch nicht mal auf irgend etwas über 8-Bit ... und VIELLEICHT - aber nur vielleicht - gibt es mal IRGENDWANN Soundroutinen (ISM), die so etwas wie Stereo unterstützen. (Es gibt bereits vorgesehene Bits/Befehle dafür.)

Bei mir liegt es eben daran, daß meine Zielsetzung bestimmte Obergrenzen hat - und solange ich diese Obergrenzen nicht einmal ansatzweise technisch erreiche, hat es überhaupt keinen Zweck, darüber zu gehen. Und die Art "Musik", die ich mache (oder zu machen imstande bin), rechtfertigt weder 16-Bit, noch irgendwelche Fließkomma-Dinge - nicht einmal in irgendwelchen Source-Daten. Und die Art Grafik, die ich mache (gepixelt) - da sind 16,7 Millionen Farben schon der reinste Schwachsinn (wer pixelt mit so vielen Farben?) und alles darüber ist der Erwähnung nicht einmal wert.
zatzen hat geschrieben:Headroom ist auch ein Begriff aus der Audiotechnik, und bei 32 Bit Float hat man praktisch beliebig viel davon. Das ist auch ein Grund warum man 32 Bit nimmt während der Bearbeitung.
Naja, man hat nicht "beliebig viel", sondern ca. 4,2 Millarden Möglichkeiten pro Frame (etwas weniger, weil Float auch eine Reihe "ungültige" Kombinationen enthält). Aber naja, ich bin weder professioneller Musiker noch professioneller Grafiker noch professioneller Programmierer - noch professionell in IRGEND ETWAS und bin daher auch nicht so abgehoben, zu meinen, ich bräuchte derart exorbitante Dinge für das bescheidene bißchen Müll, das ich so fabriziere.

Mein Malprogramm ist selbstgemacht - total freaky und hotkeyverseucht, das würde kein "Grafiker" heutzutage mit der Kneifzange anfassen... - aber mir reicht es. Mein Musik/Sound-Editor ist selbstgemacht - ebenfalls freaky und hotkeyverseucht, das würde auch kein "Musiker" heutzutage auch nur angucken. NICHTS, was ich mache, genügt IRGENDWELCHEN professionellen Ansprüchen - aber:

Ich käme mir auch eher albern vor, die Grafiken für meine Spiele mit Photoshop zu erstellen oder den Sound für meine Spiele auf einer professionellen Soundanlage zu erstellen - das ist so lächerlich wie im 5-Sterne-Restaurant Pommes rot/weiß zu bestellen. Konsolenartige "Brachialmusik" erst in 20facher Orchesterqualität zu erzeugen, nur um sie dann auf 4-Bit-Sound runterzukonvertieren... da müßt mein Herz 'n Affe sein...

Mal eine Frage zum Thema Sprachausgabe für Deine Spiele (weil Du das so oft erwähnst) :
Wie würdest Du das realisieren? Ich meine damit NICHT die technische Seite - Du hast ja sicher hervorragendes Soundequipment, um das in super Qualität aufzunehmen und zu Entrauschen usw... - sondern eher:
Wenn Du mehrere Figuren/Charaktere im Spiel haben solltest: Wer soll die Charaktere sprechen? Kennst Du so viele Leute, die Zeit UND Lust hätten, bei so etwas mitzumachen und sich zusätzlich auf den Weg zu Deinem Mikro machen würden, um viele lange Texte mit vernünftiger Betonung/Tonlage einzusprechen?

Ich für meinen Teil habe da keine Leute, die Zeit UND Lust UND Talent UND Gelegenheit hätten, da mitzumachen - und wenn man alles selbst einspricht: Selbst wenn man alles selbst spricht und da mit Verzerrung arbeitet, ist der "Akzent"/"Sprechgeschwindigkeit" immer die gleiche, da muß man schon SEHR VIEL Arbeit reinstecken, um wie verschiedene Leute zu klingen. Und nicht umsonst gibt es ja professionelle Sprecher (die, weil sie professionell sind, eben auch so viel kosten wie jemand, der professionell ist).

Wie "Sprachausgabe" mit "irgendnem Heini von der Straße" klingt, kann man sich anhören, wenn man sich die Versionen der allerersten deutsch synchronisierten Anime anhört. Ich meine NICHT die, die im TV liefen! Das TV hat ja geübte Sprecher. Sondern die, die es so zu kaufen gab (damals noch auf VHS). Wenn man SOLCHE Sprachausgabe haben will, von irgendwelchen Torfköppen, die man so privat über irgendwen kennt... Dann werden viele Spieler die Sprachausgabe zugunsten von Untertiteln abschalten und man hat sich die Mühe mit der Sprachausgabe umsonst gemacht.
zatzen hat geschrieben:PS: Wird mein Text eigentlich wirr umgebrochen weil ich den Zeilenumbruch selbst mache? Soll ich das lieber demnächst sein lassen?
Ja, Dein Text wird wirr umgebrochen und ich muß das jedes Mal nach-ändern um kein "Kamm-Quoting" zu haben. Da das Forum/der Browser den Text sowieso umbricht und zwar je nach eingestellter Textgröße trotzdem vernünftig, sind meiner Meinung nach zusätzlich selbstgemachte Umbrüche so nötig wie ein drittes Nasenloch.

Ich wollte bisher nichts dazu sagen, weil ich dachte, dieser Umbruchwahnsinn hätte bei Dir irgendwelche technischen Gründe und da will man ja nun nicht deswegen nerven; aber wo Du jetzt schon so fragst...
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Eigenes Videoformat

Beitrag von zatzen »

Hallo DOSferatu!

Ich habe zwischenzeitlich mal ein kleines Experiment gemacht und den Puffer von ZSMPLAY von 768 auf 512 Bytes runtergesetzt (Richtwert für 22 kHz, für 44 kHz wird dann das doppelte genommen). In einigen Modi kam es dann zu Stottern (44 kHz), bei 20000 Dosbox Cycles. Das hat mich schon etwas ernüchtert gestimmt, da die ZSMPLAY Modi ja nicht ansatzweise so komplex sind wie ein Spiel. Andererseits, als ich den Puffer auf 1024 vergrößert habe, lief alles problemlos sogar noch bei weniger als 8000 Cycles, was laut dem Dosbox Performance Test etwa der Leistung eines 386 mit 33 Mhz entspricht.
Mit einem Puffer von 1024 Bytes hätte ich eine Framerate von 21,5 - völlig ausreichend für meine Bedürfnisse.

Hier direkt mal die Antwort auf Deine Frage, wo ich die Daten für den nächsten Puffer generiere: In der Hauptschleife, nicht im Interrupt, der setzt nur eine Boolean Variable auf true, also ein flag.
DOSferatu hat geschrieben: Ich möchte - nach all der Mühe, die ich mir mit den Puzzleteilen für meine Spielengine(s) gegeben habe - jetzt nicht irgendeinen uninspirierten Mist zusammenmurksen.
Ich hatte in meiner Jugend wenige, dafür aber dauerhafte Ideen, so dass ich mich gar nicht lange fragen musste was ich machen solllte, siehe Kotzman... Die Idee war einfach da, und anstatt daran zu zweifeln habe ich einfach losgelegt, was auch nicht unbedingt das beste war, aber so habe ich wenigstens etwas gemacht. Es war so eine ungefähre aber beständige Ahnung was ich machen wollte, die mich antrieb. Ich hatte meine damaligen Comic-Figuren, Kotzman und Saugi, in das Spiel haben verschiedene damalige Dinge reingespielt, auch dass wir mal einen Hamster hatten. Und zwischendurch habe ich immer wieder improvisiert, wusste also am Anfang nicht wirklich wie es am Ende aussehen würde. Und ich denke, ähnlich werde ich es auch wieder machen. Alles wird parallel wachsen, Leveldesign, Grafiken, Sound. Wobei ich diesmal wohl schon eher nach einem "Format" vorgehen werde, wie das Spiel grundsätzlich strukturiert sein soll.
DOSferatu hat geschrieben:[...]Außerdem benutze ich z.B. gern BX[...]
Gut, dass Du es nochmal erwähnst, ich hatte jetzt schon daran gedacht, in meinen ZV2 Routinen BX für die Vorbereitung der Sprünge BX zu verwenden, aber ich kann da ja auch z.B. AX (jmp ax) nehmen und BX dauerhafter verwenden.
DOSferatu hat geschrieben:Dem entnehme ich, daß die Spriteroutine beim Entpacken 4x4-kachelweise abfragt, ob sich die nächste Kachel innerhalb des sichtbaren Bildausschnitts befindet?
Die Routine überprüft zuerst, ob das gesamte Sprite überhaupt sichtbar ist. Das geschieht durch simple Additionen und Subtraktionen. Wenn nicht, verabschiedet sich die Routine sofort.
Als nächstes wird das 4x4 Block clipping berechnet, wieviel links, rechts oben und unten übersprungen werden muss (auch alles Subtraktionen/Additionen), und daraus ergibt sich dann eine zweidimensionale Schleife die abgearbeitet wird, bei nicht zu zeichnenden Bereichen müssen die Daten der Quelle jeweils nur übersprungen werden.
Wenn absehbar ist, dass im Spiel kein Clipping vorkommt bzw. alle Grafiken vollständig im Bildschirm bleiben, kann man eine entsprechend optimierte Routine dafür basteln, die dann etwas schneller sein wird. Ob ich beide in die gleiche Unit packe oder zwei Units mache hängt davon ab, ob der Compiler ungenutzte Routinen mitkompiliert oder nicht.

Danke, das mit dem in den kompilierten Code gucken, wegen RETF/RET etc. am Routinenende werde ich dann mal probieren.
DOSferatu hat geschrieben:Wenn der Sound "synchron" zur Grafik sein soll, die Grafik dann aber nur 5 FPS hat - zu WAS soll der Sound dann synchron sein?
Es kommt drauf an, wie genau man das mit den Puffern anstellt. In der Hauptschleife berechne ich die Grafik und genau für dieses Bild den entsprechenden Ton. Im nächsten Schritt wird diese Grafik dargestellt und der berechnete Ton abgespielt. Somit, selbst bei nur 1 fps, würde man ein Bild von einer Explosion sehen mit dem passenden Sound. Das funktioniert dann, wenn die zeitliche Auflösung des Spiels letztlich an die Framerate gebunden ist - was bei Dir ja eher nicht er Fall ist. Mir ist bewusst dass bei soetwas, selbst wenn man es mit 20 fps betreibt, die Darstellung des Geschehens bzw. der Spielfigur, immer etwas der Steuerung hinterherhinkt. Das Problem hatten wir ja in bisherigen Schriftwechseln schon diskutiert.
Damit das Spiel aber nicht total lahm ist, muss ich intern meinetwegen mit drei oder vier Zyklen rechnen und davon eben nur einen pro Frame ausgeben. Dadurch wird die Korrelation von Ton und Bild ein wenig auseinanderdriften, aber bei vernünftigen Framerates kaum merklich. Es sei denn ich teile den Soundpuffer ebenfalls in drei oder vier Teile, dann käme es wieder genau hin. Der Performanceverlust dadurch könnte weniger drastisch ausfallen, als wenn man den Soundpuffer insgesamt verkleinert, wodurch die Framerate steigen würde und somit die Anforderung an die Grafikleistung.
Interessant wäre noch zu überlegen, statt der internen z.B. vervierfachung der Zyklen, direkt nur mit der groben Auflösung zu rechnen wie sie die Framerate vorgibt. Aber wie sollte man soetwas anstellen? Ich würde intern wenigstens Pixelgenau auflösen wollen, also dass die Kollisionen wie das abprallen von Level-Kacheln exakt detektiert wird. Du merkst vielleicht, so viel Erfahrung habe ich da noch nicht.
DOSferatu hat geschrieben:...und der Knall (oder was auch immer) hat auf der Grafik schon stattgefunden und dann wird der Effekt erst eincodiert - und dann erst im NÄCHSTEN Soundframe ausgeführt
Und genau das mache ich anders. Vielleicht mache ich es ja falsch: Ich berechne die Sounddaten und die Grafikdaten, warte auf den Interrupt, dann spielt der gerade berechnete Puffer ab und ich zeige die gerade berechnete Grafik an. Das ist dann synchron wie ein Video, nutzt nur nicht die volle Performance, weil ich auf den Interrupt warte und die Framerate fest ist.
Und wie gesagt, was bei Dir beim Sound passiert, passiert relativ zur Steuerung bei mir bei Grafik UND Sound: Sagen wir mal man drückt auf "springen". Gerade wird noch ein berechnetes Bild angezeigt, währenddessen wird der Tastendruck registriert. Nächster Frame: Die "Feinde" haben sich einen Zyklus weiterbewegt, der Befehl "springen" wird gerade berechnet. Übernächster Frame: Jetzt sieht man endlich wie sich die Figur bewegt, allerdings dann auch mit zum Bild passenden Sprungeräusch.
DOSferatu hat geschrieben:Du - als jemand aus der Sound-Ecke - scheinst bei der Spiele-Entwicklung/-planung ziemlich auf den Sound-Anteil fixiert zu sein. Will sagen: Wenn die Grafik klotzig oder ruckelig wird oder in einem verkleinerten Fenster dargestellt werden muß oder das Gameplay eventuell zu "simpel" zu werden könnte, das scheint für Dich alles kein Problem zu sein - solange der Sound dabei in hoher Qualität und Synchronität daherkommt. (Kann ich nicht mit Sicherheit sagen - wirkt aber subjektiv auf mich oft so.)
Es liegt im Prinzip vor allem daran, dass ich bisher das Timing nie anders gemacht habe als über den Soundpuffer-Interrupt. Das bringt dieses "spielbares Video" mit sich, und ist nebenbei für mich die einfachste Art, Bild und Ton auszugeben. Ansonsten habe ich natürlich eine gewisse Faszination für Sound. Seit 1992 habe ich einige Spiele, davon nur ein paar wirklich vorzeigbar, gemacht, aber meine Programmierfähigkeiten haben nie dazu gereicht, die Spiele mit ansprechendem Sound auszustatten. Kotzman II war da schon eine kleine Revolution, mit Adlib. Ich habe jetzt einfach etwas nachzuholen, und Du musst verstehen, dass jemand der vor 26 Jahren angefangen hat sich mit Tracker Musik zu beschäftigen (genauer: Den 4 Kanal MODs, die in den meisten Amiga Spielen zum Einsatz kamen), und mehrere hundert Musikstücke im Tracker gemacht hat, und sich dadurch auch sehr intensiv mit Sampling auseinandergesetzt hat (die ersten Jahre zwangsläufig mit 8 Bit und niedrigen Samplerates), jetzt, wo er soetwas programmieren kann, das auch in eigenen Spielen zum Einsatz bringen möchte. Es ist wohl so, dass ich nicht zu einem Spiel ohne Sound motiviert wäre. Das muss aber nicht heissen dass ich vor habe, ein Pong mit Beethovens Pastorale dazu zu programmieren. Es ist vielmehr so, dass ZSM flexibel ist und auch sehr bescheiden eingesetzt werden kann. Ich werde mir den Code auch nochmal genauer ansehen, ob man da bei der Delta-Decodierung nicht noch etwas beschleunigen kann.
DOSferatu hat geschrieben:Was ich damit sagen will, ist, daß sowohl der Sound, als auch die Grafik verzögert ausgegeben werden im Verhältnis zur Spielsituation. Und, wie Mr. Spock sagen würde: "Das ist nur logisch." - denn die Wirkung kann zeitlich nie VOR der Ursache liegen.
Bei mir wären Sound und Grafik, wenn ich das richtig sehe, "wenigstens" gleichermaßen verzögert, d.h. wenn es eine Taste "Explosion" gäbe, würde nach drücken der Taste zwar ein wenig Zeit vergehen, aber Grafik und Ton kämen dann relativ zueinander gleichzeitig.
DOSferatu hat geschrieben:Und übrigens: Speziell die Spiel-STEUERUNG sollte NIE ausgebremst werden - so ein "hakeliges" Spiel würde keiner spielen wollen.
Dann habe ich vielleicht ein grundsätzliches Problem. Ich sollte demnächst mal ein kleines Testspiel machen.
DOSferatu hat geschrieben:Nur: Einerseits höchste grafische Qualität wollen - ohne eventuelle "Artefakte" vom Drehen oder Skalieren - andererseits aber zufrieden sein mit ruckeligen 8-10 FPS, evtl. verkleinertem Bildausschnitt und 16-Farb-Grafik... das paßt alles irgendwie nicht zusammen. Einerseits wenig Grafikspeicher wollen und alles zusammenpacken, damit viel Platz für Samples bleibt, andererseits auch gedrehte Phasen einzeln pixeln, was wieder mehr Platz braucht... - Es geht eben nicht alles gleichzeitig.

Ich habe mich längst damit abgefunden, daß ich mit den technischen Mitteln, meinen Fähigkeiten und meiner Zeit niemals das "Spiel des Jahrhunderts" erschaffen können werde - da bin ich froh, mir ein paar Mittel geschaffen zu haben, die einen Teil der Dinge "automatisieren".
Ich will auch überhaupt nur ein bescheidenes Spiel machen, und angesichts der Menge an existenten tollen Dos-Spielen braucht man gar nicht erst versuchen noch irgendetwas zu toppen, nur wie ich oben schon sagte: Ich habe etwas nachzuholen. Es ist jetzt 2019 und ich möchte soundmäßig wenigstens mal das machen können was der Amiga konnte und ab Mitte der 90er auch der PC. Was da genau rauskommt weiss ich nicht. Es ist eine reine Hobbysache. Kotzman II war mein letztes vollendetes Projekt, und da konnte ich nur BASIC und noch lange kein Assembler. ASM ermöglicht mir jetzt Dinge von denen ich damals nur träumen konnte (und sie wären damals schon möglich gewesen), und die möchte ich gerne jetzt endlich in Spielen nutzen, auch wenn das Ergebnis nicht professionell wird.
Ich bin Dir dankbar für Deine Hinweise und Tipps, aber es würde meinen Rahmen sprengen wie eine etablierte Spielefirma vorzugehen. Mir reicht für mich schon das Erfolgserlebnis zwischendurch, dass Dinge wie mein Musikplayer oder meine Grafikdarstellungsroutinen funktionieren. Es ist ein bisschen wie wenn Rentner Teppiche knüpfen - objektiv sinnlos, aber subjektiv macht es Spaß. Vielleicht wird ZVID2 ja annähernd so performant wie eine simple kompakt gehaltene (mit Schleifen) Routine mit Transparenzprüfung. Dann hätte es für mich eine allgemeine Berechtigung, neben der Speicherersparnis, die sich schon für Adventure-Spiele trotz Verlangsamung auszahlen würde. Werde ich sehen.
DOSferatu hat geschrieben:Bei Xpyderz wurde irgendwann der "Sprite-Speicher" knapp und gleichzeitig ergab sich, daß sowieso alle "Elemente" (Hintergrundkacheln, Sprites) kaum mehr als knapp 16 Farben haben - also entstand die Idee, statt verschwenderischem 8bit einfach auf 4bit mit Paletten zu wechseln UND Figuren mit gleichem Image, die nur unterschiedliche Farben haben (z.B. Spinnen) zusammenzufassen - et voilà: über 50% Speicherersparnis ohne Einschränkungen an der bisherigen Grafik und trotzdem wahlfreier Pixelzugriff, Drehbarkeit, Skalierbarkeit beibehalten. D.h. die neuen Routinen wurden entwickelt, um ein bestehendes Problem zu lösen.
Du siehst es bei mir vielleicht anders, aber meine Formate sind auch nicht nur zum Selbstzweck da. Ich möchte mir Möglichkeiten offen halten, bei denen ich die Datenmengen einschränken kann, aber nicht muss. Mit ZSM kann ich Chiptune-Musik machen, aber auch welche die einem Orchester ähnelt. Mit ZVID2 kann ich in einem Spiel vielfarbige bis einfarbige Grafik beliebig mischen, und habe immer optimal wenig Speicherbelegung (in den Grenzen die das Format leistet). Ich habe nunmal nicht die Situation, dass ich mitten in einer Spielentwicklung stecke, aber ich denke vorausschauend, was sich an Formaten eignen könnte, um im Real-Mode ohne Erweiterungsspeicher etwas ansprechendes auf die Beine zu stellen. Ich habe nur Bedenken was die Performance angeht. Vielleicht wird das Hauptproblem ZSM werden. Lass mich einfach mal mit meinem Kram auf die Schnauze fallen. Dann werde ich vielleicht ZSM wieder zu 8 Bit unkomprimierten Samples umschreiben und RLE codierte Grafik nehmen. Meine Formatspielerei liegt auch darin begründet, dass mich bisher noch keine zündende Spielidee beim Schopf gepackt hat.
DOSferatu hat geschrieben:Und auch ISM wurde ja (bekanntlich) nicht deshalb von mir entwickelt, damit ich "irgend etwas habe, um damit Musik zu machen", sondern einzig aus der Vorlage heraus, daß meine Spiele bisher keine Musiken/Klangeffekte hatten und ich diesem Manko Abhilfe schaffen wollte, ohne (wie bisher) für jedes neue Spiel irgendeine Lösung zusammenzukrüppeln.
Ähnlich bei ZSM - natürlich wollte ich immer schon einen eigenen MOD-Player schreiben, aber natürlich auch diese Art von Musik in Spielen haben. Adlib hatte ich schon bei Kotzman II, aber anstatt das Gebiet noch zu perfektionieren (mein Adlib Tracker konnte nur ein Instrument pro Kanal) habe ich jetzt direkt in meine liebste Art von Musikformat investiert.
DOSferatu hat geschrieben:Ich hätte bei dem ganzen Aufwand, den ich inzwischen für den ganzen Kram betrieben habe, schon längst meine Spielideen in direktem Code umgesetzt haben können: Das "Mehrfigur-Jump'n'run", das Raumgleiter-Shoot'em'up, ein Rennspiel... - aber ich habe mich letztendlich dagegen entschieden; ...
So weit bin ich in meiner Erfahrung noch nicht. Ich hatte zwar die Idee mit der Jump&Run Game-Engine, aber mittlerweile hat mich die Faszination ein wenig verlassen (oder ich bin zu sehr abgelenkt von anderen Dingen momentan), und ich würde tatsächlich ein Spiel ersteinmal "hardcoded" angehen. Sprites machen, Spiel schreiben, meine Formate benutzen, sehen, ob sie performen. Nicht anders habe ich es bei Kotzman II gemacht. Ich sehe mich auch in der Zukunft nicht als jemand, der regelmäßig Spiele rausbringt. Das können andere besser, die sich dem ganzen mehr verschrieben haben. Ich will mir nur ersteinmal noch einen Jugendtraum erfüllen, ein Spiel mit Transparenz und Digisound. Und wer weiss, vielleicht packt mich dann die Faszination und ich schlage einen Weg ein, der Deinem ähnelt. Aber bis dahin bin ich wohl doch mehr auf der Soundschiene unterwegs.
DOSferatu hat geschrieben:Naja, ich will das Ganze nicht schlechtreden und JA - 32bit-Kopieren in den Speicher kann (wenn schlau gemacht) einige Zeitersparnis bringen, ABER:
Selbst dann (bei einfarbigem Block) ist es wahrscheinlich unnötig. Weil:
1. Wie oft kommt das vor?
2. Die Routine, die prüft, ob ein gleichfarbiger Block vorliegt, braucht wahrscheinlich mehr Platz UND Zeit, als es die Sache wert ist.
Oder meinst Du, daß ein ganzer 4x4-Block einfarbig ist? Naja... Einerseits alles handpixeln wollen und bei Skalierungen die klotzigen Flächen monieren (bzw. bei Drehungen die Pixelgenauigkeit) und andererseits große einfarbige Flächen in Sprites wollen... das widerspricht sich ja schon irgendwie.
Bei normalen Sprites wird es kaum vorkommen, allerdings etwas anderes, nämlich die transparenten Bereiche, aber da werden dann einfach nur die Zielregister weitergedreht.
Es gibt keine Routine die prüft in dem Sinne, sondern jeder 4x4 Block hat ja einen Header, der direkt instruiert, wie die Daten interpretiert werden müssen. Einfarbige Blöcke wären bei größeren Comic-Grafiken denkbar und wahrscheinlich, und da könnte ZVID2 (oder wahrscheinlich nenne ich es richtiggehender ZSPR) wegen der dann wenigen Farben auch sehr große Bilddaten abspeichern.
Die handvoll Byte ASM Code für eventuelle einfarbige Blöcke kann man sich ja noch leisten. Und da kann man ja irgendwie nicht anders, als sich ein 32 Bit Register nehmen, es mit vier gleichen Bytes vollzustopfen und dann viermal an entsprechender Position in den Speicher zu hauen. Ist vielleicht auch eine Stilfrage - es ist "ausgerollt" weniger Code als wenn ich 16 einzelne Bytes schreibe oder auch 8 Words schreibe. Die einzelnen Blockroutinen werden per Sprungtabelle angesteuert, es wird sich alles in einer recht großen, aber dennoch einzigen Routine befinden (ich bin noch nicht so weit dass ich die Assembler-Routine geschrieben habe, ich bin noch dabei den Encoder für mehrere Sprites in einer Datei umzuschreiben). Da ich die innersten Schleifen "ausrollen" werde, d.h. pro 4x4 Block, müsste es zumindest was Sprünge angeht schneller gehen als z.B. eine Schleifenroutine die auf Transparenz prüft.
DOSferatu hat geschrieben:Die "Grafikfähigkeiten" von dem, was Borland da mitgeliefert hat, sind aber eher ein Witz
Ja, ich hatte mal ein Buch über Spiele programmieren inn Turbo Pascal. Als Pixelgrafik-verwöhnter Mensch fand ich das total deprimierend, wie da gezeigt wurde wie man irgendwelche Kartenspiele oder soetwas mit den Zeichenfunktionen von Pascal macht. Deshalb bin ich dann auch erstmal bei QuickBASIC geblieben. Hätte ich nur mal Assembler gekonnt...

DOSferatu hat geschrieben:
zatzen hat geschrieben:Kotzman II hat technisch sehr viel mehr Rückschläge, ich hätte mir noch gewünscht:
- Sprachausgabe (gescheitert an Unfähigkeit die Soundblasterkarte zu programmieren)
Inwiefern? Für die Zwischensequenzen oder auch im Spielverlauf?
Im Spielverlauf hätte ich gerne Digi-Sound gehabt, also Samples. Ich hatte das auch schon umgesetzt, auch in der ersten Zwischensequenz die Sprache, aber damals war ich nur dazu fähig, Digi-Sound an einem selbstgelöteten 8 Bit DAC am Druckerport auszugeben. Aber das konnte man natürlich nicht voraussetzen, da hätte ich jedem so ein Teil basteln und mitgeben müssen. Und man hätte sich entscheiden müssen - entweder Adlib Musik / Effekte, oder DAC. Und mit dem DAC war das auch nicht optimal. Mit meinen damaligen Fähigkeiten konnte während der Soundausgabe nichts anderes passieren. Ich konnte das nur in Abschnitte gliedern, und dann bspw. bei den Zwischensequenzen die Grafiken zwischendurch ändern.
DOSferatu hat geschrieben:Vergleiche mal nicht Deine Ohren mit den Ohren aller anderen Leute... - Mir reichen 8 Bit oft dicke aus und mit Fließkomma arbeite ich am liebsten... GAR NICHT.
Für Spiele reicht mir auch ein ziemlich ranziger Sound aus, ich verwende bei meiner Soundengine ja nicht einmal echte 8 Bit sondern 4 Bit Delta nichtlinear. Dagegen habe ich einen Freund der in Spielen unbedingt 16 Bit haben will und Formate wie FLAC. 32 Bit Fließkomma ist als Endprodukt auch sinnfrei, ich finde 16 Bit, wie es auf der CD ist, mehr als genug, aber einige Leute meinen das reiche nicht und wollen 24 Bit und 192 kHz. Aber das hat alles nichts mit Spielen zu tun, außer dass bei aktuellen Spielen sich wenigstens "CD Qualität" durchgesetzt haben wird.
Faktisch sind übrigens viele Musikproduktionen der letzten 25 Jahre so übertrieben laut ausgesteuert dass ich auch kaum einen Unterschied zwischen 16 und 8 Bit davon hören würde. Aber deswegen funktioniert das mit dem Mischen in 8 Bit bei ZSM ja auch so gut, man kann sich nicht beklagen, da hoch ausgesteuert und die 8 Bit auch voll genutzt werden (bei den meisten ZSMs). Bei leisen 8 Bit Aufnahmen, wo nur vielleicht 5 Bit zum Tragen kommen, und dann auch noch besonders klare Klänge drin sein sollen, da hört man es schon rauschen und klirren.
DOSferatu hat geschrieben:[...]und ich werde NIEMALS (ja, NIEMALS!) für Grafiken - selbst für Source-Bearbeitungen - mehr als 24Bit-Bilder benutzen[...]
24 Bit hat für jeden Farbkanal ja auch 256 Stufen, da hat man hinsichtlich einer VGA Grafik ja noch etwas "Headroom" was das Verlieren von Bits angeht, da standard VGA nur 64 Helligkeitsstufen kennt.
DOSferatu hat geschrieben:Konsolenartige "Brachialmusik" erst in 20facher Orchesterqualität zu erzeugen, nur um sie dann auf 4-Bit-Sound runterzukonvertieren... da müßt mein Herz 'n Affe sein...
Mache ich ja auch nicht. Ich setz mich ja nicht hin und komponiere wie einer der großen klassischen Komponisten eine komplexe Orchesterpartitur in Notenschrift. Ich setze mich einfach an den Tracker von 1994, nehme mir ein paar zurechtgestutzte Samples, damit alles nicht so groß wird, und habe dann (fast) schon den Sound, wie es im Spiel zu hören sein wird. Fast, weil ja noch die delta-Codierung dazukommt, also nochmal eine leichte Degradierung im Sound.
DOSferatu hat geschrieben:Wenn Du mehrere Figuren/Charaktere im Spiel haben solltest: Wer soll die Charaktere sprechen? Kennst Du so viele Leute, die Zeit UND Lust hätten, bei so etwas mitzumachen und sich zusätzlich auf den Weg zu Deinem Mikro machen würden, um viele lange Texte mit vernünftiger Betonung/Tonlage einzusprechen?
Es kommt drauf an. Viele verschiedene Charaktere und viele lange Texte, das klingt nach Adventure. Soetwas habe ich nicht vor, das würde ja schon an der Grafik scheitern, für die ich niemanden habe. Ansonsten wäre es wahrscheinlich, talentierte Leute auch im Musikerumkreis zu suchen, und die haben dann auch vernünftiges Equipment zum Aufnehmen, so dass sie gar nicht zu mir rumkommen müssen.
Letztlich kann ich aber nicht auf die paar Freunde setzen, die Musik machen. Ich würde da schon den gesamten Freundeskreis einbeziehen und dann sehen, wer von denen einigermaßen passende Stimmen hat und gut spricht. Und welche natürlich Zeit und Lust haben.
Es sollte klar sein dass ich mir für mein Spiel keine professionellen Sprecher leisten kann.
Die deutsche Version von Day Of The Tentacle hatte da wohl auch einen Kompromiss gemacht, vielleicht waren es Schauspieler, aber keine der markanten Stimmen die man aus Film und Fernsehen kennt.
Irgendwo muss da jeder seinen Qualitätsanspruch setzen. Ich selber könnte eine handvoll verschiedener Stimmen machen, aufgrund meiner Erfahrung im kreativen/künstlerischen Audio-Bereich. Käme dann noch Verzerrung dazu (wovon es heute sehr beeindruckende Dinge gibt), würde sich das nochmal verdoppeln oder verdreifachen.

So, auch wenn es sich weiter oben im Text vielleicht etwas anders angehört hat, habe ich dennoch Lust darauf, ein kleines feines Spiel zu machen, das trotz meiner komischen Weise zu programmieren Spaß macht zu spielen.

Ich würde gern einmal das Dithering bei (extremer) Vergrößerung von Sprites von Deiner Routine sehen. TGAME.EXE konnte ich gerade weder im Forum noch bei mir auf einer Festplatte finden, auch wenn ich mir sicher bin, es schon einmal gesehen zu haben.
mov ax, 13h
int 10h

while vorne_frei do vor;
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Eigenes Videoformat

Beitrag von DOSferatu »

Leider etwas lang geworden, habe jetzt keine Lust mehr, das einzukürzen, daher in zwei Teilen:
Teil [1/2]:
zatzen hat geschrieben:Hallo DOSferatu!
Hallo Zatzen!
Verzeihung, dafür, daß ich so lange nicht geantwortet habe. Irgendwie ist mir "mein Mójo abhanden gekommen" - will sagen: Ich habe schon eine ganze Weile nichts mehr programmiert/entwickelt; selbst meine alten Tools zu verbessern (neue Features/Debuggung) will nicht so recht laufen. Ich muß mal sehen, wie ich dieses Tal durchschreite. Ich hatte jetzt vor kurzem 2 Wochen Urlaub und derzeit habe ich 3 Wochen Urlaub (ich nehme fast meinen kompletten Urlaub immer im Herbst) und hätte Zeit gehabt - aber irgendwie wird derzeit nicht viel. Ich bin oft müde und es fällt mir immer schwerer, mich für irgend etwas zu begeistern. Ich hatte immer befürchtet, daß "ich einer dieser Erwachsenen werde", scheint, daß es inzwischen immer wahrscheinlicher wird. Mein Problem dabei: Andere Erwachsene scheinen das zu kompensieren, indem sie so einen Mist machen wie im TV Fußball schauen oder Alkohol trinken... - beides so gar nichts für mich...

Egal. Ich wollte aber endlich einmal antworten, das steht hier schon lange aus. (Du hast inzwischen schon in beiden Deiner Threads geantwortet.)

Irgendwie scheint das DOSforum auch langsam etwas abzusterben. Hier ist momentan extrem wenig los.
zatzen hat geschrieben:Ich habe zwischenzeitlich mal ein kleines Experiment gemacht und den Puffer von ZSMPLAY von 768 auf 512 Bytes runtergesetzt (Richtwert für 22 kHz, für 44 kHz wird dann das doppelte genommen). In einigen Modi kam es dann zu Stottern (44 kHz), bei 20000 Dosbox Cycles. Das hat mich schon etwas ernüchtert gestimmt, da die ZSMPLAY Modi ja nicht ansatzweise so komplex sind wie ein Spiel. Andererseits, als ich den Puffer auf 1024 vergrößert habe, lief alles problemlos sogar noch bei weniger als 8000 Cycles, was laut dem Dosbox Performance Test etwa der Leistung eines 386 mit 33 Mhz entspricht.
Mit einem Puffer von 1024 Bytes hätte ich eine Framerate von 21,5 - völlig ausreichend für meine Bedürfnisse.
Als ich das gelesen hatte, mußte ich ein wenig schmunzeln.
Ich gehe ja davon aus (auch weil von Framerate geschrieben wird), daß Dein Endziel weiterhin ein interaktives Unterhaltungsprogramm auf einem elektronischen System (nennen wir es mal "Computerspiel") ist. Deine obengenannte Berechnung geht allein vom Sound-Anteil aus. Also, ich denke, die Figurensteuerung/Abfrage (Kollision, Werte), sowie VOR ALLEM die Generierung der Grafik wird einen nicht zu unterschätzenden Anteil in der Spielschleife einnehmen, das passiert nicht einfach "in Nullzeit neben der Generierung des Sounds".

Oder anders ausgedrückt: Ja, es sind zwar (bei 320x200) nur 64000 Pixel (oder lassen wir es 60000 sein, wenn noch ein statisches Anzeigefeld dazukommt), aber die müssen ja nicht einfach irgendwie "von A nach B kopiert" werden, sondern die werden auch aus Levelblockdaten und Spritedaten herausgekratzt und entsprechend umgewandelt. Meiner Erfahrung nach geht recht viel Performance für die Generierung der Grafik drauf.

Ich tue mich sowieso schwer dabei, im Vorfeld einzuschätzen, wie meine Framerate sein wird - zumal es ja keine 2 PCs auf der Welt gibt, die absolut gleich schnell sind (Baukastensystem aus unterschiedlichen Komponenten - Motherboard/Chipsatz, CPU, RAM, Grafikkarte, Soundkarte, I/O... - die ALLE die Performance beeinflussen). Ich versuche immer, einerseits möglichst performant zu programmieren (eher, nicht mit Absicht etwas langsam zu machen), andererseits aber auch, mir eine gewisse Palette an Features zu ermöglichen...

Da muß ich immer sehen, daß ich nicht "das eine Superfeature" unbedingt haben will und nur deswegen funktioniert alles andere nur noch "so lala"... Und wie sehr das performt, sehe ich leider erst am Ende, wenn alles zusammengebaut ist und gemeinsam zusammenarbeitet. Das kann ich leider nicht planen, dazu ist der Kram irgendwie zu komplex. Deshalb kann ich auch vorher nie etwas auf eine feste Framerate auslegen.

Bei interaktiven Programmen (Spielen) hängt die aktuell benötigte Leistung ja auch maßgeblich von der aktuellen Spielsituation ab - die nicht immer 100% vorhersehbar ist: Wieviele Spielfiguren (Sprites) sind aktuell darzustellen? Wieviele sind zu steuern (onscreen UND offscreen)? Wieviele Soundeffekte sind derzeit gleichzeitig abzuspielen? Dann kommt noch das Thema der Kollisionsabfragen dazu, was sich quasi mit der Anzahl vorhandener Figuren leider nicht linear erhöht, sondern potenziert (es sei denn, man benutzt ein paar Tricks, die aber etwas zusätzlichen Speicher und zusätzlichen Code brauchen - und selbst dann trotzdem etwas Leistung ziehen).

Wie ich ja schon einige Male erwähnt habe, halte ich (persönlich) es nur für eine mittelmäßig brauchbare Idee, die komplette Spielentwicklung von vornherein "um die Soundberechnung/Soundausgabe herum" zu konzipieren. Aber ich sollte ja nichts mehr dazu sagen - will auch nicht nerven.
zatzen hat geschrieben:Hier direkt mal die Antwort auf Deine Frage, wo ich die Daten für den nächsten Puffer generiere: In der Hauptschleife, nicht im Interrupt, der setzt nur eine Boolean Variable auf true, also ein flag.
Ja, so mache ich das auch. Wegen "Erweiterbarkeit" (und logischer Überlegungen) setze ich nicht nur ein Flag, sondern erhöhe eine Variable (und verringere sie wieder, wenn ein neuer Puffer generiert ist). Einerseits habe ich dann die Option, statt Doublebuffer auch z.B. Triplebuffer einzusetzen, andererseits habe ich die Kontrolle, wenn dieser Wert bei Doublebuffer z.B. mal größer wird als 0 oder 1 ("... und ich glaub, ich hab ne Zwei gesehen!" - "Ach, Bender! Beruhige dich! Es gibt doch überhaupt nicht sowas wie ne Zwei..."), daß ich dann merke, daß hier der Sound "ausläuft"/"überläuft" bevor der Rest fertig ist. - Und vielleicht dann eine Kontrollfunktion einbauen, die die Framerate der Grafikberechnung dann automatisch künstlich heruntersetzt, um Stottern zu vermeiden... Ja, ich denke wahrscheinlich schon wieder viel zu kompliziert...
zatzen hat geschrieben:
DOSferatu hat geschrieben: Ich möchte - nach all der Mühe, die ich mir mit den Puzzleteilen für meine Spielengine(s) gegeben habe - jetzt nicht irgendeinen uninspirierten Mist zusammenmurksen.
Ich hatte in meiner Jugend wenige, dafür aber dauerhafte Ideen, so dass ich mich gar nicht lange fragen musste was ich machen solllte, siehe Kotzman... Die Idee war einfach da, und anstatt daran zu zweifeln habe ich einfach losgelegt, was auch nicht unbedingt das beste war, aber so habe ich wenigstens etwas gemacht.
Naja, an Ideen mangelt es mir wahrhaftig nicht. Ausschließlich Xpyderz war keine direkte "Idee" - sondern hatte eher als eine Art Experiment angefangen. Hatte den Werdegang schonmal erklärt, muß das jetzt nicht wiederholen.

Ich meinte nicht, daß ich keine doofe Ideen zu einem Spiel zurechtmurksen will - sondern eher, daß ich gute Spielideen dann nicht technisch schlecht umsetzen will. Ich sag's mal so: Den Spieler interessiert zwar nicht die interne Programmierung/Technik dahinter - aber dem Spieler fällt eben auf, wenn sich etwas hakelig spielt, nicht richtig reagiert, bestimmte Dinge nicht passieren, die eigentlich passieren sollten usw.

Nur mal ein Beispiel: Zu grobe Kollisionsabfrage
Man schießt auf eine "Feindfigur", die einem "zu nahe kommt", um sie aufzuhalten. Projektil zu klein, Abfrage zu selten. Projektil wird einmal VOR und einmal HINTER der "Feindfigur" abgefragt, geht also "durch die Figur durch"... Dann "Feindfigur"+"Spielerfigur": Beide Figuren trotz grober Abfrage groß genug - da funktioniert Kollision, ergo: Spieler verliert ohne eigene Schuld Energie oder Spielerleben. Ergebnis: Da kann die Grafik noch so schön sein und die Musik/Effekte noch so toll - der wird sagen "Scheiß Spiel" und "unfaire Engine" usw. Und spielt das nicht mehr. Wäre dann schade um die ganze Mühe. Das meine ich.
zatzen hat geschrieben:Es war so eine ungefähre aber beständige Ahnung was ich machen wollte, die mich antrieb. Ich hatte meine damaligen Comic-Figuren, Kotzman und Saugi, in das Spiel haben verschiedene damalige Dinge reingespielt, auch dass wir mal einen Hamster hatten.
Ja, wie gesagt: Ich habe inzwischen 4 Spielideen, von denen 2 mit der derzeitigen "Kombi-Engine" (SLOT) umsetzbar wären, wenn sie fertig wäre und 2 noch etwas Zusatzkram bräuchten.
Die 2 ersten:
- Raumschiff-Ballerspiel Einfach mal selbst so etwas machen, im Stile von R-Type und Katakis. Habe hier schon 16-Farb-Grafiken, weil ich das damals mal ganz anders angefangen hatte und die Grafiken in meinem ersten, IN TEXTMODE gebauten(!) Malprogramm gemacht hatte.
- Jump'n'run mit mehreren Spielcharas. Komplett eigene neue Spielidee mit interessanter Story und viel Humor. Habe auch schon einige Grafiken/Sprites teilweise fertig.

Die 2 anderen:
- Rennspiel in 3D (2,5D) mit Spritefiguren und 3D-Level (habe da schon ne 3D-Engine, die schon in Pascal ganz OK ist, aber in ASM der totale Performer wäre. Allerdings ist die bestimmt auch schon über 10 Jahre alt.)- Spielidee auch etwas crazy, einiges an Humor. Etwas "futuristisches" Setting. Habe hier auch schon teilweise Grafiken/Sprites.
- Point&Click-Adventure. Technisch zwar kein Problem, erfordert aber für die Grafiken Zusatzzeug (Objekt/Wege-Markierung), außerdem natürlich noch die Reaktions-Engine für Adventures, obwohl ich dazu schon 100% wüßte, wie die zu funktionieren hätte. Da auch schon eine konkrete Idee/Story vorhanden, noch keine Grafiken vorhanden.

Ich habe schon so ca. 12 (vielleicht auch mehr) Musiken (Melodien usw.) mal aufgenommen (ins Mikro gesummt/gepfiffen), um sie mir zu merken, die meisten eher passend für "Action"-lastiges Zeug. Müßte die dann in prISM umsetzen.

Will also sagen: Ich habe mindestens 4 Spielideen, die ich, falls der Code-Anteil fertig vorhanden wäre, sofort anfangen könnte umzusetzen. Zusätzlich habe ich noch einige Idee-Fragmente. Eine davon ist z.B., das Raumschiff-Ding zurückzustellen, weil in o.g. Jump'n'run auch ein Fluglevel enthalten sein soll, das sich dann so steuert.
zatzen hat geschrieben:Und zwischendurch habe ich immer wieder improvisiert, wusste also am Anfang nicht wirklich wie es am Ende aussehen würde. Und ich denke, ähnlich werde ich es auch wieder machen. Alles wird parallel wachsen, Leveldesign, Grafiken, Sound. Wobei ich diesmal wohl schon eher nach einem "Format" vorgehen werde, wie das Spiel grundsätzlich strukturiert sein soll.
Naja, bei Xpyderz habe ich viel improvisiert und bei anderen Spielen auch mehr oder weniger.
Aber ALLE anderen meiner PC-Spiele waren dermaßen winzige Projekte, daß es da nicht schlimm war, weil die Leistung/Speicher eines PC dafür in jedem Fall dicke ausgereicht hat und man somit keine Überlegungen über Performance oder Speicheraufteilung anstellen mußte.

Aber genau das will ich ja jetzt vermeiden und deshalb dauert es schon so eine Ewigkeit: Ich will nicht während der Spielentwicklung dauernd am Programm herumschrauben müssen und die so schicken glatten und (für sich alleine) gut funktionierenden Engines (Grafik, Sprite, Sound, Steuerung, Menüsystem, I/O, Laden/Speichern...) dann wieder durch unsaubere reingeklatschte Workarounds "versauen", die alles größer und langsamer machen ohne Mehrwert für das Spiel/den Spieler.

Ich meine: Wenn man irgendwelche Fremd-Engines/Codeschnipsel benutzt (ohne zu wissen, wie sie funktionieren) und die nicht GENAU das tun was man will und man deshalb so einen Workaround "außenherum anflanschen" muß, weil einem keine andere Chance bleibt - das wäre das EINE - aber etwas ganz ANDERES ist es, Dinge, die man SELBST entwickelt hat (wo man also die Sourcen hat und weiß was sie tun) trotzdem zu workarounden, anstatt sie gleich so zu machen, wie man sie haben will.

Ich verstehe natürlich, was Du meinst: Man kann während der Entwicklung Fehler sehen und die Dinge dann entsprechend im Source noch anpassen. Wird wahrscheinlich auch noch irgendwann passieren. Andererseits ist es so, daß irgendwann dieser ganze Kram wie eine komplette Einheit funktionieren muß, wo die Einzelteile aufeinander abgestimmt zusammen in dem, was ich immer die "Spielschleife" nenne, funktionieren müssen und wo Änderungen an gewissen Einzelteilen/Werten sich dann im schlimmsten Fall wieder auf den Rest auswirken.

Auch hier - wahrscheinlich denke ich da wieder viel zu kompliziert. Ja, es liegt bei mir eben daran, daß ich dieses Xpyderz gemacht habe und von hingemurksten Workarounds kann ich da leider ein Lied singen. Ich finde es immer noch erstaunlich, daß das Ding so stabil läuft (ist mir noch nie abgestürzt!) - Aber da denke ich, daß da eine Menge Glück dabei war. Und gerade bei elektronischen Systemen, die binär "denken", sollte man sich nicht auf Glück verlassen.

Früher habe ich, wenn etwas (endlich) funktioniert hat, nicht mehr nachgefragt/geforscht, warum, sondern habe das so hingenommen und war froh. Leider kann es aber passieren, daß da auch quasi nur "mehrere Bugs sich gegenseitig auffressen" oder ähnliches und man dann irgendwann, wenn man schon an ganz anderen Baustellen arbeitet, von plötzlichen unvorhergesehenen Ereignissen überrascht wird, bei denen man dann Monate verbringt, diese zu verstehen, ohne damit zu rechnen, daß sie von einem Teilsystem stammen, das schon als "funktionierend bestätigt" gegolten hat.

Es ist eben schade - wenn man so ein Hobby-Krauter ist, der alles allein macht, ist man selbst gleichzeitig Entwickler und Tester und "betrügt sich leider manchmal selbst", ohne es zu merken...
zatzen hat geschrieben:
DOSferatu hat geschrieben:[...]Außerdem benutze ich z.B. gern BX[...]
Gut, dass Du es nochmal erwähnst, ich hatte jetzt schon daran gedacht, in meinen ZV2 Routinen BX für die Vorbereitung der Sprünge BX zu verwenden, aber ich kann da ja auch z.B. AX (jmp ax) nehmen und BX dauerhafter verwenden.
Naja, was man wo verwendet, bleibt einem ja selbst überlassen - je nachdem, wo es am besten paßt.
Ich muß allerdings sagen, daß ich ganz gut damit gefahren bin (Code wird kleiner und gescheiter), vor allem bei "Engine-artigen" Dingen, vorher festzulegen, welches der CPU-Register welche Aufgaben erhält. Auf diese Art ist man nicht dauernd am "Register-jonglieren" - man weiß ja auch, welche x86-CPU-Register was können usw.

Das bedeutet nicht, daß man nicht auch Ausnahmen davon machen kann, wenn es mal besser paßt. Aber in Situationen, wo die Registerwahl quasi EGAL wäre (und das ist oft so, weil für viele Operationen JEDES Register genommen werden kann!), nimmt man eben das (vom selbstgemachten Plan) dafür vorgesehene. Damit bin ich persönlich immer ganz gut gefahren. Bei GameSys2 z.B. habe ich wirklich alle 7 (Ausnahme SP) verwendet, wobei 5 (quasi-)fest zugewiesene Aufgaben hatten und 2 als "frei" für die ganzen Operationen genutzt wurden. In ISM habe ich das dann ebenfalls so gemacht - da war es nur eine andere Registeranordnung.

Als ich mit Assembler angefangen hatte und mit diesen ganzen Dingen noch etwas "erschlagen war", habe ich da erst einmal so weitergemacht, wie ich es von Pascal gewohnt war... Allerdings bietet einem Assembler ja ganz andere Möglichkeiten, einige komfortabler, einige weniger komfortabel als Hochsprache. Und sich bei Assembler-Programmierung erst einmal zu 70% von allem zu verabschieden, was man aus der Hochsprachen-Programmierung kennt, das mußte ich auch erst einmal lernen.
zatzen hat geschrieben:Die Routine überprüft zuerst, ob das gesamte Sprite überhaupt sichtbar ist. Das geschieht durch simple Additionen und Subtraktionen. Wenn nicht, verabschiedet sich die Routine sofort.
Das ist natürlich klar - alles andere wäre ja albern.
zatzen hat geschrieben:Als nächstes wird das 4x4 Block clipping berechnet, wieviel links, rechts oben und unten übersprungen werden muss (auch alles Subtraktionen/Additionen), und daraus ergibt sich dann eine zweidimensionale Schleife die abgearbeitet wird, bei nicht zu zeichnenden Bereichen müssen die Daten der Quelle jeweils nur übersprungen werden.
Wenn absehbar ist, dass im Spiel kein Clipping vorkommt bzw. alle Grafiken vollständig im Bildschirm bleiben, kann man eine entsprechend optimierte Routine dafür basteln, die dann etwas schneller sein wird. Ob ich beide in die gleiche Unit packe oder zwei Units mache hängt davon ab, ob der Compiler ungenutzte Routinen mitkompiliert oder nicht.
Der (Borland) Pascal-Compiler kompiliert nur Dinge, die mindestens einmal irgendwo im Code namentlich aufgerufen/verwendet werden (verschachtelt, d.h. wenn Routine B Routine C aufruft, aber Routine B von Routine A nie aufgerufen wird, wird Routine B UND Routine C nicht einkompiliert). Anders ist es mit Assembler. Ein Assemblerblock wird immer genau so in den Code einassembliert, wie er da ist - außer er wird als Pascal-Procedure/Function aufgerufen (bzw ist Teil einer Pascal Procedure/Function) - in dem Fall dann natürlich auch nur dann, wenn diese Procedure/Function in irgendeinen nicht auskommentierten/ausgefilterten Soucebereich erwähnt wird.

Natürlich gibt es ja auch noch die Compilerschalter - diese funktionieren auch innerhalb von Assemblerblöcken.
zatzen hat geschrieben:Danke, das mit dem in den kompilierten Code gucken, wegen RETF/RET etc. am Routinenende werde ich dann mal probieren.
Naja. wie gesagt: Eigentlich gibt es ja nur zwei Gründe, wieso eine Routine beendet werden soll: Grund 1: Routine ist fertig. Dann kann man auch einfach den "Fertig"-Bereich ans Ende setzen, außer wenn das nicht so performt - dann eben in die Mitte noch einen RETF/RET mit entsprechenden Dingen zusätzlich einbauen.
Grund 2: Routine ist vorzeitig "fertig" oder muß wegen Fehler abgebrochen werden (ist also eine andere Art von fertig) - dies ist aber immer Ergebnis einer Entscheidung, also ein bedingter Sprung. So ein bedingter Sprung kann ja dann auch direkt ans Ende der Routine springen. Meist ist die "Fertig"-Bedingung ja die seltenere als die "Noch am Laufen"-Bedingung - somit macht also der Sprung nicht den Prefetch-Queue nur dann kaputt, wenn da sowieso nichts mehr zum Kaputtmachen da wäre, weil der Rücksprung (RET/RETF) ohnehin keine Prefetch-Daten benötigt. (bedingter Sprung löscht Prefetch-Queue nur dann, wenn gesprungen wird).
zatzen hat geschrieben:
DOSferatu hat geschrieben:Wenn der Sound "synchron" zur Grafik sein soll, die Grafik dann aber nur 5 FPS hat - zu WAS soll der Sound dann synchron sein?
Es kommt drauf an, wie genau man das mit den Puffern anstellt. In der Hauptschleife berechne ich die Grafik und genau für dieses Bild den entsprechenden Ton. Im nächsten Schritt wird diese Grafik dargestellt und der berechnete Ton abgespielt. Somit, selbst bei nur 1 fps, würde man ein Bild von einer Explosion sehen mit dem passenden Sound. Das funktioniert dann, wenn die zeitliche Auflösung des Spiels letztlich an die Framerate gebunden ist - was bei Dir ja eher nicht er Fall ist. [...]
Naja - kommt drauf an. Wenn der Rechner schnell genug ist, dann ist es so, daß Framerate und Spielrate gleich sind (kann die Framerate sogar höher werden, das kann an dann begrenzen, damit nicht sinnlos identische Bilder berechnet werden). Bei mir ist der Unterschied nur der, daß, wenn der Rechner zu langsam ist, bzw. falls der Rechner man VORÜBERGEHEND zu langsam ist (kurzer Peak der Auslastung durch irgend etwas kompliziertes) das ganze kompensiert wird.

Das würde ich auf einem monolithischen System nicht so machen - da weiß man genau, was das leistet und könnte mit richtig sauberem (d.h. auf die Bildwiederholrate der Ausgabehardware angepaßtem) Scrolling arbeiten. Aber bei einem PC weiß ich eben nicht vorher, welche Leistung der bringt und bei Spielen, die auch von anderen benutzt werden sollen, gehe ich nicht immer nur von meiner eigenen Maschine aus.

Ich hatte Xpyderz damals auf meinem langsameren 486er-Laptop (66 MHz, langsameres Motherboard) angefangen, da war ich quasi "unterwegs bei Kumpels". D.h. ich habe hier verschiedene DOS-Maschinen (und auch Windows-Maschinen, die sowohl "Halb-Echt" (NTVDM von WinXP) also auch "Unecht" (DOSBox) das Zeug abspielen können und überall habe ich unterschiedliche Frameraten - aber überall ist das Ding noch spielbar. Hab ja mal erwähnt: Bei niedrigerer Framerate (außer wenn sie ZU niedrig ist) interpoliert das Gehirn Bewegungen selbst mit.
zatzen hat geschrieben:Damit das Spiel aber nicht total lahm ist, muss ich intern meinetwegen mit drei oder vier Zyklen rechnen und davon eben nur einen pro Frame ausgeben. Dadurch wird die Korrelation von Ton und Bild ein wenig auseinanderdriften, aber bei vernünftigen Framerates kaum merklich.
Ja, genau das ist ja auch das Geheimnis dahinter, wie man "Kollisionen" (z.B. mit dem Level), d.h. daß Figuren genau "auf dem Boden" landen (nicht 3px darüber, nicht 3px darin) oder wenn irgendwas "von Wänden abgelenkt" werden soll, daß das dann genau so passiert wie es muß. Unterschied bei mir ist da: KEINER. Denn die Steuerung passiert IMMER 100% genau, jeder der Schritte wird ausgeführt, egal wie lahm die Kiste ist, damit es überall das gleiche Spiel ist. (Da gibt es dann eben eine Untergrenze, ab welcher Rechnerleistung es nicht mehr spielbar ist,) Es wird eben (wie ich mal erwähnte) von der Grafik immer "wenn mal Zeit ist", d.h. wenn das vorige Grafik/Sound-Frame berechnet wurde, eine "Moment-Aufnahme" der derzeitigen Spielsituation in Grafik umgesetzt. Die Steuerungs-Routine weiß nichts davon, ob/wann das, was sie da macht, angezeigt wird oder nur intern läuft - die hat das auch nichts anzugehen.

Natürlich ist es IMMER klar, daß ein Spiel mit zu geringer Framerate irgendwann unspielbar wird. Beispiel: Spiel hat 3 FPS, intern wird mit 50 FPS gerechnet - da gehen einem als Spieler 47 Spielzustände ungesehen verloren, d.h. es passieren ca. 16 interne Schritte, bevor man wieder sieht, was passiert ist. Dabei können dann natürlich schon sehr leicht "unfaire Situationen" entstehen, weil das Spiel intern jeden Schritt des Spielers "sieht"/ausführt und auch die "eigenen" Figuren darauf reagieren läßt - der Spieler jedoch nicht die gleiche Situation hat.

In gewissem Maße geht das ja noch - weil sich die Figuren ja quasi "auf einem Weg" bewegen und man auch die Zwischenpositionen selbst impliziert (ein Spiel, das ein Mensch spielen kann, hat NICHT 50x pro Sekunde eine komplett andere Spielsituation, die NICHTS mit der davor und der danach zu tun hätte).

Die Erklärung ist ja einfach: Wäre der Mensch wie ein Computer, bräuchte er keine grafische Ausgabe der Spielsituation, sondern nur eine große Anzeige in Textmode, bei der alle Koordinaten der beteiligten Elemente und des Levels ständig ausgegeben werden und würde darauf wie ein Computer reagieren können - und Framerate wäre bei Textmode für so etwas kein Problem. Allerdings IST der Mensch ja KEIN Computer und lebt in einer Welt, die er über audiovisuelle Reize wahrnimmt. (Die restlichen werden durch Computerspiele noch nicht umgesetzt, trotz "Rumble" im Control-Pad. Es gab sogar mal ein Dongle - glaub für LPT - da hat so ein Ding 1024 verschiedene GERÜCHE abgesondert, für das Spielerlebnis...)

Das heißt, daß der Mensch natürlich leichter und schneller auf bildlich dargestellte, pseudo-bewegliche Objekte reagieren kann - und beim Computer ist es genau umgekehrt. Der Computer braucht viel mehr Aufwand/Rechenleistung, um auf bildliche Objekte zu reagieren als auf sich ändernde numerische Werte.

Das ist eigentlich der Witz an jedem Computerspiel. Eigentlich ist der Computer eine Rechenmaschine und der kann auch nichts anderes als Berechnungen anstellen und auf die Rechenergebnisse zu reagieren - und dazu noch Werte von Speicher zu Speicher kopieren. Daraus ein interaktives audiovisuelles Erlebnis zu machen, da muß man schon Lust drauf haben...
zatzen hat geschrieben:Es sei denn ich teile den Soundpuffer ebenfalls in drei oder vier Teile, dann käme es wieder genau hin. Der Performanceverlust dadurch könnte weniger drastisch ausfallen, als wenn man den Soundpuffer insgesamt verkleinert, wodurch die Framerate steigen würde und somit die Anforderung an die Grafikleistung.
Naja, den Soundpuffer in mehrere Teile teilen ist (für die Performances) das gleiche, wie ihn zu verkleinern. Aber ich schätze, Dir geht es dabei darum, eventuelle "Unregelmäßigkeiten" durch Triple-/Quadruple-Buffering (statt Double) ausgleichen zu können (für langsame Maschinen). Um Sounddaten "vorzuberechnen", wenn Zeit ist und immer noch "genug Sounddaten" da zu haben, falls es mal knapp wird. Sollte es so sein, dann hast Du prinzipiell verstanden, worum es mir bei dieser "von der internen Spielsteuerung getrennten Framerate" wirklich geht.

Der gravierende Unterschied bei Sound (im Gegensatz zu Grafik) ist, daß es bei Grafik auch noch akzeptabel ist, wenn die Framerate mal einbricht - bei Sound aber nicht! Wenn Sound zu stottern oder zu "loopen" anfängt, wäre es wohl allen Leuten lieber, GARKEINEN zu haben, als diese Beleidigung für die Ohren. Es wäre natürlich mega-genial (!), wenn man, wenn das System merkt, daß die Performance nicht reicht, automatisch die Soundqualität (also die Abtastrate!) runtersetzen könnte, ohne daß der Sound abbricht. Ulkigerweise wäre das für MEINE Routinen sogar technisch möglich! Ich kann bei jedem Soundbufferframe angeben, in welcher Rate die generiert werden soll und könnte auch für jede Ausgabe des Frames dann die Ausgaberate ändern.

Klingt erstmal wie Schwachsinn - glaube auch nicht, daß das JEMALS irgendwer mal so gemacht hätte (aber technisch wäre es wie gesagt möglich). Normalerweise wurde man bei PC-Spielen vorher nicht nur nach der eingbauten Soundhardware gefragt (außer die haben die BLASTER / ULTRASND Env.Variablen abgefragt), sondern man konnte auch immer die Soundqualität/Rate wählen, weil zu den Hauptzeiten von DOS viele Heim-PCs noch ziemliche "Krücken" waren (naja, so'n voll ausgestatteten guten 486er für so um die 5000 DM konnte sich 1993 nunmal nicht jedes Zocker-Kid leisten...) und da war es eben gut, auch so Optionen wie 11kHz (oder bei so Emulatoren auch 8kHz) zur Auswahl zu haben.
zatzen hat geschrieben:Interessant wäre noch zu überlegen, statt der internen z.B. vervierfachung der Zyklen, direkt nur mit der groben Auflösung zu rechnen wie sie die Framerate vorgibt. Aber wie sollte man soetwas anstellen? Ich würde intern wenigstens Pixelgenau auflösen wollen, also dass die Kollisionen wie das abprallen von Level-Kacheln exakt detektiert wird. Du merkst vielleicht, so viel Erfahrung habe ich da noch nicht.
Ja, wie gesagt, genau DAS ist eigentlich die Idee dahinter, wieso ich meinen Kram so mache, wie ich ihn mache! Der Thread (und auch der andere) sind schon so lang, will nicht extra suchen, aber ich bin mir fast sicher, daß es es schon erwähnt habe: Der ursprüngliche Plan bei Xpyderz war ja, daß es Multiplayer werden soll. Bei einem Multiplayer-Spiel darf aber nicht auf jedem PC das Spiel in unterschiedlicher Geschwindigkeit laufen, sonst ist das schon nach ein paar Sekunden nicht mehr synchron.

Also muß das "eigentliche Spiel" (also nicht das, was da grafisch passiert) intern überall gleich schnell laufen. Das war eigentlich das ursprüngliche Ansinnen, was mich auf diese Idee brachte. Allerdings hat sich herausgestellt, daß das auch für Singleplayer gilt. Wer will schon, daß auf einem Rechner mit der halben Rechenleistung die Figur nur halb so schnell rennt? Dann ist es ja nicht mehr das gleiche Spiel. Man kann bei Xpyderz übrigens sogar die Spielgeschwindigkeit runterdrehen. Eigentlich ist das dazu gedacht, unter den WinNT-Systemen (vor XP) die Geschwindigkeit anzupassen, weil die nicht 1:1 so umgesetzt wird, wie ich die im Ticker einstelle (habe eine Vermutung, woran das liegt, aber das würde jetzt zu weit führen. Ich sage nur mal: Der zweite Timer...)
zatzen hat geschrieben:
DOSferatu hat geschrieben:...und der Knall (oder was auch immer) hat auf der Grafik schon stattgefunden und dann wird der Effekt erst eincodiert - und dann erst im NÄCHSTEN Soundframe ausgeführt
Und genau das mache ich anders. Vielleicht mache ich es ja falsch: Ich berechne die Sounddaten und die Grafikdaten, warte auf den Interrupt, dann spielt der gerade berechnete Puffer ab und ich zeige die gerade berechnete Grafik an. Das ist dann synchron wie ein Video, nutzt nur nicht die volle Performance, weil ich auf den Interrupt warte und die Framerate fest ist.
Und wie gesagt, was bei Dir beim Sound passiert, passiert relativ zur Steuerung bei mir bei Grafik UND Sound: Sagen wir mal man drückt auf "springen". Gerade wird noch ein berechnetes Bild angezeigt, währenddessen wird der Tastendruck registriert. Nächster Frame: Die "Feinde" haben sich einen Zyklus weiterbewegt, der Befehl "springen" wird gerade berechnet. Übernächster Frame: Jetzt sieht man endlich wie sich die Figur bewegt, allerdings dann auch mit zum Bild passenden Sprungeräusch.
Naja, kommt eben auch darauf an, wie oft man das abfragt, was der Spieler steuert. Wenn man das auch nur 10x oder 20x abfragt, genau wie den ganzen Rest, ist es wohl OK. Ich weiß auch nicht, ob Deine oder meine Vorgehensweise die schlauere ist und kann mir da auch kein Urteil erlauben.

Bei mir ist das Konzept eben schon an sich völlig anders: Die Grafikroutine, die Soundroutine, die Steuerroutine und die I/O-Routine wissen voneinander gar nicht, was die andere gerade macht. Grafik+Sound sind reine Ausgabe. Steuerung ist reine Verarbeitung. I/O (Hauptsächlich dann I) ist reine Eingabe. D.h. die Steuerung erhält kein Feedback von den Sound- oder Grafik-Routinen. Bei mir bauen sich die Sachen nicht aufeinander auf, sondern laufen die ganze Zeit "nebenher" in der Schleife und versuchen jederzeit, soviel wie technisch möglich zu schaffen.
zatzen hat geschrieben:
DOSferatu hat geschrieben:Du - als jemand aus der Sound-Ecke - scheinst bei der Spiele-Entwicklung/-planung ziemlich auf den Sound-Anteil fixiert zu sein. Will sagen: Wenn die Grafik klotzig oder ruckelig [...]
Es liegt im Prinzip vor allem daran, dass ich bisher das Timing nie anders gemacht habe als über den Soundpuffer-Interrupt. Das bringt dieses "spielbares Video" mit sich, und ist nebenbei für mich die einfachste Art, Bild und Ton auszugeben. Ansonsten habe ich natürlich eine gewisse Faszination für Sound. [...]
Naja, ich habe immer einen Unterschied zwischen Video und Spiel gemacht. Beim Video bekommt man wesentlich leichter Klang und Bild synchron als bei einem Spiel - da kann man einfach bestimmte, durch technische Dinge bedingte Dinge umgehen, indem man hier einen zeitlichen Versatz einbaut. Bei einem Spiel muß man ja auf die unvorhersehbare Komponente (den Spieler) reagieren, der wie der Stein ins Wasser ist (schlägt Wellen, beeinflußt alles andere mit) bzw. wie der Schmetterlingsflügelschlag, der auf der anderen Seite der Erde einen Tsunami verursacht.

Will sagen: Der Spieler tut etwas, das das Programm vorher nicht "weiß", zusätzlich muß das Spiel (die restlichen Figuren) darauf reagieren - wobei man vorher auch nicht weiß, wie, weil das ebenfalls vom Spieler abhängt, usw. Somit kann man hier nichts "vorberechnen", bevor es passiert ist. (Außer, man hätte so viel Speicher/Rechenzeit, daß man für alle denkbaren nächsten Situationen vorher schon Grafik und Sound berechnen würde und wenn es soweit ist, nimmt man die eine richtige und löscht die anderen wieder.)
zatzen hat geschrieben:Seit 1992 habe ich einige Spiele, davon nur ein paar wirklich vorzeigbar, gemacht, aber meine Programmierfähigkeiten haben nie dazu gereicht, die Spiele mit ansprechendem Sound auszustatten. Kotzman II war da schon eine kleine Revolution, mit Adlib. Ich habe jetzt einfach etwas nachzuholen, und Du musst verstehen, dass jemand der vor 26 Jahren angefangen hat sich mit Tracker Musik zu beschäftigen (genauer: Den 4 Kanal MODs, die in den meisten Amiga Spielen zum Einsatz kamen), und mehrere hundert Musikstücke im Tracker gemacht hat, und sich dadurch auch sehr intensiv mit Sampling auseinandergesetzt hat (die ersten Jahre zwangsläufig mit 8 Bit und niedrigen Samplerates), jetzt, wo er soetwas programmieren kann, das auch in eigenen Spielen zum Einsatz bringen möchte.
Selbstverständlich verstehe ich das. Es geht mir auch nicht darum, Dir irgendwelche Vorhaben schlechtzureden - mir geht es hier rein um die technische Seite des Ganzen.
zatzen hat geschrieben:Es ist wohl so, dass ich nicht zu einem Spiel ohne Sound motiviert wäre. Das muss aber nicht heissen dass ich vor habe, ein Pong mit Beethovens Pastorale dazu zu programmieren. Es ist vielmehr so, dass ZSM flexibel ist und auch sehr bescheiden eingesetzt werden kann. Ich werde mir den Code auch nochmal genauer ansehen, ob man da bei der Delta-Decodierung nicht noch etwas beschleunigen kann.
Naja, ich denke schon, daß ZSM besser performt als ISM und das auch mit höherer Qualität des Klangergebnisses. Und ja, genau so etwas wollte ich damit sagen: Daß man - bei aller Liebe zum Sound - nicht vergessen sollte, daß guter Sound (genau wie auch z.B. gute Grafik) keine Rechtfertigung sein darf für kein gescheites Gameplay, schlechte Steuerung oder ähnliches - in diesem Fall (d.h., wenn da im "interaktiven" Bereich keine Begeisterung rüberkäme) könnte man den Leuten auch gleich ein Soundarchiv oder ein Bilderarchiv geben, wenn's einem nur darum ginge, Bilder oder Klänge "unter die Leute zu bringen" und ein "primitives/ ruckeliges/ schlecht-steuerbares" Spiel an sich nur als Vehikel/Krücke dazu dient, dies zu "transportieren". Ich bin zwar auch begeistert, wenn ein Spiel schöne Grafiken/Musiken/Effekte hat - aber wenn da nichts gescheit Spielbares dran ist - und es mir ums SPIELEN geht - dann spiele ich eher ein 4-farb Game mit Speakersound, wenn dafür das Gameplay stimmt.
zatzen hat geschrieben:
DOSferatu hat geschrieben:Was ich damit sagen will, ist, daß sowohl der Sound, als auch die Grafik verzögert ausgegeben werden im Verhältnis zur Spielsituation. Und, wie Mr. Spock sagen würde: "Das ist nur logisch." - denn die Wirkung kann zeitlich nie VOR der Ursache liegen.
Bei mir wären Sound und Grafik, wenn ich das richtig sehe, "wenigstens" gleichermaßen verzögert, d.h. wenn es eine Taste "Explosion" gäbe, würde nach drücken der Taste zwar ein wenig Zeit vergehen, aber Grafik und Ton kämen dann relativ zueinander gleichzeitig.
Ja, bei mir ja prinzipiell auch. Eine "Explosion" z.B. besteht ja nicht nur aus EINEM Frame - weder bei Grafik, noch bei Sound. D.h. die Explosion ist für mehrere Frames zu sehen und evtl. auch mit einigen Phasen animiert, genau wie der dazugehörige Sound ja nicht auch nur ein 1/20-Sekunde "Plick" ist, sondern auch einen zeitlicher Verlauf hat, der vielleicht 0,5 bis 2 Sekunden dauert (also ebenfalls über etliche Frames hinweg). Das gleiche ist es bei Sprüngen und Schüssen. Und ich persönlich denke da, daß dem Spieler nicht auffällt, ob irgendein Sprung-"BOING!" oder ein Schuß-"PENG!" oder ein Explosions-"BUUUMMMM!" ein paar Pixel eher ODER später als die grafische Darstellung passieren - das würde man höchstens bemerken, wenn man das Ganze in Zeitlupe ablaufen ließe. Wie ich bereits gesagt habe: Die Spiel-Framerate runtersetzen nur um eine 100%ig zeitliche Synchronität bei einem interaktiven Aktionsspiel zu erreichen, empfinde ich (persönlich) als kontraproduktiv.
zatzen hat geschrieben:
DOSferatu hat geschrieben:Und übrigens: Speziell die Spiel-STEUERUNG sollte NIE ausgebremst werden - so ein "hakeliges" Spiel würde keiner spielen wollen.
Dann habe ich vielleicht ein grundsätzliches Problem. Ich sollte demnächst mal ein kleines Testspiel machen.
Naja, ich meine damit nur, daß auf gar keinen Fall irgend etwas, das der Spieler "eingibt" (Tastendrücke/-Loslassen, oder Knöpfe auf Joypads/-Sticks/Maus) "verlorengehen" darf - ich schwöre, wenn ein Spiel so reagiert, schmeißt jeder Spieler das Ding nach 5 Minuten frustriert in die Ecke.
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Eigenes Videoformat

Beitrag von DOSferatu »

Teil [2/2]:
zatzen hat geschrieben:Ich will auch überhaupt nur ein bescheidenes Spiel machen, und angesichts der Menge an existenten tollen Dos-Spielen braucht man gar nicht erst versuchen noch irgendetwas zu toppen, nur wie ich oben schon sagte: Ich habe etwas nachzuholen. Es ist jetzt 2019 und ich möchte soundmäßig wenigstens mal das machen können was der Amiga konnte und ab Mitte der 90er auch der PC. Was da genau rauskommt weiss ich nicht. Es ist eine reine Hobbysache.
Naja, geht mir ja nicht anders. Als Hobby-Bastler ist man ja aus mehreren Gründen gegebenüber den "professionellen" Entwicklern im Nachteil:

1.) Profis arbeiten immer im Team
Jeder tut, was er am besten kann: Coden, Musik, Grafik. Keiner muß "Allrounder" sein. Bei 3D-Spielen gibt es z.B. Leute, die die ganze Zeit nichts weiter machen, außer Texturen für Stoffe von Kleidungen zu designen... - Da braucht man eben genügend Leute.

2.) Profis machen das Vollzeit
Unsereins hat nebenher einen Job, der nicht nur viel Zeit frißt, während der man nichts Sinnvolleres machen kann (wie z.B. Spiele bauen) und auch Kraft frißt, d.h. selbst die verbliebene freie Zeit ist nicht wirklich etwas, mit der man viel anfangen kann, außer sich vom Job zu erholen und für den nächsten Tag im Job erholt zu sein. Diese maximal (!) 3-4 Stunden täglich, die quasi direkt vorm Schlafengehen stattfinden, also die "müdesten Stunden des Tages" sind, sind alles, was einem bleibt. Da kann man keine Höchstleistungen und keinen Elan mehr erwarten.

3.) Profis haben ganz andere Materialien
Profis erhalten schon JAHRE, bevor die neuen Systeme für den Käufer erhältlich sind, entsprechende Entwickler-Kits, mit denen sie arbeiten können. Sie erhalten professionelle Software zur Bearbeitung von Sound und Grafik, usw. Da kommt auch wieder 1.) dazu: Der Mensch, der die Levels baut, ist NICHT derselbe, der den Leveleditor gebaut hat. Der, der den Leveleditor baut, ist gut darin, intuitiv bedienbare, mit umfangreichen Features ausgestattete Anwendersoftware zu programmieren. Der, der die Levels baut, braucht sich über die technischen Hintergründe keine Gedanken zu machen, sondern kann sich kreativ austoben und somit das Bestmögliche herausholen.

1.+2.+3.)
So Hobby-Krauter wie wir müssen aber all das gleichzeitig sein und können - und noch einiges mehr - und das nur NEBEN einem Restleben und ohne etwas zurückzubekommen.
Klar - wir MÜSSEN natürlich nicht. - Man kann sich auch einfach jeden Feierabend vor dem Fernseher besaufen und das als Leben bezeichnen...
zatzen hat geschrieben:Kotzman II war mein letztes vollendetes Projekt, und da konnte ich nur BASIC und noch lange kein Assembler. ASM ermöglicht mir jetzt Dinge von denen ich damals nur träumen konnte (und sie wären damals schon möglich gewesen), und die möchte ich gerne jetzt endlich in Spielen nutzen, auch wenn das Ergebnis nicht professionell wird.
Naja, so etwas richtig Professionelles habe ich in dem Bereich auch noch nie gemacht. Alles, was ich da heutzutage mache, beruht ausschließlich auf autodidaktischem Lernen und jahrzehntelanger Erfahrung.

Aber darauf muß man eben nichts geben. Denn, wer bin ich schon? Da hat mal irgendein Philosoph gesagt (habe das mal vor etlichen Jahrzehnten auf einem Kalenderblatt gelesen) : "Glaube nicht blind Leuten, die sagen: Das ist richtig, wir machen das seit 20 Jahren so. - Man kann eine Sache auch 20 Jahre lang falsch machen." Und daran muß ich immer wieder denken.
zatzen hat geschrieben:Ich bin Dir dankbar für Deine Hinweise und Tipps, aber es würde meinen Rahmen sprengen wie eine etablierte Spielefirma vorzugehen.
Naja, ich gehe ja ebenfalls nicht wie ein etablierte Spielefirma vor. Wie die genau vorgehen, kann man zwar nur spekulieren, aber man kann sich das in etwa vorstellen. Aber das, was ich hier so privat zurechtschustere hat mit dem, was professionelle Spielefirmen machen, wohl eher gar nichts zu tun.
zatzen hat geschrieben:Mir reicht für mich schon das Erfolgserlebnis zwischendurch, dass Dinge wie mein Musikplayer oder meine Grafikdarstellungsroutinen funktionieren. Es ist ein bisschen wie wenn Rentner Teppiche knüpfen - objektiv sinnlos, aber subjektiv macht es Spaß.
Mehr ist es bei mir ja auch nicht. Ich weiß auch, daß ich mich in meinen "Engines" immer so verrenne - wohl, weil ich mich eher als Programmierer sehe als als alles anderes (Grafiker, Musiker, Leveldesigner). Es ist nur ein Hobby - und es gibt keinen Zeitplan dafür, wann (und ob) hier etwas fertig wird.

Und ja: Objektiv ist es sinnlos. Aber das hängt auch immer davon ab, in welche Relativität man es setzt. Objektiv ist DAS LEBEN AN SICH schon sinnlos, weil der einzige Sinn des Lebens zu sein scheint, das Leben zu erhalten. Jede Maschine hat da mehr Sinn: Da ist vorgesehen, was sie können soll und wenn sie das kann, was sie soll, hat sie einen Sinn. Beim Leben ist es so, daß es die ganze Zeit nur damit beschäftigt ist, da zu sein und möglichst da zu bleiben - also ist Ausgabe gleich Eingabe, eine endlose Feedbackschleife die zur Erfüllung eines Selbstzwecks dient. Im Prinzip ist es wie ein Stein. Der liegt nur da und braucht nur möglichst steinig zu sein - was er ja auch ist. Der Vorteil des Steins ist, daß er nicht darüber nachdenken kann, was er macht, warum er es macht, warum er nichts anderes macht usw. - Aber ab einem gewissen Intelligenzlevel stellt sich ein Objekt/Subjekt solche Fragen und kommt damit leider nur auf das gleiche Ergebnis wie der Stein käme - und stellt sich dann die Frage, wozu es dann diesen, dem Stein überlegenen riesigen Verstand hat...

Also denke ich, daß man, um da nicht in die allgemeinen Sinnfragen abzugleiten, es wahrscheinlich gesünder ist, diese auf wesentlich kleinere Bereiche anzuwenden, ohne Betrachtung des Universums. (Würden morgen alle ABC-Waffen der Erde gleichzeitig losgehen und sämtliches biologisches Leben ausradieren als hätte es nie existiert, hätte dies auf das restliche Universum NULL - ja, NULL! - Auswirkung. Gesetz von der Erhaltung der Masse, usw. Nicht einmal die Flugbahnen irgendwelcher Raumobjekte würden sich also ändern.)
zatzen hat geschrieben:Vielleicht wird ZVID2 ja annähernd so performant wie eine simple kompakt gehaltene (mit Schleifen) Routine mit Transparenzprüfung. Dann hätte es für mich eine allgemeine Berechtigung, neben der Speicherersparnis, die sich schon für Adventure-Spiele trotz Verlangsamung auszahlen würde. Werde ich sehen.
Tja, sage ich ja auch immer: Bei all unserem Streben kann man es sowieso nur versuchen. Was sich hinterher ergibt, sieht man dann, wenn es sich ergeben hat. Man kann zwar bestimmte Dinge vermuten, aber, sobald ein Programm etwas komplexer wird (und dazu gehören so Engines schon mal), ist es unmöglich, da eine Vorhersage zu treffen. Außerdem hängt so etwas bei Programmen, die erst während der Laufzeit mit externen Daten versorgt werden (also z.B. Sound-/Grafikdaten) auch von der Zusammensetzung der Daten selbst ab, wie sehr es performt. Für JEDES Programm, das an irgend einem Punkt auf Ergebnisse folgende Entscheidungen/Verzweigungen trifft/ausführt, wird es IMMER Daten geben, die ein Best Case, genauso wie ein Worst Case Szenario erzeugen. Und das gilt selbst noch für die heutigen Out-Of-Order-CPUs mit Sprungvorberechnung/Sprungvorhersage.
zatzen hat geschrieben:Du siehst es bei mir vielleicht anders, aber meine Formate sind auch nicht nur zum Selbstzweck da. Ich möchte mir Möglichkeiten offen halten, bei denen ich die Datenmengen einschränken kann, aber nicht muss. Mit ZSM kann ich Chiptune-Musik machen, aber auch welche die einem Orchester ähnelt. Mit ZVID2 kann ich in einem Spiel vielfarbige bis einfarbige Grafik beliebig mischen, und habe immer optimal wenig Speicherbelegung (in den Grenzen die das Format leistet).
Ja, schon klar. Bei der Entwicklung all meiner Engines/Routinen habe ich immer schon meine Spielideen im Hinterkopf, darauf basiert die Ein-/Ausgabe und deren "Bindeglied" zur Steuerung, dann die Steuerung selbst. Die Sprites eben auch nur, weil ich sie so brauchte - daß sie drehbar sind, auch nur, weil sie es (wegen der Draufsicht bei Xpyderz) sein mußten. Und die Soundengine, die der SID-Arbeitsweise (und der "programmierten Musik") stellenweise abgekupfert ist, lag daran, weil es bisher die einzige Art war, auf die ich mir vorstellen konnte, Klänge zu erzeugen. Die ist sogar dermaßen auf Spiele ausgelegt, daß sie als "Standalone" total unpraktisch ist. (Nicht absichtlich, aber es ist eben so.)
zatzen hat geschrieben:Ich habe nunmal nicht die Situation, dass ich mitten in einer Spielentwicklung stecke, aber ich denke vorausschauend, was sich an Formaten eignen könnte, um im Real-Mode ohne Erweiterungsspeicher etwas ansprechendes auf die Beine zu stellen.
Ich wünschte, ich würde in einer Spieleentwicklung stecken. Momentan stecke ich irgendwie in gar nichts. Nicht einmal an SLOT arbeite ich seit Monaten weiter. Der Hauptgrund ist, daß mir das komische Format zur Levelspeicherung nicht mehr ganz gefällt, weil es etwas unflexibel für Daten ist, die für mehrere Levels gleichzeitig gelten.

Beispiel: Man will ja nicht alle "Feindfiguren" eines Levels zusammen mit dem Level speichern, wenn man weiß, daß einige dieser Figuren in einem anderen Level ebenfalls auftreten - aus zwei Gründen: Der offensichtlichere ist natürlich, daß man nicht Platz verschwenden will, indem man identische Daten mehrfach speichert. Der andere ist der, daß, wenn eine Änderung (z.B. an der Figur) vorgenommen werden soll, das an jeder Stelle wo diese verwendet wird, einzeln zu machen wäre (anstatt einmal zentral) - und das wäre natürlich sinnlose Verschwendung von Zeit und Mühe.
zatzen hat geschrieben:Ich habe nur Bedenken was die Performance angeht. Vielleicht wird das Hauptproblem ZSM werden. Lass mich einfach mal mit meinem Kram auf die Schnauze fallen. Dann werde ich vielleicht ZSM wieder zu 8 Bit unkomprimierten Samples umschreiben und RLE codierte Grafik nehmen. Meine Formatspielerei liegt auch darin begründet, dass mich bisher noch keine zündende Spielidee beim Schopf gepackt hat.
Naja, bei meinem Zeug habe ich quasi ständig Bedenken, was die Performance angeht (und auch den Speicherverbrauch). Es sind eben viele große Einzelteile aus monolithischen Routinen, die zwar für sich allein ganz OK funktionieren, ihre erfolgreiche "Zusammenarbeit in der Gruppe" aber noch nicht unter Beweis stellen konnten.

Ich werde nicht umhin kommen, sobald dieses verdammte Ding ("SLOT") endlich "fertig" ist, ein Testspiel/Testlevel zu bauen, mit dem ich das Ding einem extremen "Streßtest" aussetze, um festzustellen, wieviel von dem, was datentechnisch einstellbar ist, in der Realität auch sinnvoll umsetzbar ist, damit es noch ein spielbares Spiel bleibt.

Ich meine: z.B. GameSys2 ist darauf ausgelegt, 2047 Figuren/Objekte gleichzeitig zu steuern, inklusive entsprechender Kollisionsabfrage. ISM ist darauf ausgelegt, für 16 Stimmen gleichzeitig Daten für digitale Klangsynthese und/oder Samples zu berechnen. Arcade01 ist darauf ausgelegt, große Levels gekachelte in Auflösungen von 128x150 bis 512x512 darstellen zu können, inklusive Sprites, die gedreht/gespiegelt/vergrößert+verkleinert/gedithert werden können. Die Steuerung enthält umfangreiche Möglichkeiten der Tastaturabfrage, inklusive Optionen für Tasten wie "Durchschalten", Halten/"Rapidfire", mehrere Tasten gleichzeitig inklusive mehrere Belegungen UND Joystickabfrage, die intern wie digitaler Joystick behandelt und auf "Tasten" gelegt und wie diese behandelt werden (wer weiß, wie komisch Joystickabfrage am PC ist, weiß auch, wieso das ein Problem sein kann). Das alles klingt ganz gut. Das alles wurde aber noch nicht einmal einzeln getestet (z.B. noch nie die Performance von ISM 16-stimmig gesehen). Aber es steht zu bezweifeln, daß, wenn da alles "auf Anschlag gestellt" wird, auf meinem 486er da immer noch Performance vorhanden ist - geschweige denn auf langsameren Maschinen...

Und (wohl im Gegensatz zu Dir) reißen mir meine zündenden Spielideen schon seit Jahren dermaßen am Schopf, daß ich eigentlich schon kreisrunden Haarausfall haben müßte...
zatzen hat geschrieben:Ähnlich bei ZSM - natürlich wollte ich immer schon einen eigenen MOD-Player schreiben, aber natürlich auch diese Art von Musik in Spielen haben. Adlib hatte ich schon bei Kotzman II, aber anstatt das Gebiet noch zu perfektionieren (mein Adlib Tracker konnte nur ein Instrument pro Kanal) habe ich jetzt direkt in meine liebste Art von Musikformat investiert.
Und das ist auch gut so.
zatzen hat geschrieben:
DOSferatu hat geschrieben:Ich hätte bei dem ganzen Aufwand, den ich inzwischen für den ganzen Kram betrieben habe, schon längst meine Spielideen in direktem Code umgesetzt haben können: Das "Mehrfigur-Jump'n'run", das Raumgleiter-Shoot'em'up, ein Rennspiel... - aber ich habe mich letztendlich dagegen entschieden; ...
So weit bin ich in meiner Erfahrung noch nicht. Ich hatte zwar die Idee mit der Jump&Run Game-Engine, aber mittlerweile hat mich die Faszination ein wenig verlassen (oder ich bin zu sehr abgelenkt von anderen Dingen momentan), und ich würde tatsächlich ein Spiel ersteinmal "hardcoded" angehen. Sprites machen, Spiel schreiben, meine Formate benutzen, sehen, ob sie performen. Nicht anders habe ich es bei Kotzman II gemacht.
Naja, der einzige Unterschied besteht bei mir inzwischen wohl darin, daß ich im Gegensatz zu Xpyderz, wo die Steuerung und Kollisionsabfrage noch "hardcoded" war, diese künftig durch dieses GameSys2 erledigen lassen will und daß ich für so Dinge wie Tastenabfrage und "-vorverarbeitung" inzwischen ebenfalls eine kleine "Zwischenengine" habe, die mir da etwas Arbeit abnehmen soll.

Eigentlich nimmt mir nix wirklich Arbeit ab - die Arbeit ist nur andere. Ich versuche nur, Daten und Programm immer weiter voneiander zu entkoppeln, um manche Schwierigkeiten zu vermeiden. Früher habe ich vieles wie monolithische Klötze programmiert und gerade bei Spielen empfinde ich das inzwischen als nicht mehr so nötig - vor allen, weil viele Dinge, die Spiel A macht, von Spiel B, was den Code angeht, genauso gemacht werden - und dadurch kein neuer Code für Spiel B gebraucht wird, wenn Spiel A den schon hatte.
zatzen hat geschrieben:Ich sehe mich auch in der Zukunft nicht als jemand, der regelmäßig Spiele rausbringt.
Ich auch nicht. Tut mir leid, falls das so 'rüberkam (weil ich mal sagte, daß man das Ganze, sobald es mal funktioniert, auch für mehrere Spiele nehmen könnte). Es geht ja auch darum, daß die restliche "Entwicklung" eines Spiels ja nicht "mal eben so von alleine" passiert: Musiken, Grafiken/Figuren, Klänge, Levels, allgemeines Gameplay, sogar so Menüs... All das muß ja trotzdem noch gemacht werden und kostet auch eine Menge Arbeit und Zeit.
zatzen hat geschrieben:Das können andere besser, die sich dem ganzen mehr verschrieben haben. Ich will mir nur ersteinmal noch einen Jugendtraum erfüllen, ein Spiel mit Transparenz und Digisound. Und wer weiss, vielleicht packt mich dann die Faszination und ich schlage einen Weg ein, der Deinem ähnelt. Aber bis dahin bin ich wohl doch mehr auf der Soundschiene unterwegs.
Naja, wie gesagt: Mein Traum war immer, selbst so (2D) Spiele machen zu können, wie sie so auf Konsolen der frühen 1990er liefen. Und einige Spielideen (siehe oben) haben sich eben über die Jahre im Hirn allmählich sedimentiert und warten auf Erfüllung.
zatzen hat geschrieben:
DOSferatu hat geschrieben:[...]2. Die Routine, die prüft, ob ein gleichfarbiger Block vorliegt, braucht wahrscheinlich mehr Platz UND Zeit, als es die Sache wert ist.[...]
Bei normalen Sprites wird es kaum vorkommen, allerdings etwas anderes, nämlich die transparenten Bereiche, aber da werden dann einfach nur die Zielregister weitergedreht.
Es gibt keine Routine die prüft in dem Sinne, sondern jeder 4x4 Block hat ja einen Header, der direkt instruiert, wie die Daten interpretiert werden müssen. Einfarbige Blöcke wären bei größeren Comic-Grafiken denkbar und wahrscheinlich, und da könnte ZVID2 (oder wahrscheinlich nenne ich es richtiggehender ZSPR) wegen der dann wenigen Farben auch sehr große Bilddaten abspeichern.
Achso, das ist also quasi in den Spritedaten entsprechend vorbereitet. Ja gut, das macht natürlich Sinn. Ich könnte auch vereinfachte (und schnellere) Spriteroutinen bauen als meine jetzigen - vor allem die Drehbarkeit verhindert bei mir jegliches Packen wie Du es machst. Grund ist, daß ich bei Drehbarkeit jederzeit auf jeden Pixel Zugriff brauche (ohne die vorhergehenden Daten gelesen haben zu müssen), weil man da nie weiß, welcher Pixel als nächstes gebraucht wird, weil das ja von Drehwinkel abhängt. Skalierung wäre in gewissem Maße auch mit so gepackten Daten noch möglich - allerdings schwieriger bei Verkleinerungen (selbes Problem wie Du beim Deltapacken Deiner Samples hast wenn mit hoher Frequenz gespielt).
zatzen hat geschrieben:Die handvoll Byte ASM Code für eventuelle einfarbige Blöcke kann man sich ja noch leisten. Und da kann man ja irgendwie nicht anders, als sich ein 32 Bit Register nehmen, es mit vier gleichen Bytes vollzustopfen und dann viermal an entsprechender Position in den Speicher zu hauen. Ist vielleicht auch eine Stilfrage - es ist "ausgerollt" weniger Code als wenn ich 16 einzelne Bytes schreibe oder auch 8 Words schreibe.
Ja, wie schonmal erwähnt: Wenn die 4 gleichen Bytes nicht schon irgendwo direkt "ladbar" hintereinander herumliegen, sondern einzeln in das 32bit-Register reinmüssen, nur damit man den 1mal-32bit-auf-Grafikspeicher-Zugriff nutzen kann, frißt das Einzelladen der Bytes eventuell den Zeitgewinn wieder auf. Kann ich nicht mit Sicherheit sagen - müßte die Praxis zeigen. Wenn ein 4x4 Pixel Block einfarbig ist, müßte man die eine Farbe 4x in die jeweiligen Bytes des 32bit-Registers laden. Mind. 1x SHL 16 oder ROL 16 (oder ROR 16) wäre dann nötig, dann jeweils in die xL und xH Bytes... Und dann könnte man die 4 untereinanderliegenden 4Pixel-Blöcke einfarbig beschreiben. Schon klar. Gehen also nur EAX/EBX/ECX/EDX. Oder man spendiert eine 1kByte Tabelle, aus der das Register die dann lädt mit 'nem 32-Bit-Operand-UND-Address-Befehl...
zatzen hat geschrieben:Die einzelnen Blockroutinen werden per Sprungtabelle angesteuert, es wird sich alles in einer recht großen, aber dennoch einzigen Routine befinden (ich bin noch nicht so weit dass ich die Assembler-Routine geschrieben habe, ich bin noch dabei den Encoder für mehrere Sprites in einer Datei umzuschreiben). Da ich die innersten Schleifen "ausrollen" werde, d.h. pro 4x4 Block, müsste es zumindest was Sprünge angeht schneller gehen als z.B. eine Schleifenroutine die auf Transparenz prüft.
Klar - immer, wo Dinge schon vorberechnet/vorbereitet sind und man auf Entscheidungsabfragen/Sprünge verzichten kann, wird es einem die CPU mit Performance danken.
zatzen hat geschrieben:
DOSferatu hat geschrieben:Die "Grafikfähigkeiten" von dem, was Borland da mitgeliefert hat, sind aber eher ein Witz
Ja, ich hatte mal ein Buch über Spiele programmieren inn Turbo Pascal. Als Pixelgrafik-verwöhnter Mensch fand ich das total deprimierend, wie da gezeigt wurde wie man irgendwelche Kartenspiele oder soetwas mit den Zeichenfunktionen von Pascal macht. Deshalb bin ich dann auch erstmal bei QuickBASIC geblieben. Hätte ich nur mal Assembler gekonnt...
Naja, man war zu gewissen Zeiten froh, überhaupt IRGENDETWAS zu können. Wenn ich daran denke, wie lange ich in Pascal reines Textmode-Zeug gemacht habe, bevor ich dann wenigstens mal den MCGA 320x200x256 bemüht habe... Ist schon ein Wahnsinn.
zatzen hat geschrieben:
DOSferatu hat geschrieben:
zatzen hat geschrieben:Kotzman II hat technisch sehr viel mehr Rückschläge, ich hätte mir noch gewünscht:
- Sprachausgabe (gescheitert an Unfähigkeit die Soundblasterkarte zu programmieren)
Inwiefern? Für die Zwischensequenzen oder auch im Spielverlauf?
Im Spielverlauf hätte ich gerne Digi-Sound gehabt, also Samples. Ich hatte das auch schon umgesetzt, auch in der ersten Zwischensequenz die Sprache, aber damals war ich nur dazu fähig, Digi-Sound an einem selbstgelöteten 8 Bit DAC am Druckerport auszugeben. Aber das konnte man natürlich nicht voraussetzen, da hätte ich jedem so ein Teil basteln und mitgeben müssen. Und man hätte sich entscheiden müssen - entweder Adlib Musik / Effekte, oder DAC. Und mit dem DAC war das auch nicht optimal. Mit meinen damaligen Fähigkeiten konnte während der Soundausgabe nichts anderes passieren. Ich konnte das nur in Abschnitte gliedern, und dann bspw. bei den Zwischensequenzen die Grafiken zwischendurch ändern.
Ja, mich hat es auch immer gestört - selbst bei einfachsten Projekten, von denen ich ahnte/wußte, daß die sowieso nie jemand außer ich selbst auf meinen eigenen Systemem benutzen werde.... - wenn da etwas war, was nicht geeignet war, es an andere Leute weitergeben zu können. Deshalb habe ich ja auch immer versucht, nie mein eigenes System als Referenz zu benutzen.

Der PC ist zwar nicht monolithisch - aber daß man inzwischen voraussetzen kann, daß so'n DOS-PC-Fan mindestens irgendwo etwas rumstehen hat, was Dinge enthält, die kompatibel zu 'ner VGA und 'ner Sound Blaster sind, nimmt einem schon teilweise etwas den Druck. Wenn ich daran denke, wie so Spiele um direkt um 1990 herum, um eine möglichst große Käuferschicht zu erreichen, oft in max. 286er-Code geschrieben waren und dann Optionen hatten für CGA, Hercules, TandyJr, EGA, VGA und dann für Speaker, Game Blaster, Sound Blaster (verschiedene), GUS, Roland... - nur damit auch jede noch so komisch zusammengeschusterte Kiste eine Möglichkeit hatte, das abzuspielen...

Ich sag's mal so: Das könnte ich gar nicht. Ich meine: Ich weiß z.B. auch, wie man Herc/CGA/EGA programmiert... Aber das alles dann extra auch noch einzubauen, wo ich sowieso schon mit meinem Kram kaum hinterherkomme - und mich dann für große Projekte mit scrollenden Levels und Sprites auf 286er-Code zu beschränken... Das könnt ich nur, wenn ich a) nicht dauernd so müde wäre, b) so'n Elan hätte wie The 8-Bit-Guy und c) keinen Job hätte, sondern mir irgendwas anderes mein Restleben finanzieren würde.

Naja, ich schätze mal, die paar DOS-Fans da draußen (mit echten Kisten) sind schon froh über jedes neue Tool/Spiel, was da einer macht. Nur habe ich oft mitbekommen, daß sehr viele Leute eher den 286er als "die" typische DOS-Maschine ansehen... Naja, für 286er habe ich sehr wenige Sachen hier, eher meine älteren, reinen Pascal-Produkte (was aber eher am Pascal-Compiler liegt, der für max. 286er compiliert).
zatzen hat geschrieben:
DOSferatu hat geschrieben:Vergleiche mal nicht Deine Ohren mit den Ohren aller anderen Leute... - Mir reichen 8 Bit oft dicke aus und mit Fließkomma arbeite ich am liebsten... GAR NICHT.
Für Spiele reicht mir auch ein ziemlich ranziger Sound aus, ich verwende bei meiner Soundengine ja nicht einmal echte 8 Bit sondern 4 Bit Delta nichtlinear.
Ach naja, ich find' sowas gar nicht mal "ranzig"...
zatzen hat geschrieben:Dagegen habe ich einen Freund der in Spielen unbedingt 16 Bit haben will und Formate wie FLAC. 32 Bit Fließkomma ist als Endprodukt auch sinnfrei, ich finde 16 Bit, wie es auf der CD ist, mehr als genug, aber einige Leute meinen das reiche nicht und wollen 24 Bit und 192 kHz. Aber das hat alles nichts mit Spielen zu tun, außer dass bei aktuellen Spielen sich wenigstens "CD Qualität" durchgesetzt haben wird.
Ja, weil Speicherplatz und Rechenleistung inzwischen vorhanden ist - UND - weil Musik in Spielen ja inzwischen auch nicht mehr von irgendeiner Routine "generiert" wird, sondern von einem eingebauten MPEG-Framework die im Spiel vorhandenen MP3-Files nebenher abgespielt werden.
zatzen hat geschrieben:Faktisch sind übrigens viele Musikproduktionen der letzten 25 Jahre so übertrieben laut ausgesteuert dass ich auch kaum einen Unterschied zwischen 16 und 8 Bit davon hören würde.
Ja, ich find's ganz gut, weil da beim Runterkonvertieren auf 8bit oder 4bit nicht allzuviel "kaputtgeht", was man dann so deutlich hören würde.
zatzen hat geschrieben:
DOSferatu hat geschrieben:[...]und ich werde NIEMALS (ja, NIEMALS!) für Grafiken - selbst für Source-Bearbeitungen - mehr als 24Bit-Bilder benutzen[...]
24 Bit hat für jeden Farbkanal ja auch 256 Stufen, da hat man hinsichtlich einer VGA Grafik ja noch etwas "Headroom" was das Verlieren von Bits angeht, da standard VGA nur 64 Helligkeitsstufen kennt.
So ist es - und selbst die nutze ich nicht immer völlig aus bei Spielgrafiken. Ich meine: Wenn eine Spielfigur z.B. nur 15 Farben (+1 Transparenz) hat, kann man nicht allzuviele Farben für "Farbverläufe" nehmen, weil man dann keine mehr für andere übrig hat.

Ich persönlich finde ja, daß für größere Spielfiguren so 5bit (31+1 Farben) am besten aussehen würden - aber 5bit ist so ekelhaft "live" zu packen. Mit meiner angedachten "Layer" Methode wäre das wahrscheinlich ganz gut, beispielsweise ein Layer 5bit für große Sprites, darunter ein 3bit Layer für so kleine Objekte/Projektile/Bonusgegenstände usw. Man könnte sogar z.B. eine ganze "Seite" machen, die einen ganzen 3bit (7-farbig) Font enthält (schöne Buchstaben für ein Spiel) und "darüber/darunter" dann die 5bit (31-farbig) die Spielfiguren...

Man hätte schöne einfache Routinen, die immer pro Pixel auf ne normale Byte-Adresse zugreifen und trotzdem 'ne Reduktion der Farbanzahl... Naja, hatte das schonmal erklärt. So eine Routine existiert bei mir momentan ja nicht, habe nur meine 8bit/4bit-Routinen (wo die 4bit-Pixel aus zwei nebeneinanderliegenden Nybbles eines Bytes bestehen), aber naja, ich wälze auch manchmal Ideen... obwohl ich ja auch mal fertig werden will.
zatzen hat geschrieben:
DOSferatu hat geschrieben:Vergleiche mal nicht Deine Ohren mit den Ohren aller anderen Leute... - Mir reichen 8 Bit oft dicke aus und mit Fließkomma arbeite ich am liebsten... GAR NICHT.
Für Spiele reicht mir auch ein ziemlich ranziger Sound aus, ich verwende bei meiner Soundengine ja nicht einmal echte 8 Bit sondern 4 Bit Delta nichtlinear.
Ach naja, ich find' sowas gar nicht mal "ranzig"...
zatzen hat geschrieben:Dagegen habe ich einen Freund der in Spielen unbedingt 16 Bit haben will und Formate wie FLAC. 32 Bit Fließkomma ist als Endprodukt auch sinnfrei, ich finde 16 Bit, wie es auf der CD ist, mehr als genug, aber einige Leute meinen das reiche nicht und wollen 24 Bit und 192 kHz. Aber das hat alles nichts mit Spielen zu tun, außer dass bei aktuellen Spielen sich wenigstens "CD Qualität" durchgesetzt haben wird.
Ja, weil Speicherplatz und Rechenleistung inzwischen vorhanden ist - UND - weil Musik in Spielen ja inzwischen auch nicht mehr von irgendeiner Routine "generiert" wird, sondern von einem eingebauten MPEG-Framework die im Spiel vorhandenen MP3-Files nebenher abgespielt werden.
zatzen hat geschrieben:Faktisch sind übrigens viele Musikproduktionen der letzten 25 Jahre so übertrieben laut ausgesteuert dass ich auch kaum einen Unterschied zwischen 16 und 8 Bit davon hören würde.
Ja, ich find's ganz gut, weil da beim Runterkonvertieren auf 8bit oder 4bit nicht allzuviel "kaputtgeht", was man dann so deutlich hören würde.
zatzen hat geschrieben:
DOSferatu hat geschrieben:[...]und ich werde NIEMALS (ja, NIEMALS!) für Grafiken - selbst für Source-Bearbeitungen - mehr als 24Bit-Bilder benutzen[...]
24 Bit hat für jeden Farbkanal ja auch 256 Stufen, da hat man hinsichtlich einer VGA Grafik ja noch etwas "Headroom" was das Verlieren von Bits angeht, da standard VGA nur 64 Helligkeitsstufen kennt.
So ist es - und selbst die nutze ich nicht immer völlig aus bei Spielgrafiken. Ich meine: Wenn eine Spielfigur z.B. nur 15 Farben (+1 Transparenz) hat, kann man nicht allzuviele Farben für "Farbverläufe" nehmen, weil man dann keine mehr für andere übrig hat. Ich persönlich finde ja, daß für größere Spielfiguren so 5bit (31+1 Farben) am besten aussehen würden - aber 5bit ist so ekelhaft "live" zu packen. Mit meiner angedachten "Layer" Methode wäre das wahrscheinlich ganz gut, beispielsweise ein Layer 5bit für große Sprites, darunter ein 3bit Layer für so kleine Objekte/Projektile/Bonusgegenstände usw. Man könnte sogar z.B. eine ganze "Seite" machen, die einen ganzen 3bit (7-farbig) Font enthält (schöne Buchstaben für ein Spiel) und "darüber/darunter" dann die 5bit (31-farbig) die Spielfiguren... Man hätte schöne einfache Routinen, die immer pro Pixel auf ne normale Byte-Adresse zugreifen und trotzdem 'ne Reduktion der Farbanzahl... Naja, hatte das schonmal erklärt. So eine Routine existiert bei mir momentan ja nicht, habe nur meine 8bit/4bit-Routinen (wo die 4bit-Pixel aus zwei nebeneinanderliegenden Nybbles eines Bytes bestehen), aber naja, ich wälze auch manchmal Ideen... obwohl ich ja auch mal fertig werden will.
zatzen hat geschrieben:
DOSferatu hat geschrieben:Konsolenartige "Brachialmusik" erst in 20facher Orchesterqualität zu erzeugen, nur um sie dann auf 4-Bit-Sound runterzukonvertieren... da müßt mein Herz 'n Affe sein...
Mache ich ja auch nicht. Ich setz mich ja nicht hin und komponiere wie einer der großen klassischen Komponisten eine komplexe Orchesterpartitur in Notenschrift. Ich setze mich einfach an den Tracker von 1994, nehme mir ein paar zurechtgestutzte Samples, damit alles nicht so groß wird, und habe dann (fast) schon den Sound, wie es im Spiel zu hören sein wird. Fast, weil ja noch die delta-Codierung dazukommt, also nochmal eine leichte Degradierung im Sound.
Ja, ich meinte das eher so allgemein. Genauso, wie es seltsam wirkt, wenn ein fotorealistisches hochauflösendes Spiel als Klang nur ein paar Piepser - z.B. aus dem PC-Speaker - hätte, würde es auch seltsam wirken, wenn ein grobkörniges 4farb-Flickscreen(ohne Scrollen)-Spiel Sound in CD-Qualität hätte - sebst Sound in 'nem Zehntel der CD-Qualität wäre da schon seltsam. (Da würden wohl viele sagen: Haben soviel Arbeit in den Sound reingesteckt, hätten sie mal die Hälfte davon für den Rest benutzt.)
zatzen hat geschrieben:
DOSferatu hat geschrieben:Wenn Du mehrere Figuren/Charaktere im Spiel haben solltest: Wer soll die Charaktere sprechen? Kennst Du so viele Leute, die Zeit UND Lust hätten, bei so etwas mitzumachen und sich zusätzlich auf den Weg zu Deinem Mikro machen würden, um viele lange Texte mit vernünftiger Betonung/Tonlage einzusprechen?
Es kommt drauf an. Viele verschiedene Charaktere und viele lange Texte, das klingt nach Adventure. Soetwas habe ich nicht vor, das würde ja schon an der Grafik scheitern, für die ich niemanden habe. Ansonsten wäre es wahrscheinlich, talentierte Leute auch im Musikerumkreis zu suchen, und die haben dann auch vernünftiges Equipment zum Aufnehmen, so dass sie gar nicht zu mir rumkommen müssen.
Es geht ja nicht nur darum, daß man talentierte Leute (mit Equipment) KENNT - sondern, daß die auch ZEIT+LUST haben, das für UMSONST zu machen, wo sie in der gleichen Zeit auch eigene Dinge machen könnten, die sie auch verkaufen können...

Und ich KENNE nicht mal genügend Leute, denen ich zutraue, so Texte gescheit einzusprechen (das kann nunmal nicht jeder gut genug) und ich könnte denen auch nichts dafür bieten - nicht mal das fertige Spiel würden die haben wollen, weil DOS.
zatzen hat geschrieben:Letztlich kann ich aber nicht auf die paar Freunde setzen, die Musik machen. Ich würde da schon den gesamten Freundeskreis einbeziehen und dann sehen, wer von denen einigermaßen passende Stimmen hat und gut spricht. Und welche natürlich Zeit und Lust haben.
Naja, ich bin das (und war es früher noch mehr), was man heutzutage als Nerd bezeichnen würde - mit anderen Worten: Ich habe keinen Freundes-KREIS. Es reicht gerade mal knapp für ein "Dreieck" (und, wie gesagt: der eine ist stumm und der andere hätte definitiv keinen Bock auf sowas). Und von all meinen Verwandten interessiert sich niemand - ja, wirklich: NIEMAND! - für irgend etwas, das mit Computern und Computerspielen zu tun hat.
zatzen hat geschrieben:Es sollte klar sein dass ich mir für mein Spiel keine professionellen Sprecher leisten kann.
Achnee, wirklich?! Wer hätte das gedacht...
Ja, so geht's mir auch. Aber naja, außer für eventuelle Anfangs-/Zwischensequenzen (so weit bin ich noch LANGE nicht!) des o.g. Jump'n'run bräuchte ich auch keine Sprachausgabe. Nicht einmal wirklich für das Adventure. (Und nein - Zwischensequenzen, falls überhaupt, würde ich als ALLER-ALLER-LETZTES in so Spiel einbauen, wenn wirklich ALLES ANDERE 100% läuft.)
zatzen hat geschrieben:Die deutsche Version von Day Of The Tentacle hatte da wohl auch einen Kompromiss gemacht, vielleicht waren es Schauspieler, aber keine der markanten Stimmen die man aus Film und Fernsehen kennt.
Ach, ich fand die gar nicht mal schlecht. Am besten gefiel mir die Stimme von Dr. Fred.
zatzen hat geschrieben:Irgendwo muss da jeder seinen Qualitätsanspruch setzen. Ich selber könnte eine handvoll verschiedener Stimmen machen, aufgrund meiner Erfahrung im kreativen/künstlerischen Audio-Bereich. Käme dann noch Verzerrung dazu (wovon es heute sehr beeindruckende Dinge gibt), würde sich das nochmal verdoppeln oder verdreifachen.
Naja, schon, aber die Art zu sprechen, verschiedene Charaktere abzubilden usw. - Ich könnte das nicht "einfach so". Synchronsprechen ist schon nicht einfach etwas, das man "so nebenher" macht. Und wenn es schlecht gemacht ist, schaltet man erfahrungsgemäß lieber die Sprachunterstützung AUS, als sich das anzuhören - weil es nervt. Da wäre der ganze Aufwand dann umsonst gewesen, wenn es nicht wirklich überzeugend ist. Man muß auch immer sehen, daß heutzutage, bei (im Gegensatz zu früher) all dem Überangebot an Software (auch freier Software), die Leute viel kritischer geworden sind und viel schneller etwas mal eben so in die Ecke schmeißen... - Klar, kann einem als Hobby-Entwickler ja auch egal sein, ist aber trotzdem immer irgendwie traurig.
zatzen hat geschrieben:So, auch wenn es sich weiter oben im Text vielleicht etwas anders angehört hat, habe ich dennoch Lust darauf, ein kleines feines Spiel zu machen, das trotz meiner komischen Weise zu programmieren Spaß macht zu spielen.
Ach, komische Weise zu programmieren... - Gibt's eine normale Weise?
Wenn man so mitbekommt, was heutzutage Leute, die aus dem Informatik-Studium machen (ja, ich weiß: Das ist NICHT programmieren - leider wissen so Firmenchefs das nicht, die immer so "abgeschlossenes Informatik-Studium" voraussetzen, ohne zu wissen, was die da lernen.)... Die schmeißen selbst für das kleinste Projekt erst einmal irgendwelche (fremdentwickelten) mehrere MB-große (bis mehrere HUNDERT MB große) Frameworks auf die Maschine, bevor sie überhaupt erst einmal ANFANGEN, eine eigene Zeile Code zu schreiben... Für MICH auch ne "komische Weise zu programmieren" - scheint aber heute zum Standard zu mutieren. Da denke ich, was man da komisch findet und was nicht, ist wohl eher subjektiv.

Meine Art zu programmieren, ist ja auch eher komisch: Ich baue inzwischen gerne so das, was als schlechten Code bezeichnet wird: Große monolithische Engines, die dann einfach als "Blackbox" irgendwo eingebaut werden und "alles machen, was sie müssen". So etwas wird als "schlechte Programmierung" angesehen, gehört zu den sog. "Anti-Pattern" (in diesem Fall das sogenannte "God-Objekt"). Ist mir aber egel, weil es mir um Performance und/oder Speichersparen, im besten Fall beides, geht - nicht darum, wie schick mein Code für 'n Informatikprofessor aussieht.
zatzen hat geschrieben:Ich würde gern einmal das Dithering bei (extremer) Vergrößerung von Sprites von Deiner Routine sehen. TGAME.EXE konnte ich gerade weder im Forum noch bei mir auf einer Festplatte finden, auch wenn ich mir sicher bin, es schon einmal gesehen zu haben.
Ja, vielleicht baue ich da mal ein kleines leicht zu bedienendes Testprogramm, mit dem man das beurteilen kann - falls ich mal wieder Lust/Kraft für's Coden bekomme.

Auf Deinen anderen Beitrag (im "Tracker-Engine" Thread) antworte ich auch demnächst mal.
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Eigenes Videoformat

Beitrag von zatzen »

Hallo DOSferatu!

Nun nach längerer Zeit auch mal wieder eine Antwort von mir in diesem Thread.

Vorab: Ich habe noch eine Idee was das nur bedingte "refreshen" des Hintergrunds bei einem Spiel betrifft.

Für den Fall ohne Scrolling:
- Hintergrund vorbereiten:
Hintergrundgrafik und unbewegliche Elemente (die auch nicht im Vordergrund sein sollen) zu einem unkomprimierten Bild zusammenbasteln
- Dieses Bild z.B. in 8x8 Blöcke unterteilt verstehen, bei 320x200 ein 1000 Byte
Datenfeld anlegen und wie bei einer Kollisionsabfrage flaggen, welche Bereiche
durch ein Sprite überdeckt werden
- beim nächsten Durchlauf nur diese Bereiche restaurieren

Sicherlich etwas Speicherintensiv, zusammen mit einem 64000 Bytes Grafikpuffer, da ich keine mehreren Seiten benutze, hätte ich dann um die 128000 Bytes nur für diese Technik.

Fall mit Scrolling: Fixe Hintergrundgrafik wie oben behandeln, alles andere muss ja dann immer neu gezeichnet werden.

Ich finde das ist auf jeden Fall ein deutlich einfacher realisierbarer Ansatz als die Sache, den Hintergrund vor dem Setzen jedes Sprites in einer Art Ringpuffer zu sichern.

Wenn kein Scrolling involviert ist kann man zudem das Kopieren in den Grafikspeicher reduzieren (und das ist ja meine ich das langsamste an der Sache), auch immer nur die Bereiche aktualisieren, in denen ein Sprite geschrieben wurde, also praktisch dafür das gleiche 1000er Datenfeld bemühen, wie bei der Kollisionsabfrage mit dem Hintergrund. Ein kleiner Denkfehler ist hier dabei - denn es müssen ja nicht nur die restaurierten Bereiche aktualisiert werden sondern auch die von dem Sprite beschriebenen. Bzw. umgekehrt, nicht nur wie in der obigen 1000er Flagtabelle vermerkt die Bereiche die die Sprites belegen, sondern auch die Bereiche in denen die Sprites einen Frame zuvor waren und jetzt "wegradiert" werden müssen. Also wenn man so will braucht man eine neue Tabelle in der man die jetzige mit der davor mit OR Verknüpft. Bin mir nicht sicher, aber ich glaube das macht Sinn.
Voraussetzung ist natürlich, dass man schnelle Kollisionsabfragen für diese 8x8 Blöcke hat. Aber mal gesetzt den Fall, wir haben ein Sprite, 40x20 Pixel, an Positon 234, 123. Block-Anfangs-Koordinaten 234 shr 3 = 29, 123 shr 3 = 15. Block-Ende-Koordinaten: (234 + (40 - 1)) shr 3 = 34, (123 + (20 - 1)) shr 3 = 17.

Naja das müsste dann pro Sprite jeweils so gesetzt werden.
Mich hat das Spiel "Prehistorik" dazu inspiriert, ein Fullscreen Jump&Run bei dem sich aber eher wenig bewegt, und es lief flott auf nem 286er. Vielleicht haben die das irgendwie so gemacht, aber ich denke mir dann auch sicher nicht gerade so. Ist ja irgendwie umständlich.

Es geht hier ja nur um Geschwindigkeit. Wenn Hintergrund herstellen mittels 64000 Bytes in den Speicher klatschen und selbige Anzahl Bytes in der Grafikspeicher hauen schnell genug ist braucht man das ja nicht machen.
Klar, mit Mode-X hat man mehrere Seiten und spart den Zwischenpuffer was Speicher spart und auch ne Ecke schneller ist. Aber sehr viele Spiele nehmen einfach VGA bzw. MCGA und das wäre mir auch lieb.

Leider ist es ja nicht so wie beim C64 wo die Hardware das mit den Sprites übernimmt. Womit ich nicht sagen will dass ich mir einen C64 wünschen würde, da kann der PC ja grafisch schon mehr.

Ich werde mir dazu nochmal Gedanken machen, um die Sache mit zwei Ebenen irgendwie zu emulieren, dass es letztlich dem Gedanken näher kommt, den Hintergrund nicht immer komplett restaurieren zu müssen und ebenfalls nicht immer den kompletten Bildschirminhalt in den Grafikspeicher kopieren zu müssen, sondern nur die Differenz zum vorherigen Frame.
Geschwindigkeit wäre letztlich wohl am einfachsten ohne solche Umständlichkeiten zu erreichen, einfach unkomprimierte Bitmaps, vielleicht noch die Transparenz von denen lauflängencodiert (das beschleunigt), und AdLib Musik und nur einfach Sound-Samples per One-Shot DMA. Wenn ich unbedingt nur möglichst schnell ein Spiel machen wollte würde ich es vielleicht so angehen, aber mir macht irgendwie dieses rätseln mindestens so viel Spaß wie die kreative Arbeit ein Spiel zu machen, und das führt dann auch zum Aufschieben, dass ich ewig über sowas wie Formate und "Engines" nachdenke aber noch kein Spiel anfange.
DOSferatu hat geschrieben:Ich gehe ja davon aus (auch weil von Framerate geschrieben wird), daß Dein Endziel weiterhin ein interaktives Unterhaltungsprogramm auf einem elektronischen System (nennen wir es mal "Computerspiel") ist. Deine obengenannte Berechnung geht allein vom Sound-Anteil aus. Also, ich denke, die Figurensteuerung/Abfrage (Kollision, Werte), sowie VOR ALLEM die Generierung der Grafik wird einen nicht zu unterschätzenden Anteil in der Spielschleife einnehmen, das passiert nicht einfach "in Nullzeit neben der Generierung des Sounds".
Wobei "write" von Pascal ziemlich langsam ist. Ich habe mir für zeitkritische Textausgaben schon Routinen in Assembler geschrieben, die direkt in den Speicher schreiben, aber z.B. läuft ZSMPLAY im Scope Mode noch am besten, auch bei kleinen Puffergrößen. Obwohl ich da aus dem Soundpuffer lese und daraus die Wellenform baue.
DOSferatu hat geschrieben:Wie ich ja schon einige Male erwähnt habe, halte ich (persönlich) es nur für eine mittelmäßig brauchbare Idee, die komplette Spielentwicklung von vornherein "um die Soundberechnung/Soundausgabe herum" zu konzipieren. Aber ich sollte ja nichts mehr dazu sagen - will auch nicht nerven.
Du hast schon recht, mir ist bisher nur nicht klar wie ich die Sounddaten und die Grafikdaten unabhängig voneinander berechnen soll. Wenn der Soundpuffer meinetwegen auf 15 mal die Sekunde eingestellt ist, das Spiel aber auf 25 fps läuft, wie passt das zusammen? Oder machen wir für bessere Veranschaulichung den Fall 10 Hz Soundpuffer und 30 fps Grafik. Wenn ich den Sound dann nur jeden dritten Frame berechnen lassen würde gäbe das ja dann immer einen Performance-Engpass. Ich bin immerhin so weit zu verstehen dass der Sound im Hintergrund laufen kann, aber wie ich dessen Berechnung gleichmäßig über die Zeit verteilen kann ist mir noch unklar. Ich könnte es natürlich so machen dass ich den Puffer nochmal entsprechend unterteile und dann eben in Teilen berechne. Aber ich glaube da muss es noch einen anderen Weg geben.
DOSferatu hat geschrieben:Der (Borland) Pascal-Compiler kompiliert nur Dinge, die mindestens einmal irgendwo im Code namentlich aufgerufen/verwendet werden (verschachtelt, d.h. wenn Routine B Routine C aufruft, aber Routine B von Routine A nie aufgerufen wird, wird Routine B UND Routine C nicht einkompiliert). Anders ist es mit Assembler. Ein Assemblerblock wird immer genau so in den Code einassembliert, wie er da ist - außer er wird als Pascal-Procedure/Function aufgerufen (bzw ist Teil einer Pascal Procedure/Function) - in dem Fall dann natürlich auch nur dann, wenn diese Procedure/Function in irgendeinen nicht auskommentierten/ausgefilterten Soucebereich erwähnt wird.
Also eine

Code: Alles auswählen

procedure bla; assembler;
asm
  mov ax, blubb
end;
Kommt ins Kompilat rein, egal ob sie aufgerufen wird oder nicht? Oder gilt die auch als Pascal-Procedure?

Zu bedingten Sprüngen noch: Kosten die Takte wenn sie nicht ausgeführt werden?
EDIT: Hab's schon nachgelesen: 1 Takt auf einem 486.
DOSferatu hat geschrieben:Naja, den Soundpuffer in mehrere Teile teilen ist (für die Performances) das gleiche, wie ihn zu verkleinern. Aber ich schätze, Dir geht es dabei darum, eventuelle "Unregelmäßigkeiten" durch Triple-/Quadruple-Buffering (statt Double) ausgleichen zu können (für langsame Maschinen). Um Sounddaten "vorzuberechnen", wenn Zeit ist und immer noch "genug Sounddaten" da zu haben, falls es mal knapp wird. Sollte es so sein, dann hast Du prinzipiell verstanden, worum es mir bei dieser "von der internen Spielsteuerung getrennten Framerate" wirklich geht.
Ich glaube, langsam komme ich dahinter, langsam. Sound vorzuberechnen wenn gerade Zeit ist klingt erstmal gut, aber wohin damit? Ich will ja auch keinen Puffer von 64 KB. Wie gesagt ist das Problem, zumindest wenn der Soundpuffer bzw. die Puffer-Zeitintervalle größer oder einfach nicht gleich den Grafikintervallen sind, die Berechnung des Puffers sozusagen zu zerstückeln, damit die Berechnung nicht schubweise auftaucht und alle paar Frames die Grafik ausbremst.
DOSferatu hat geschrieben:Will sagen: Der Spieler tut etwas, das das Programm vorher nicht "weiß", zusätzlich muß das Spiel (die restlichen Figuren) darauf reagieren - wobei man vorher auch nicht weiß, wie, weil das ebenfalls vom Spieler abhängt, usw. Somit kann man hier nichts "vorberechnen", bevor es passiert ist. (Außer, man hätte so viel Speicher/Rechenzeit, daß man für alle denkbaren nächsten Situationen vorher schon Grafik und Sound berechnen würde und wenn es soweit ist, nimmt man die eine richtige und löscht die anderen wieder.)
Ja, ich hätte mit dem Soundpuffer-Timing auch eine Verzögerung, nur dass der Ton auch nur so weit verzögert wäre wie die Grafik. Wenn ich nun Grafik und Ton noch unabhängig mache bekommt der Ton nochmal eine Verzögerung drauf, die von der Puffergröße abhängt, und zu welchem Zeitpunkt relativ zur gerade gespielten Soundpuffer-Position der "Auftrag" für den Ton gerade kommt.
DOSferatu hat geschrieben:Wie ich bereits gesagt habe: Die Spiel-Framerate runtersetzen nur um eine 100%ig zeitliche Synchronität bei einem interaktiven Aktionsspiel zu erreichen, empfinde ich (persönlich) als kontraproduktiv.
Ich wusste (und weiss) es einfach nicht genau, wie ich eine variable (und immer möglichst hohe) Framerate mit einem festen Soundpuffer kombinieren soll. Wenn Du mir da helfen kannst verzichte ich gerne auf exaktes Ton-Timing, wenn ich dafür ein Spiel habe das grafisch und steuerungsmäßig richtig leistungsfähig ist.


(Teil2)
DOSferatu hat geschrieben:Und ja: Objektiv ist es sinnlos. Aber das hängt auch immer davon ab, in welche Relativität man es setzt.
Der technische Fortschritt bringt mich auf solche Gedanken. Ich denke eben manchmal immer noch, auf dem Niveau von vor 30 Jahren zu programmieren macht nicht viel Sinn, wenn heute solche Maschinen fast niemand mehr hat. Was definitiv fehlt ist einfach dieses Gefühl dass man Software kreirt die sich potentiell jeder auf seinen Rechner holen würde. Bis Ende der 90er war das noch so, ich habe kleine Spiele programmiert oder Intros oder irgendwelche Patches für Spiele, und die wurden auf echten DOS-Systemen verwendet. Der Zug der Aktualität ist für mich abgefahren, ich programmiere ja nicht für Windows mit GPU Unterstützung, würde mir auch keinen Spaß machen weil mich gerade dieses Assembler-Gefummel im Detail fasziniert. Es liegt sicher auch daran dass es für mich ökonomischer ist einen Emulator zu verwenden, dadurch habe ich zwar im Hinterkopf immer das Gefühl dass ich es nicht mit echter Hardware zu tun habe (aber es fühlt sich trotzdem sehr echt an), beim Programmieren bin ich aber bei Abstürzen, wie gesagt, immer froh wenn ich keinen echten Rechner neu booten sondern nur ein Fenster neu aufmachen muss. Uncool, lame, aber praktikabel.
DOSferatu hat geschrieben:Es geht ja auch darum, daß die restliche "Entwicklung" eines Spiels ja nicht "mal eben so von alleine" passiert: Musiken, Grafiken/Figuren, Klänge, Levels, allgemeines Gameplay, sogar so Menüs... All das muß ja trotzdem noch gemacht werden und kostet auch eine Menge Arbeit und Zeit.
Eben, das ist ja der künstlerisch-kreative Teil, während das Programmieren sich ja mit der Lösung technischer Probleme beschäftigt. Ich habe mich in den letzten Jahren auch eher für die technische Seite begeistern können und habe auch nicht mehr so viel (musikalisch) kreativen Output wie in meiner Jugend, wo ich mal so ca. 3 Songs die Woche gemacht habe.
DOSferatu hat geschrieben:Mein Traum war immer, selbst so (2D) Spiele machen zu können, wie sie so auf Konsolen der frühen 1990er liefen. Und einige Spielideen (siehe oben) haben sich eben über die Jahre im Hirn allmählich sedimentiert und warten auf Erfüllung.
Meine erste Spieleerfahrung hatte ich am NES, daher vielleicht auch eine negative Prägung mit Super Mario oder Zelda, als 6-7jähriger ist man zu begeistert von sowas und spielt es mehr als gesund für die Nerven wäre. Jedenfalls habe ich dann bei einem Freund etwas vergleichbares am C64 gesehen und irgendwie kam der Gedanke auf, man könnte soetwas auch selber machen, da der C64 ja ein richtiger Computer ist. Grafiken durch eigene austauschen hätte mir schon gereicht, und es war nur eine kleine S/W Röhre, wie damals üblich. Eigentlich würde mir auch soetwas als Spiel genügen, also noch unterhalb des technischen Niveaus von 1990er Konsolenspielen, aber das wäre dann auf einem 486er System schon wieder wie "retro" auf Windows 10. Wobei ich finde, dass so ein NES mit seinen monolithischen 50 fps schon ziemlich performant ist... Da kam der PC lange nicht mit.
DOSferatu hat geschrieben:Wenn ich daran denke, wie so Spiele um direkt um 1990 herum, um eine möglichst große Käuferschicht zu erreichen, oft in max. 286er-Code geschrieben waren und dann Optionen hatten für CGA, Hercules, TandyJr, EGA, VGA und dann für Speaker, Game Blaster, Sound Blaster (verschiedene), GUS, Roland...
Als eine Art Cargo-Kult (nennt man manchmal so wenn z.B. Eingeborene Flugzeug aus Holz nachbauen weil sie so beeindruckt waren und sie sich ihre "Götter" zurückwünschen) habe ich meine nicht vollendeten Spiele auch schonmal so ausgelegt, dass ich die Grafiken in mehreren Versionen vorbereitete, aber nur EGA und CGA.
DOSferatu hat geschrieben:Naja, ich schätze mal, die paar DOS-Fans da draußen (mit echten Kisten) sind schon froh über jedes neue Tool/Spiel, was da einer macht. Nur habe ich oft mitbekommen, daß sehr viele Leute eher den 286er als "die" typische DOS-Maschine ansehen...
Das ist ja eigentlich eine schöne Motivation. Aber klar, mit dem 286er das kann man schon verstehen, denn ab 386 droht ja Windows immer mehr zu dominieren.

Ich verabschiede mich für heute mit einem Zitat aus der Windows-Anfangs-Zeit um 1990: "Der rödelt ganz schön auf der Festplatte rum!" - tut Windows ja heute noch gerne...
mov ax, 13h
int 10h

while vorne_frei do vor;
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Eigenes Videoformat

Beitrag von DOSferatu »

zatzen hat geschrieben:Hallo DOSferatu!
Hallo zatzen!
zatzen hat geschrieben:Nun nach längerer Zeit auch mal wieder eine Antwort von mir in diesem Thread.
Und - ebenfalls nach (viel zu) langer Zeit auch Antwort von mir.
zatzen hat geschrieben:Vorab: Ich habe noch eine Idee was das nur bedingte "refreshen" des Hintergrunds bei einem Spiel betrifft.[...]

Sicherlich etwas Speicherintensiv, [...] 128000 Bytes nur für diese Technik.

Fall mit Scrolling: Fixe Hintergrundgrafik wie oben behandeln, alles andere muss ja dann immer neu gezeichnet werden.

Ich finde das ist auf jeden Fall ein deutlich einfacher realisierbarer Ansatz als die Sache, den Hintergrund vor dem Setzen jedes Sprites in einer Art Ringpuffer zu sichern.

Wenn kein Scrolling involviert ist kann man zudem das Kopieren in den Grafikspeicher reduzieren (und das ist ja meine ich das langsamste an der Sache), auch immer nur die Bereiche aktualisieren, in denen ein Sprite geschrieben wurde, also praktisch dafür das gleiche 1000er Datenfeld bemühen, wie bei der Kollisionsabfrage mit dem Hintergrund.
Naja, wie ich immer sage: Müßte man testen, um zu sehen, wie das wirkt.
Mitunter geht sowas auch nach hinten los - will sagen: Man spart Zeit durch Vermeidung der (langsamen) Grafikkarten-Zugriffe - aber, falls das Ganze zu kompliziert wird, braucht die Alternative dann am Ende vielleicht mehr Zeit auf der CPU. - Man kann da aber wohl keine generelle Aussage machen, weil es von CPU, Grafikkarte und Motherboard-Chipsatz abhängt, was mehr performt. Mir selbst würden knapp 128 kB weniger Speicher für sowas schon wehtun - dann müßte für mich der Performancegewinn schon enorm außergewöhnlich sein, um mir das zu geben. Aber ist natürlich wie immer Ansichtssache.
zatzen hat geschrieben:Ein kleiner Denkfehler ist hier dabei - denn es müssen ja nicht nur die restaurierten Bereiche aktualisiert werden sondern auch die von dem Sprite beschriebenen. Bzw. umgekehrt, nicht nur wie in der obigen 1000er Flagtabelle vermerkt die Bereiche die die Sprites belegen, sondern auch die Bereiche in denen die Sprites einen Frame zuvor waren und jetzt "wegradiert" werden müssen. Also wenn man so will braucht man eine neue Tabelle in der man die jetzige mit der davor mit OR Verknüpft. Bin mir nicht sicher, aber ich glaube das macht Sinn.
Ja, wie gesagt: Wenn das Ganze am Ende so kompliziert wird... Man müßte es nicht nur "in Theorie" denken, sondern sich einen wirklichen Plan davon machen, um zu sehen, ob da irgend ein Pferdefuß dabei ist.
zatzen hat geschrieben:Voraussetzung ist natürlich, dass man schnelle Kollisionsabfragen für diese 8x8 Blöcke hat. Aber mal gesetzt den Fall, wir haben ein Sprite, 40x20 Pixel, an Positon 234, 123. Block-Anfangs-Koordinaten 234 shr 3 = 29, 123 shr 3 = 15. Block-Ende-Koordinaten: (234 + (40 - 1)) shr 3 = 34, (123 + (20 - 1)) shr 3 = 17.

Naja das müsste dann pro Sprite jeweils so gesetzt werden.
Wie ich schon mal erwähnt habe: Wahrscheinlich muß man da aber auch die ganze Zeit bei der Sprite-Steuerung beachten, daß sich keine Sprites überdecken. Meist ist so "Bildbereich-Merken" Methode (um Komplett-Screen-Refresh zu vermeiden) damit verbunden, daß sich Sprites nicht annähern/überdecken können.
zatzen hat geschrieben:Mich hat das Spiel "Prehistorik" dazu inspiriert, ein Fullscreen Jump&Run bei dem sich aber eher wenig bewegt, und es lief flott auf nem 286er. Vielleicht haben die das irgendwie so gemacht, aber ich denke mir dann auch sicher nicht gerade so. Ist ja irgendwie umständlich.
Kann man natürlich nicht wissen, ohne den Code zu sehen - oder evtl. das Ding abstürzen zu lassen, um an "halbfertigem Bild" zu erraten, wie sie es gemacht haben. (Als ne frühe DOOM-Version mal "abgestürzt" ist - d.h. wieder zurückgegangen ins DOS, mit eingeschaltetem Grafikmode, hat man den ModeY gut gesehen.)
Aber kenne das Spiel "Prehistorik" nicht.
zatzen hat geschrieben:Es geht hier ja nur um Geschwindigkeit. Wenn Hintergrund herstellen mittels 64000 Bytes in den Speicher klatschen und selbige Anzahl Bytes in der Grafikspeicher hauen schnell genug ist braucht man das ja nicht machen.
Klar, mit Mode-X hat man mehrere Seiten und spart den Zwischenpuffer was Speicher spart und auch ne Ecke schneller ist. Aber sehr viele Spiele nehmen einfach VGA bzw. MCGA und das wäre mir auch lieb.
Ja, wie es eben am besten geht. Der Beitrag hier ist ja schon etwas älter, daher wohl nicht mehr so aktuell. Neuere Beiträge von Dir sagen ja, daß Du Dich inzwischen ja so ein wenig mit der Idee von Mode-X anfreunden kannst.
zatzen hat geschrieben:Leider ist es ja nicht so wie beim C64 wo die Hardware das mit den Sprites übernimmt. Womit ich nicht sagen will dass ich mir einen C64 wünschen würde, da kann der PC ja grafisch schon mehr.
Naja, einerseits sind es gerade mal 8 Sprites beim C64 (und die sind auch nicht wirklich riesig). Alles, was mehr als 8 Sprites oder größere Sprites o.ä. sind, haben findige Programmierer gemacht.
Aber, ob PC oder C64 grafisch mehr kann, hängt auch davon ab, was man selbst kann. Ich meine: Wenn man auf PC z.B. auch nur mit 16 Farben und 320x200 arbeitet, ist man nicht wirklich VIEL besser als ein C64. (Denn 320x200 ist die native Auflösung des C64. Und er hat 16 Farben. Nur daß aus diversen Gründen die Ansteuerung beim C64 etwas komplizierter ist, weil das System da auch auf Speichersparen ausgelegt ist.)
zatzen hat geschrieben:Ich werde mir dazu nochmal Gedanken machen, um die Sache mit zwei Ebenen irgendwie zu emulieren, dass es letztlich dem Gedanken näher kommt, den Hintergrund nicht immer komplett restaurieren zu müssen und ebenfalls nicht immer den kompletten Bildschirminhalt in den Grafikspeicher kopieren zu müssen, sondern nur die Differenz zum vorherigen Frame.
Ja, ich verstehe schon die Idee dahinter. Aber, wie gesagt: Muß man eben sehen, wie sehr das performt. Bei stehenden Bildern (ohne Scrolling) ist die Idee sicher OK.
zatzen hat geschrieben:Geschwindigkeit wäre letztlich wohl am einfachsten ohne solche Umständlichkeiten zu erreichen, einfach unkomprimierte Bitmaps, vielleicht noch die Transparenz von denen lauflängencodiert (das beschleunigt), und AdLib Musik und nur einfach Sound-Samples per One-Shot DMA.
Naja, ist eben immer ein Trade-Off. Unkomprimierte Bitmaps brauchen dafür wieder Speicher. Aber, wenn man mal selbst ein Spiel programmiert und sich dann auch noch das Ziel setzt, daß 286er/386er von damals die Grenze sein soll, dann lernt man dabei erst wirklich zu würdigen, was damalige (Spiele-)Programmierer wirklich geleistet haben.
zatzen hat geschrieben:Wenn ich unbedingt nur möglichst schnell ein Spiel machen wollte würde ich es vielleicht so angehen, aber mir macht irgendwie dieses rätseln mindestens so viel Spaß wie die kreative Arbeit ein Spiel zu machen, und das führt dann auch zum Aufschieben, dass ich ewig über sowas wie Formate und "Engines" nachdenke aber noch kein Spiel anfange.
Geht mir ja genauso.
Derzeit baue ich an meinem neuen (skriptgesteuerten bzw. skriptgestützten) Spiel-Editor (Level/Grafik/Paletten/Sprites/Zusammenbau) herum. Also Speicher läßt er wirklich sehr viel frei - da brauche ich mir keine Sorgen zu machen. Alles durch dieses "wird nur gerade das Skript geladen, das gebraucht wird" und auch dadurch, daß der Skriptinterpreter in 100% Assembler ist.
zatzen hat geschrieben:
DOSferatu hat geschrieben:Ich gehe ja davon aus (auch weil von Framerate geschrieben wird), daß Dein Endziel weiterhin ein interaktives Unterhaltungsprogramm auf einem elektronischen System (nennen wir es mal "Computerspiel") ist. Deine obengenannte Berechnung geht allein vom Sound-Anteil aus. Also, ich denke, die Figurensteuerung/Abfrage (Kollision, Werte), sowie VOR ALLEM die Generierung der Grafik wird einen nicht zu unterschätzenden Anteil in der Spielschleife einnehmen, das passiert nicht einfach "in Nullzeit neben der Generierung des Sounds".
Wobei "write" von Pascal ziemlich langsam ist. Ich habe mir für zeitkritische Textausgaben schon Routinen in Assembler geschrieben, die direkt in den Speicher schreiben, aber z.B. läuft ZSMPLAY im Scope Mode noch am besten, auch bei kleinen Puffergrößen. Obwohl ich da aus dem Soundpuffer lese und daraus die Wellenform baue.
An dieser Stelle mußte ich mehrmals lesen - und verstehe es immer noch nicht. Wie kommst Du hier auf die Erwähnung von "write" von Pascal? Das war irgendwie nirgends das Thema.

Und selbstverständlich benutze ich (fast) NIE das "write" von Pascal - das nutzt nämlich die (langsamen) BIOS-Routinen, sondern (wie jeder gescheite Pascal-Coder) habe mir selbstverständlich ebenfalls Routinen gebaut, die direkt in den Grafikspeicher/Textspeicher schreiben. (Anm.: Ein etwas schnelleres "write" bekommt man, wenn man die Unit CRT benutzt, die auch eigene Routinen dafür hat. Aber seit wir wissen, daß diese auch diesen unseligen Kram mit ihrer (RTE200)-Timerschleife macht, um für ihren DELAY-Befehl zu timen, nutzt die auch kaum noch einer...)

Es gibt aber eine Ausnahme, wo ich DOCH das Pascal-write benutze: Wenn ich absichtlich (bei Kommandozeilen-Tools) die Ausgaben so mache, daß man diese auch in ein File "umleiten" können soll (also mit EXAMPLE.EXE >TEXT.TXT).

Aber, wie schon erwähnt: Ich habe nicht ganz verstanden, wieso Du an dieser Stelle das write von Pascal erwähnt hast. In SPIELEN würde ich das nie benutzen...
zatzen hat geschrieben:
DOSferatu hat geschrieben:Wie ich ja schon einige Male erwähnt habe, halte ich (persönlich) es nur für eine mittelmäßig brauchbare Idee, die komplette Spielentwicklung von vornherein "um die Soundberechnung/Soundausgabe herum" zu konzipieren. Aber ich sollte ja nichts mehr dazu sagen - will auch nicht nerven.
Du hast schon recht, mir ist bisher nur nicht klar wie ich die Sounddaten und die Grafikdaten unabhängig voneinander berechnen soll. Wenn der Soundpuffer meinetwegen auf 15 mal die Sekunde eingestellt ist, das Spiel aber auf 25 fps läuft, wie passt das zusammen? Oder machen wir für bessere Veranschaulichung den Fall 10 Hz Soundpuffer und 30 fps Grafik. Wenn ich den Sound dann nur jeden dritten Frame berechnen lassen würde gäbe das ja dann immer einen Performance-Engpass. Ich bin immerhin so weit zu verstehen dass der Sound im Hintergrund laufen kann, aber wie ich dessen Berechnung gleichmäßig über die Zeit verteilen kann ist mir noch unklar. Ich könnte es natürlich so machen dass ich den Puffer nochmal entsprechend unterteile und dann eben in Teilen berechne. Aber ich glaube da muss es noch einen anderen Weg geben.
Naja, in Deinen neueren Beiträgen scheinst Du allmählich nachzuvollziehen, was ich meine: Man kann - gerade, wenn man mit Interrupts und Timertick arbeitet, mehrere Prozesse "nebeneinander" mit "unterschiedlicher Geschwindigkeit" ablaufen lassen, ohne daß diese sich beeinflussen/behindern müssen.

Wenn der Soundkarte "die Daten ausgehen" (der Halb-Puffer ausgelesen ist und neue Daten braucht, also Switch zum andderen Halb-Puffer und dann wieder neu generieren in den alten) und die SB das z.B. per IRQ5 signalisiert, kann man das ja machen - aber davon braucht doch "das restliche Programm nichts zu wissen".
zatzen hat geschrieben:
DOSferatu hat geschrieben:Der (Borland) Pascal-Compiler kompiliert nur Dinge, die mindestens einmal irgendwo im Code namentlich aufgerufen/verwendet werden (verschachtelt, d.h. wenn Routine B Routine C aufruft, aber Routine B von Routine A nie aufgerufen wird, wird Routine B UND Routine C nicht einkompiliert). Anders ist es mit Assembler. Ein Assemblerblock wird immer genau so in den Code einassembliert, wie er da ist - außer er wird als Pascal-Procedure/Function aufgerufen (bzw ist Teil einer Pascal Procedure/Function) - in dem Fall dann natürlich auch nur dann, wenn diese Procedure/Function in irgendeinen nicht auskommentierten/ausgefilterten Soucebereich erwähnt wird.
Also eine

Code: Alles auswählen

procedure bla; assembler;
asm
  mov ax, blubb
end;
Kommt ins Kompilat rein, egal ob sie aufgerufen wird oder nicht? Oder gilt die auch als Pascal-Procedure?
Gilt als Pascal-Procedure. Wenn die keiner irgendwo aufruft/erwähnt, wird sie NICHT eincompiliert. Nur alles was zwischen ASM und END; steht, das wird 1-zu-1 assembliert. Also wenn man z.B. (in ASM) einen Sprung abhängig von einer Konstanten macht und diese Konstante dafür sorgt, daß ein bestimmter Bereich NIE ausgeführt wird (weil da nie hingesprungen/hingewechselt wird), wird es IN ASM TROTZDEM assembliert/eincompiliert. Hingegen, wenn man sowas in Pascal selbst (also im Pascal-Bereich, NICHT zwischen asm/end;) macht, dann wird sowas NICHT eincompiliert.
Hintergrund ist der, daß man in ASM ja quasi "jeden Scheiß" machen kann, auch Code modifizieren u.ä. - oder daß z.B. ein bestimmter Bereich nur dafür da ist, als "Tabelle zum Auslesen" zu dienen, dann muß der trotzdem da sein.

Weiß nicht, ob ich das nun verständlich genug ausgedrückt habe.
zatzen hat geschrieben:Zu bedingten Sprüngen noch: Kosten die Takte wenn sie nicht ausgeführt werden?
EDIT: Hab's schon nachgelesen: 1 Takt auf einem 486.
JEDER Befehl kostet Takte. Es ist nicht so, daß Sprünge keine Zeit brauchen, wenn sie NICHT springen - immerhin muß der Befehl gelesen und die Sprungbedingung ausgewertet werden. Wenn gesprungen wird, brauchen Sprünge nur mehr. Und, was bei CPUs mit Prefetch-Queue (wie z.B. der x86-Familie) hinzukommt ist: Die CPU liest schon die nächsten Befehle im Voraus (je nach CPU, wieviele Bytes sie "vorliest"), das bringt etwas Performance. Bei einem Sprung braucht sie diese "vorausgelesenen" Daten aber nicht mehr, löscht also nach einem (erfolgten!) Sprung ihren "Vorauslese-Speicher" (=Prefetch-Queue) und muß dann an der neuen Position wieder "Vorauslesen". DAS ist es, wieso man auf x86 gern Sprünge vermeidet, wo sie nicht nötig sind. Natürlich passiert das nicht nur bei Sprüngen, sondern auch bei CALLs/RETs - was ja klar sein dürfte.

Es gibt noch einen anderen Aspekt, bei dem man den Prefetch-Queue der x86er beachten muß: Wenn man selbstmodifizierenden Code schreibt und der ist "zu nah" an der aktuellen Position, dann hat die CPU schon den noch unveränderten Code eingelesen und führt den aus ohne die Änderung zu berücksichtigen. Allerdings kann man damit auch "rumtricksen" wenn man sich auskennt - muß aber beachten, daß 286er, 386er und 486er unterschiedlich lange Prefetch-Queue (PFQ) haben.

Wenn man z.B. direkt vor einer Schleife die ersten Befehle modifiziert, dann werden diese beim ersten Mal unmodifiziert ausgeführt, erst beim zweiten Schleifendurchlauf (weil es ja dann mind. 1 Sprung gab) in der veränderten Weise.

Wenn man Code modifiziert und zwischen aktueller Position und modifizierter Stelle kein (ausgeführter!) Sprung kommt UND diese Stelle weniger als 32 Bytes entfernt ist (das ist die Länge beim 486er PFQ), muß man einen künstlichen "Nullsprung" einfügen (z.B. mit DW $EB), das fügt einen jmp 0 ein, also einen unbedingten Short-Jump zur direkt nächsten Position - löscht aber den PFQ (und macht damit eine "zu nahe" Code-Modifizierung wirksam).

Naja, weiß nicht - das ist evtl. schon wieder "zu viel Voodoo" für Dich...
zatzen hat geschrieben:Ich glaube, langsam komme ich dahinter, langsam. Sound vorzuberechnen wenn gerade Zeit ist klingt erstmal gut, aber wohin damit? Ich will ja auch keinen Puffer von 64 KB. Wie gesagt ist das Problem, zumindest wenn der Soundpuffer bzw. die Puffer-Zeitintervalle größer oder einfach nicht gleich den Grafikintervallen sind, die Berechnung des Puffers sozusagen zu zerstückeln, damit die Berechnung nicht schubweise auftaucht und alle paar Frames die Grafik ausbremst.
Naja, das hatte ich etwas ungeschickt ausgedrückt. Es geht darum, daß der Sound einfach, "wenn nichts mehr im Puffer ist" (also der IRQ kommt), IM IRQ schon auf den neuen Puffer umgeschaltet wird UND das Flag gesetzt wird für "brauche neue Daten". Und dann "irgendwann" im Hauptprogramm (in der "Hauptschleife") die neuen Sounddaten generiert werden, wenn das Flag gesetzt ist. Die Schleife muß dabei natürlich so schnellen Umlauf haben, daß sie schneller ist als ein Puffer abspielt, damit rechtzeitig die neuen Daten kommen können.

Wie gesagt: Ein audiovisuelles interaktives Spiel braucht quasi sowas wie "Multitasking" im Kleinen. Die ganzen Dinge (Steuerung abfragen/berechnen, Grafik berechnen/ausgeben, Sound berechnen/ausgeben, usw.) werden alle nacheinander in der Schleife ausgeführt - jedes davon hat ein "Flag" (bzw. einen Countdown), und nur wenn das <>0 ist, wird das Jeweilige ausgeführt. Wenn man einen sehr schnellen Computer hat, kann es also auch passieren, daß es zwischendurch Schleifendurchläufe gibt, in denen "nichts passiert" (weil gerade alle Flags=0 sind). Im Normalfall wird die Grafikausgabe (was in der Regel das Zeitaufwendigste ist) wohl kein so Flag brauchen, weil diese sowieso fast jedes Mal getan werden muß, außer, wenn die Schleife trotz Grafikausgabe öfter durchläuft als die Monitor-Wiederholfrequenz (70 Hz bei MCGA)).

Die Grafikausgabe (inkl. Sprites) ist also meistens die größte Bremse. Wenn man es nicht so kompliziert machen will, daß die "Grafikberechnung" unterbrechbar ist (um auf eventuellen "braucht neuen Puffer" vom Sound reagieren zu können, bevor der nächste Puffer abgelaufen ist), sollte bei dieser Arbeitsweise der Soundpuffer mindestens so lang sein, daß er EINEN kompletten Hauptschleifendurchlauf "übersteht", selbst wenn alle Flags AN sind.

Das mit den Flags erwähne ich nur so, weil Du es so machst. Bei mir sind es keine Flags, sondern wie gesagt "Zähler", die hochgezählt werden. Bei Sound sollte es natürlich max. =1 werden, außer falls man z.B. Triple-Buffering macht, dann eben max. =2. Aber bei der Steuerung, da kann es eben auch mehr sein, falls der Rechner zu langsam ist, also nicht die volle Framerate schafft. Der "Spielertick" läuft im IRQ0 (INT8) die ganze Zeit mit und zählt den "brauche neuen Steuerschritt" im IRQ jedes Mal um 1 hoch - auch, während die Grafik oder der Sound berechnet wird. Wenn man dann an die Stelle in der Schleife kommt, wo die Steuerung berechnet wird, werden dann so viele Steuer-Schritte berechnet, wie dieser Zähler bis dahin hatte.

Das ist die Erklärung, wie ich hier "multitaske" in meiner Spielschleife.
zatzen hat geschrieben:Ja, ich hätte mit dem Soundpuffer-Timing auch eine Verzögerung, nur dass der Ton auch nur so weit verzögert wäre wie die Grafik. Wenn ich nun Grafik und Ton noch unabhängig mache bekommt der Ton nochmal eine Verzögerung drauf, die von der Puffergröße abhängt, und zu welchem Zeitpunkt relativ zur gerade gespielten Soundpuffer-Position der "Auftrag" für den Ton gerade kommt.
Naja, der "Auftrag" kann ja nur aus der Steuerung kommen und muß in einen Puffer geschmissen werden, bis die Soundberechnung dran ist. Und ja, die Verzögerung durch Puffergröße ist vorhanden - aber das ist sie in jedem Fall. Allerdings hat man so eine Verzögerung auch immer bei der Grafik - denn diese wird ja auch erst "irgendwo anders" generiert und danach angezeigt (entweder Double/Triple/etc-Buffering bei Mode-X, wo man mehrere "Bilder" hat, oder eben RAM-Puffer im Heap und dann hinkopieren). In beiden Fällen wird die Grafik erst angezeigt, nachdem sie vollständig berechnet wurde, hat also ebenfalls eine Verzögerung gegenüber der "realen" Situation. Geht ja wie gesagt nicht anders. Sowohl Grafik als auch Sound können ja erst erzeugt werden, wenn man weiß, was es sein soll. Und das kann man erst "wissen", NACHDEM die Steuerung es "weiß". Ursache immer VOR Wirkung.

Ja, klingt ernüchternd. Dagegen muß man eben damit kontern, was ein Computer richtig gut kann: Schnell sein. Das kann er natürlich nur, wenn es der Programmierer hinbekommt. Durch ausreichende Geschwindigkeit wirken Dinge, die eigentlich alle nacheinander passieren, für den User/Spieler so, als wäre es alles gleichzeitig.
zatzen hat geschrieben:
DOSferatu hat geschrieben:Wie ich bereits gesagt habe: Die Spiel-Framerate runtersetzen nur um eine 100%ig zeitliche Synchronität bei einem interaktiven Aktionsspiel zu erreichen, empfinde ich (persönlich) als kontraproduktiv.
Ich wusste (und weiss) es einfach nicht genau, wie ich eine variable (und immer möglichst hohe) Framerate mit einem festen Soundpuffer kombinieren soll. Wenn Du mir da helfen kannst verzichte ich gerne auf exaktes Ton-Timing, wenn ich dafür ein Spiel habe das grafisch und steuerungsmäßig richtig leistungsfähig ist.
Naja, ich versuche es ja seit einer ganzen Weile zu erklären - aber ich bin offenbar nicht gut genug darin.
zatzen hat geschrieben:
DOSferatu hat geschrieben:Es geht ja auch darum, daß die restliche "Entwicklung" eines Spiels ja nicht "mal eben so von alleine" passiert: Musiken, Grafiken/Figuren, Klänge, Levels, allgemeines Gameplay, sogar so Menüs... All das muß ja trotzdem noch gemacht werden und kostet auch eine Menge Arbeit und Zeit.
Eben, das ist ja der künstlerisch-kreative Teil, während das Programmieren sich ja mit der Lösung technischer Probleme beschäftigt. Ich habe mich in den letzten Jahren auch eher für die technische Seite begeistern können und habe auch nicht mehr so viel (musikalisch) kreativen Output wie in meiner Jugend, wo ich mal so ca. 3 Songs die Woche gemacht habe.
Ja, ich bin (leider) auch eher der "Engine-Bastler". Ich kriege inzwischen echt gute Dinge und brauchbare für "interne Abläufe" hin. Aber das alleine reicht eben nicht für ein gutes Spiel. Tolle Ideen, Grafiken, Levels, Sounds, Musiken - sowas macht sich auch nicht von alleine.

Und nur, weil man ein mathematisches Verständnis hat und deshalb auf 'ner x86 (16bit/32bit) mittlerweile spielen kann wie auf 'nem Instrument (aber dafür leider keine Instrumente spielen kann), bedeutet das eben nicht, daß man deswegen auch gut im Designen von Levels und Grafiken ist oder im Komponieren von guter Spiele-Hintergrundmusik oder Erstellen von Soundeffekten. Das sind ja schließlich auch alles Fähigkeiten von talentierten und/oder fleißligen Leuten - das ist nicht "einfach so da" und macht sich nicht von allein.
zatzen hat geschrieben:Meine erste Spieleerfahrung hatte ich am NES, daher vielleicht auch eine negative Prägung mit Super Mario oder Zelda, als 6-7jähriger ist man zu begeistert von sowas und spielt es mehr als gesund für die Nerven wäre. Jedenfalls habe ich dann bei einem Freund etwas vergleichbares am C64 gesehen und irgendwie kam der Gedanke auf, man könnte soetwas auch selber machen, da der C64 ja ein richtiger Computer ist. Grafiken durch eigene austauschen hätte mir schon gereicht, und es war nur eine kleine S/W Röhre, wie damals üblich. Eigentlich würde mir auch soetwas als Spiel genügen, also noch unterhalb des technischen Niveaus von 1990er Konsolenspielen, aber das wäre dann auf einem 486er System schon wieder wie "retro" auf Windows 10.
Naja, da man das Zeug sowieso nicht verkaufen will, kann man es so "retro" oder modern machen, wie man will (und kann). Wem es gefällt, der spielt es eben - wer nicht, läßt es bleiben. Man kann es sowieso nicht allen Leuten recht machen.
zatzen hat geschrieben:Wobei ich finde, dass so ein NES mit seinen monolithischen 50 fps schon ziemlich performant ist... Da kam der PC lange nicht mit.
Wobei man aber sagen muß, daß das NES (und z.B. der C64) einen dedizierten Grafikchip und Soundchip hatten, die all die Dinge quasi "alleine" gemacht haben, die man auf PC softwaremäßig machen muß. Das ist auch die Erklärung dafür, daß ein PC wesentlich mehr Leistung als ein C64 braucht, um das zu machen, was ein NES oder C64 so macht. So gekachelte Levels und Sprites kann das NES z.B. auch schon im Prinzip hardwaremäßig. Wenn man einen PC mit einer x86 mit 1 Mhz hätte, könnte man also nicht mal so Spiele wie auf NES oder C64 machen. Allerdings muß man auch berücksichtigen, daß der PC ursprünglich für Büroanwendungen gedacht war.
zatzen hat geschrieben:
DOSferatu hat geschrieben:Wenn ich daran denke, wie so Spiele um direkt um 1990 herum, um eine möglichst große Käuferschicht zu erreichen, oft in max. 286er-Code geschrieben waren und dann Optionen hatten für CGA, Hercules, TandyJr, EGA, VGA und dann für Speaker, Game Blaster, Sound Blaster (verschiedene), GUS, Roland...
Als eine Art Cargo-Kult (nennt man manchmal so wenn z.B. Eingeborene Flugzeug aus Holz nachbauen weil sie so beeindruckt waren und sie sich ihre "Götter" zurückwünschen) habe ich meine nicht vollendeten Spiele auch schonmal so ausgelegt, dass ich die Grafiken in mehreren Versionen vorbereitete, aber nur EGA und CGA.
Naja, ich meinte eher, wieviel zusätzliche Mühe die Leute sich auf PC so um 1990 herum machen mußten, um eine möglichst breite Käuferschicht zu gewinnen, weil der PC ja so "Baukasten" ist und jeder sich da anderen Kram einbauen konnte und da war es noch nicht so selbstverständlich, daß jeder mind. VGA oder SB hatte.
zatzen hat geschrieben:
DOSferatu hat geschrieben:Naja, ich schätze mal, die paar DOS-Fans da draußen (mit echten Kisten) sind schon froh über jedes neue Tool/Spiel, was da einer macht. Nur habe ich oft mitbekommen, daß sehr viele Leute eher den 286er als "die" typische DOS-Maschine ansehen...
Das ist ja eigentlich eine schöne Motivation. Aber klar, mit dem 286er das kann man schon verstehen, denn ab 386 droht ja Windows immer mehr zu dominieren.
Naja, daran liegt es wohl weniger. Auch unter 386er war Windows ja noch eine "DOS-Anwendung". Aber der 286er hatte eben - obwohl es schon (teure!) 486er gab - eine recht lange Zeitspanne in der "DOS-Zeit" gehabt.

Und ja, ich könnte auch reine 286er-Spiele schreiben (oder Anwendungen), diese komische "Artishoq" Datenbank, die ich im Auftrag vor 2,5 Jahren gemacht habe, ist auch in 286er Code gemacht. Aber für Spiele habe ich bereits so viel Zeug zusammengeschustert, was nun mind. 386er erfordert (und eigentlich erst wirklich auf 486er performt), da fange ich jetzt nicht wieder bei Null an, um ein 286er-Spiel zu machen. Ich wäre schon froh, ÜBERHAUPT endlich mal wieder ein Spiel zu machen. Ich weiß, das ist lame. Aber ich bin nur ein einzelner Knilch, mit wenig Zeit und inzwischen auch immer weniger Kraft.
zatzen hat geschrieben:Ich verabschiede mich für heute mit einem Zitat aus der Windows-Anfangs-Zeit um 1990: "Der rödelt ganz schön auf der Festplatte rum!" - tut Windows ja heute noch gerne...
Naja, EINER der Gründe, wieso Windows so "gerödelt" hat (und es immer noch tut) ist, daß einige Leute so programmieren (oder von ihrer Anwendung erwarten), daß "grenzenlos Speicher" vorhanden ist. Weil es das in der Realität NICHT so ist - UND weil bei Multitasking MEHRERE Programme "gleichzeitig" auf dem System laufen (und wenn man Pech hat, ALLE der Programmierer dieser Programme gedacht haben: "Ach, Speicher ist genug da, kann ich ja rumaasen!").... Was Windows dann tut, um diesem Umstand gerecht zu werden, ist, sogenanntes Memory-Swapping: weniger benutzte Speicherbereiche werden ständig auf Festplatte ausgelagert und bei Zugriff auf ausgelagerte Bereiche werden sie wieder von Festplatte geladen (dafür andere ausgelagert). Der Geschwindigkeits-Unterschied von Zugriff auf RAM und Festplatte ist ungefähr wie der zwischen einem Düsenjet und einem Fußgänger - oder eigentlich sogar wie der zwischen einer NASA-Rakete und einer Schildkröte.

Und ja, es gibt Gründe, wieso ich - selbst in der heutigen "wir haben ja alles" Zeit immer noch die Leute ermahne, nicht alles so speicherfressend zu machen. Aber auf mich hört ja keiner. Tja, naja - dann rödelt Windows eben weiter...
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Eigenes Videoformat

Beitrag von zatzen »

Hallo DOSferatu, ich möchte noch einmal das Verfahren zum nur Teilweise refreshen/updaten der Grafik konkretisieren:
Voraussetzung: Spiel-Level mit festem Hintergrundbild
1. Schritt: Hintergrund restaurieren, anhand der Informationen im 1000 Byte Array.
Der Hintergrund sollte dabei in 8x8-Blöcke unterteilt sein, und man kann die Lauflängencodiert speichern, so dass man je nach Hintergrundgrafik keine 64000 Bytes braucht sondern nur die Hälfte oder ein Viertel.
Wird ein Sprite geschrieben, werden in Mitleidenschaft gezogene Blöcke in einem 1000 Byte Array markiert.
2. Schritt: Sprites schreiben. Dabei überschriebene Blöcke s.o. markieren.
3. Schritt: Aktuelles Flag Array (1000 Bytes) mit einem LastFlag-Array "ORen".
4. Schritt: Nur die 8x8 Blöcke anhand Flag-Array in den Grafikspeicher kopieren
Anmerkungen:
Wie und wo genau das mit dem LastFlag-Array passiert ist mir gerade etwas zu abstrakt durchzudenken, aber ich sehe darin kein Problem. Der Zweck ist, die aktuelle Blöckeüberdeckung UND die im Frame davor zusammenzufassen, so dass Bereiche von Sprites die sich bewegt haben und nun verschwunden sind auch entsprechend im Grafikspeicher aktualisiert werden.
Sprites können sich problemlos überdecken, es werden dann nur etwas "dumm" im Flag-Array mehrmals die gleichen Blöcke geflagt. Das flaggen der Blöcke kann man, nachdem Start- und End-Blockkoordinaten berechnet sind, sehr schnell in unrolled loops in Kombination mit einer Sprungtabelle realisieren, wenigstens für die Horizontale.
Leider bleibt auch hier natürlich der 64000 Byte Grafikpuffer, wenn man es denn für MCGA realisiert. Für Mode-X oder Y (320x200), wenn man die Möglichkeit hat zum Pageflip, braucht man diesen Puffer natürlich nicht, und auch die Sache mit den Flag-Arrays vereinfacht sich: Man braucht kein zusätzliches Last-Flag-Array, sondern einfach zwei Flag-Arrays, für die jeweiligen Seiten. Sprich, Sprites auf Seite 1 schreiben und in Flag-Array 1 markieren, entsprechendes für Seite zwei, und einfach vor jedem Seitenwechsel zuerst den geflaggten Hintergrund restaurieren. Dieser kann als RLE komprimiert relativ klein ausfallen und so auch bei 320x240 unter 64K bleiben, gleichzeitig erlaubt er völlig freie grafische Gestaltung der Level-Optik, im Gegensatz zu Kacheln. Die Frage die sich mir nur stellt ist, ob ein internes kopieren der VGA nicht wahnsinnig schnell ist und es daher besser wäre, den Hintergrund komplett in einer übrigen Bildschirmseite zu hinterlegen und jedes mal komplett umzukopieren. Vielleicht kannst Du diese Frage aufgrund Deiner Erfahrungen beantworten.
Bleibt noch zu sagen dass diese ganzen Überlegungen natürlich nur wirklich Sinn machen für Spiele, bei denen wenigstens sagen wir mal nur 25% des Bildschirminhalts bewegt ist.
Dagegen gibt es auch Spiele mit Scrolling im Mode-X. Ich weiss noch nicht viel darüber, aber bspw. Lost Vikings ist ein Spiel dass 1993 raus kam, also sich Leute gerade erst einen 486 leisten konnten, ein 4 Richtungen Scroller mit einer Framerate von 60 Hz. Nach meinem Verständnis geht das nur, indem die Hintergrundgrafik, also quasi Kachelweise, in den restlichen 108544 Bytes der VGA untergebracht ist und in enormer Geschwindigkeit auf die Seiten zusammenkopiert wird. Aber nur eine Vermutung, ich verstehe noch zu wenig davon.
DOSferatu hat geschrieben:Aber kenne das Spiel "Prehistorik" nicht.
Auf Youtube kann man sich so gut wie jedes Spiel jeglicher Plattform ansehen.
Im Thread wo funkheld sich auch mit Mode-X beschäftigte habe ich ein paar Spiele untersucht. Bei "Prehistorik" bin ich zum Schluss VGA gekommen, 70 Hz, 320x200. Die Bildschirmseiten werden übergangsweise schnell weitergescrollt, eben mit 70 Hz, während das eigentliche Spielgeschehen eine deutlich niedrigere Framerate aufweist.
DOSferatu hat geschrieben:Ja, wie es eben am besten geht. Der Beitrag hier ist ja schon etwas älter, daher wohl nicht mehr so aktuell. Neuere Beiträge von Dir sagen ja, daß Du Dich inzwischen ja so ein wenig mit der Idee von Mode-X anfreunden kannst.
Ja absolut. Aber es ist wohl noch ein relativ weiter Weg. Kaum Literatur, und vor allem: Zum ersten mal ist es komplizierter als einfach einen linearen Speicherbereich zu füllen.
DOSferatu hat geschrieben:Wie kommst Du hier auf die Erwähnung von "write" von Pascal? Das war irgendwie nirgends das Thema.
Das war im Zusammenhang mit ZSMplay und dem Versuch, den Puffer zu verkleinern. Hauptsächlich im Main Mode stotterte das dann, und im Main Mode habe ich eben sehr viel gotoxy und write benutzt. Mir war das alles nicht so klar wie langsam das ist, weil man einfach denkt, Textmodus ist ja schnell. Aber allein schon die Übersetzung von Binärzahlen in Dezimaldarstellung dürfte ja mit einiger Rechnerei verbunden sein. So eine Procedure wie write wüsste ich aber nicht zu programmieren, weil man die Parameter ja praktisch völlig beliebig übergeben kann. Also ein Mischmasch aus Strings und Zahlen, und dazu noch Formatierung.
Die CRT hab ich vor langer Zeit gepatcht.

Und nein, in Spielen würde ich write auch nicht benutzen, höchstens in Text Adventures.

Thema was wird ins Kompilat übernommen (bzgl. ASM Prozeduren): Habe ich verstanden, danke.

Thema unabhägige Soundpuffer-Berechnung bzw. eben nicht alles "um die Soundausgabe herum" machen:
DOSferatu hat geschrieben:Naja, ich versuche es ja seit einer ganzen Weile zu erklären - aber ich bin offenbar nicht gut genug darin.
Ich suche die Schuld erstmal bei mir selber und werde Deine Erklärungen erstmal nachzuvollziehen versuchen, da bildet sich immer mehr Verstehen, Du warst ja jetzt schon sehr ausführlich. Bei manchen Dingen habe ich ein Brett vorm Kopf, wie auch bei der rekursiven Programmierung von Huffman.
DOSferatu hat geschrieben:Naja, daran liegt es wohl weniger. Auch unter 386er war Windows ja noch eine "DOS-Anwendung". Aber der 286er hatte eben - obwohl es schon (teure!) 486er gab - eine recht lange Zeitspanne in der "DOS-Zeit" gehabt.
Scheinbar eine so lange Zeit, dass einige Programmierer den 286er schon monolithisch auffassten, weshalb die Spiele dann auf folgenden Rechnergenerationen unspielbar schnell waren. Ich glaube, Spiele wie dieses https://youtu.be/I9W5rmvM2ns haben mich als Programmieranfänger ermutigt, einfach loszulegen und meine Ideen in Spiele umzusetzen, auch wenn ich technisch kaum etwas konnte.
mov ax, 13h
int 10h

while vorne_frei do vor;
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Eigenes Videoformat

Beitrag von DOSferatu »

zatzen hat geschrieben:Hallo DOSferatu, ich möchte noch einmal das Verfahren zum nur Teilweise refreshen/updaten der Grafik konkretisieren:...
Ich hatte das Problem an sich schon verstanden.
zatzen hat geschrieben:Leider bleibt auch hier natürlich der 64000 Byte Grafikpuffer, wenn man es denn für MCGA realisiert. Für Mode-X oder Y (320x200), wenn man die Möglichkeit hat zum Pageflip, braucht man diesen Puffer natürlich nicht, und auch die Sache mit den Flag-Arrays vereinfacht sich: Man braucht kein zusätzliches Last-Flag-Array, sondern einfach zwei Flag-Arrays, für die jeweiligen Seiten. Sprich, Sprites auf Seite 1 schreiben und in Flag-Array 1 markieren, entsprechendes für Seite zwei, und einfach vor jedem Seitenwechsel zuerst den geflaggten Hintergrund restaurieren.
Weiter unten wartet eine Überraschung...
zatzen hat geschrieben:Dieser kann als RLE komprimiert relativ klein ausfallen und so auch bei 320x240 unter 64K bleiben, gleichzeitig erlaubt er völlig freie grafische Gestaltung der Level-Optik, im Gegensatz zu Kacheln.
Beim Packen kann man nie vorher wissen, ob es gut/schlecht packt. Im Worst Case werden Daten sogar größer. (Siehe PCX: Auch RLE - aber nicht gerade schlau gelöst.)
zatzen hat geschrieben:Die Frage die sich mir nur stellt ist, ob ein internes kopieren der VGA nicht wahnsinnig schnell ist und es daher besser wäre, den Hintergrund komplett in einer übrigen Bildschirmseite zu hinterlegen und jedes mal komplett umzukopieren. Vielleicht kannst Du diese Frage aufgrund Deiner Erfahrungen beantworten.
Ja, diesem Trugschluß sind schon einige aufgesessen, weil es erst einmal plausibel klingt. ABER: Die Grafikkarte (wir reden jetzt von VGA) hat keine internen "Hacks" eingebaut, um Kopieren "innerhalb" des Grafikspeichers irgendwie zu beschleunigen - das muß also alles durch die CPU.
Was erschwerend hinzukommt, ist, daß Grafikkartenspeicher (der sowieso schon langsamer ist als der restliche RAM im PC), auf SCHREIBEN optimiert ist, weil das die bei Weitem häufigere Anwendung ist. LESEN aus Grafikkartenspeicher ist noch mal 'ne Ecke langsamer als schreiben.

Ja, das ist natürlich Mist - weil jetzt sicher der Eine oder Andere schon gedacht hat: Cool, dann kann ich ja Mode-X benutzen und die nicht benötigten Seiten für anderweitige Daten haben... Ja, kann man, ist dann wirklich etwas mehr Speicher. Aber schneller als der normale RAM isser nicht. Leider.
zatzen hat geschrieben:Bleibt noch zu sagen dass diese ganzen Überlegungen natürlich nur wirklich Sinn machen für Spiele, bei denen wenigstens sagen wir mal nur 25% des Bildschirminhalts bewegt ist.
Dagegen gibt es auch Spiele mit Scrolling im Mode-X. Ich weiss noch nicht viel darüber, aber bspw. Lost Vikings ist ein Spiel dass 1993 raus kam, also sich Leute gerade erst einen 486 leisten konnten, ein 4 Richtungen Scroller mit einer Framerate von 60 Hz. Nach meinem Verständnis geht das nur, indem die Hintergrundgrafik, also quasi Kachelweise, in den restlichen 108544 Bytes der VGA untergebracht ist und in enormer Geschwindigkeit auf die Seiten zusammenkopiert wird.
Ja, wie gesagt: Da täuscht Dich das Verständnis. Von RAM auf Grafikkarte kopieren ist immer noch schneller als von Grafikkarte auf Grafikkarte. Letzteres ist sozusagen der "Worst Case" - wenn man's extra langsam will... OK, ich speichere/lese auch öfter mal aus der Grafikkarte. Bei meinen Anwendungen kommt es manchmal nicht auf Echtzeit, sondern eher auf Speichersparen an.

Mein Malprogramm z.B. benutzt direkt die "Bild-Seiten" im Grafikkartenspeicher. (Allerdings hab ich neuerdings eine zweite Version, die XMS benutzt. Beide werden parallel weiterentwickelt - selber Sourcecode - Compilerschalter und so...)
zatzen hat geschrieben:Aber nur eine Vermutung, ich verstehe noch zu wenig davon.
Ja, wie gesagt: Innerhalb des gleichen Segments herumkopieren usw. klingt erstmal gut/schnell. Nur Zugriff auch Grafikkartenspeicher verhält sich hardwaremäßig anders als der restliche RAM. Der ist da "eingeblendet" und das ist im PC so verschaltet, daß bei Zugriff auf die speziellen Segmente dann "weitergeroutet" wird.

zatzen hat geschrieben:
DOSferatu hat geschrieben:Ja, wie es eben am besten geht. Der Beitrag hier ist ja schon etwas älter, daher wohl nicht mehr so aktuell. Neuere Beiträge von Dir sagen ja, daß Du Dich inzwischen ja so ein wenig mit der Idee von Mode-X anfreunden kannst.
Ja absolut. Aber es ist wohl noch ein relativ weiter Weg. Kaum Literatur, und vor allem: Zum ersten mal ist es komplizierter als einfach einen linearen Speicherbereich zu füllen.
Ja, weißt ja: Wenn Hilfe benötigt wird, stehe ich gern mit meinem Wissen zur Verfügung. Ich war damals auch froh, wenn ich mal jemanden getroffen habe, der mir Dinge gezeigt oder empfohlen hat. Und Dinge wie die ASM86FAQ.TXT, die SWAG oder RalphBrown'sInterruptList möchte ich einfach nicht mehr missen.
zatzen hat geschrieben:So eine Procedure wie write wüsste ich aber nicht zu programmieren, weil man die Parameter ja praktisch völlig beliebig übergeben kann. Also ein Mischmasch aus Strings und Zahlen, und dazu noch Formatierung.
Die CRT hab ich vor langer Zeit gepatcht.
Naja. Meinen eigenen Routinen werden nur Strings übergeben. Aber ich habe ja so Funktionen gebaut, die z.B. Zahlen in Strings wandeln (und umgekehrt) - auch für verschiedene Zahlensysteme. Dann wird eben nicht mit Komma getrennt, sondern die String-Teile mit + quasi "addiert" beim Übergeben. Klingt vielleicht weniger elegant als WRITE, aber wenn ich damit universelle und schnelle Routinen habe, ist mir diese "Eleganz" egal. INTERN wird aus dem WRITE ja sicher ein totales Wurstium, zum Einen, weil es die (eher langsamen) BIOS-Routinen benutzt, zum Anderen, weil es dann die ganzen "aufgezählten" Werte (Strings, Zahlen, usw.) ebenfalls umwandeln muß - und das macht es auch nicht besser als man es selbst könnte.
zatzen hat geschrieben:Und nein, in Spielen würde ich write auch nicht benutzen, höchstens in Text Adventures.
Selbst in Textadventures wär mir das zu doof...
zatzen hat geschrieben:
DOSferatu hat geschrieben:Naja, daran liegt es wohl weniger. Auch unter 386er war Windows ja noch eine "DOS-Anwendung". Aber der 286er hatte eben - obwohl es schon (teure!) 486er gab - eine recht lange Zeitspanne in der "DOS-Zeit" gehabt.
Scheinbar eine so lange Zeit, dass einige Programmierer den 286er schon monolithisch auffassten, weshalb die Spiele dann auf folgenden Rechnergenerationen unspielbar schnell waren. Ich glaube, Spiele wie dieses https://youtu.be/I9W5rmvM2ns haben mich als Programmieranfänger ermutigt, einfach loszulegen und meine Ideen in Spiele umzusetzen, auch wenn ich technisch kaum etwas konnte.
Naja, ich sag's mal so: Spätestens als 386er/486er auf dem Markt waren (auch wenn sie anfangs quasi noch in Gold aufgewogen wurden), waren sich die Softwareentwickler im Klaren, daß "Timing" durch "Bremsschleifen" oder gar kein Timing nicht mehr zukunftssicher ist. Daß der 286er so lange überdauert hat und einige Leute selbst zu 486er/Pentium-Zeiten noch 286er hatten, lag damals weniger daran, daß alle den so toll fanden, sondern eher daran, daß die jeweils neuesten Computer-/CPU-Modelle quasi halb soviel wie ein Neuwagen gekostet haben...

Und ja, ich hab mir das Spielchen mal angesehen... Naja, ehrlich gesagt: So'n Ding zu bauen wäre für mich inzwischen keine Herausforderung mehr. Mir wäre es etwas schade um die Zeit, die ich damit verbringe, sowas zu bauen, wenn ich eigentlich auch Zeug hier hab, um was Cooleres zu machen.

Hatte ich die "Überraschung" erwähnt?
Also, ich sag's mal so: Gestern, als ich wieder mal Deine Beiträge bezüglich 1000er-Feld (40x25 "Flag"-Quadrate für 320x200) gelesen habe, hatte ich mich mal drangemacht, das zu bauen, um zu sehen, ob das so funktionieren kann.

Und, was soll ich sagen? - Es funktioniert:
http://www.imperial-games.de/z/sprmtx.zip
Schenke ich Dir - viel Spaß damit!

Das Bild (PICTURE.PCX) ist nur dabei, damit man einen "Hintergrund" hat. Man kann auch eigene Bilder als Parameter angeben - derzeit aber nur 8bit PCX (256 Farben) unterstützt - weil's ja nur ein Demo ist.

Ich habe den Source natürlich beigelegt - eigentlich geht's ja um den Source.
Das Ganze ist in Pascal+ASM, wobei ich die Ganzen "Abläufe" in Pascal gelassen habe (könnte man in Asm umsetzen), damit man leichter durchschauen kann, was passiert.

Das Ding ist MCGA mit zwei 64000 Bytes großen Puffern

Bei der Anzeige werden unten links dann die Anzahl "Sprites" (habe da nur "bunte leere Rahmen" als Platzhalter gemacht) angezeigt, die kann man mit beiden Shift-Tasten erhöhen/verringern. Mit CTRL Links/Rechts kann man die Anzeige ausschalten. Die habe ich der Einfachheit halber nämlich mit WRITE gemacht - ich wollte das Ganze nicht so überladen mit eigenen Textausgabe-Routinen.
Natürlich kratzt WRITE etwas an der Performance, deshalb kann man das auch abschalten.
Übrigens, ESC beendet das Ding.

Achja, es werden 2 Werte angezeigt. Links die derzeit vorhandenen Sprites. Rechts daneben die Anzahl der nach VGA zu kopierenden 8x8-"Kästchen". Es ist mit 2 Temp-Screens zu je 64000 Bytes realisiert, der eine enthält das unveränderte Bild, der andere ist der Temp, in den die Sprites gesetzt werden und von dem aus "Kästchen" nach VGA-Speicher kopiert werden.

Ja, die Tastenbelegung (Shift, Ctrl) ist natürlich Käse. Auch hier ging es mir darum, daß ich nicht den eigentlichen Kern der Sache (das was in der Procedure Frame passiert) mit zu viel Geraffel aufblasen wollte, so daß man die Vorgehensweise nicht mehr nachvollziehen könnte. Deshalb so simple Tastenabfrage.

Die Variable CountBlocks (und das Zählen dieser) könnte man natürlich später weglassen - das dient nur dazu, zu sehen, wieviele der 1000 Felder im jeweiligen Frame "aktiviert" werden. Das ist der Wert, der neben der Anzahl Sprites angezeigt wird.

Vielleicht gefällt Dir das Ganze ja.

So, es ist schon wieder sehr viel Text, ich mache dann mal Schluß.
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Eigenes Videoformat

Beitrag von zatzen »

Hallo!

Vielen Dank für die Demo!

Ich habe Spaß damit und freue mich sehr, meine Idee mal umgesetzt zu sehen.
Sieht lustig aus, ein Hokuspokus aus Rechtecken. Die Mosaik-Blende ist auch eine gute Idee, evtl. sogar für ein Spiel, um zu vermeiden, für einen kurzen Moment einen heftigen Datendurchsatz zu haben, was zu einem kleinen Hänger führen könnte.
Und von dem Code kann ich auch noch was lernen. Die Funktion PRED war mir z.B. neu, bedeutet in dem Zusammenhang im Code aber nichts anderes als -1 oder? Aber auch überhaupt, wie Du die Sache technisch angehst wird mir helfen und mich inspirieren.

Ich hab das hier in Dosbox ersteinmal mit den default nur 3000 Cycles laufen gehabt am Laptop, das entspricht etwa 286er Niveau. Bis ca. 8 Sprites hab ich volle 70 fps (je nach zufälliger Größe), dann bis ca. 25 Stück noch 35, und ab etwa 50 dann 23,3. Dabei kratzen die Anzahl der Blöcke aber schon an der 400er Marke. Für "286er" aber eine ziemlich gute Performance. Bei 20000 Cycles (eher langsamem 486 entsprechend) hab ich bis etwa 128 Sprites 70 fps, und dann sind es schon 700 Blöcke. Je mehr Sprites man hat, desto langsamer steigt die Anzahl der Blöcke (klar, wegen Überlappung), das ist gut. Sicherlich wird es so sein, dass Pixeldaten-Sprites noch einmal mehr Performance kosten als gezeichnete leere Rechtecke.
Wenn man wirklich ein Spiel mit festem Screen ohne Scrolling machen will ("Gobliiins" ist z.B. so eins) macht dieses Verfahren in dem Fall sicherlich mehr Sinn als jedesmal den ganzen Hintergrund zu restaurieren, und Double-Buffering mit Mode-X ist dann nicht unbedingt notwendig - auch wenn man dabei Speicher sparen würde.
Aber man kann ja probieren das Hintergrundbild zu komprimieren, und dann bräuchte man sowieso eine 2000 Byte Tabelle für Offsets in die Daten für jeden 8x8 Block, da würde ich dann noch ein Info-Byte über die Art der Kompression hinzufügen, das dann z.B. sagen kann "einfach kopieren" für den Fall dass die Kompression nicht effektiv ist. Oder ein Verweis auf einen Block der genau so schonmal vorkommt, da würde dann einfach die Offset-Tabelle direkt reinzeigen, also mehrfach auf die gleiche Position. Da ist also wieder jede Menge denkbar, bloß so einen Aufwand mit Meta-Paletten wie bei ZVID würde ich da nicht machen, vielleicht aber alternativ zusätzlich zu RLE eine 1 bis 4 Bit Komprimierung und die 2 bis 16 Farben direkt in die Blockdaten hängen, aber keinesfalls wieder diese Bruteforce Orgie mit der langen Metapalette veranstalten. Manche Bereiche in dem Brückenbild von MI2 sehen jedenfalls so aus, als hätten sie nur 2 oder 4 Farben (z.B. der Himmel). Ein tatsächliches Level-Bild könnte dann eine Mischung aus beliebigen und kachelartigen Formen sein, teils ähnlich wie bei Lemmings (bloß da hat man keinen Hintergrund in dem Sinne), wo je nachdem eine wie o.g. Komprimierung sehr gut anschlagen könnte. Man könnte auch bewusst Kachelweise arbeiten im 8x8 Raster, dann würde besonders die Redundanzkomprimierung greifen.
Für Vordergrundebenen könnte man weitere "Hintergründe" mit Transparenz verwenden, und die Bereiche die diese abdecken wiederum im wirklichen Hintergrund transparent halten, so dass dort Daten und Transfer gespart werden - insgesamt hätte man so trotz mehrerer Ebenen im Prinzip nicht mehr Bilddaten und Datendurchsatz als hätte man nur einen Hintergrund ohne Vordergrundebenen.
Ich glaube ich werde da erstmal einen Converter schreiben, der komprimierte Hintergrund-/Vordergrund-Daten erzeugt, sowas macht mir ja Spaß.
Mir geht es ja bei einem Spiel nicht nur um das sichtbare Endergebnis, sondern auch in einem großen Maß um die ungewöhnlichen Techniken die ich einbaue, die auf meinem Mist gewachsen sind. Spielerei eben auch, Dinge realisieren die mir lange Zeit verwehrt blieben und dank Assembler jetzt mit brauchbarer Performance machbar sind.
DOSferatu hat geschrieben:Und ja, ich hab mir das Spielchen mal angesehen... Naja, ehrlich gesagt: So'n Ding zu bauen wäre für mich inzwischen keine Herausforderung mehr. Mir wäre es etwas schade um die Zeit, die ich damit verbringe, sowas zu bauen, wenn ich eigentlich auch Zeug hier hab, um was Cooleres zu machen.
Klar, ich meinte nur, damals, ca. 1991. Als ich noch so wenig Verständnis von den ganzen Sachen hatte, gerade mal Text auszugeben vermochte in Basic, und über das Buch "Spiele Programmieren mit QBasic" Plötzlich eine Möglichkeit reinkam, einfache Pixelgrafik darzustellen mit PUT, das war für mich schon revolutionär. Und etwa auf diesem Niveau ist dieses Alf-Spiel - ich wollte hier im Grunde auch nur sagen dass ich damals meine Ideen mit so rudimentärem Programmierwissen einfach umgesetzt habe. Und für jetzt bedeutet das vielleicht, dass ich zwar immer noch nicht in der Lage bin einen DOS-Computer bis aufs letzte auszureizen, aber seit meinem letzten Großprojekt (Kotzman II), was jetzt 25 Jahre her ist, doch so nach und nach einige Fortschritte gemacht habe und jetzt einfach viel mehr kann, was für mich auch schon ohne Mode-X ein Erlebnis wert wäre. Ich hab zwar jetzt immer gesagt, klar, Mode-X wäre gut und würde ich machen, allerdings ist es ja etwas "krumm" zu programmieren, und es ist vielleicht mit dieser oben diskutieren 8x8 Block-Flag-Technik nicht unbedingt nötig für nicht-Scrollendes, und Mode-X würde mich momentan noch aufhalten etwas zu realisieren. Ich kann jetzt definitiv einen ganzen Batzen mehr als vor 25 Jahren und würde auf diesem Fundament gerne ersteinmal etwas errichten. Mich motivieren derzeit noch so Dinge wie dieses ZVID2 mit den 4x4 Blöcken, und das gestaltet sich in Mode-X leider ziemlich schwer wie ich das einschätze.
DOSferatu hat geschrieben:Ja, weißt ja: Wenn Hilfe benötigt wird, stehe ich gern mit meinem Wissen zur Verfügung.
Da komm ich gerne nochmal drauf zurück wenn ich z.B. ein Konzept für ein Spiel habe mit Scrolling, was man dann besser mit Pageflip realisiert. Momentan scheint mir ja mein komisches Blockverfahren für nicht-Scroller sogar noch performanter zu sein bei relativ geringem Sprite-Aufkommen.

Wenn Du Dich vielleicht mal ein bisschen berieseln lassen willst und Zeit hast, hätte ich hier ein Video, ein Vortrag über die Zukunft des Programmierens, bei dem thematisiert wird wie wichtig es ist, dass wieder wirklich sauber programmiert wird - nicht nur um die Leistung der Systeme optimal auszureizen (von Assembler ist z.B. nicht wirklich die Rede), sondern weil man als Programmierer, auch wenn man es nicht direkt ahnt, heutzutage oft Verantwortung für Menschenleben hat. Ein schöner Einblick auch in die Geschichte des Programmierens und der frühen Computer.
https://youtu.be/ecIWPzGEbFc
mov ax, 13h
int 10h

while vorne_frei do vor;
Antworten