Programmera spel i C++ för nybörjare/Studsande boll
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.
Hur får man saker att studsa på kanterna? Det är den enklaste formen av kollisionsberäkning men samtidigt grunden för tidiga spel som Pong och Space invaders.
Anta att du har en fyrkantig spelplan. I spelplanen finns en boll. Den bollen får inte gå utanför kanten. Hur gör man då? Skaffa en bollsprite med genomskinlig bakgrund (om du vill att den skall se snygg ut). Jag snodde en 24x24 pixels bild (th_Bag_Dive_Ball_Sprite.png) och döpte om den till ”bollsprite.png” Bilden finns på: http://s601.photobucket.com/albums/tt92/Thehellkidd/Pokemon/?start=20
Placera den i samma mapp som main.cpp filen, (se i exemplet med sprites hur man gör) så att programmet kan hitta bilden. Eftersom bollens hastighet skall styras utifrån är det bäst att ha en variabel i början som definierar bollens hastighet. Fördelen med att ha en variabel deklarerad i början är att den går att ändra ganska lätt. Utöver det måste vi hela tiden veta var bollen är i förhållande till väggarna för att se om den slår i någonstans.
Kommer du ihåg hur vi fick fram koordinaterna för kon och pojken i det andra exemplet med pojken och kon? Ange variablerna på samma sätt i början.
float bollX=0.0f; //bollens x-koordinat float bollY=0.0f; //bollens y-koordinat
Vi måste också veta vilken hastighet vi skall ha på bollen, och hastigheten är detsamma som hur många steg den rör sig i X- och Y-led. Så även dessa variabler skall ändras, jag kallar dem fartX och fartY:
float fartX = 0.5f; //rörelse i xled float fartY = 0.5f; //rörelse i yled
Jag gav dem 0.5f för enkelhetens skull, du kan ta vilket värde du vill. Vill du att den skall gå snabbare kan du alltid göra så att farten ökar 0.05f varje gång bollen träffar en vägg…
Placera sedan ut bollen en pixel in så att den inte aktiverar kollisionen direkt från början. boll.SetPosition(1.0f,1.0f); //Placera ut bilden i övre vänstra hörnet
Hur vet vi då om vi krockar? I loopen ser vi om vi krockar med höger vägg genom att se om bollens x >(800-24), dvs. spelfönstrets bredd – bollbildens bredd. Kom ihåg att man räknar bildens position utifrån dess övre vänstra hörn. Om den slår in i väggen skall den få ett negativt x-värde så att den går åt vänster istället.
bollX = boll.GetPosition().x; if (bollx > 766) //slår in I högervägg fartX = fartX * -1; //spegelvänd riktning
Tumregel, multiplikation med negativa tal: -2 * -2 = 4 (negativt * negativt blir positivt) -2 * 2 = -4 (negativt * positivt blir negativt) 2 * -2 = -4 (positivt * negativt blir negativt) 2 * 2 = 4 (positivt * positivt blir positivt)
Bara genom att multiplicera med -1 byter vi alltså riktning eftersom det gör negativa tal positiva och positiva tal negativa.
Så kan vi göra med alla riktningarna:
if (bollX > 766 || bollX < 0 ) //den slår in i höger- eller vänsterväggen fartX = fartX * -1; //spegelvänd riktning else if (bollY > 576 || bollY < 0) //den slår in neder- eller överväggen fartY = fartY * -1; //spegelvänd riktning
|| är tecknet för ”eller”. Det kan översättas som:
Om bollen är 766 pixlar från vänster vägg, eller har sitt övre vänstra hörn på en negativ del i koordinatsystemets x-axel (utanför skärmen åt vänster) så byt riktning.
Provkör koden.
#include <iostream> #include <SFML\System.hpp> #include <SFML\Graphics.hpp> #include <SFML\Window.hpp> int main() { //Början av programkörningen float bollX=0.0f; //x position för bollen float bollY=0.0f; //y position för bollen float fartX = 0.5f; //rörelse i xled float fartY = 0.5f; //rörelse i yled sf::RenderWindow App(sf::VideoMode(800, 600, 32), "SFML studsande boll"); // Skapa fönstret vi skall visa färgerna i sf::Image bollbild; //skapa en tom bildhållare som heter bollbild if (!bollbild.LoadFromFile("ballsprite.png")) return EXIT_FAILURE; //fyll den tomma bildhållaren med // bilden ballsprite.png bilden är 24x24 sf::Sprite boll(bollbild); //Skapar den grafiska spelpjäsen boll med grafiken från bollbild boll.SetPosition(1.0f,1.0f); //Placera ut bilden i övre vänstra hörnet while (App.IsOpened()) // Start spel-loopen { //while 1 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 bollX=boll.GetPosition().x; //var är bollen i x-led bollY=boll.GetPosition().y; //var är bollen i y-led if (bollX > 766 || bollX < 0 ) //den slår in i höger- eller vänsterväggen fartX = fartX * -1; //spegelvänd riktning else if (bollY > 576 || bollY < 0) //den slår in neder- eller överväggen fartY = fartY * -1; //spegelvänd riktning boll.Move(fartX,fartY); //bollen skickas iväg App.Clear(sf::Color(0, 0, 0)); //rensa allt i fönstret och ersätt med svart färg App.Draw(boll); //Rita upp figuren på den yta spelaren ser App.Display(); //visa upp ändringarna för användaren } //slut, while 1 return 0; } //slut på programkörningen