c++ - hjälp med "fightsystem".

Permalänk

c++ - hjälp med "fightsystem".

Hej, jag började att programmera för bara drygt någon vecka sedan, dock har lärt mig mycket på den korta tid :P.
Åter till saken, jag håller på att göra ett textbaserat RPG spel, gör det med en win32 console application.
Nu har jag kommit till då man ska attackera fiender, men det funkar inte riktigt som jag tänkt.

Här är en bit av koden
--------------------------------------------------------------------------------------------------------------
int random; //min damage på fienden, i detta fallet en varg
int random2; //fiendens damage på mig

for (; wolfhealth >= 1 && health >= 1; wolfhealth - random && health - random2) {
system("cls");
random=rand()%8+2;
random2=rand()%6+1;

cout << "You got " << random << " damage" << endl;
Sleep(1000);
cout << "The enemy got " << random2 << " damage" << endl;
Sleep(1500);
}

cout << "Somebody is dead" << endl; //kommer sedan göra en if sats här för att visa vem som dog
//men vill få det att funka först

--------------------------------------------------------------------------------------------------------
Har längre bak i koden gjort ints för vargens och min hälsa.

Själva slumpgeneratorn i sig fungerar som jag vill, jag har inkluderat filerna <ctime> och <cstdlib>

Problemet är bara att jag aldrig kommer ut ur loopen, hur många damage jag än får.
Har även testat whileloopar men har inte fått det att funka...

Vad tror ni problemet är?

Permalänk
Medlem

dina for-villkor ser skumma ut, en for-loop brukar man använda typ så här

for(int i=0;i<10;i++){...}

dvs du har villkor i stegringssektionen om jag inte ser fel for(initiering;villkor;stegring)...
du kanske bör satsa på en while ist? där skriver du bara in villkoren som ska vara sant när loopen körs, om falskt so hoppar ur:

while(i<10 && i>0){}

du kan även hoppa ur vilken loop som helst mha break;

int i=0; while(true) //loopa för alltid { i++; if(i==5) break; //hoppa ur }

Permalänk
Medlem
Skrivet av 3liteSoldier:

...
Problemet är bara att jag aldrig kommer ut ur loopen, hur många damage jag än får.
Har även testat whileloopar men har inte fått det att funka...

Vad tror ni problemet är?

Problemet är att du aldrig drar ditt framslumpade värde ifrån vargen eller din egen hälsa. Du har ... wolfhealth - random ... i din for-loop men resultatet tilldelas ingen variabel, ungefär som att skriva 5+5 utan att ha en variabel som "fångar upp" det. Sålunda förändras aldrig health eller health2.

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Skrivet av Dalton Sleeper:

dina for-villkor ser skumma ut, en for-loop brukar man använda typ så här

for(int i=0;i<10;i++){...}

dvs du har villkor i stegringssektionen om jag inte ser fel for(initiering;villkor;stegring)...
du kanske bör satsa på en while ist? där skriver du bara in villkoren som ska vara sant när loopen körs, om falskt so hoppar ur:

while(i<10 && i>0){}

du kan även hoppa ur vilken loop som helst mha break;

int i=0; while(true) //loopa för alltid { i++; if(i==5) break; //hoppa ur }

Tack för svaret!
Ändringen (alltså stegringen som du skrev) är i detta fallet att hälsan ska subtraheras med damagen(rand formeln), initieringen har jag skippat i detta fallet eftersom jag redan har skrivit dem variabler som ska finnas med, dock har jag skrivit ett semikolon eftersom det alltid måste finnas två semikolon mellan forloopars paranteser.

Och du har kanske rätt, ska nog satsa på en whileloop istället, får tänka på hur jag ska organisera det...
Kom gärna med fler tips!

Permalänk
Skrivet av Teknocide:

Problemet är att du aldrig drar ditt framslumpade värde ifrån vargen eller din egen hälsa. Du har ... wolfhealth - random ... i din for-loop men resultatet tilldelas ingen variabel, ungefär som att skriva 5+5 utan att ha en variabel som "fångar upp" det. Sålunda förändras aldrig health eller health2.

