ProfilProfil
 Registrieren
 Login
Bild der WocheBild der Woche

(von Backslider)
Kommentare (0)
****

Weitere
User onlineBenutzer online
Gäste online: 5
Mitglieder online: Keine
Registrierte Mitglieder: 2117
Neustes Mitglied: vitapen

Blender Animation in XNA importieren?

Gehe zu Seite Zurück  1, 2
Neue Antwort erstellen
 

 

Autor Nachricht
 
 
bassfader
Member


Anmeldedatum: 28.02.2012
Beiträge: 133

Antworten mit Zitat
BeitragVerfasst am: 19.06.2012, 15:48    Titel:

Zu dem extrem schnell abspielen hatte ich in einem Post weiter oben bereits geschrieben dass ich in meinem code einen kleinen Fehler entdeckt habe:
Zitat:
Und mir ist noch was aufgefallen, bei der "if (animLast >= 60)" Bedingung fehlt am ende des Blocks noch das zurücksetzen der "animLast" Variable auf 0, sonst bringt das ganze zählen der Zeit nichts xD


Dann müsste das aber eigentlich funktionieren. Wenn du dort die "60" in dieser Bedingung anpasst kannst du damit wie bereits beschrieben die Geschwindigkeit regeln.

Zudem fällt mir auf dass dein Spritesheet nicht nur in eine Richtung geht, wie es von meinem Code voraussgesetzt würde. Ohne Änderungen am Code müssten alle bilder nebeneinander sein, d.h. Bild1, rechts daneben Bild2, daneben dann Bild3, etc..

EDIT: Das erstellen des Spritesheets sollte mit GIMP ziemlich einfach zu lösen sein. Einfach über "Datei" -> "Bilder als Ebenen öffnen" alle Bilder in ein Bild laden, dann solltest du 30 Ebenen mit all deinen Bildern haben. Danach gehst du auf "Bild" -> "Leinwandgröße ändern" und stellst dort die Breite des Bildes größer sodass alle 30 Bilder nebeneinander platz haben, die höhe bleibt gleich. Danach musst du lediglich die ebenen nebeneinander schieben und das ganze als PNG "exportieren".
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


Young Link
Member


Anmeldedatum: 26.02.2012
Beiträge: 393

Antworten mit Zitat
BeitragVerfasst am: 19.06.2012, 20:09    Titel:

Ich habe jetzt ein besseres Sprite Sheet mit Gimp und diesem Plugin erstellt: http://registry.gimp.org/node/20943
Ich habe aber noch ein Problem mit dem Code. Die Animation läuft zwar jetzt richtig ab, jedoch wird die Animation an zwei unterschiedlichen Stellen auf dem Bild gleichzeitig abgespielt. Ich gehe mal davon aus dass in dieser Zeile Code ein Fehler ist:
Code:
spriteBatch.Draw(image, new Rectangle(0, 0, tileWidth, tileHeight), new Rectangle(animIndex * tileWidth, 0, tileWidth, tileHeight), Color.White);

Außerdem hatte ich schon am Anfang als ich den Code gelesen habe diese Zeile nicht verstanden. Warum sieht diese Zeile nicht so ähnlich aus?
Code:
spriteBatch.Draw(image, new Rectangle(...), Color.White);
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


bassfader
Member


Anmeldedatum: 28.02.2012
Beiträge: 133

Antworten mit Zitat
BeitragVerfasst am: 19.06.2012, 21:08    Titel:

Zitat:
Außerdem hatte ich schon am Anfang als ich den Code gelesen habe diese Zeile nicht verstanden. Warum sieht diese Zeile nicht so ähnlich aus?


Das liegt daran dass ja immer nur ein ausschnitt gezeichnet wird und nicht das ganze Bild, daher wird noch das sogenannte sourceRect angegeben, das angibt welchen Teil des Spritesheets es zeichnen soll.

Das wird als Rectangle gemacht. Das erste Rectangle ist die Position wo das ganze gezeichnet wird, das 2te Rectangle gibt den zu zeichnenden ausschnitt des Spritesheets an.

