• Advertisement

ICanC

Member
  • Content count

    28
  • Joined

  • Last visited

Community Reputation

147 Neutral

About ICanC

  • Rank
    Member

Personal Information

  • Interests
    Programming
  1. C++ and SDL loop

    I'm a C++ and SDL beginner and I'm trying to make my first 2d game (blackjack) but I'm struggling to get an elegant loop in place to control the images, animations and input. in my rush and excitement to get graphics on the screen I ended up with a massive function handling everything, which just 2 'player decisions' in, has become a monstrous unmaintainable mess, e.g.: bool decision_one = true; bool decision_two = false; card playercard3 = this->deal(); while (decision_one) { SDL_PollEvent(&e); if (e.type == SDL_KEYDOWN) { if (e.key.keysym.sym == SDLK_h) { while (playersource3.x != playerdestination3.x) { playersource3.x += 10; playersource3.y += 10; SDL_BlitSurface(background, NULL, screenSurface, NULL); SDL_BlitSurface(this->getImage(playercard1.image_number), NULL, screenSurface, &playersource1); SDL_BlitSurface(redback, NULL, screenSurface, &dealersource1); SDL_BlitSurface(this->getImage(playercard2.image_number), NULL, screenSurface, &playersource2); SDL_BlitSurface(this->getImage(dealercard2.image_number), NULL, screenSurface, &dealersource2); SDL_BlitSurface(this->getImage(playercard3.image_number), NULL, screenSurface, &playersource3); SDL_UpdateWindowSurface(window); decision_one = false; decision_two = true; } } else if (e.key.keysym.sym == SDLK_s) { card dealercard1 = this->deal(); SDL_BlitSurface(this->getImage(dealercard1.image_number), NULL, screenSurface, &dealersource1); SDL_UpdateWindowSurface(window); decision_one = false; } } SDL_Delay(80); } So I'm trying break it up into smaller chunks like this: class card { private: std::string name; int value; int suit; public: int image_number; SDL_Rect source; SDL_Rect dest; int vel; card(std::string name, int value, int suit, int image_number); card() {}; ~card() {}; void display() const; }; class blackjack { private: std::vector<card> deck; int minBet; int maxBet; int decks; public: blackjack(int minBet, int maxBet, int decks); ~blackjack() {}; SDL_Surface* getImage(int i); void play_hand(std::shared_ptr<player> p); void getinput(std::shared_ptr<player> p); void create_card(card c, int sourceX, int sourceY, int destX, int destY, int vel); void animate_card(card c); void shuffle(); void reshuffle(); void render(); card deal(); void play(std::shared_ptr<player> p); }; card blackjack::deal() { card dealCard = this->deck[this->deck.size() - 1]; this->deck.pop_back(); return dealCard; } void blackjack::create_card(card c, int sourceX, int sourceY, int destX, int destY, int vel) { SDL_Surface* newCard = this->getImage(c.image_number); entities.push_back(*newCard); c.source.x = sourceX; c.source.y = sourceY; c.dest.x = destX; c.dest.y = destY; c.vel = vel; } void blackjack::animate_card(card c) { while (c.source.x != c.dest.x) { c.source.x += c.vel; c.source.x += c.vel; for (auto i : entities) { SDL_Surface *s = &i; SDL_BlitSurface(background, NULL, screenSurface, NULL); SDL_BlitSurface(s, NULL, screenSurface, //HOW TO GET IMAGE POS HERE?); SDL_UpdateWindowSurface(window); } } } void blackjack::render() { } void blackjack::play(std::shared_ptr<player> p) { this->shuffle(); init_graphics(); this->getinput(p); } The main problem I'm struggling to get my head around is rendering all current images in the game and animating them until they reach their destination. I've created a global variable std::vector<SDL_Surface> entities to hold all images in a hand, and I've gotten to the animate card function above but can't understand how i'm going to pass in the location of all the sdl_surface entities for the blitsurface function - any advise on a simple way to add images, animate them from a source to a dest, and keep track of all of this in one 'render' function would be great
  2. C++ comparing 2 floats

    thanks haegarr, that fixed it. and thanks Bregma, my logic was backwards, when writing that code I was wrongly thinking that 'return 0' indicates a 'true' and successful end to the program, when it is infact true values that indicate failure
  3. C++ comparing 2 floats

    hi all, I'm testing with floats for the first time and have discovered that you can't compare 2 floats due to rounding errors. I've read online that you must use an epsilon and test for less than, however I don't seem to be able to get it working with the below code. - when running the code below it it is looping through 6 floats testing for equality with f entered by the player, but even if I put something totally different from the options, the message "not a valid position" is never executed void locks::try_lock() { print("\nEnter lock position: "); float f; cin >> f; int fexists = 1; float epsilon = 0.0000001; // Not sure what the best value to put here is? for (float &a : this->answers) { if ((a - f) < epsilon) { fexists = 0; } } if (fexists == 1) { cout << endl << f << " is not a valid position\n\n"; Sleep(2000); return; } }
  4. C++ buffer or vector issue

    Thanks for all the replies. I've fixed the iterator issue, and the actual cause of the problem was something to do with the messages not being properly conditioned, adding in a few ifs below fixed the issue void merchant::buyfrom(character *a) { print("\nItem to buy: "); string item1; getline(cin, item1); vector<item>::iterator it; unsigned vector_size = this->items.size(); int check = 0; // to handle merchant does not have msg with not enough gold msg for (it = this->items.begin(); it != this->items.end();) { if (it->name == item1) { if (it->price > a->gold) { print("\n\nYou don't have enough gold to buy the "); cout << it->name; check = 1; break; } print("\n\nYou bought "); std::cout << item1; print(" for "); std::cout << it->price; print(" gold"); a->inventory.push_back(*it); a->gold -= it->price; this->gold += it->price; this->items.erase(it); break; } else { ++it; } } if (this->items.size() == vector_size && check == 0) { print("\n\nMerchant does not have a "); std::cout << item1; print(" to sell"); } print("\n\n\n1. Back\n\n\n> "); char c; std::cin >> c; } void merchant::sellto(character *a) { print("\nItem to sell: "); string item1; getline(cin, item1); vector<item>::iterator it; unsigned vector_size = a->inventory.size(); for (it = a->inventory.begin(); it != a->inventory.end();) { if (it->name == item1) { print("\n\nYou sold "); std::cout << item1; print(" for "); std::cout << it->price; print(" gold"); this->items.push_back(*it); a->gold += it->price; this->gold -= it->price; a->inventory.erase(it); break; } else { ++it; } } if (a->inventory.size() == vector_size) { print("\nYou do not have "); std::cout << item1; print(" to sell"); } /* int increase = (it->price * 1.2+1); vector<item>::iterator it2; for (it2 = this->items.begin(); it2 != this->items.end(); ++it2) { if (it2->name == it->name) { it2->price = increase; } } */ print("\n\n\n1. Back\n\n\n> "); char c; std::cin >> c; }
  5. C++ buffer or vector issue

    Thanks, i've put the erase just before the break but the problem still occurs. I guess if there isn't anything obviously wrong the bug must be on the menu function which calls the above 2 functions? Or possibly the item struct?
  6. I'm looking for a bit of help please, I have a merchant class that you can buy from and sell to. The merchant has his own vector of struct 'items' as does the player. To begin the transactions, a merchants menu function is called, passing in the address of a player (character class) The below code works perfectly as expected, (e.g. if you haven't got enough gold, it states it correctly, or if either person doesn't have the item, etc) but as soon as a transaction occurs, like the player selling something, any attempts to sell anything else will show no message and just show the ".1. Back" option, or trying to buy something will say twice the merchant doesn't have it, or if he does, it will say he doesn't have it, but then say you bought it... it's probably something really simple and bad design on my part, but I can't figure it out void merchant::buyfrom(character *a) { print("\nItem to buy: "); string item1; fflush(stdin); getline(cin, item1); vector<item>::iterator it; for (it = this->items.begin(); it != this->items.end(); ++it) { if (it->name == item1) { if (it->price > a->gold) { print("\n\nYou don't have enough gold to buy the "); cout << it->name; break; } print("\n\nYou bought "); std::cout << item1; print(" for "); std::cout << it->price; print(" gold"); this->items.erase(it); a->inventory.push_back(*it); a->gold -= it->price; this->gold += it->price; break; } else { print("\n\nMerchant does not have a "); std::cout << item1; print(" to sell"); } } print("\n\n\n1. Back\n\n\n> "); char c; std::cin >> c; } void merchant::sellto(character *a) { print("\nItem to sell: "); string item1; fflush(stdin); getline(cin, item1); vector<item>::iterator it; for (it = a->inventory.begin(); it != a->inventory.end(); ++it) { if (it->name == item1) { print("\n\nYou sold "); std::cout << item1; print(" for "); std::cout << it->price; print(" gold"); a->inventory.erase(it); this->items.push_back(*it); a->gold += it->price; this->gold -= it->price; break; } else { print("\nYou do not have "); std::cout << item1; print(" to sell"); } } print("\n\n\n1. Back\n\n\n> "); char c; std::cin >> c; }
  7. C++ Random number issue

    Thanks TheChubu, that's exactly what I needed
  8. C++ Random number issue

    I'm struggling to get random numbers, in the below code, If I take out the time seed, I get different random numbers each roll, however they are the same on each play through. If I leave the time seed in, the rolls are always 1 and 1. Please can someone advise what I am doing wrong? I've tried making the game sleep a few seconds to change the results of time time seed call void dicegame::battle(character *a, character *b) { int rollone = this->roll(); int rolltwo = this->roll(); int total1 = rollone+rolltwo; Sleep(5000); int rollone2 = this->roll(); int rolltwo2 = this->roll(); int total2 = rollone2+rolltwo2; Sleep(5000); } int dicegame::roll() { static std::uniform_int_distribution<int> u(1, 6); static std::default_random_engine e; e.seed(time(0)); int roll = (u(e)); return roll; }
  9. C++ Text Adventure Design

    Thanks for the replies, and thanks Satharis, that makes a lot of sense. I feel a lot more confident now and will go and have a dabble this afternoon!
  10. C++ Text Adventure Design

    Thanks very much for the replies, I'm still struggling with this one. For the kind of actions I want (where they could be vastly different and load up various console displays), I feel like I need to have them as functions, somehow nicely wrapped in up an object. I've tried making an Actions class with all the functions, that take the player, current location, and int pressed as parameters (the int refers to what action number it is in a room) - or do away with the actions class and list them all in the character class (as I've tested at the bottom of the code below - obviously they won't all be just taking an item). But it doesn't seem orderly - Also, for all these objects to communicate with each other, it feels like I have to declare global pointers for the header files to see other objects I want them to be able to take parameters for in their functions? What I also find challenging (probably the most), is having all the control flow from the area class switch statement which currently handles direction: switch(choice) { case '1': this->look(); break; case '2': if (this->north != NULL) {current = this->north; here = false; break;} else {print("\n\nCan't go North"); Sleep(2500); break;} case '3': if (this->east != NULL) {current = this->east; here = false; break;} else {print("\n\nCan't go East"); Sleep(2500); break;} case '4': if (this->south != NULL) {current = this->south; here = false; break;} else {print("\n\nCan't go South"); Sleep(2500); break;} case '5': if (this->west != NULL) {current = this->west; here = false; break;} else {print("\n\nCan't go West"); Sleep(2500); break;} case '6': if (this->options >= 6) {} - somehow get action(function call for another object) by passing area, character and choice????? } Character class class character { private: short age; short health; short gold; std::vector<std::string> inventory; public: std::string name; character(); ~character(); void setname (std::string); void setage (short); void sethealth (short); void setgold (short); void buyitem (std::string, short); void sellitem (std::string, short); void takedamage (short); void display (); void additem (std::string); void removeitem (std::string); /* ACTIONS */ void takegem(); void takesword(); void findaction(); }; character::character() { this->name = "Unknown"; this->age = 0; this->health = 100; this->gold = 0; } character::~character() { } bool operator==(character& c1, character& c2) { if (c1.name == c2.name) { std::cout << "\n\nName is the same.\n\n"; return true; } else { std::cout << "\n\nName is different.\n\n"; return false; } } void character::setname(std::string name) { this->name = name; } void character::setage(short age) { this->age = age; } void character::sethealth(short health) { this->health = health; } void character::setgold(short gold) { this->gold = gold; } void character::buyitem(std::string item, short price) { if (price > this->gold) { print("\n\nYou do not have enough gold to buy "); std::cout << item; print("\n\n"); print("1. Back\n\n> "); char c; std::cin>>c; } else { this->gold -= price; this->inventory.push_back(item); print("\n\nYou bought "); std::cout << item; print(" for "); std::cout<<price; print(" gold\n\n"); print("1. Back\n\n> "); char c; std::cin>>c; } } void character::sellitem(std::string item, short price) { short temp = this->gold; std::vector<std::string>::iterator it; for (it = this->inventory.begin(); it != this->inventory.end(); ++it) { if (*it == item) { this->inventory.erase(it); this->gold += price; print("\n\nYou sold "); std::cout << item; print(" for "); std::cout << price; print(" gold"); break; } } if (temp == this->gold) { print("\nYou do not have "); std::cout << item; print(" to sell."); } print("\n\n1. Back\n\n> "); char c; std::cin>>c; } void character::takedamage(short damage) { this->health -= damage; if (this->health <= 0) { system("cls"); std::cout << TITLE; print("Your bones are swept clean by the desolate wind... your adventure is done."); print("\n\n1. Game Over\n\n> "); char c; std::cin>>c; exit (EXIT_SUCCESS); } } void character::display() { system("cls"); std::cout << TITLE; print("\nName: "); std::cout << this->name; print("\nAge: "); std::cout << this->age; print("\nHealth: "); std::cout << this->health; print("\nGold: "); std::cout << this->gold << "\n\n"; std::cout << this->name; print(" Inventory\n\n"); for (std::string s : this->inventory) { std::cout << s << std::endl; } print("\n\n1. Back\n\n> "); char c; std::cin>>c; } void character::additem(std::string item) { this->inventory.push_back(item); std::cout << "\nItem added"; } void character::removeitem(std::string item) { for (std::vector<std::string>::iterator it = this->inventory.begin(); it != this->inventory.end(); ++it) { if (*it == item) { this->inventory.erase(it); std::cout << "\nItem removed"; break; } } } // ACTIONS ///////////////////////////// ///////////////////////////// ///////////////////////////// void character::takegem() { system("cls"); print("You take a rough gemstone from the rocks"); char c; std::cin>>c; this->additem("Gemstone"); } void character::takesword() { system("cls"); print("You pick up a sword."); char c; std::cin>>c; this->additem("Sword"); } void character::findaction() { if (current->name == "Plains") { this->takegem(); } }
  11. C++ Text Adventure Design

    I've created a few text adventures in plain C, whereby every 'area' was a function with its own switch statement to get user input. Instead of traditional "commands" the user is given options e.g. "1. Go north 2. Go south 3. Examine note" etc. This resulted in great flexibitly and options within an area but serious code bloat and ugliness. I'm now trying it in C++ and really like OOP, I've built a class for characters and the areas which takes care of the displaying and world navigation aspects, but I'm now finding the whole approach really inflexible and don't know how to add all my extra content and options to each area. For instance in the test code below I've created 2 areas, once you look around in the plains area, you can see option 6. Examine paper - but how will I add this functionality in an elegant way without resorting back to my old functions for areas mess? Main.CPP #include "character.hpp" #include "area.hpp" void setupareas(); extern area* current; area* plains = new area; area* town = new area; area* swamp = new area; area* chapel = new area; area* mountain = new area; void setupareas() { std::vector<std::string> plainsmenu1 {"1. (Plains) Look Around\n\n", "2. Go North\n\n", "3. Go East\n\n", "4. Go South\n\n", "5. Go West\n\n\n> "}; std::vector<std::string> plainsmenu2 {"1. (Plains) Look Around\n\n", "2. Go North\n\n", "3. Go East\n\n", "4. Go South\n\n", "5. Go West\n\n6. Examine paper\n\n\n> "}; std::vector<std::string> chapelmenu1 {"1. (Chapel) Look Around\n\n", "2. Go North\n\n", "3. Go East\n\n", "4. Go South\n\n", "5. Go West\n\n\n> "}; std::vector<std::string> chapelmenu2 {"1. (Chapel) Look Around\n\n", "2. Go North\n\n", "3. Go East\n\n", "4. Go South\n\n", "5. Go West\n\n6. Open door\n\n\n> "}; plains->setdesc("You are standing in a wide plain\n\n1. Back\n\n\n> "); plains->setmenu1(plainsmenu1); plains->setmenu2(plainsmenu2); plains->setdoors(chapel, mountain, swamp, town); chapel->setdesc("You are outside a chapel\n\n1. Back\n\n\n> "); chapel->setmenu1(chapelmenu1); chapel->setmenu2(chapelmenu2); chapel->setdoors(NULL, NULL, plains, NULL); } int main(void) { setupareas(); current = plains; while (1) { current->getinput(); } return 0; } area.HPP class area { public: area(); ~area(); std::vector<std::string> menu1; std::vector<std::string> menu2; std::string desc; short seen; area *north, *east, *south, *west; void setmenu1(std::vector<std::string>); void setmenu2(std::vector<std::string>); void setdesc(std::string); void display(); void look(); void getinput(); void setdoors(area*,area*,area*,area*); }; area* current; area::area() { this->seen = 0; } area::~area() { } void area::setmenu1(std::vector<std::string> line) { for (std::string s : line) { this->menu1.push_back(s); } } void area::setmenu2(std::vector<std::string> line) { for (std::string s : line) { this->menu2.push_back(s); } } void area::display() { if (this->seen == 0) { for (std::string s : this->menu1) { print(s); } } else { for (std::string s : this->menu2) { print(s); } } } void area::getinput() { char choice; bool here = true; while (here) { system("cls"); std::cout << TITLE; this->display(); std::cin>>choice; switch(choice) { case '1': this->look(); break; case '2': if (this->north != NULL) {current = this->north; here = false; break;} else {print("\n\nCan't go North"); Sleep(2500); break;} case '3': if (this->east != NULL) {current = this->east; here = false; break;} else {print("\n\nCan't go East"); Sleep(2500); break;} case '4': if (this->south != NULL) {current = this->south; here = false; break;} else {print("\n\nCan't go South"); Sleep(2500); break;} case '5': if (this->west != NULL) {current = this->west; here = false; break;} else {print("\n\nCan't go West"); Sleep(2500); break;} } } } void area::look() { system("cls"); this->seen = 1; std::cout << TITLE; print(this->desc); char c; std::cin>>c; } void area::setdesc(std::string desc) { this->desc = desc; } void area::setdoors(area* north, area* east, area* south, area* west) { this->north = north; this->east = east; this->south = south; this->west = west; }
  12. Text Based RPG

    If you're writing it in C and you are new, I find the difficult part to be using structs and pointers to create a 'database' of the world. It can get surprisingly complicated very quickly if you aren't thoroughly grounded in that type of stuff. So I personally would make sure you fully understand and do a few test programs involving linked lists and the like. If you're really impatient and just want to get some exposure and write a small game quickly. you can cheat like I did and just have a function for every room, then a switch statement for player choice. Although this results in a lot of copy and paste ugly code and is not to be recommended. Let us know how you get on as I'm still trying to find the best way of doing this in C too.
  13. Find and delete Vector element

    yeah, presumably with the above example by Bregma? So it is valid so long as it doesn't point to the end of the vector auto it = std::find(test.begin(), test.end(), "Boat"); if (it != test.end()) test.erase(it); else std::cout << "No Boat element in vector";  
  14. Find and delete Vector element

    ah yes, it failed simply because I didn't include algorithm, very sorry   solved : #include <iostream> #include <vector> #include <algorithm> void displayvec(std::vector<std::string>&); int main () { std::vector<std::string> test {"Knife", "Boat", "Gun", "Water"}; displayvec(test); test.erase(test.begin()+2); displayvec(test); auto it = std::find(test.begin(), test.end(), "Boat"); test.erase(it); displayvec(test); return 0; } void displayvec(std::vector<std::string>&v) { for (std::string s : v ) { std::cout << s << std::endl; } }
  15. hi all,   I'm learning C++ and trying to understand how to handle vectors, specifically how to find an element of any type in a vector, then delete it.   I've been reading through my book which gives lots of theory and short examples, and some google searches have turned up more errors than my own attempts! I'd apprecite a bit of guidance please, here is my test attempt, which fails on the std::find line #include <iostream> #include <vector> void displayvec(std::vector<std::string>&); int main () { std::vector<std::string> test {"Knife", "Boat", "Gun", "Water"}; displayvec(test); test.erase(test.begin()+2); displayvec(test); auto it = std::find(test.begin(), test.end(), "Boat"); return 0; } void displayvec(std::vector<std::string>&v) { for (std::string s : v ) { std::cout << s << std::endl; } } How do I find and delete Boat?
  • Advertisement