XML und Animationen

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
Dasix
User
Beiträge: 13
Registriert: Dienstag 8. April 2008, 07:35
Wohnort: Stuttgart

Hallo,

ich habe gerade ein kleines privates Projektchen "fertig" gestellt, dass ich jetzt aber unbedingt vorstellen möchte :D
(Release Early Release Often)

Hierbei handelt es sich um eine Animationsengine, die XML-Dateien parst um diese als Animationsabläufe darzustellen.

Das ganze steht derzeit unter der GPL lizenz, kann aber unter Rücksprache für einzelne auch umlizenziert werden.

Ich bin etwas schreibfaul, deswegen kopiere ich hier einen Teil der README.txt.
Das README-File beinhaltet die deutsche Dokumentation,
die im Laufe der nä. Tage noch überarbeitet und ins Englische übersetzt wird.

README.txt

Code: Alles auswählen

EasyAni - A xml based animation scriptlanguage

Contact: Oliver Riehle
Website: -
Version: 1.0.0

Requirements
	
	Python
	EasyAni is compatible with python 2.7

	Pygame
	Get it from http://pygame.org or your package manager



Manual (GERMAN)

EasyAni ist eine XML basierte Animationsengine für computerspiele.

Gesteuert wird das ganze über die EasyAni-Klasse,
mittels derer man das Parsen von XML-Dateien oder Strings,
sowie das Anzeigen der daraus resultierenden Animationen veranlassen kann.

Animationen starten immer mit dem "animation" tag.
Tags auf gleicher Ebene werden soweit möglich "simultan" verarbeitet.


#### Implemented Tags:

animation:
	
	Die Animation selbst.
	Alle animationen beginnen mit diesem Tag.
	Sämmtliche Animationsabläufe werden in seinem Bauch definiert
	
	@param name:
		der name Parameter ist der name über den die Animation später aufgerufen werden soll.
	@param top: OPTIONAL
		die position der Animation auf der Y achse des Koordinaten systems
	@param left: OPTIONAL
		die position der Animation auf der X achse des Koordinaten systems

image:
	
	Der Image-Tag läd ein Bild und zeigt dieses an.
	Transparenzwerte können leider nicht berücksichtigt werden,
	da die SDL-Engine alpha per pixel und den alphakanal bei geladenen Bildern 
	nicht gleichzeitig unterstützt.
	Es wird empfohlen mit dem colorkey zu arbeiten
	Soll das Bild nicht sofort angezeigt werden kann man den Initialisationswert von alpha
	auf "0" stellen.
	Es ist zu empfehlen immer zuerst alle in der animation zu verwendenden Bilder gleich zu beginn
	zu definieren. Dies macht es später einfacher eventuelle Fehler schneller zu finden.

	@param src:
		der Pfad zu dem Bild
	@param name:
		der Name des bildes, über den es in anderen Tags manipuliert werden soll.
		Vorsicht, der Name ist eine Identifikationsnummer und kann nicht zwei mal vorkommen.
	@param cut: OPTIONAL
		Der sichtbare Bereich des Bildes.
		Standartmäßig wird das gesammte Bild verwendet
		left,top,width,height
	@param top: OPTIONAL
		die position des Bildes auf der Y achse des Koordinaten systems.
		Entspricht "0" wenn nichts übergeben
	@param left: OPTIONAL
		die position des Bildes auf der X achse des Koordinaten systems.
		Entspricht "0" wenn nichts übergeben
	@param width: OPTIONAL
		Die Breite des Bildes in die es skaliert werden soll
	@param height: OPTIONAL
		Die Höhe des Bildes in die es skaliert werden soll
	@param alpha: OPTIONAL
		Die Transparenz des Bilds
		255 = Visible
		0   = invisible
	@param angle: OPTIONAL
		der Winkel in dem das Bild gedreht werden soll von 0 bis 360
	@param colorkey: OPTIONAL
		Die Farbe in hexadezimal, die durch transparent ersetzt werden soll.
		Wenn der wert -1 entspricht, wird die farbe des ersten Pixels links oben als colorkey verwendet

sound:
	
	Der Sound-Tag initialisiert einen Sound, der später anhand des Play-Tags abgespielt werden kann.
	
	@param name:
		Der Name des Sounds, um diesen später wiedergeben zu können.
		Vorsicht, der Name darf nicht zweimal vorkommen
	@param src:
		der Pfad zu dem Sound, der geladen werden soll

