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.