#include "main.h" AbstractInteractive* getWeaponInfo(Weapon* w, SDL_Rect target, int textSize) { SDL_Rect tRect = target; tRect.w -= 10; tRect.x = 0; tRect.y = 0; string info; info += w->name + "\n"; info += "Cost: " + lltostr(w->cost) + "\n"; info += "DPS: " + dbltostr(w->getDPS(),1) + "\n"; info += "DPE: " + dbltostr(w->getDPE(),1) + "\n"; info += "Energyusage: " + dbltostr(w->energyUsage,1); TextBox* tb = new TextBox(textField(info, tRect, textSize)); return new Scrollable(target, tb, tRect, 0, 0); } AbstractInteractive* getShipInfo(UserShip* s, SDL_Rect target, int textSize) { SDL_Rect tRect = target; tRect.w -= 10; tRect.x = 0; tRect.y = 0; string info; info += s->name + "\n"; info += "Cost: " + lltostr(s->cost) + "\n"; info += "HP: " + lltostr(s->hp) + "\n"; info += "Armor: " + lltostr(s->armor) + "\n"; info += "Energy Storage: " + lltostr(s->maxEnergy) + "\n"; info += "Energy Production: " + lltostr(s->energyProduction) + "\n"; info += "Acceleration: " + lltostr(s->handling) + "\n"; info += "Top Speed: " + lltostr(s->moveSpeed) + "\n"; info += "Slots: " + lltostr(s->weapons.size()) + "\n"; TextBox* tb = new TextBox(textField(info, tRect, textSize)); return new Scrollable(target, tb, tRect, 0, 0); } Shop::~Shop() { for(int i = 0; i < (int) weapons.size(); ++i) delete weapons[i]; for(int i = 0; i < (int) ships.size(); ++i) delete ships[i]; delete menu; delete back; delete goldLabel; } Shop::Shop(Account** nuser, int ngameMenu) { user = nuser; SDL_Rect labelPos; labelPos.x = 350; labelPos.y = 18; labelPos.h = 16; goldLabel = new Label("gold: " + lltostr((*user)->gold),labelPos); SDL_Rect subScreen; subScreen.w = 400; subScreen.h = 400; subScreen.x = 50; subScreen.y = 70; gameMenu = ngameMenu; currentWeapon = 0; currentShip = 0; SDL_Surface* BG = loadBMP("data/images/bg_stars.bmp"); SDL_Surface* mbg = SDL_CreateRGBSurface(0,400,400,32,0,0,0,0); SDL_FillRect(mbg,NULL,0x000102); SDL_SetColorKey(mbg,SDL_SRCCOLORKEY,0x000102); vector ts1; vector ti1; tu = (*user)->ships[(*user)->current]->getUpgradeables(); for(int i = 0; i < (int) tu.size(); ++i) { ts1.push_back("Upgrade " + tu[i]->name); // if(tu[i]->cost <= user->gold) ti1.push_back(i+(1<<7)); // else // ti1.push_back(0); // cout << tu[i]->cost << " " << user->gold << endl; } vector submenues; Menu* upgradeMenu = new Menu(ts1, ti1, mbg, false, mbg); for(int i = 0; i < (int) upgradeMenu->buttons.size(); ++i) disabledUpgrades.push_back(&upgradeMenu->buttons[i]->deactivated); submenues.push_back(upgradeMenu); int height; //reading available weapons ifstream ins; string path = "data/weapons/"; ins.open((path+"weapons.txt").c_str()); char workaround; ins >> workaround; vector weaponPics; SDL_Rect targetRect; targetRect.x = 400 -58; targetRect.y = 0; targetRect.w = 58; targetRect.h = 400; SDL_Rect infoRect; infoRect.x = 50; infoRect.y = 75; infoRect.w = 400 - 68; infoRect.h = 390; while(ins.good()) { string filepath; getline(ins,filepath); Weapon* w = new Weapon(path+workaround+filepath); if(w->sellable) { weaponInfos.push_back(getWeaponInfo(w, infoRect, 15)); weaponPics.push_back(copyImage(w->getImage())); weapons.push_back(w); //cout << w->name << ": " << estimateValue(*w) << endl; } else delete w; ins >> workaround; } ins.close(); SDL_Rect subRect; subRect.w = 48; Menu* tempm = new Menu(weaponPics, subRect.w,height, true, false); subRect.h = height; Scrollable* temps = new Scrollable(targetRect, tempm, subRect, false, true); submenues.push_back(temps); path = "data/ships/user/"; ins.open((path+"userships.txt").c_str()); ins >> workaround; vector shipPics; Weapon empty = Weapon("data/weapons/empty.txt"); while(ins.good()) { string filepath; getline(ins,filepath); UserShip* s = new UserShip(path+workaround+filepath); for(int i = 0; i < (int) s->weapons.size(); ++i) { delete s->weapons[i]; s->weapons[i] = new Weapon(empty); } if(true)//s->sellable) { shipPics.push_back(copyImage(s->getImage())); shipInfos.push_back(getShipInfo(s, infoRect, 16)); // cout << s->name << " " << estimateValue(*s) << endl; ships.push_back(s); } else delete s; ins >> workaround; } ins.close(); targetRect.x = 400 -58; targetRect.y = 0; targetRect.w = 58; targetRect.h = 400; subRect.w = 48; tempm = new Menu(shipPics, subRect.w,height, true, false); subRect.h = height; temps = new Scrollable(targetRect, tempm, subRect, false, true); submenues.push_back(temps); SDL_Rect backPos; backPos.x = 0; backPos.y = subScreen.h + subScreen.y; backPos.w = 500; backPos.h = 500 - backPos.y; int tsize = 0; back = new Button(backPos, "back", tsize); int NStates = 3; int topmargin2 = 45; backPos.x = 0; backPos.y = topmargin2; backPos.w = 500/NStates; backPos.h = subScreen.y-topmargin2; tsize = 0; vector choices; choices.push_back(new Button(backPos, "Upgrades", tsize)); backPos.x = 500 / NStates; backPos.y = topmargin2; backPos.w = 500/NStates; backPos.h = subScreen.y-topmargin2; choices.push_back(new Button(backPos, "Weapons", tsize)); backPos.x = 2* 500 / NStates; backPos.y = topmargin2; backPos.w = 500/NStates; backPos.h = subScreen.y - topmargin2; choices.push_back(new Button(backPos, "Ships", tsize)); for(int i = 0; i < (int) choices.size(); ++i) choices[i]->isDblClckButton = true; menu = new CompositMenu(submenues, BG, subScreen, choices); } int Shop::handleEvents(SDL_Event event){ int result = 0; if(back->handleEvents(event) == BUTTON_CLICKED) result = gameMenu; int bought = menu->handleEvents(event); if(menu->getState() == 0 && (bought & 1<<7)) { bought -= 1 << 7; // cout << "tried to buy something!" << endl; if(tu[bought]->cost <= (*user)->gold) { (*user)->gold -= tu[bought]->cost; double oldvalue = *tu[bought]; tu[bought]->upgrade(); double newvalue = *tu[bought]; cout << "Bought Upgrade from " << oldvalue << " to " << newvalue << endl; refresh(); cout << "nextcost: " << tu[bought]->cost << endl; } } if(menu->getState() == 1 && (bought & MENU_CLICK)) { bought -= MENU_CLICK; if(weapons[bought]->cost <= (*user)->gold) { (*user)->gold -= weapons[bought]->cost; bool hasEmptySlot = false; int EmptySlot; for(int i = 0; i < (int) (*user)->ships[(*user)->current]->weapons.size(); ++i) if((*user)->ships[(*user)->current]->weapons[i]->name == "empty Slot") { hasEmptySlot = true; EmptySlot = i; } if(hasEmptySlot) (*user)->ships[(*user)->current]->weapons[EmptySlot] = new Weapon(*weapons[bought]); else (*user)->weapons.push_back(new Weapon(*weapons[bought])); cout << "Bought " << weapons[bought]->name << endl; refresh(); } } if(menu->getState() == 1 && (bought & MENU_SELECT)) { bought -= MENU_SELECT; currentWeapon = bought; } if(menu->getState() == 2 && (bought & MENU_CLICK)) { bought -= MENU_CLICK; if(ships[bought]->cost <= (*user)->gold) { (*user)->gold -= ships[bought]->cost; (*user)->current = (*user)->ships.size(); (*user)->ships.push_back(new UserShip(*ships[bought])); cout << "Bought " << ships[bought]->name << endl; refresh(); } } if(menu->getState() == 2 && (bought & MENU_SELECT)) { bought -= MENU_SELECT; currentShip = bought; } return result; } void Shop::frame(double time) { menu->frame(time); } void Shop::draw(SDL_Surface* screen) { menu->draw(screen); SDL_Color textColor; textColor.r = 255; textColor.g = 255; textColor.b = 255; TTF_Font *font = TTF_OpenFont("data/fonts/OpenSans-Semibold.ttf", 30); SDL_Surface* headline = NULL; headline = TTF_RenderText_Solid(font, "Shop",textColor); if(headline == NULL) { cout << "Error rendering headline of shop" << endl; return; } TTF_CloseFont(font); SDL_Rect headpos; headpos.x = screen->w/2 - headline->w/2; headpos.y = 5; SDL_BlitSurface(headline, NULL, screen, &headpos); SDL_FreeSurface(headline); back->draw(screen); goldLabel->draw(screen); if(menu->getState() == 1) weaponInfos[currentWeapon]->draw(screen); if(menu->getState() == 2) shipInfos[currentShip]->draw(screen); } void Shop::refresh() { goldLabel->setCaption("gold: " + lltostr((*user)->gold)); menu->refresh(); tu = (*user)->ships[(*user)->current]->getUpgradeables(); for(int i = 0; i < (int) tu.size(); ++i) *disabledUpgrades[i] = (*user)->gold < tu[i]->cost; } InventoryMenu::~InventoryMenu() { delete BG; delete back; delete shipMenu; delete weaponMenu; for(int i = 0; i < slots.size(); ++i) delete slots[i]; SDL_FreeSurface(ship); delete title; } InventoryMenu::InventoryMenu(Account** nuser, int ngameMenu) { MX = 0; MY = 0; user = nuser; gameMenu = ngameMenu; BG = new SlidingBackground(loadBMP("data/images/bg_stars.bmp"), 0, 100); SDL_Rect backPos; backPos.x = 0; backPos.y = 460; backPos.w = 500; backPos.h = 500 - backPos.y; int tsize = 0; back = new Button(backPos, "back", tsize); cursor = NULL; sellDropzone.x = 100; sellDropzone.h = 40; sellDropzone.y = 460; sellDropzone.w = 150; sellLabel = new Label("SELL",sellDropzone); SDL_Rect titlePos; titlePos.x = 0; titlePos.h = 50; titlePos.y = 0; titlePos.w = 500; title = new Label("Inventory",titlePos); vector tships; for(int i = 0; i < (*user)->ships.size(); ++i) { ships.push_back(copyImage((*user)->ships[i]->getImage())); tships.push_back(copyImage((*user)->ships[i]->getImage())); } int height = 0; Menu* temp = new Menu(tships, 48, height, true, false); SDL_Rect shipMenuPos; shipMenuPos.x = 10; shipMenuPos.y = 50; shipMenuPos.h = 410; shipMenuPos.w = 58; SDL_Rect subRect; subRect.h = height; subRect.w = 48; shipMenu = new Scrollable(shipMenuPos, temp, subRect, 0, 1); vector tweapons; for(int i = 0; i < (*user)->weapons.size(); ++i) { weapons.push_back(copyImage((*user)->weapons[i]->getImage())); tweapons.push_back(copyImage((*user)->weapons[i]->getImage())); } height = 0; temp = new Menu(tweapons, 48, height, false, true); SDL_Rect weaponMenuPos; weaponMenuPos.x = 500-68; weaponMenuPos.y = 50; weaponMenuPos.h = 410; weaponMenuPos.w = 58; subRect.h = height; subRect.w = 48; weaponMenu = new Scrollable(weaponMenuPos, temp, subRect, 0, 1); ship = copyImage((*user)->ships[(*user)->current]->getImage()); int factor = 1; while(ship->w < 190 && ship->h < 190) { SDL_Surface* temp = ship; ship = rotozoomSurface(temp, 0, 2, 0); SDL_FreeSurface(temp); factor *= 2; } for(int i = 0; i < (*user)->ships[(*user)->current]->weapons.size(); ++i) { UserShip* s = (*user)->ships[(*user)->current]; SDL_Rect slotPos; slotPos.x = 250 - 24 + factor * s->slotPositions[i].first; slotPos.y = 250 - 24 + factor * s->slotPositions[i].second; slotPos.w = 48; slotPos.h = 48; slots.push_back(new Button(slotPos, copyImage(s->weapons[i]->getImage()), 0)); } } void InventoryMenu::draw(SDL_Surface *screen) { BG->draw(screen); SDL_Rect shipPos; shipPos.x = 250 - ship->w/2; shipPos.y = 250 - ship->h/2; SDL_BlitSurface(ship, NULL, screen, &shipPos); title->draw(screen); back->draw(screen); sellLabel->draw(screen); shipMenu->draw(screen); weaponMenu->draw(screen); for(int i = 0; i < slots.size(); ++i) slots[i]->draw(screen); if(cursor != NULL) { SDL_Rect cursorPos; cursorPos.x = MX - cursor->w/2; cursorPos.y = MY - cursor->h/2; SDL_BlitSurface(ship,NULL,screen,&cursorPos); } } /*SlidingBackground* BG; Label* title; Account** user; int gameMenu; Button* back; Label* sellLabel; SDL_Rect sellDropzone; AbstractInteractive* shipMenu; vector ships; AbstractInteractive* weaponMenu; vector weapons; SDL_Rect weaponDropzone; vector slots; SDL_Surface* ship; SDL_Surface* cursor;*/ int InventoryMenu::handleEvents(SDL_Event event) { if(event.type == SDL_MOUSEMOTION) { MX = event.motion.x; MY = event.motion.y; } int tempShip = shipMenu->handleEvents(event); if(tempShip & MENU_SELECT) { tempShip -= MENU_SELECT; cout << tempShip << endl; (*user)->current = tempShip; refresh(); } int tempweapon = weaponMenu->handleEvents(event); if(tempweapon & MENU_SELECT) { tempweapon -= MENU_SELECT; cout << tempweapon << endl; cursor = copyImage(weapons[tempweapon]); dragged = tempweapon; } if(event.type == SDL_MOUSEBUTTONUP) { if(event.button.button == SDL_BUTTON_LEFT) { SDL_FreeSurface(cursor); cursor = NULL; int x = event.button.x; int y = event.button.y; } } int backb = back->handleEvents(event); if(backb == BUTTON_CLICKED) return gameMenu; return 0; } void InventoryMenu::frame(double time) { BG->frame(time); } void InventoryMenu::refresh() { if(cursor != NULL) { SDL_FreeSurface(cursor); cursor = NULL; } } bool init(SDL_Surface*& screen) { srand(time(0)); if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) == -1) { cout << "Error: Could not initialize SDL" << endl; return 0; } screen = SDL_SetVideoMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,SDL_SWSURFACE); if(!screen) { cout << "could not initialize screen" << endl; return 0; } if(TTF_Init() == -1) { cout << "could not initialize True Fonts" << endl; return 0; } if(Mix_OpenAudio(22050, MIX_DEFAULT_FORMAT, 2, 4096) == -1) { return 0; } SDL_WM_SetCaption("RCade - v0.03", NULL); return 1; } Menu* makeLoadGameMenu(SDL_Surface *screen) { string bfile = "data/images/bg_stars.bmp"; SDL_Surface *bg = loadBMP(bfile); vector ts; vector ti; ifstream ins; ins.open("save/saves.txt"); char workaround; ins >> workaround; int counter = 0; while(ins.good()) { string account; getline(ins, account); account = workaround + account; _tospace(account); ts.push_back(account); ti.push_back(counter | LOAD); counter++; ins >> workaround; } ins.close(); ts.push_back("back"); ti.push_back(MENU | 0); return new Menu(ts,ti,bg,true,screen); } Menu* makeMainMenu(SDL_Surface *screen) { string bfile = "data/images/bg_stars.bmp"; SDL_Surface *bg = loadBMP(bfile); vector ts; ts.push_back("New Game"); ts.push_back("Load Game"); ts.push_back("Settings"); ts.push_back("Quit"); vector ti; ti.push_back(MENU | 5); ti.push_back(MENU | 4); ti.push_back(0); ti.push_back(GAME_QUIT); return new Menu(ts,ti,bg,true,screen); } Menu* makeGameMenu(SDL_Surface *screen) { string bfile = "data/images/bg_stars.bmp"; SDL_Surface *bg = loadBMP(bfile); vector ts; ts.push_back("Missions"); ts.push_back("Shop"); ts.push_back("Inventory"); ts.push_back("Skills"); ts.push_back("Settings"); ts.push_back("Save Game"); ts.push_back("Main Menu"); vector ti; ti.push_back(MENU | 2); ti.push_back(MENU | 3); ti.push_back(MENU | 6); ti.push_back(0); ti.push_back(0); ti.push_back(SAVE); ti.push_back(MENU | 0); return new Menu(ts,ti,bg,true,screen); } Menu* makeLevelMenu(vector levels, SDL_Surface *screen) { string bfile = "data/images/bg_stars.bmp"; SDL_Surface *bg = loadBMP(bfile); vector ts; vector ti; ifstream ins; for(int i = 0; i < (int) levels.size(); ++i) { ins.open(levels[i].c_str()); string levelname; getline(ins,levelname); ins.close(); ts.push_back(levelname); ti.push_back(LEVEL | i); } ts.push_back("back"); ti.push_back(MENU | 1); return new Menu(ts,ti,bg,true,screen); } GameHandler::GameHandler() { isGood = true; screen = NULL; if(!init(screen)) isGood = false; //reading available levels ifstream ins; string path = "data/levels/"; ins.open((path+"levels.txt").c_str()); char workaround; ins >> workaround; while(ins.good()) { string filepath; getline(ins,filepath); levelpaths.push_back(path+workaround+filepath); ins >> workaround; } ins.close(); state = MENU | 0; user = new Account(); menus.push_back(makeMainMenu(screen)); menus.push_back(makeGameMenu(screen)); menus.push_back(makeLevelMenu(levelpaths,screen)); menus.push_back(new Shop(&user, MENU | 1)); menus.push_back(makeLoadGameMenu(screen)); SDL_Surface* bg = loadBMP("data/images/bg_stars.bmp"); GetStringMenu* mt = new GetStringMenu("Enter your Nickname:", MENU | 0, LEVEL | 0, bg, screen); acname = &mt->s; menus.push_back(mt); user->resetShips(); menus.push_back(new InventoryMenu(&user, MENU | 1)); } GameHandler::~GameHandler() { delete user; if(state &LEVEL) delete LG; for(int i = 0; i < (int) menus.size(); ++i) delete menus[i]; Mix_CloseAudio(); TTF_Quit(); SDL_Quit(); IMG_Quit(); } int GameHandler::game() { // SDL_Rect nPos; // nPos.x = 10; // nPos.y = 10; // nPos.w = 200; // nPos.h = 400; // TextBox* blub = new TextBox(textField("Dies ist ein doofer Tesptsatzg.\nBBBBBBBBesser nicht allzu sehr beachten, denn der Inhalt ist unwichtig!",nPos,24)); // cout << nPos.h << endl; SDL_Event event; if(!isGood) return 1; while(state != GAME_QUIT) { Uint32 start = SDL_GetTicks(); while(SDL_PollEvent(&event)) { if(state & MENU) { // blub->handleEvents(event); int newstate = menus[state - MENU]->handleEvents(event); if(newstate) { state = newstate; if(state & LEVEL) { if(*acname != "") { delete user; user = new Account("save/default account.txt"); user->name = *acname; menus[5]->refresh(); menus[3]->refresh(); user->resetShips(); } if(state - LEVEL < 0 || state - LEVEL > (int) levelpaths.size()) { cout << "levellinking failed!" << endl; return 1; } user->resetShips(); LG = new LevelGenerator(levelpaths[state - LEVEL], user, screen); } if(state & MENU) menus[state - MENU]->refresh(); if(state & LOAD) { ifstream ins; ins.open("save/saves.txt"); char workaround; ins >> workaround; int counter = 0; while(ins.good()) { string account; getline(ins, account); if(counter == state - LOAD) { account = workaround + account; delete user; user = new Account("save/" + account + ".txt"); menus[3]->refresh(); menus[6]->refresh(); user->resetShips(); state = MENU | 1; } counter++; ins >> workaround; } ins.close(); } if(state & SAVE) { user->save(); delete menus[4]; menus[4] = makeLoadGameMenu(screen); state = MENU | 1; cout << "Saved!" << endl; } } } if(event.type == SDL_QUIT) state = GAME_QUIT; else if(event.type == SDL_MOUSEBUTTONDOWN) { // if(event.button.button == SDL_BUTTON_WHEELUP) // cout << "Wheel up!" << endl; // else // cout << "wheel down..." << endl; } } Uint32 time = SDL_GetTicks()-start; if(1000/60.0 - time > 0) SDL_Delay(1000/60.0 - time); else cout << "Warning: Frame missed" << endl; if(state & LEVEL) { int status = LG->frame(1/60.0); if(status == LEVEL_FAILED) { state = 1 | MENU; cout << "You lost the game!\n"; cout << "highscore: " << LG->OH->highscore << endl; cout << "Level: " << user->getLevel() << endl; user->highscore += LG->OH->highscore; delete LG; user->resetShips(); } else if(status == LEVEL_COMPLETED) { state = 1 | MENU; cout << "You have completed the level!\n"; cout << "highscore: " << LG->OH->highscore << endl; cout << "gold: " << LG->OH->gold << endl; cout << "exp: " << user->getExp() << endl; cout << "Level: " << user->getLevel() << endl; user->highscore += LG->OH->highscore; user->gold += LG->OH->gold; delete LG; user->resetShips(); } } if(state & MENU) { menus[state - MENU]->frame(1/60.0); menus[state - MENU]->draw(screen); // blub->frame(1/60.0); // blub->draw(screen); } SDL_Flip(screen); } // delete blub; return 0; } int main(int argc, char* args[]) { GameHandler* GH = new GameHandler(); // Account a = Account(); // a.name = "Start-Account"; // a.save(); // Account b = Account("save/Start-Account.txt"); // b.save(); // return 0; if(GH->game()) return 1; delete GH; return 0; }