move:
	
	Der Move-Tag bewegt ein Bild in einer vorgegebenen Geschwindigkeit zu einer vorgegebenen Position.
	
	@param top:
		Die Position auf der Y-Achse, in der die Bewegung enden soll.
		Steht ein "+BASE:" oder "-BASE:" vor der Zahl wird die Position zu der letzten position des Bilds gerechnet
		+Base:0 würde nichts verändern
	@param left:
		Die Position auf der X-Achse, in der die Bewegung enden soll.
		Steht ein "+BASE:" oder "-BASE:" vor der Zahl wird die Position zu der letzten position des Bilds gerechnet
		+Base:0 würde nichts verändern
	@param speed:
		Die Geschwindigkeit mit der die Bewegung durchgeführt werden soll
	@param image:
		Der Name des Bilds, das bewegt werden soll.
		Wird dieser Tag nicht verwendet bezieht sich die Bewegung auf die gesammte Animation
		Wird "PARENT" als wert übergeben,
		wird das Bild des Elterntags übernommen.

resize:
	
	Der Resize-Tag dehnt ein Bild mit einer vorgegebenen Geschwindigkeit auf eine vorgegebenen Größe.
	Der BASE Zoomingfaktor wird mit der Breite des Bildes gerechnet.
	Verfügt das Bild über einen Cut bereich, so wird nur dieser vergrößert.
	
	@param image:
		Der Name eines Bilds, das verändert werden soll.
		Wird "PARENT" als wert übergeben,
		wird das Bild des Elterntags übernommen.
	@param speed:
		Die Geschwindigkeit mit der das Bild verändert werden soll
	@param width:
		Die endgültige Breite des Bilds.
		Steht ein "+BASE:" oder "-BASE:" vor der Zahl wird die neue Größe zu der vorhandenen gezählt.
		+10 wäre die Größe des Bilds +10 pixel
	@param height:
		Die endgültige Höhe des Bilds.
		Steht ein "+BASE:" oder "-BASE:" vor der Zahl wird die neue Größe zu der vorhandenen gezählt.
		+10 wäre die Größe des Bilds +10 pixel

fade:
	
	Der Fade-Tag verändert den Alphawert eines Bildes
	
	@param image:
		Der Name eines Bilds, das verändert werden soll.
		Wird "PARENT" als wert übergeben,
		wird das Bild des Elterntags übernommen.
	@param speed:
		Die Geschwindigkeit mit der das Bild ein oder ausgeblendet werden soll
	@param alpha:
		Die opacity des Bilds in Prozent
		Steht ein "+" oder "-" vor der Zahl wird die neue opacity zu der vorhandenen gezählt.
		255 = Visible
		0   = invisible

rotate:
	
	Der Rotate-Tag dreht ein Bild in einer vorgegebenen Geschwindigkeit in einen vorgegebenen Winkel.
	Verfügt das Bild über einen cut bereich, so wird nur dieser rotiert.
	
	@param image:
		Der Name eines Bilds, das verändert werden soll.
		Wird "PARENT" als wert übergeben,
		wird das Bild des Elterntags übernommen.
	@param speed:
		Die Geschwindigkeit mit der das Bild gedreht werden soll
	@param angle:
		der Winkel von 0 bis 360
		Steht ein "+BASE:" oder "-BASE:" vor der Zahl wird der neue Winkel mit dem alten verrechnet.
	@param left: OPTIONAL
		Der Punkt auf der x-Achse um den das Bild rotiert werden soll von dem Mittelpunkt des Bilds ausgehend
	@param top: OPTIONAL
		Der Punkt auf der y-Achse um den das Bild rotiert werden soll von dem Mittelpunkt des Bilds ausgehend
		

alter:
	
	Der Alter-Tag ändert den cut bereich
	
	@param image:
		Der Name eines Bilds, das ersetzt oder geändert werden soll.
		Wird "PARENT" als wert übergeben,
		wird das Bild des Elterntags übernommen.
	@param cut:
		Ändert den Sichtbaren Bereich des Bilds.
		left,top,width,height

remove:
	
	Der Remove-Tag löscht ein Bild von der Anzeige
	
	@param image:
		Der Name eines Bilds, das gelöscht werden soll.
		Wird "PARENT" als wert übergeben,
		wird das Bild des Elterntags übernommen.

wait:
	
	Führt seinen Tag-Bauch nach einem kurzem Delay aus.
	
	@param time:
		Die Zeit die gewartet werden soll in millisekunden als Fließkommazahl
		1.00 oder 0.234 etc.

play:
	
	Der Play-Tag spielt einen Sound ab
	
	@param sound:
		der Name des Sounds der wiedergegeben werden soll


