Hoppa till innehållet

Programmera spel i C++ för nybörjare/Bakgrunden

Från Wikibooks


Bakgrunden 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.

Det är inte så kul att springa omkring på en färg. Spelkänslan ökar dramatiskt med en snygg bakgrund.

En stor bild

[redigera]

Det finns ett flertal sätt att skapa bakgrunder på. Enklast är att ha en bild exakt lika stor som spelfönstret. Det kan mycket väl vara en jpg-bild eftersom det troligen inte kommer att finnas någon del som är genomskinlig. Man skapar en bakgrund precis som man skapar en spelare:

	 sf::Image graesbakgrund; //skapa en tom bildhållare som heter graesbakgrund
	 if (!graesbakgrund.LoadFromFile("grass.jpg")) return EXIT_FAILURE; //fyll den tomma bildhållaren med bilden av gräs
	 sf::Sprite graess(graesbakgrund); //Skapar den grafiska spelpjäsen graess med grafiken från Image
	 graess.SetPosition(0.0, 0.0); //Placera ut bilden

I mitt fall hittade jag en 800x600 fotografi av gräs på internet som jag döpte till grass.jpg och sparade i samma mapp som projektets main.cpp fil.

Genom den sista raden placeras bildens övre vänstra hörn i fönstrets övre vänstra hörn, och därmed blir hela spelytan täckt. Det är dock viktigt att alla orörliga bakgrunder ritas upp innan de rörliga, så när alla sprites skall ritas ut i slutet skall bakgrunden ritas upp först av alla.

<namn på fönstret>.Draw(graess); //Rita upp den yta spelaren spelar på

Tiling/kakling

[redigera]
Exempel på kvadratiska plattor som bildar spelplan
Exempel på sexkantiga plattor som bildar spelplan
Exempel på isometriska plattor som bildar spelplan

Ett annat alternativ är att man har olika fyrkanter av exakt samma storlek som man kopierar in på bildytan. Vissa spel har ärvt den gamla varianten från när man spelade med pappbrickor på en fysisk spelplan då sexkantiga rutor var vanligast

En variant av tiling är att använda en isometrisk bakgrundsbild. Varje platta, eller ruta, får en liggande diamantform och ögat luras att tro att bakgrunden egentligen är 3D. Några av de mest populära 2D spelen som gjorts har skapats med isometriska bakgrundsplattor, som: Age of Empires 1, Starcraft 1 och Zyngas Farmville (Facebook). En lektion om teorierna bakom att skapa en isometrisk bakgrund finns här:

http://www.lingoworkshop.com/Articles/Isometric_Game_1.php

Enklast möjliga kod för tiling är denna:

int n = 0;
for( int x = 0; x < MAP_W; ++x )
{
   for( int y=0; y < MAP_H; y++ )
   {
       if(mapa[n] == 1) 
       {
           tilesprite1.SetPosition(x*32,y*32);
           App.Draw(tilesprite1);
       }
       
       ++n;
   }
}
  • tilesprite1 = en sprite med bakgrundsbild som är 32x32 stor.
  • mapa[n] = array med olika nummer motsvarande olika sprites.
  • x = antal rutor i sidled.
  • y = antal rutor i höjdled.
  • MAP_W = kartans bredd i antal rutor, en konstant.
  • MAP_H = kartans höjd i antal rutor, en konstant.

Om du vill hoppa över möjligheten att göra detta själv med egen programkod, finns det et enkelt freeware för Linux/Mac och Windows som heter Tiled som används för att skapa spelkartor med. Du kan ladda ner det här:

http://www.mapeditor.org/

Kantutjämning

[redigera]

Om man har olka bilder från ett sprite sheet som kopplas samman är risken stor att man får kanter som är spikraka när t.ex. hav möter land. Havsrutan är fyrkantig och landrutan är fyrkantig. När de två fyrkantiga rutorna möts blir gränsen spikrak. För att undvika det måste man också ha "gränszons" plattor. En platta med en strand i mitten där man ser hur strand och hav möts på ett mjult vis. Alternativt så har man extra grafik som läggs över alla raka kanter efterår.