Man kann es sich so vorstellen dass auf dem Bild ein Rectangle wandert, und es wird immer nur das gezeichnet was im Rectangle ist. Mein Code ist auf eine verschiebung nach rechts ausgelegt, dafür ist der "animIndex * tileWidth" teil zuständig. Das läuft in etwa so ab (davon ausgehend dass du tileWidth wie in meinem Beispiel auf 32 stehen hast, bedenke aber dass du wie erwähnt bei tileWidth und tileHeight die höhe und breite eines einzelbildes angeben musst):
Code:
1. animIndex hat den Wert 0
animIndex * tileWidth => 0 * tileWidth = 0
Also sitzt das Rectangle an der X Koordinate auf 0

2. animIndex hat den Wert 1
animIndex * tileWidth => 1 * tileWidth = 32
Also sitzt das Rectangle jetzt bei der X Koordinate 32

3 ...


Die restlichen Parameter des Rectangles geben nur noch die Y Koordinate (in diesem Fall immer 0 da das Rectangle nur nach rechts und nich noch nach unten wandert), sowie die höhe und breite des zu zeichnenden Ausschnitts an (diese sind wie gesagt als tileWidth und tileHeight defniert und müssen der größe eines Einzelbildes entsprechen).


Zitat:
Ich habe aber noch ein Problem mit dem Code. Die Animation läuft zwar jetzt richtig ab, jedoch wird die Animation an zwei unterschiedlichen Stellen auf dem Bild gleichzeitig abgespielt


Warum du jetzt 2 mal die Animation siehst kann ich so nur schwer sagen.
Hast du 2 Draw Calls?
Oder hast du vielleicht tileWidth bzw. tileHeight falsch eingestellt?

Sonst vielleicht einfach mal deinen bisherigen Code posten, vielleicht entdecke ich oder jemand anders den Fehler ja da drin direkt Wink
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


Young Link
Member


Anmeldedatum: 26.02.2012
Beiträge: 393

Antworten mit Zitat
BeitragVerfasst am: 19.06.2012, 23:47    Titel:

Danke für die Erklärung. Jetzt habe ich es verstanden.
Der Grund warum ich 2 Animationen sah lag an tileWidth und tileHeigh. Die Werte waren doppelt so hoch eingestellt.
Ich habe dem Ausgangscode noch ein paar Zeilen hinzugefügt damit das Bild sich sehr langsam(ist so gewollt) nach rechts bewegt(1 Pixel pro Sekunde). Außerdem ist meine Animation jetzt nur noch 21 frames lang. Deshalb musste ich den animIndex auf 20 setzen.
Wenn ich mehrere Animationen machen möchte die unabhängig von einander im Spiel auftauchen sollen, dann könnte ich ja für jede Animation diesen Code hier verwenden und ihn nur ein wenig ändern und als eigene Klasse speichern, oder?

Code:
namespace WindowsGame10
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        int animIndex = 0;
        int animLast = 0;
        Texture2D image;
        int tileWidth = 192;
        int tileHeight = 108;
        int rechts = 0;
        int count = 0;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
         
            base.Initialize();
        }

        protected override void LoadContent()
        {         
            spriteBatch = new SpriteBatch(GraphicsDevice);
            image = Content.Load<Texture2D>("aniii");
           
        }
       
        protected override void UnloadContent()
        {
           
        }
 
        protected override void Update(GameTime gameTime)
        {
            count += 1;
            if (count == 60)
            {
              rechts += 1;
              count = 0;
            }
           animLast += gameTime.ElapsedGameTime.Milliseconds;       
         if (animLast >= 60)
         {     
             animIndex++;
             if (animIndex == 20) animIndex = 0;
             animLast = 0;
         }

            base.Update(gameTime);
        }
     
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            spriteBatch.Begin();
           spriteBatch.Draw(image,new Rectangle(rechts, 0, tileWidth, tileHeight),new Rectangle(animIndex * tileWidth, 0, tileWidth, tileHeight),Color.White);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


bassfader
Member


Anmeldedatum: 28.02.2012
Beiträge: 133

Antworten mit Zitat
BeitragVerfasst am: 20.06.2012, 00:30    Titel:

Bitte bitte, gern geschehen Wink

Genau so würde ich es dann auch machen, also einfach eine eigene Klasse erstellen die sich um die eigentliche Animation kümmert - unabhängig vom Bild, dessen größe oder der Abspielgeschwindigkeit, diese "Einstellungen" kann man dann ja z.B. im Konstruktor übergeben - und dann diese einfach für spätere weitere animationen verwenden.

