From e3a66514d57ff4acf2f02df7d86bd2cf8be0e730 Mon Sep 17 00:00:00 2001 From: Reimar Date: Tue, 8 Dec 2015 11:31:35 +0100 Subject: initial commit --- enginecore.cpp | 835 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 835 insertions(+) create mode 100644 enginecore.cpp (limited to 'enginecore.cpp') diff --git a/enginecore.cpp b/enginecore.cpp new file mode 100644 index 0000000..047511e --- /dev/null +++ b/enginecore.cpp @@ -0,0 +1,835 @@ +#include "enginecore.h" + +DObject::DObject(){}; + +DObject::DObject(string filename, double newx, double newy) +{ + image = NULL; + image = loadBMP(filename); + if(!image) + cout << "Problem loading file!" << endl; + x = newx; + y = newy; +} + +DObject::DObject(SDL_Surface* newImage, double newx, double newy) +{ + image = NULL; + image = copyImage(newImage); + if(!image) + cout << "Problem loading file!" << endl; + x = newx; + y = newy; +} + +DObject::DObject(const DObject &o) +{ + image = NULL; + image = copyImage(o.image); + if(!image) + cout << "Problem copying file!" << endl; + x = o.x; + y = o.y; +} + +DObject::~DObject() +{ + SDL_FreeSurface(image); +} + +void DObject::draw(SDL_Surface* screen) +{ + SDL_Rect position; + position.x = x - image->w / 2.0; + position.y = y - image->h / 2.0; + SDL_BlitSurface(image,NULL,screen,&position); +} + +//checks if DObject is out of Bounds +bool ooB(const DObject* o, SDL_Surface* screen) +{ + if(o->x < 0) + return true; + if(o->y < 0) + return true; + if(o->x > screen->w) + return true; + if(o->y > screen->h) + return true; + return false; +} + +double armorF(double damage, double armor) +{ + if(armor > 0) + armor *= armor/(armor+damage); + damage *= pow(0.5,armor/50); + return damage; +} + + +Levelable::Levelable() +{ + exp = 0; + level = 1; + lin = 30; + quad = 10; + cube = 2; + next = lin; +} + +int Levelable::addExp(double moreExp) +{ + int levelups = 0; + exp += moreExp; + while(exp > next) + { + levelups++; + level++; + next += lin; + lin += quad; + quad += cube; + } + return levelups; +} + +int Levelable::getLevel() +{ + return level; +} + +double Levelable::getExp() +{ + return exp; +} + +double* Levelable::getExpPointer() +{ + return &exp; +} + + +Projectile::Projectile(SDL_Surface* newimage, double newx, double newy, double newdamage, double newcollisionSize, double newxSpeed, double newySpeed) : DObject(newimage, newx, newy) +{ + damage = newdamage; + collisionSize = newcollisionSize; + xSpeed = newxSpeed; + ySpeed = newySpeed; + armorPiercing = 0; +} + +Projectile::Projectile(const Projectile& P) : DObject((DObject) P) +{ + damage = P.damage; + armorPiercing = P.armorPiercing; + collisionSize = P.collisionSize; + xSpeed = P.xSpeed; + ySpeed = P.ySpeed; +} + +/*structure of a ProjectileFile +data/projectile2.bmp #path of the imagefile +data/sounds/spit #path of the soundfile without n.wav for int n +10 #damage +2 #armorPiercing +1.4142 #collisionSize +*/ +Projectile::Projectile(string filename, vector& sounds) +{ + ifstream ins; + ins.open(filename.c_str()); + if(!ins.is_open()) + { + cout << "Error: Could not load from file " << filename << endl; + } + string imageFilename; + getline(ins, imageFilename); + image = loadBMP(imageFilename); + string soundPath; + getline(ins, soundPath); + bool good = true; + long long files = 1; + while(good) + { + string actualPath = soundPath + lltostr(files) + ".wav"; + Mix_Chunk* temp = NULL; + temp = Mix_LoadWAV(actualPath.c_str()); + if(temp == NULL) + good = false; + else + sounds.push_back(temp); + ++files; + } + ins >> damage; + ins >> armorPiercing; + ins >> collisionSize; +} + +void Projectile::frame(double time) +{ + x += xSpeed*time; + y += ySpeed*time; +} + +void Projectile::rotateAccordingly() +{ + double norm = sqrt(xSpeed*xSpeed + ySpeed*ySpeed); + if(norm != 0) + { + double angle = asin(xSpeed / norm); + if(ySpeed < 0) + { + angle = M_PI-angle; + } + SDL_Surface* temp = image; + image = rotozoomSurface(image,angle/M_PI*180,1,0); + SDL_FreeSurface(temp); + } +} + + + +Item::Item(const Item& item):DObject((DObject) item) +{ + cost = item.cost; + sellable = item.sellable; +} + +Item::Item(const DObject& dObject):DObject(dObject) +{ +} + +SDL_Surface* Item::getImage() +{ + return image; +} + +Weapon::Weapon(const Weapon& w):Item((Item) w) +{ + playSound = true; + for(int i = 0; i < (int) w.prototypes.size(); ++i) + { + prototypes.push_back(new Projectile(*w.prototypes[i])); + } + for(int i = 0; i < (int) w.sounds.size(); ++i) + { + vector temp; + for(int j = 0; j < (int) w.sounds[i].size(); ++j) + { + temp.push_back(w.sounds[i][j]); + } + sounds.push_back(temp); + } + sellable = w.sellable; + cost = w.cost; + active = true; + energyUsage = w.energyUsage; + name = w.name; + cooldown = w.cooldown; + startTimer = w.startTimer; + currentTimer = startTimer; +} + +/* structure of a Weaponfile: +epic imbaweapon of massdestruction #name +data/weapon89.bmp #filename of image of weapon +0.5 #energyusage +0 #sellable +10000000 #cost +2 #number of distinguished Projectiles +1 #cooldown +0.5 #startTimer +data/projectile11.txt #path +0 #xSpeed +700 #-ySpeed +5 #cooldown +0 #startTimer +data/projectile14.txt #path +0 #xSpeed +500 #-ySpeed +*/ +Weapon::Weapon(string filename) +{ + playSound = true; + ifstream ins; + ins.open(filename.c_str()); + if(!ins.is_open()) + { + cout << "Error: Could not open file " << filename << endl; + } + getline(ins,name); + string imageFilename; + getline(ins, imageFilename); +// cout << imageFilename << endl; + image = loadBMP(imageFilename); + active = true; + ins >> energyUsage; + ins >> sellable; + ins >> cost; + int Nprojectiles; + ins >> Nprojectiles; + for(;Nprojectiles;Nprojectiles--) + { + double temp; + ins >> temp; + cooldown.push_back(temp); + ins >> temp; + startTimer.push_back(temp); + string projectileFilename; + //this workaround discards all \n + char workaround; + ins >> workaround; + getline(ins,projectileFilename); + vector projectileSounds; + prototypes.push_back(new Projectile(workaround + projectileFilename, projectileSounds)); + ins >> prototypes[prototypes.size()-1]->xSpeed; + ins >> prototypes[prototypes.size()-1]->ySpeed; + prototypes[prototypes.size()-1]->ySpeed *= -1; + sounds.push_back(projectileSounds); + } + currentTimer = startTimer; + ins.close(); + if(cost == 0) + cost = round_beautiful(estimateValue(*this)); +} + +Weapon::~Weapon() +{ + for(int i = 0; i < (int) prototypes.size(); ++i) + delete prototypes[i]; +} + +vector Weapon::frame(double time) +{ + vector result; + for(int i = 0; i < (int) prototypes.size(); ++i) + { + currentTimer[i] += time; + while(currentTimer[i] > cooldown[i]) + { + Projectile* tempP = new Projectile(*prototypes[i]); + if(sounds[i].size() && playSound) + { + int temp = Mix_PlayChannel(-1,sounds[i][rand()%sounds[i].size()],0); + if(temp == -1) + { + cout << "there was an error playing sound of projectile" << " from weapon " << name << endl; + } + } + tempP->x = x; + tempP->y = y; + tempP->rotateAccordingly(); + currentTimer[i] -= cooldown[i]; + tempP->frame(currentTimer[i]); + result.push_back(tempP); + } + } + return result; +} + +void Weapon::mirror() +{ + for(int i = 0; i < (int) prototypes.size(); ++i) + prototypes[i]->ySpeed *= -1; +} + +double Weapon::getDPS() const +{ + double result = 0; + for(int i = 0; i < (int) prototypes.size(); ++i) + result += prototypes[i]->damage/cooldown[i]; + return result; +} + +double Weapon::getDPE() const +{ + if(energyUsage == 0) + return 0; + return getDPS()/energyUsage; +} + +double estimateValue(const Weapon& w) +{ + double result = w.getDPS()*w.getDPS()*5; + if(w.getDPE() != 0) + result /= 0.3 + 1 / w.getDPE(); + else + result /= 0.3; + return result; +} + +void Upgradeable::setValue(double nvalue) +{ + value = nvalue; +} + +double Upgradeable::getValue() const +{ + return value; +} + +Upgradeable::Upgradeable() +{ + level = 1; + cost = 0; + maxLevel = 0; +} + +Upgradeable::operator double() const +{ + return value; +} + +Upgradeable& Upgradeable::operator=(const double& d) +{ + value = d; + return *this; +} + +Upgradeable::Upgradeable(double nvalue) +{ + level = 1; + cost = 0; + maxLevel = 0; + value = nvalue; +} + +void Upgradeable::upgrade() +{ + if(level == maxLevel) + { + cout << "Can't Upgrade! Already at max Level." << endl; + } + level++; + cost += cost * (3+level)/10.0; + value += 0.3*value; +} + + +void Upgradeable::save(ofstream& o) +{ + o << name << endl; + o << value << endl; + o << cost << endl; + o << level << endl; + o << maxLevel << endl; +} + +void Upgradeable::load(ifstream& i) +{ + char workaround; + i >> workaround; + getline(i,name); + name = workaround + name; + i >> value; + i >> cost; + i >> level; + i >> maxLevel; +} + +ifstream& operator>>(ifstream& ins, Upgradeable& u) +{ + double d; + ins >> d; + u = d; + return ins; +} + +Ship::Ship(string filename,int x, int y):DObject(filename,x,y) +{ + collisionSize = image->w; +} + +Ship::~Ship() +{ + for(int i = 0; i < (int) weapons.size();++i) + delete weapons[i]; +} + +vector Ship::frame(double time) +{ + vector result; + return result; +} + +int Ship::hit(const Projectile& P) +{ + double tempArmor = 0; + if(armor > 0) + tempArmor = max(tempArmor,armor-P.armorPiercing); + hp -= armorF(P.damage,tempArmor); + if(hp < 0) + return 1; + return 0; +} + +Ship::Ship(const Ship& s):DObject((DObject) s) +{ + name = s.name; + maxhp = s.maxhp; + hp = maxhp; + moveSpeed = s.moveSpeed; + collisionSize = s.collisionSize; + armor = s.armor; + for(int i = 0; i < (int) s.weapons.size(); ++i) + { + weapons.push_back(new Weapon(*s.weapons[i])); + slotPositions.push_back(s.slotPositions[i]); + } +} + + +EnemyShip::EnemyShip(const EnemyShip& s): Ship((Ship) s) +{ + path = s.path; + gold = s.gold; + exp = s.exp; + score = s.score; + current = 0; + if(!path.size()) + { + path.push_back(make_pair(s.x,s.y)); + } + x = path[0].first; + y = path[0].second; + +} + +/*structure of an EnemShipfile +Tork Spacerocket #name +data/images/tork_spacerocket.bmp #path of imagefile +7 #maxhp +5 #armor +50 #moveSpeed +4 #collisionSize +3 #Gold +3 #exp +3 #score +1 #number of weapons +0 -1 #relative Position of weapon +data/fireball.txt #path of weapon +*/ +EnemyShip::EnemyShip(string filename) +{ + current = 0; + path.push_back(make_pair(0,0)); + ifstream ins; + ins.open(filename.c_str()); + if(!ins.is_open()) + cout << "Error: Could not open enemyfile " << filename << endl; + getline(ins, name); + string imagePath; + getline(ins, imagePath); + image = loadBMP(imagePath); + ins >> maxhp; + hp = maxhp; + ins >> armor; + ins >> moveSpeed; + ins >> collisionSize; + ins >> gold; + ins >> exp; + ins >> score; + int Nweapons = 0; + ins >> Nweapons; + for(;Nweapons;Nweapons--) + { + double temp1, temp2; + ins >> temp1; + ins >> temp2; + slotPositions.push_back(make_pair(temp1,temp2)); + //A workaround that helps discarting \n + char workaround; + ins >> workaround; + string weaponpath; + getline(ins, weaponpath); + weapons.push_back(new Weapon(workaround + weaponpath)); + weapons[weapons.size()-1]->mirror(); + } + if(!(exp || gold || score)) + assignValue(); +} + +vector EnemyShip::frame(double time) +{ + //adjusting position + while(current != path.size()-1 && path[current] == make_pair(x,y)) + current++; + if(path[current] != make_pair(x,y)) + { + double dirx = path[current].first - x; + double diry = path[current].second - y; + double norm = sqrt(dirx*dirx + diry*diry); + dirx /= norm; + diry /= norm; + if(norm < moveSpeed*time) + { + x = path[current].first; + y = path[current].second; + } + else + { + x += dirx * moveSpeed * time; + y += diry * moveSpeed * time; + } + } + for(int i = 0; i < (int) weapons.size(); ++i) + { + weapons[i]->x = x + slotPositions[i].first; + weapons[i]->y = y + slotPositions[i].second; +// cout << weapons[i]->x << " " << weapons[i]->y << " weapon " << i << endl; + } + + + vector result; + for(int i = 0; i < (int) weapons.size(); ++i) + { + vector temp; + temp = weapons[i]->frame(time); + for(int j = 0; j < (int) temp.size(); ++j) + result.push_back(temp[j]); + } + return result; +} + +void EnemyShip::assignValue() +{ + exp = 0; + for(int i = 0; i < (int) weapons.size(); ++i) + exp += weapons[i]->getDPS(); +// exp *= 4; + gold = maxhp * pow(2,armor/(50.0+maxhp/10))*2.5; + score = gold * moveSpeed / 140; + double sum = (gold + score + exp)/9; + exp = (int)(sqrt(exp+sum)+0.5); + gold = (int)(sqrt(gold+sum) +0.5); + score = (int)(sqrt(score+sum)+0.5); +// cout << s.name << '\n'; +// cout << "gold: " << s.gold << " -> " << gold << '\n'; +// cout << "high: " << s.score << " -> " << high << '\n'; +// cout << "exp: " << s.exp << " -> " << exp << '\n'; +// cout << "sum: " << sum << '\n'; +} + + +vector UserShip::getUpgradeables() +{ + vector result; + result.push_back(&maxhp); + result.push_back(&armor); + result.push_back(&maxEnergy); + result.push_back(&energyProduction); + result.push_back(&handling); + result.push_back(&moveSpeed); + return result; +} + +vector UserShip::frame(double time, SDL_Surface* screen) +{ + vector result; + //adjust energy + energy += energyProduction*time; + if(energy > maxEnergy) + energy = maxEnergy; + if(shooting) + { + double energyNeed = 0; + for(int i = 0; i < (int) weapons.size(); ++i) + energyNeed += weapons[i]->energyUsage*time; + if(energyNeed < energy) + { + energy -= energyNeed; + for(int i = 0; i < (int) weapons.size(); ++i) + { + vector temp; + temp = weapons[i]->frame(time); + for(int j = 0; j < (int) temp.size(); ++j) + result.push_back(temp[j]); + } + } + } + + //adjust speed and position of the ship + double norm1 = sqrt(right*right + down*down); + double norm2 = sqrt(xSpeed*xSpeed + ySpeed*ySpeed); + double handconst = time*handling; + double speedconst = norm2/moveSpeed; + if(handconst * speedconst > norm2 || norm2 == 0) + { + xSpeed = 0; + ySpeed = 0; + } + else + { + xSpeed *= 1 - speedconst * handconst / norm2; + ySpeed *= 1 - speedconst * handconst / norm2 ; + } + norm2 = sqrt(xSpeed*xSpeed + ySpeed*ySpeed); + if(norm1 != 0) + { + xSpeed += handconst*right / norm1; + ySpeed += handconst*down / norm1; + } + else + { + if(handconst > norm2) + { + xSpeed = 0; + ySpeed = 0; + } + else + { + xSpeed -= handconst * xSpeed / norm2; + ySpeed -= handconst * ySpeed / norm2; + } + } +// cout << xSpeed << " " << ySpeed << endl; + x += xSpeed*time; + y += ySpeed*time; + if(x - image->w/2.0 < 0) + { + x = image->w/2.0; + xSpeed = 0; + } + if(y - image->h/2.0 < 0) + { + y = image->h/2.0; + ySpeed = 0; + } + if(x + image->w/2.0 > screen->w) + { + x = screen->w - image->w/2.0; + xSpeed = 0; + } + if(y + image->h/2.0 > screen->h) + { + y = screen->h - image->h/2.0; + ySpeed = 0; + } + for(int i = 0; i < (int) weapons.size(); ++i) + { + weapons[i]->x = slotPositions[i].first + x; + weapons[i]->y = slotPositions[i].second + y; + } + return result; +} + +/*structure of an UserShipfile +small Fighter #name +data/images/small_fighter.bmp #path of imagefile +200 #cost +7 #maxhp +50 #armor +200 #moveSpeed +100 #handling +10 #maxEnergy +2 #energyProduction +7 #collisionSize +2 #number of weapons +4 4 #relative Position of weapon +3 #maxSize of attached weapon +data/fireball.txt #path of weapon +4 4 #relative Position of weapon +3 #maxSize of attached weapon +data/fireball.txt #path of weapon +*/ +UserShip::UserShip(string filename) +{ + xSpeed = 0; + ySpeed = 0; + down = 0; + right = 0; + shooting = 0; + ifstream ins; + ins.open(filename.c_str()); + if(!ins.is_open()) + cout << "Error: Could not open userShip " << filename << endl; + getline(ins, name); + string imagePath; + getline(ins, imagePath); + image = loadBMP(imagePath); + ins >> cost; + ins >> maxhp; + maxhp.name = "Hitpoints"; + maxhp.cost = cost/10; + hp = maxhp; + ins >> armor; + armor.name = "Armor"; + armor.cost = cost/10; + ins >> moveSpeed; + moveSpeed.name = "Max Speed"; + moveSpeed.cost = cost/10; + ins >> handling; + handling.name = "Acceleration"; + handling.cost = cost/10; + ins >> maxEnergy; + maxEnergy.name = "Battery"; + maxEnergy.cost = cost/10; + energy = maxEnergy; + ins >> energyProduction; + energyProduction.name = "Generator"; + energyProduction.cost = cost/10; + ins >> collisionSize; + ins >> weaponSlots; + for(int i = 0; i < weaponSlots;i++) + { + double temp1, temp2; + ins >> temp1; + ins >> temp2; + slotPositions.push_back(make_pair(temp1,temp2)); + ins >> temp1; + maxSize.push_back(temp1); + //A workaround that helps discarting \n + char workaround; + ins >> workaround; + string weaponpath; + getline(ins, weaponpath); + weapons.push_back(new Weapon(workaround + weaponpath)); + } + if(cost == 0) + cost = round_beautiful(estimateValue(*this)); + ins.close(); +} + +void UserShip::reset() +{ + hp = maxhp; + energy = maxEnergy; + xSpeed = 0; + ySpeed = 0; + for(int i = 0; i < (int) weapons.size(); ++i) + { + weapons[i]->playSound = false; + vector dump = weapons[i]->frame((rand()%2000)/1000.0); + weapons[i]->playSound = true; + for(int j = 0; j < (int) dump.size(); ++j) + delete dump[j]; + } +} + +void UserShip::draw(SDL_Surface* screen) +{ + DObject::draw(screen); + for(int i = 0; i < (int) weapons.size(); ++i) + weapons[i]->draw(screen); +} + +SDL_Surface* UserShip::getImage() +{ + return image; +} + +double estimateValue(const UserShip& s) +{ + double result; + result = s.maxhp * pow(2,s.armor/(50.0+s.maxhp/10)); + result *= result; + result += s.maxEnergy*s.maxEnergy + s.energyProduction * s.energyProduction * 50; + result *= s.weapons.size(); + result *= s.moveSpeed / 300 * s.handling / 300; + + return result/11; +} + + + + -- cgit v1.2.3