Programmera spel i C++ för nybörjare/Animation 1
Baserat på VC++ 2010 express, Win 7 och SFML 1.6, du bör ha gjort installationerna för ett fungerande SFML-fönster i ditt projekt innan du börjar.
Att skapa animationer på ett enkelt sätt är tämligen omöjligt i SFML. I DirectX finns i alla fall en sprite-animationsklass som standard, tyvärr ingår inte den i SFML så man får dyka ner i arbeten som andra har gjort.
I SFML:s wiki http://www.sfml-dev.org/wiki/en/sources/anisprite finns en enkel lektion över hur man får en liten pojke att gå omkring. För att få exemplet att fungera måste du dessutom skapa ett två andra projekfiler:
AniSprite.h – där klassen anisprite deklareras. AniSprite.cpp – där koden för anisprite finns.
Är det så att du vill kunna animera spelpjäser i framtiden, får du leva med att dessa filer alltid måste ingå i projekten i framtiden.
En animationsklass
[redigera]på det stora hela taget direkt från wikin, men kommentarer och liknande är översatt till svenska. Se till så att du har ett fungerande projekt där alla dll filer är länkade på rätt sätt. Spara ner filen med den gående pojken från http://www.sfml-dev.org/wiki/_media/en/sources/character.png Lägg den i den mapp som main.cpp ligger så att programmet hittar den. Sprite-kartan är 191x256 punkter och varje bild i den är 47 pixels bred och 64 pixels hög Byt ut koden i main.cpp (vanliga programmeringsfönstret) till:
#include <iostream> #include <SFML\System.hpp> #include <SFML\Graphics.hpp> #include <SFML\Window.hpp> #include <AniSprite.h> int main() { //Början av programkörningen sf::RenderWindow App(sf::VideoMode(800, 600, 32), "Test - animation"); float pojkfart = 0.05f; //hastigheten när pojken flyttar sig // Ladda in in sprite-karta, en uppsättning bilder som skall visas i sekvens //Första bilden = 0, alla måste vara lika stora. sf::Image pojkkarta; if (!pojkkarta.LoadFromFile("character.png")) return EXIT_FAILURE; //Skapa hållaren för sprite-animationen AniSprite Spritepojk(pojkkarta,47,64); //bildkarta och storleken på varje enskild bild x,y-led Spritepojk.SetLoopSpeed(12); //12 fps //Spritepojk.Play(0,1); //Frivillig - visa första och andra bilden enbart vid programstart, får inte vara 0,0 Spritepojk.SetPosition(200.f, 200.f); //Placera ut bilden bool left, right, up, down; //sk. state enum- left = right = up = down = false; //avgör om animationen skall visas eller ej när pojken går. while(App.IsOpened()) { sf::Event Event; while (App.GetEvent(Event)) // Ta hand om händelser { //while 2 if (Event.Type == sf::Event::Closed) //kryssat på [x] symbolen? stäng programmet App.Close(); if (Event.Type == sf::Event::KeyPressed) // En tangent har tryckts ner { //if 1 if (Event.Key.Code == sf::Key::Escape) // ESC tangenten = stäng programmet App.Close(); } //slut if 1 } //slut, while 2 //OBS Man räknar inte rutorna från 0, utan från 1. Första rutraden i animationen //består av fyra rutor, numrerade från 1 till 4, i motsats till att C++ vanligen börjar //räkna från 0 if (App.GetInput().IsKeyDown(sf::Key::Left)) { Spritepojk.Move(-pojkfart, 0); //Går åt vänster if (left == false) //redo att starta animation { Spritepojk.Play(13,16); //fyra sista bilderna left = true; //ställ om så att det går- down = right = up =false; //att visa animation med andra tangenter } } //Visa nedersta raden, pojken går åt vänster else if (App.GetInput().IsKeyDown(sf::Key::Right)) { Spritepojk.Move(pojkfart, 0); if (right == false) { Spritepojk.Play(5,8); right = true; left = up = down = false; } }//Visa andra raden, pojken går åt höger else if (App.GetInput().IsKeyDown(sf::Key::Up)) { Spritepojk.Move(0, -pojkfart); if(up == false) { Spritepojk.Play(1,4); up = true; left = right = down = false; } }//Visa första raden, man ser ryggen på pojken else if (App.GetInput().IsKeyDown(sf::Key::Down)) { Spritepojk.Move(0, pojkfart); if (down == false) { Spritepojk.Play(9,12); down = true; left = right = up = false; } }//Visa tredje raden, man ser ansiktet på pojken else { Spritepojk.Stop(); //Ingen animation när han står still left=right=up=down=false; //så att man kan klicka 2 ggr i rad //och få animation bägge gångerna } // Rensa skärmen App.Clear(); //updatera animation Spritepojk.Update(); App.Draw(Spritepojk); App.Display(); } return 0; } //slut på programkörningen
Nu får du mängder med felmeddelanden om du bygger projektet [CTRL]+[ALT]+[B], tre steg kvar innan det skall fungera.
Skapa projektfilerna
[redigera]- Högerklicka i vänster panel på den feta texten som har projektets namn.
- I mitten av menyn finns alternativet [Add], välj det.
- Välj [New Item...], översta alternativet.
- Mitt på sidan finns nu några filalternativ. Ett har ett ”h” mitt på. Klicka på den, och ge den namnet ”AniSprite.h” utan citattecken.
- Klicka på [Add] knappen längst ner till höger.
Nu får du upp ett helt tomt dokument. Det skall dessutom synas under mappen [Header Files] i den vänstra panelen Kopiera in följande text i dokumentet:
// AniSprite.h #pragma once //Läs bara in filen en enda gång även om den associeras flera gånger #include <SFML\Graphics.hpp> //fellänkad i originaldokumentet class AniSprite : public sf::Sprite { public: AniSprite(); //Initieringslista AniSprite(const sf::Image& Img, int frameWidth, int frameHeight); ~AniSprite(void); //Ange detta när du skapar en animation, //T.ex. Sprite(Image,47,64); //var i animationen skall man börja? sf::IntRect AniSprite::GetFramePosition(int frame); //Hur många bilder skall visas? int GetFrameCount(); //Hur stora är bilderna? void SetFrameSize(int frameWidth, int frameHeight); //Ställer in visaren på nuvarande bild. void SetFrame(int frame); //sets loop-hastighetens bildvisning i bilder per sekund void SetLoopSpeed(float fps); //starta animationen/loopningen void Play(); //Nummer på startbild och nummer på slutybild void Play(int start, int end); //stopp void Stop(); //rita upp förändring void Update(); private: sf::Clock clock; float fps; bool isPlaying; int loopStart; int loopEnd; int currentFrame; int frameWidth; int frameHeight; };
Nu skall du skapa filen med klassens programkod: Högerklicka i på ditt projektnamn där det är skrivet med fet stil i den vänstra panelen igen.
I mitten av menyn finns alternativet [Add], välj det. Välj [New Item...], översta alternativet. Näst överst bland alternativen på den sida som kommer upp finns bilden av ett dokument med två gula + tecken på. Det heter C++ File (.cpp). Välj det och döp det till ”AniSprite.cpp ” utan citattecken. Klicka på [Add] knappen längst ner till höger. Nu får du upp ett helt tomt dokument. Det skall dessutom synas under mappen [Source Files] i den vänstra panelen Kopiera in följande text i dokumentet:
//AniSprite.cpp #include "AniSprite.h" AniSprite::AniSprite(void) : sf::Sprite() { this->fps=1; this->currentFrame=0; this->isPlaying = false; this->loopStart = 0; this->SetFrameSize(0, 0); } AniSprite::AniSprite(const sf::Image& Img, int frameW, int frameH) : sf::Sprite(Img) { this->fps=1; this->currentFrame=0; this->isPlaying = false; this->loopStart = 0; this->SetFrameSize(frameW, frameH); //Dags att beräkna animationen } AniSprite::~AniSprite(void) { } int AniSprite::GetFrameCount() //Avgör antalet frames isprite-sheet { unsigned int across = this->GetImage()->GetWidth() / this->frameWidth; unsigned int down = this->GetImage()->GetHeight() / this->frameHeight; return across*down; } //första bilden är bild 0 sf::IntRect AniSprite::GetFramePosition(int frame) { //get number across and down unsigned int across = (this->GetImage()->GetWidth() / this->frameWidth); unsigned int down = (this->GetImage()->GetHeight() / this->frameHeight); int tileY = frame / across ; //hitta Y på sprite sheet int tileX = frame % across ; //hitta X på sprite sheet sf::IntRect result( tileX*this->frameWidth, tileY*this->frameHeight, tileX*this->frameWidth + this->frameWidth, tileY*this->frameHeight + this->frameHeight); // for SFML 2.0 använd dessa och kommentera bort ovanstående /* sf::IntRect result( tileX*this->frameWidth, tileY*this->frameHeight, this->frameWidth, this->frameHeight); */ //end return result; } // void AniSprite::SetFrameSize(int frameW, int frameH) { this->frameWidth = frameW; this->frameHeight = frameH; this->SetSubRect(sf::IntRect(0,0,frameW,frameH)); } //Ställer in nuvarande bild void AniSprite::SetFrame(int frame) { this->currentFrame = frame; } //ställer in animationshastigheten i bilder per sekund void AniSprite::SetLoopSpeed(float newfps) { this->fps = newfps; } //startar animationen void AniSprite::Play() { this->Play(0,GetFrameCount()); } void AniSprite::Play(int start, int end) { loopStart = start; loopEnd = end; currentFrame = start; isPlaying = true; clock.Reset(); } //stoppar animationen void AniSprite::Stop() { isPlaying = false; } //uppdaterar funktionen void AniSprite::Update() { if(isPlaying) { int frameCount = loopEnd - loopStart; // för sfml 2.0 byt ovanstående rad med... // int frameCount = (loopEnd+1) - loopStart; float timePosition = (clock.GetElapsedTime() * fps); currentFrame = loopStart + (int)timePosition % frameCount; //printf("%f:%i\n",clock.GetElapsedTime(),currentFrame); this->SetSubRect(GetFramePosition(currentFrame)); } }
Du kan fortfarande inte pröva projektet. Det sista du måste göra är att spara AniSprite.h på något ställe som Visual C++ 2010 express hittar till. Titta först i ditt projekt där du sparat bilderna, så kommer du att se att både AniSprite.cpp och AniSprite.h ligger i rätt mapp. Tyvärr är C++ för korkat för att förstå det. Kopiera bägge filerna och klistra in dem i SFML:s include bibliotek. Du hittar var det är genom att.
- Högerklicka på ditt projektnamn i vänstra panelen.
- Välj [properties] alternativet längst ner i menyn som poppar upp.
- Ändra alternativrutan överst till vänster till [All Configurations]
- Klicka på C/C++ alternativet.
- Välj [General]
- På översta raden står det var include biblioteket finns. För mig ligger det på:
C:\sfml16\SFML-1.6\include
- Klistra in filerna där. Först nu går det att köra animationen.
Provkör, nu borde det gå att vandra omkring med pojken.
Andra programmet
[redigera]Om det är så att du skapar ett nytt spel och vill använda AniSprite.h och AniSprite.cpp i det projektet får du söka upp den mapp där du sparat filerna. Starta VC++, öppna ditt projekt och högerklicka på ditt projektnamn (svart text högt upp). Välj add/lägg till och sedan Existing Item. Därefter söker du upp AniSprite.h och AniSprite.cpp och länkar in dem i ditt spelprojekt den vägen.