Und wenn du es richtig machst (ohne abhängigkeiten von anderen Klassen in deinem Projekt die nur auf dein Spiel bezogen sind) kannst du diese Klasse auch in zuünftigen Projekten immer wieder verwenden, ohne dort Anpassungen vornehmen zu müssen Wink
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


Young Link
Member


Anmeldedatum: 26.02.2012
Beiträge: 393

Antworten mit Zitat
BeitragVerfasst am: 21.06.2012, 11:33    Titel:

Ich habe noch eine Frage. Mir ist erst jetzt aufgefallen dass die Textur nicht bei den Koordinaten(0,0) beginnt. Warum wird das Bild nicht zuerst bei den Koordinaten(0,0) gezeichnet? Im spriteBatch steht doch: new Rectangle(rechts, 0, tileWidth, tileHeight)
Also müsste das ganze doch bei 0,0 beginnen. Ich bin jetzt etwas verwirrt Confused
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


fire
Member


Anmeldedatum: 26.07.2011
Beiträge: 143

Antworten mit Zitat
BeitragVerfasst am: 21.06.2012, 11:43    Titel:

wo wird es denn gezeichnet?
_________________
http://www.mediahdcenter.de
Kostenloses und gutes Farbkorrekturprogramm auf meiner Webseite
Ich suche noch nach einem Namen für dieses Programm.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen


Glatzemann
XNA.mag - Team


Anmeldedatum: 24.07.2009
Beiträge: 7420
Wohnort: Leverkusen

Antworten mit Zitat
BeitragVerfasst am: 21.06.2012, 12:03    Titel:

Vermutlich bei Vector2(rechts, 0), so wie es angegeben wurde Smile
_________________
MVP · starLiGHT · "Mit ohne Haare" · ANX

Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen


Young Link
Member


Anmeldedatum: 26.02.2012
Beiträge: 393

Antworten mit Zitat
BeitragVerfasst am: 21.06.2012, 12:25    Titel:

Ich weiß jetzt wo der Fehler lag. Jedes Bild der Animation ist 192x108 Pixel groß. Da die Figur in der Mitte des Bildes aber nicht sehr breit ist hat mein Bild einen großen transparenten Bereich links und rechts von der Figur. Ich hatte diesen transparenten Bereich vergessen mit einzuberechnen und war deshalb erstaunt warum die Figur nicht ganz links am Bildrand gezeichnet wurde.
Nächstes Mal muss ich die Figur anders rendern. Ich wusste beim Rendern nicht welche Auflösung ich wählen sollte und auf welchen Wert ich die Einstellung Scale setzen sollte.
Welche Einstellungen würdet ihr für eine South Park Animation(Gehanimation) wählen die danach in einem Xbox Spiel eingebaut werden soll?
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


Young Link
Member


Anmeldedatum: 26.02.2012
Beiträge: 393

Antworten mit Zitat
BeitragVerfasst am: 09.07.2012, 11:13    Titel:

Ich habe leider wieder ein kleines Problem. Ich habe jetzt eine XML Datei erstellt in der Informationen über Sprites gespeichert sind. Es handelt sich dabei um 3 Items, jedoch benutze ich nur 2 verschiedene png Dateien. "light" ist ein normales Bild und "aniii" die Animation. In meiner Sprite-Klasse wird jetzt die XML Datei ausgelesen und jedem Sprite seine Werte zugeteilt. Bei normalen Bildern klappt auch alles wunderbar, jedoch funktionieren Animationen noch nicht richtig. Das Problem ist dass Animationen nicht Bild für Bild(die Animation besteht aus 21 Bildern) abgespielt werden, in einer Sekunde wird ein paar mal die gesamte Animationsdatei angezeigt und anschließend sofort wieder ausgeblendet. Ich verstehe aber nicht was falsch ist, ich habe den Animationcode fast 1:1 übernommen. Ich habe nur die Variable "animationframes" eingeführt die angibt aus wie vielen Bildern eine Animation besteht. Außerdem habe ich vor dem eigentlichen Animationscode noch diese Zeile geschrieben: if (animationframes > 0) Ich bin mir nicht sicher ob ich die Zeile überhaupt brauche, ich wollte nur prüfen ob es sich bei dem Sprite überhaupt um eine Animation handelt, denn wenn die Variable "animationframes" den Wert 0 hat handelt es sich nur um ein normales Bild.
Hier der komplette Code meiner Sprite-Klasse. Die beiden Variablen "Z" und "wave" musste ich einbauen da am Anfang nicht alle Sprites geladen werden sollen, einige Sprites dürfen erst zu einem späteren Zeitpunkt erscheinen.
XML Datei:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<XnaContent>
  <Asset Type="System.Collections.Generic.List[SharedContent.Sprite]">
    <Item>
      <TexID>0</TexID>
      <Wave>1</Wave>
      <Speed>5</Speed>
      <Position>100 100</Position>
      <Animationframes>0</Animationframes>
      <Rotation>0</Rotation>
      <Scale>.1 .1</Scale>
      <TextureAsset>light</TextureAsset>
      <Health>2</Health>
    </Item>
    <Item>
      <TexID>1</TexID>
      <Wave>120</Wave>
      <Speed>2</Speed>
      <Position>200 100</Position>
      <Animationframes>20</Animationframes>
      <Rotation>0</Rotation>
      <Scale>.1 .1</Scale>
      <TextureAsset>aniii</TextureAsset>
      <Health>3</Health>
    </Item>

    <Item>
      <TexID>2</TexID>
      <Wave>30</Wave>
      <Speed>3</Speed>
      <Position>400 100</Position>
      <Animationframes>20</Animationframes>
      <Rotation>0</Rotation>
      <Scale>.1 .1</Scale>
      <TextureAsset>aniii</TextureAsset>
      <Health>2</Health>
    </Item>
  </Asset>