### Besondere Parameter
	Den Parameter wait kann man in jedem Tag außer dem Wait-Tag verwenden.
	Es wird solange gewartet, bis die Wartezeit abgelaufen ist.
	wait="0.50" würde 50ms warten bis der Tag ausgeführt werden würde. 

	Der Parameter speed beschreibt immer einen Abstand je sekunde.
	move speed="60" würde das Bild 60 pixel pro Sekunde verschieben

#### Besondere Parameter eigenschaften:
	Man kann die Position, Größe zoomfaktor etc. auch um den Basiswert erhöhen oder niedriger machen lassen.
	Hierzu schreibt man entweder ein "+BASE:" oder "-BASE:" vor eine Zahl

	In manchen Tags kann PARENT als attribute value übergeben werden, was auf den Parent tag verweisst

	Um eine zufällige Zahl zu erzeugen, kann man an Stelle einer Zahl "rdm:min/max" schreiben.
	Um eine zufällige Zahl zwischen 1 und 10 zu generieren würde man also "rdm:1/10" als Parameter wert übergeben.



#### Beispiel:

<animation name="Stun" top="0" left="0">
	<image name="char" src="stun_32x36.png" cut="192, 0, 32, 36" />
	
	<wait time="0.20">
		<alter image="char" cut="0, 0, 32, 36" />
		<move image="char" top="+BASE:0" left="+BASE:10" speed="1" />
		
		<wait time="0.13">
			<alter image="char" cut="32, 0, 32, 36" />

			<wait time="0.13">
				<alter image="char" cut="64, 0, 32, 36" />
				
				<wait time="0.50">
					<alter image="char" cut="96, 0, 32, 36" />
					
					<wait time="0.13">
						<alter image="char" cut="128, 0, 32, 36" />
						
						<wait time="0.13">
							<alter image="char" cut="160, 0, 32, 36" />
							
							<wait time="0.13">
								<alter image="char" cut="192, 0, 32, 36" />
								<wait time="0.50" />
							</wait>
						</wait>
					</wait>
				</wait>
			</wait>
		</wait>
	</wait>
</animation>
Die Subversion:
http://orkah.de/websvn/

Vielen Dank und noch einen angenehmen Abend,
ix
Zuletzt geändert von Dasix am Mittwoch 11. April 2012, 01:26, insgesamt 4-mal geändert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hallo,

Du solltest das ganze über eine Code-Verwaltungsseite a la BitBucket oder GitHub hier vorstellen. Da kann jeder den Code online betrachten und muss sich nicht erst ein u.U. dubioses Tar-Archiv herunterladen ;-)

Die Beschreibung oben hat mich zunächst ein wenig irritiert... der XML-Parser ist doch imho eher Beiwerk. Dein Anliegen war es doch wohl, eine Animationsengine zu schreiben und als Grundlage eine XML basierte Deklarationssprache zu nutzen?! Dass Du intern dann einen Parser brauchst ergibt sich dann von selbst. Beim Lesen Deines Beitrags habe ich erst an eine Visualisierung des Parsing-Vorgangs gedacht (analog zu den div. Sortier-Animations-Scripten). Evtl. kannst Du das noch mal klar stellen.

Als Tipp vielleicht: SAX ist eigentlich nur in seltenen Fällen, wenn überhaupt, unter Python sinnvoll. Setze lieber auf die ElementTree-API. Neben der Implementierung in der StandardLib gibt es mit `lxml` die Killer-Lib zu XML unter Python schlecht hin ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
deets

Diverse Anmerkungen:

- tar ist ja schoen und gut (sourcecode ist besser, ich schliesse mich dem vorredner an) - aber dann bitte mit *Unterverzeichnis* drin, damit man's gefahrlos entpacken kann.

- XML - naaaaja. Warum baust du nicht einfach eine simple DSL mittels Python-Operatoren zB, mit der du diese Dinge in Python-Code zusammenbauen kannst? Da wird am Ende Flexibilitaet und Kompaktheit bei rausspringne - und seien wir ehrlich: ausser einem Programmierer wird *niemand* so eine Datei schreiben. Und deine ganzen Pseudo-Ausdruecke (+BASE und Co) kannst du dann gleich in echtem Code definieren, vielleicht als Lambdas, oder zur Deklarationszeit ausgewertet.

- zum Format: die Notwendigkeit, <wait>s schachteln zu muessen macht das XML sehr schnell sehr unleserlich - weil tief indentiert. Wenn du da also drauf bestehst, XML zu benutzen, dann solltest du das zB aendern.

- du konfigurierst in deinem Modul selbst das logging! Das ist ein absolutes no-no, dazu habe ich hier schonmal laenger was ausgefuehrt. http://www.python-forum.de/viewtopic.php?f=1&t=27264