Aha, förstår hur du menar.
Men om jag har en ytterligare variabel som du sa fångar upp hälsan - skadan så var ska jag då placera satsen t.ex "wolfhealth - random = variabelns_namn"?
Om jag har den inne i forloopens sats så kommer värdet på variabeln nollställas varje gång loopen repeteras, vad jag har förstått det iaf...

Permalänk
Medlem

Grejen var det att jag såg tecknen && i stegringen, jag tippar på att det inte får rätt betydelse i detta fall, sedan behöver du inte köra med stegring i detta exempel så en while vore att rekommendera, du kan då utföra din stegring manuellt där.

Permalänk
Medlem
Skrivet av 3liteSoldier:

Aha, förstår hur du menar.
Men om jag har en ytterligare variabel som du sa fångar upp hälsan - skadan så var ska jag då placera satsen t.ex "wolfhealth - random = variabelns_namn".
Om jag har den inne i forloopens sats så kommer värdet på variabeln nollställas varje gång loopen repeteras, vad jag har förstått det iaf...

om du har din variabel deklarerad utanför loopen så kan du minska health i loopen och värdet sparas, ett bättre skäl till att köra while:

int health=100; int damage; while(true){ if(health<=0) break; damage=rand()... health=health-damage; //samma som health-=damage; }

eller:

int health=100; int damage; while(health>0){ damage=rand()... health-=damage; }

Permalänk
Skrivet av Dalton Sleeper:

om du har din variabel deklarerad utanför loopen så kan du minska health i loopen och värdet sparas, ett bättre skäl till att köra while:

int health=100; int damage; while(true){ if(health<=0) break; damage=rand()... health=health-damage; //samma som health-=damage; }

eller:

int health=100; int damage; while(health>0){ damage=rand()... health-=damage; }

Tack så mycket!
Först funkade det inte (trodde jag) men det var bara för att jag hade glömt ha med Sleep(..) i satsen så att hela processen gick så fort att jag trodde det bara var en attack när loopen sedan blev negativ. Precis som man hade fått en critical vars damage är högre än vargens hälsa xD

Men det funkar utmärkt nu!

Permalänk
Medlem
Skrivet av 3liteSoldier:

Precis som man hade fått en critical vars damage är högre än vargens hälsa xD

critical är aldrig kul, speciellt om man råkar ut för den själv...

Tips: Du kanske kan ha med en/flera health potions?

int potions=3; string answer=""; while(true){ //någon fråga: vill du bla bla? cin >> answer; //input if(answer=="y"){ if(potions>0) {health+=25; potions--;} //öka health med 25, minska antalet potions med 1 else //utskrift: du har inga potions kvar :P } ... }

Obs, ingen kod är testad, bara snabbknappat från minnet så du förstår principen.

Permalänk
Skrivet av Dalton Sleeper:

critical är aldrig kul, speciellt om man råkar ut för den själv...

Tips: Du kanske kan ha med en/flera health potions?

int potions=3; string answer=""; while(true){ //någon fråga: vill du bla bla? cin >> answer; //input if(answer=="y"){ if(potions>0) {health+=25; potions--;} //öka health med 25, minska antalet potions med 1 else //utskrift: du har inga potions kvar :P } ... }

Obs, ingen kod är testad, bara snabbknappat från minnet så du förstår principen.

Tack! Fast jag tänkte ha mat som man kan köpa istället för potions, men spelar roll. Principen e densamma, hehe.

Men hur gör man på bästa sätt om man ska ha med ett sorts inventory/väska i spelet?
Hur ska funktionen/klassen se ut?
Jag hade tänkt mig att när man börjar spela så är väskan tom, sedan kan man köpa armor, svärd osv. för ett antal guld.
När man väl har köpt så hamnar dem i inventoryt som man kan kika på när som önskas.

Elr om fienden droppar ngt svärd när dem dör.

Hehe, ni tänker säkert "ojojoj, ska den nybörjaren göra ett sånt avancerat spel", men jag hade inte tänkt att detta projekt skulle gå på ett par dagar, utan jag har tålamod och vill spendera tid...

Permalänk

Har stött på ett ytterligare problem...
När man har attackerat vargen 1 gång så när man går tillbaka för att attackera en ny varg så kommer det upp det som står när man har dödat vargen.
Alltså finns det bara en varg och när man dödat den så är den död :\

Ngn som har en lösning?

Permalänk
Medlem

Jag satt & snabbknappade & se om jag kunde ge något lätt förslag, men det blir lätt ickelätt också, kom så här långt, mycket fattas och förmodligen behöver det många ändringar till slut, designa när man skriver är ingen bra ide Detta är några få definitioner som inte är körbara.

class Item{ //inget arv här inte :P private: string name; double damage; //damage på food? poison :P int numberOf; public: Item(string n, double d); double GetDamage(); string GetName(); //... }; class Inventory{ private: vector<Item*> list; public: void Add(Item* i); void Clear(); Item* GetFirst(); Item* GetItem(int i); }; void main(){ Inventory* inv=new Inventory(); inv->Add(new Item("Greatsword",32.5)); Item* currentWeapon=inv->GetFirst(); //vi antar att svärd ligger här string strdamage=""; char buffer[255]; while(true){ //... double damage=rand()* currentWeapon->GetDamage(); //kanske 0.5-1.5*damage? sprintf(buffer,"%f",damage); // nån konvertering till string strdamage=strdamage + buffer; cout << "Du smackade trollet med ett " + currentWeapon->GetName() + " som det nu droppar " + strdamage + " liter blod från" << endl; } }

Permalänk
Medlem
Skrivet av 3liteSoldier:

Har stött på ett ytterligare problem...
När man har attackerat vargen 1 gång så när man går tillbaka för att attackera en ny varg så kommer det upp det som står när man har dödat vargen.
Alltså finns det bara en varg och när man dödat den så är den död :\

Ngn som har en lösning?

har du flera vargar, eller använder du en återkommande?
om du har en ressurectad en så måste du väll öka dess health igen efter den dött & meddelandet skrivits ut, du bör kontrollera & skriva ut om nån dör "i" loopen om du vill återanvända den, inte efter (där bör det stå om du dör). kanske ha en int som säger att det finns 5 vargar som du räknar ner?

Permalänk
Skrivet av Dalton Sleeper:

har du flera vargar, eller använder du en återkommande?
om du har en ressurectad en så måste du väll öka dess health igen efter den dött & meddelandet skrivits ut, du bör kontrollera & skriva ut om nån dör "i" loopen om du vill återanvända den, inte efter (där bör det stå om du dör). kanske ha en int som säger att det finns 5 vargar som du räknar ner?

Jag använder en återkommande, jag tänkte att spelaren ska ha en möjlighet att döda hur många vargar som han vill, det finns ju gott om dem i skogen xD.

Tror du det funkar bra om man har en if sats (varav villkor kräver att vargen har dött) inne i loopen där det först står att vargen har dött och sedan skriver jag en break så att loopen avslutas?

Permalänk
Medlem
Skrivet av 3liteSoldier:

Tror du det funkar bra om man har en if sats (varav villkor kräver att vargen har dött) inne i loopen där det först står att vargen har dött och sedan skriver jag en break så att loopen avslutas?

Du använder dig väll bara av en loop? dvs om du avslutar den så avslutas programmet, jag tippar på att du:

  • med en ifsats avgör om vargen har dött, som du sa

  • skriver ut att den är död

  • räknar ner en vargvariabel (antalVargar--)

  • ökar vargens health (inför nästa vända i loopen som motsvarar en ny varg)

  • inte använda break, du avslutar då hela loopen och ditt program avslutas.

Permalänk
Skrivet av Dalton Sleeper:

Jag satt & snabbknappade & se om jag kunde ge något lätt förslag, men det blir lätt ickelätt också, kom så här långt, mycket fattas och förmodligen behöver det många ändringar till slut, designa när man skriver är ingen bra ide Detta är några få definitioner som inte är körbara.

class Item{ //inget arv här inte :P private: string name; double damage; //damage på food? poison :P int numberOf; public: Item(string n, double d); double GetDamage(); string GetName(); //... }; class Inventory{ private: vector<Item*> list; public: void Add(Item* i); void Clear(); Item* GetFirst(); Item* GetItem(int i); }; void main(){ Inventory* inv=new Inventory(); inv->Add(new Item("Greatsword",32.5)); Item* currentWeapon=inv->GetFirst(); //vi antar att svärd ligger här string strdamage=""; char buffer[255]; while(true){ //... double damage=rand()* currentWeapon->GetDamage(); //kanske 0.5-1.5*damage? sprintf(buffer,"%f",damage); // nån konvertering till string strdamage=strdamage + buffer; cout << "Du smackade trollet med ett " + currentWeapon->GetName() + " som det nu droppar " + strdamage + " liter blod från" << endl; } }

Tack för exemplet!
Sitter och tänker på hur det funkar och om ngt behöver ändrats med hjälp av en C++ bok :P.

Permalänk
Skrivet av Dalton Sleeper:

[*]inte använda break, du avslutar då hela loopen och ditt program avslutas.
[/LIST]

Men jag tänkte att efter loopen så skriver jag funktionens namn (funktionen som själva ingamet är på) så hamnar man automatisk på början av funktionen.
Jag kan ju testa om det funkar iaf.

Permalänk
Medlem
Skrivet av 3liteSoldier:

Men jag tänkte att efter loopen så skriver jag funktionens namn (funktionen som själva ingamet är på) så hamnar man automatisk på början av funktionen.
Jag kan ju testa om det funkar iaf.

Okey, vet inte hur du har lagt upp det, bara du inte kallar mingameloop() i funktionen mingameloop(), i slutändan blir det 500 funktioner som körs i varandra vilket inte är att rekommendera

Permalänk
Skrivet av Dalton Sleeper:

Okey, vet inte hur du har lagt upp det, bara du inte kallar mingameloop() i funktionen mingameloop(), i slutändan blir det 500 funktioner som körs i varandra vilket inte är att rekommendera

Hehe, du hade rätt, det blir samma oavsätt om man har en ifsats inne i loopen där man lägger upp det som jag sa.
Får tänka på vad du skrev tidigare och se hur jag löser det.

Permalänk
Medlem
Skrivet av Dalton Sleeper:

Grejen var det att jag såg tecknen && i stegringen, jag tippar på att det inte får rätt betydelse i detta fall, sedan behöver du inte köra med stegring i detta exempel så en while vore att rekommendera, du kan då utföra din stegring manuellt där.

Sant, däremot ska följande fungera:

for (; wolfhealth >= 1 && health >= 1; wolfhealth -= random, health -= random2) {

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem
Skrivet av Teknocide:

Sant, däremot ska följande fungera:

for (; wolfhealth >= 1 && health >= 1; wolfhealth -= random, health -= random2) {

yes, jag tyckte jag mindes det även om jag inte använder komma ofta, snabbskummade mestadels koden i början och la inte märke till vad det gjorde eller om det stämde, kanske något snyggare med while enligt mej ändå

Permalänk
Hedersmedlem
Skrivet av Dalton Sleeper:

yes, jag tyckte jag mindes det även om jag inte använder komma ofta, snabbskummade mestadels koden i början och la inte märke till vad det gjorde eller om det stämde, kanske något snyggare med while enligt mej ändå

Den mest uppenbara skillnaden är att &&-varianten avbryter om någon tilldelning (med start från vänster) blir 0; det är alltså möjligt att endast några variabler uppdateras.

Permalänk
Skrivet av Dalton Sleeper:

Jag satt & snabbknappade & se om jag kunde ge något lätt förslag, men det blir lätt ickelätt också, kom så här långt, mycket fattas och förmodligen behöver det många ändringar till slut, designa när man skriver är ingen bra ide Detta är några få definitioner som inte är körbara.

Jag tog mig friheten att göra lite små ändringar i din kod, med kommentarer på ändringarna.

När du gör en vektor med pekare så kommer vektor att allokera minne för pekarna, men sen måste du själv allokera minnet för objektet, istället för att bara vektor allokerar minne för objekten. Förutom att det tar mera minne att låta vektor allokera en pekare extra för varje objekt så är risken större för minnesläckor.

Det kan säkert finnas fall när man vill göra det ändå, men min uppfattning är att det är bättre att låta bli att göra manuell minneshantering (new/delete) när det är möjligt.

class Item { private: string m_name; // en vanlig konvention är att sätta något prefix på medlemsvariabler double m_damage; // i C# är det ofta _varName, i Java mVarName och i C++ m_varName int m_numberOf; public: Item(string name, double damage); // då kan man använda namnen utan prefix som argument eller temporära variabler double GetDamage(); const string& GetName(); // här returneras en referens till strängen istället för en kopia //... }; void main() { vector<Item> inventory; // det verkade onödigt att ha en klass som enbart wrappar en vektor inventory.push_back(Item("Greatsword", 32.5)); // vektorn håller nu items, istället för pekare till items Item& currentWeapon = inventory[0]; while (true) { //... double damage = rand() * currentWeapon.GetDamage(); cout << "Du smackade trollet med ett " << currentWeapon.GetName() << " som det nu droppar " << damage << " liter blod från" << endl; } }

Permalänk
Medlem
Skrivet av VirtualIntent:

Jag tog mig friheten att göra lite små ändringar i din kod, med kommentarer på ändringarna.

När du gör en vektor med pekare så kommer vektor att allokera minne för pekarna, men sen måste du själv allokera minnet för objektet, istället för att bara vektor allokerar minne för objekten. Förutom att det tar mera minne att låta vektor allokera en pekare extra för varje objekt så är risken större för minnesläckor.

Det kan säkert finnas fall när man vill göra det ändå, men min uppfattning är att det är bättre att låta bli att göra manuell minneshantering (new/delete) när det är möjligt.

...

Nu ser det lite snyggare ut...
Kontainerklassen hade jag för ytterligare utökning, ev för att leta upp element, sätta in dom sorterat om behövs, plussa på/ändra samt ta bort. Känns onödigt att ha det i kod i huvudprogrammet varje gång man kan tänkas göra det. Kanske några ytterligare anledningar jag inte kan komma på Pekarna hade jag för att man ska kunna plocka ut element och göra något, snabbare länkning utan att behöva kopiera hela elementet, grejerna i inventoryn är väll inte direkt permanenta. Nu är det visserligen inga större datastrukturer men men.

Permalänk
Skrivet av Dalton Sleeper:

Kontainerklassen hade jag för ytterligare utökning, ev för att leta upp element, sätta in dom sorterat om behövs, plussa på/ändra samt ta bort. Känns onödigt att ha det i kod i huvudprogrammet varje gång man kan tänkas göra det.

Det håller jag definitivt med om, alltså att de sakerna du skriver där är sånt man inte vill ha inblandad med spellogiken Men det kanske finns nån färdig container i ramverket som stödjer de operationerna?

Skrivet av Dalton Sleeper:

Pekarna hade jag för att man ska kunna plocka ut element och göra något, snabbare länkning utan att behöva kopiera hela elementet, grejerna i inventoryn är väll inte direkt permanenta. Nu är det visserligen inga större datastrukturer men men.

Om du vill ha snabb länkning så kanske en länkad lista (std::list<>) är att föredra över en dynamisk array (std::vector<>)?

De två principer jag försöker följa är att 1. undvika manuell minneshantering, för min erfarenhet är att det funkar ok för mindre projekt men när projektet blir större så blir risken för buggar större och större, och 2. använda ramverksklasser (STL eller boost för C++) där det är möjligt, för att undvika att duplicera kod, för risken är större att jag introducerar någon bugg om jag skriver om algoritmerna och datastrukturerna själv istället för att använda de existerande.

Det finns självklart massvis av sätt att lösa ett problem på. Det här är detaljer, din första lösning fungerade ju såklart Jag tänkte bara passa på att diskutera lite detaljer så kanske någon annan kan få ut nått av det.

Men en sak jag har tänkt på är att det kanske vore bra att ha en liten tutorial här i forumet om hur olika datastrukturer är tänkta att användas och vad de har för karakteristik, det är nått som jag sett att även personer som jobbat med programmering i flera år kan ha lite osäker koll på. I själva verket finns det inte så många varianter så det kan vara väl värt att göra sig bekant med dem.

http://www.cplusplus.com/reference/stl/
http://msdn.microsoft.com/en-us/library/1fe2x6kt%28v=VS.100%2...

Permalänk
Medlem
Skrivet av VirtualIntent:

Om du vill ha snabb länkning så kanske en länkad lista (std::list<>) är att föredra över en dynamisk array (std::vector<>)?

Det har du helt rätt i, tänkte inte så långt när jag snabbknappade
Jag hade inte heller räknat ut riktigt hur jag ville ha det med items osv, typer, arv, polymorfism, åtkomst, dubbletter, sortering osv så mycket består av frågetecken Det är svårt att hålla detta på nybörjarnivå även om själva iden är hyfsat lätt.

I vilket fall känns det skönt att ni kommer med kommentarer & förslag, nyttigt för mej men också trådskaparen tror jag och många andra som kanske snabbskummar.

Skrivet av VirtualIntent:

Men en sak jag har tänkt på är att det kanske vore bra att ha en liten tutorial här i forumet om hur olika datastrukturer är tänkta att användas och vad de har för karakteristik, det är nått som jag sett att även personer som jobbat med programmering i flera år kan ha lite osäker koll på. I själva verket finns det inte så många varianter så det kan vara väl värt att göra sig bekant med dem.

Iden med tutorials tycker jag låter finfint, men det skulle också vara bra med en separat forumdel för programmering ist för nuvarande digitalt skapande...

Permalänk
Skrivet av Dalton Sleeper:

I vilket fall känns det skönt att ni kommer med kommentarer & förslag, nyttigt för mej men också trådskaparen tror jag och många andra som kanske snabbskummar.

Javisst, sjukt bra inlärning att titta på spelexempel om hur man ska använda sig av klasser, containerklasser, funktioner osv. i spel

Permalänk
Skrivet av VirtualIntent:

class Item { private: string m_name; // en vanlig konvention är att sätta något prefix på medlemsvariabler double m_damage; // i C# är det ofta _varName, i Java mVarName och i C++ m_varName int m_numberOf; public: Item(string name, double damage); // då kan man använda namnen utan prefix som argument eller temporära variabler double GetDamage(); const string& GetName(); // här returneras en referens till strängen istället för en kopia //... }; void main() { vector<Item> inventory; // det verkade onödigt att ha en klass som enbart wrappar en vektor inventory.push_back(Item("Greatsword", 32.5)); // vektorn håller nu items, istället för pekare till items Item& currentWeapon = inventory[0]; while (true) { //... double damage = rand() * currentWeapon.GetDamage(); cout << "Du smackade trollet med ett " << currentWeapon.GetName() << " som det nu droppar " << damage << " liter blod från" << endl; } }

Men vad spelar det för roll om man har "m_" före variablernas namn i klassen Item?

Permalänk
Medlem
Skrivet av 3liteSoldier:

Men vad spelar det för roll om man har "m_" före variablernas namn i klassen Item?

Ingen som helst roll egentligen, men som han skrev i kommentaren så brukar man markera variablerna med ett prefix så det får lite mer struktur, man kan då också använda parametrar med de rätta namnen och tilldela till sina m_* variabler, sedan är det lätt att hitta variablerna då man kan skriva m_ och sedan ctrl+space så får man upp alla liknande i en liten lista.

Permalänk
Skrivet av Dalton Sleeper:

Ingen som helst roll egentligen, men som han skrev i kommentaren så brukar man markera variablerna med ett prefix så det får lite mer struktur, man kan då också använda parametrar med de rätta namnen och tilldela till sina m_* variabler, sedan är det lätt att hitta variablerna då man kan skriva m_ och sedan ctrl+space så får man upp alla liknande i en liten lista.

Aha