</XnaContent>


Sprite-Klasse. Die wichtigen Teile die mit der Animation zu tun haben habe ich markiert.
Zitat:
namespace SharedContent
{
public class Sprite
{
private MouseState oldState;
int animIndex = 0;
int animLast = 0;
int Z = 0;

int texID;
int wave;
int speed;


Vector2 position;
int animationframes;
float rotation;
Vector2 scale;

string textureAsset;
Texture2D texture;
SpriteFont leben;

int health;


public int TexID
{
get { return texID; }
set { texID = value; }
}


public int Wave
{
get { return wave; }
set { wave = value; }
}

public int Speed
{
get { return speed; }
set { speed = value; }
}

public Vector2 Position
{
get { return position; }
set { position = value; }
}

public int Animationframes
{
get { return animationframes; }
set { animationframes = value; }
}


public float Rotation
{
get { return rotation; }
set { rotation = value; }
}

public Vector2 Scale
{
get { return scale; }
set { scale = value; }
}

public string TextureAsset
{
get { return textureAsset; }
set { textureAsset = value; }
}

public int Health
{
get { return health; }
set { health = value; }
}


[ContentSerializerIgnore]
public Texture2D Texture
{
get { return texture; }
}

[ContentSerializerIgnore]
public SpriteFont Leben
{
get { return leben; }
}


public void Load(ContentManager content)
{
texture = content.Load<Texture2D>(textureAsset);
leben = content.Load<SpriteFont>("Arial");


}

public void Update(GameTime gameTime)
{
MouseState newState = Mouse.GetState();
Z += 1;
if (Z >= wave)
{
position.X += speed;

if (animationframes > 0)
{
animLast += gameTime.ElapsedGameTime.Milliseconds;
if (animLast >= 60)
{
animIndex++;
if (animIndex == animationframes)
{
animIndex = 0;
animLast = 0;
}
}
}

}

if (newState.LeftButton == ButtonState.Pressed && oldState.LeftButton == ButtonState.Released)
{
health -= 1;
}
oldState = newState;
}

public void Draw(SpriteBatch batch)
{
if ( Z > wave)
{
batch.Draw(
texture,
position,
new Rectangle(animIndex * texture.Width,0,texture.Width,texture.Height),
Color.White,
rotation,
Vector2.Zero,
scale,
SpriteEffects.None,
0f);

batch.DrawString(leben,health.ToString(), new Vector2(position.X, position.Y+20), Color.White);
}
}
}
}

und hier noch der Code aus der Game1.Update:
Code:
foreach (Sprite sprite in sprites)
            {
                sprite.Update(gameTime);   
            }
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden


Beiträge der letzten Zeit anzeigen:   
 
Neue Antwort erstellen Alle Zeiten sind GMT + 1 Stunde
Gehe zu Seite Zurück  1, 2
Seite 2 von 2

 
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


Powered by phpBB © 2001, 2005 phpBB Group
Deutsche Übersetzung von phpBB.de