Bra engelska artiklar som fördjupar sig i kantutjämning kan du hitta här:

http://www.gamedev.net/page/resources/_/technical/game-programming/tilemap-based-game-techniques-handling-terrai-r934

http://www.srrngames.com/blog/tilemap-roadmap-episode-1-tiles-tilesets

Klassförslag

[redigera]

Hur skall en klass som innehåller information om en platta se ut om man vill skapa en värld av kvadratiska bakgrundsplattor? För det första bör du skapa en lista eller vector där de skall placeras. Därefter skapar du klassdefinitionen. Den måste innehålla följande:

  • x- och y-koordinater för den plats som den skall ligga på
  • Övre vänstra hörnets x-koordinat i sprite sheeten
  • Övre vänstra hörnets y-koordinat i sprite sheeten
  • Storleken i x-led
  • Storleken i y-led
  • en sprite

Vet du bara dessa värden så kan du lätt placera ut spriten på rätt plats på spelkartan och därefter förse den med rätt "urklipp" ur sprite sheeten så att du kan ha en enda sprite sheet för samtliga bakgrundsbilder som skall visas upp.

Klassexempel

[redigera]

Så här skulle en klass för bakgrundsrutorna kunna se ut. Nu finns inga värden med för om man kan gå i den, om den blockerar sikt, vilken höjd den är på osv. Det får du hitta på själv.

class bakgrundsruta
{
public :

bakgrundsruta(int _utplacering_x, int _utplacering_y, int _bild_x, int _bild_y, int _bredd, int _hojd) ; //Konstruktion
~bakgrundsruta(){};
int utplacering_x; //Var den skall hamna i sidled
int utplacering_y; //Var den skall hamna i höjdled
int bild_x; //Var man skall börja kopiera rutan i sprite sheeten i sidled
int bild_y; //Var man skall börja kopiera rutan i sprite sheeten i höjdled
int bredd; //Hur bred är bilden som skall visas upp för spelarna
int hojd; //Hur hög är bilden som skall visas upp för spelarna
sf::Sprite sprite;  //Den sprite som skall visas upp för spelarna och som innehåller bilden.
};

bakgrundsruta::bakgrundsruta(int _utplacering_x, int _utplacering_y, int _bild_x, int _bild_y, int _bredd, int _hojd) 
{ //Ge rutan sina värden redan när den skapas, för enkelhetens skull
utplacering_x = _utplacering_x;
utplacering_y = _utplacering_y;;
bild_x = _bild_x;
bild_y = _bildy;
bredd = _bredd;
hojd = _hojd;
}

När den sedan skall skapas kan vi anta att det rör sig om en ruta som är 64x64 som skall placeras i översta vänstra hörnet, och den andra rutan från vänster på översta raden i sprite sheeten:

bakgrundsruta bakgrundsruta1(0,0,64,0,64,64);

Anta sedan att du har en sprite sheet som heter bakgrundsbilder.jpg:

sf::Image bakgrundsbild_spritesheet; 
if (!bakgrundsbild_spritesheet.LoadFromFile("bakgrundsbilder.jpg")) //Programmet försöker att ladda in en bildfil i det tomma bildobjektet      
std::cout << "Kan inte hitta bilden!" << std::endl; //Om det misslyckas med att ladda in bilden

Därefter kan du ange att spriten i klassen (och samtliga därefter - ladda bara in biden i minnet en gång) skall använda sig av just den bilden/sprite sheeten:

bakgrundsruta1.sprite.SetImage(bakgrundsbild_spritesheet);

Och längst ner i slutet av källkoden inom main:

App.Draw(bakgrundsruta1.sprite); 

så att bilden ritas ut för spelarna.

Scrolling/rörlig bakgrund

[redigera]

Om du har en spelplan som är mycket större än vad som visas i fönstret kan man göra den ”scrollande”, dvs du kan ha spelaren rörlig i sidled i botten men få intrycket av att man flyger över havet, rymden eller liknande. Scrolling kommer bakom principen att det liknar en pappersrulle med påmålad bakgrund som rullas upp som underlag i spelet.