- es fehlt natuerlich noch ne Menge - rotation? Schoen und gut, aber doch bitte um einen frei waehlbaren Punkt herum! Usw.

- type(base) == int ist schlechter Stil, besser isinstance verwenden. Und sowas hier erst recht nicht: type(parent).__name__.lower() == "step". Warum nicht "isinstance(parent, step)"?

- deine Exceptions definieren alle die exakt gleiche __repr__-Methode. Kommt dir das nicht komisch vor?

-die pygame-Adaption scheint nicht richtig clever geloest, du verlaesst dich zuviel auf Vererbung statt auf Delegation. Deine EasyAni-Basic-Dinger sollten eine Engine uebergeben bekommen, an die sie Dinge wie Bilder oder Sounds laden, darstellen usw. delegieren - nicht durch Vererbung, das ist das falsche Mittel dafuer.
Dasix
User
Beiträge: 13
Registriert: Dienstag 8. April 2008, 07:35
Wohnort: Stuttgart

Ich verwende svn
http://orkah.de/websvn/
Hatte ich nur vergessen zu posten.

Ich sehe schon, da gibt es viel zu ändern, danke für die schnelle Kritik.
Zuletzt geändert von Dasix am Mittwoch 11. April 2012, 01:27, insgesamt 5-mal geändert.
Dasix
User
Beiträge: 13
Registriert: Dienstag 8. April 2008, 07:35
Wohnort: Stuttgart

So, hatte mir einige Gedanken gemacht und vieles aufgearbeitet.

Es ist nun möglich jedem Tag ein "wait"-Attribut zu übergeben um so den "wait"-Tag umgehen zu können.
Dies kann einige Zeilen Sparen und mach das xml insgesammt übersichtlicher.

Die Größte Änderung ist die Vereinfachung der implementierung von rendering/gui engines wie pygame oder auch gtk, qt etc.
So muss man nun noch lediglich von einer der Basisklassen erben und wenige Methoden überschreiben.
Als Beispiel hierfür dient die Datei
easyAni_pygame.py

Das Logging wurde ausgelagert.

Das Rotieren wurde überarbeitet.
Nun werden Bilder sowie Ausschnitte um den Mittelpunkt rotiert.
Es ist nun auch möglich das Bild um einen beliebigen Punkt zu drehen.
Ausgeschnittene Bereiche von Bildern können ebenfalls um einen beliebigen Punkt rotiert werden.

Das Resizeing wurde überarbeitet.
Nun werden auch ausgeschnittene Bereiche richtig vergrößert.

Die Bewegungs, Animations, Rotations etc. geschwindigkeit wird nun mittels der pygame.Clock ticks berechnet
um alle Animationen so gut wir möglich auf allen systemen gleich schnell darzustellen.
Als Beispiel dient die Datei
example_pygame.py

Ich bin derzeit noch damit beschäftigt den Code aufzuräumen, wiederholungen zu löschen und alles insgesammt zu vereinfachen.
Auch sind noch weitere Tags zur Image/Sound-Manipulation geplant.


Ich bin bei dem SAX-Parser geblieben, da er IMO bestens für meine Zwecke geeignet ist.
lxml ist für das was ich brauche viel zu überladen.
DOM ist für meine Zwecke unbrauchbar und langsam.
ElementTree würde funktionieren, ist auch mit iterparse SAX kompatibel
und hat den Vorteil einer konstanten Speicher-Auslastung,
jedoch müsste ich mehr code schreiben um das umzusetzen, was ich bislang mit SAX geschafft habe.
Ich bin mir also noch nicht sicher, ob sich der Mehraufwand wirklich lohnen würde
diesen Teil des Codes mit ElementTree neu zu schreiben.
Ich werde noch etwas darüber nachdenken.

Meine Exceptions muss ich noch aufarbeiten.

Ich will mich nocheinmal für die sehr hilfreiche Kritik bedanken
und wünsche allen noch einen angenehmen Oster-Sonntag-Abend.
Benutzeravatar
C4S3
User
Beiträge: 292
Registriert: Donnerstag 21. September 2006, 10:07
Wohnort: Oberösterreich

<ot>
:D
Da sieht man 2 Jahre lang nix vom "Brot" und dann das!
Hoffe es geht dir gut!? Lass mal wieder was von dir hören.
</ot>
Gruß!
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Leute, dafür gibt es doch PNs. Ich hab ja nichts gegen Offtopic, aber das ist halt schon überhaupt nicht Threadbezogen und gehört woanders hin.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten