void Application::Shoot(Projectile::PROJECTILE_TYPE type) { Projectile* p = FetchProjectile(); if (p) { float posX = ships_.at(0)->GetX(); float posY = ships_.at(0)->GetY(); switch (type) { case Projectile::PROJ_BULLET: { // TODO: Find pos p->Init(ships_.at(0), type, posX, posY, ships_.at(0)->GetW()); p->SetDamage(1); p->SetSpeed(400.f); bulletShootTimer = 0.f; } break; case Projectile::PROJ_SEEKING_MISSLE: { // TODO: Find pos p->Init(ships_.at(0), type, posX, posY, ships_.at(0)->GetW()); p->SetDamage(5); p->SetSpeed(250.f); p->SetTarget(FindNearest()); missileShootTimer = 0.f; } break; } RakNet::BitStream bs; bs.Write((unsigned char)ID_SHOOT); bs.Write(p->GetID()); bs.Write(p->GetType()); bs.Write(p->GetX()); bs.Write(p->GetY()); bs.Write(p->GetW()); bs.Write(p->GetVelocityX()); bs.Write(p->GetVelocityY()); bs.Write(p->GetSpeed()); bs.Write(p->GetDamage()); bs.Write(p->GetOwner()->GetID()); // Send target if available if (p->GetTarget()) { bs.Write(p->GetTarget()->GetID()); } else { bs.Write(-1); } rakpeer_->Send(&bs, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true); } }
Projectile * Application::FindProjectileByID(int id) { for (vector<Projectile*>::iterator it = projectileList.begin(); it != projectileList.end(); ++it) { Projectile* p = *it; if (p->GetID() == id) { return p; } } return nullptr; }
/** * Update cycle * * Checks for keypresses: * - Esc - Quits the game * - Left - Rotates ship left * - Right - Rotates ship right * - Up - Accelerates the ship * - Down - Deccelerates the ship * * Also calls Update() on all the ships in the universe */ bool Application::Update() { float timedelta = hge_->Timer_GetDelta(); if (bulletShootTimer < S_BULLET_SHOOT_INTERVAL) { bulletShootTimer += timedelta; } if (missileShootTimer < S_MISSILE_SHOOT_INTERVAL) { missileShootTimer += timedelta; } ships_.at(0)->SetAngularVelocity(0.0f); // Lab 13 Task 4 : Add a key to shoot missiles /*if (hge_->Input_GetKeyState(HGEK_ENTER)) { if (!keydown_enter) { CreateMissile(ships_.at(0)->GetX(), ships_.at(0)->GetY(), ships_.at(0)->GetW(), ships_.at(0)->GetID()); keydown_enter = true; } } else { if (keydown_enter) { keydown_enter = false; } }*/ static const float MAX_ENTER_TIMER = 0.5f; static float enterTimer; if (enterTimer < MAX_ENTER_TIMER) { enterTimer += timedelta; } // Chat if (chatMode) { char input = hge_->Input_GetKey(); if (input == HGEK_ESCAPE) { chatMode = false; typingMsg = ""; } else if (input == HGEK_ENTER && enterTimer >= MAX_ENTER_TIMER) { // Send if (typingMsg != "") { RakNet::BitStream chatBS; chatBS.Write((unsigned char)ID_CHAT_SEND); chatBS.Write(typingMsg.c_str()); rakpeer_->Send(&chatBS, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true); chatList.push_back(typingMsg); } // Reset chatMode = false; typingMsg = ""; enterTimer = 0.f; chatShowTimer = 5.f; } else if (input >= 32 && input <= 126) { typingMsg += input; } } else { if (chatShowTimer > 0.f) { chatShowTimer -= timedelta; } if (hge_->Input_GetKeyState(HGEK_ENTER) && enterTimer >= MAX_ENTER_TIMER) { chatMode = true; enterTimer = 0.f; } // Ship controls if (hge_->Input_GetKeyState(HGEK_LEFT)) { ships_.at(0)->SetAngularVelocity(ships_.at(0)->GetAngularVelocity() - DEFAULT_ANGULAR_VELOCITY); } if (hge_->Input_GetKeyState(HGEK_RIGHT)) { ships_.at(0)->SetAngularVelocity(ships_.at(0)->GetAngularVelocity() + DEFAULT_ANGULAR_VELOCITY); } if (hge_->Input_GetKeyState(HGEK_UP)) { ships_.at(0)->Accelerate(DEFAULT_ACCELERATION, timedelta); } if (hge_->Input_GetKeyState(HGEK_DOWN)) { ships_.at(0)->Accelerate(-DEFAULT_ACCELERATION, timedelta); } // Shooting if (hge_->Input_GetKeyState(HGEK_1)) { if (missileShootTimer >= S_MISSILE_SHOOT_INTERVAL) { Shoot(Projectile::PROJ_SEEKING_MISSLE); } } if (hge_->Input_GetKeyState(HGEK_2)) { if (bulletShootTimer >= S_BULLET_SHOOT_INTERVAL) { Shoot(Projectile::PROJ_BULLET); } } if (hge_->Input_GetKeyState(HGEK_ESCAPE)) { return true; } } // Update all ships for (ShipList::iterator ship = ships_.begin(); ship != ships_.end(); ship++) { (*ship)->Update(timedelta); //collisions /*if ((*ship) == ships_.at(0)) checkCollisions((*ship));*/ } // Lab 13 Task 5 : Updating the missile /*if (mymissile) { if (mymissile->Update(ships_, timedelta)) { //havecollision delete mymissile; mymissile = 0; } }*/ // Lab 13 Task 13 : Update network missiles /*for (MissileList::iterator missile = missiles_.begin(); missile != missiles_.end(); missile++) { if ((*missile)->Update(ships_, timedelta)) { //havecollision delete*missile; missiles_.erase(missile); break; } }*/ // Update enemies /*for (vector<Enemy*>::iterator it = enemyList.begin(); it != enemyList.end(); ++it) { Enemy* e = *it; if (e->GetActive()) { bool reset = e->Update(timedelta); if (reset) { RakNet::BitStream bs; bs.Write((unsigned char)ID_DESTROY_ENEMY); bs.Write(e->GetID()); rakpeer_->Send(&bs, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true); } } }*/ // Update projectile for (vector<Projectile*>::iterator it = projectileList.begin(); it != projectileList.end(); ++it) { Projectile* p = *it; if (/*p->GetOwner() == ships_.at(0) && */p->GetActive()) // Only update your own projectile { bool reset = p->Update(timedelta); RakNet::BitStream bs; if (reset) { DestroyProjectile(p); bs.Write((unsigned char)ID_DESTROY_PROJECTILE); bs.Write(p->GetID()); rakpeer_->Send(&bs, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true); } else { for (vector<Enemy*>::iterator it2 = enemyList.begin(); it2 != enemyList.end(); ++it2) { Enemy* e = *it2; if (e->GetActive()) { bool collision = p->CollideWith(e); if (collision) { int newHP = e->Injure(p->GetDamage()); if (newHP <= 0) { RakNet::BitStream bs; // Add score to player p->GetOwner()->AddScore(100); bs.Write((unsigned char)ID_UPDATE_SCORE); bs.Write(p->GetOwner()->GetID()); bs.Write(p->GetOwner()->GetScore()); rakpeer_->Send(&bs, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true); // Destroy enemy DestroyEnemy(e); // Send to server to destroy enemy bs.ResetWritePointer(); bs.Write((unsigned char)ID_DESTROY_ENEMY); bs.Write(e->GetID()); rakpeer_->Send(&bs, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true); } else { // Send to server to injure enemy RakNet::BitStream bs; bs.ResetWritePointer(); bs.Write((unsigned char)ID_INJURE_ENEMY); bs.Write(e->GetID()); bs.Write(e->GetHP()); rakpeer_->Send(&bs, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true); } // Reset projectile DestroyProjectile(p); bs.ResetWritePointer(); bs.Write((unsigned char)ID_DESTROY_PROJECTILE); bs.Write(p->GetID()); rakpeer_->Send(&bs, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true); } } } /*int max = projectileUpdateList.size(); int count = 0; for (vector<Projectile*>::iterator it2 = projectileUpdateList.begin(); it2 != projectileUpdateList.end(); ++it2) { Projectile* p2 = *it2; if (p == p2) { break; } else { ++count; } } if (count == max) { projectileUpdateList.push_back(p); }*/ /*bs.Write((unsigned char)ID_UPDATE_PROJECTILE); bs.Write(p->GetID()); bs.Write(p->GetActive()); bs.Write(p->GetType()); bs.Write(p->GetX()); bs.Write(p->GetY()); bs.Write(p->GetVelocityX()); bs.Write(p->GetVelocityY()); bs.Write(p->GetSpeed()); bs.Write(p->GetDamage()); bs.Write(p->GetOwner()->GetID()); // Send target id if available if (p->GetTarget()) { bs.Write(p->GetTarget()->GetID()); } else { bs.Write(-1); } rakpeer_->Send(&bs, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);*/ } } } // Update explosions for (vector<Explosion*>::iterator it = explosionList.begin(); it != explosionList.end(); ++it) { Explosion* e = *it; if ( e->isActive()) { e->Update(timedelta); } } // Update boom for (vector<Boom*>::iterator it = boomList.begin(); it != boomList.end(); ++it) { Boom* b = *it; if (b->isActive()) { b->Update(timedelta); } } // Packet receive if (Packet* packet = rakpeer_->Receive()) { RakNet::BitStream bs(packet->data, packet->length, false); unsigned char msgid = 0; RakNetTime timestamp = 0; bs.Read(msgid); if (msgid == ID_TIMESTAMP) { bs.Read(timestamp); bs.Read(msgid); } switch(msgid) { case ID_CONNECTION_REQUEST_ACCEPTED: { std::cout << "Connected to Server" << std::endl; SendScreenSize(); InitEnemyList(); InitExplosionList(); InitBoomList(); InitProjectileList(); InitBackground(); InitBase(); InitScore(); chatMsg = new hgeFont("font1.fnt"); chatMsg->SetScale(1); } break; case ID_NO_FREE_INCOMING_CONNECTIONS: case ID_CONNECTION_LOST: case ID_DISCONNECTION_NOTIFICATION: std::cout << "Lost Connection to Server" << std::endl; rakpeer_->DeallocatePacket(packet); return true; case ID_WELCOME: { unsigned int shipcount, id; float x_, y_; int type_; std::string temp; char chartemp[5]; bs.Read(id); ships_.at(0)->setID( id ); bs.Read(shipcount); for (unsigned int i = 0; i < shipcount; ++ i) { bs.Read(id); bs.Read(x_); bs.Read(y_); bs.Read(type_); std::cout << "New Ship pos" << x_ << " " << y_ << std::endl; Ship* ship = new Ship(type_, x_, y_ ); temp = "Ship "; temp += _itoa(id, chartemp, 10); ship->SetName(temp.c_str()); ship->setID( id ); ships_.push_back(ship); } for (vector<Enemy*>::iterator it = enemyList.begin(); it != enemyList.end(); ++it) { int id, hp; bool active; Enemy::ENEMY_TYPE type; float x, y, vel_x, vel_y, speed; bs.Read(id); bs.Read(active); bs.Read(type); bs.Read(x); bs.Read(y); bs.Read(vel_x); bs.Read(vel_y); bs.Read(speed); bs.Read(hp); Enemy* e = FindEnemyByID(id); if (e) { float w = CalcW(Vector2(vel_x, vel_y)); /*if (speed != 0) { w = acosf(vel_x / speed); } else { w = 0.f; }*/ e->Init(type, x, y, w, active); e->SetVelocityX(vel_x); e->SetVelocityY(vel_y); e->SetSpeed(speed); e->SetHP(hp); } } // Base hp bs.Read(base_hp); SendInitialPosition(); } break; case ID_REJECT_PLAYER: { std::cout << "Rejected player" << std::endl; return true; } break; case ID_NEWSHIP: { unsigned int id; bs.Read(id); if( id == ships_.at(0)->GetID() ) { // if it is me break; } else { float x_, y_; int type_; std::string temp; char chartemp[5]; bs.Read( x_ ); bs.Read( y_ ); bs.Read( type_ ); std::cout << "New Ship pos" << x_ << " " << y_ << std::endl; Ship* ship = new Ship(type_, x_, y_); temp = "Ship "; temp += _itoa(id, chartemp, 10); ship->SetName(temp.c_str()); ship->setID( id ); ships_.push_back(ship); } } break; case ID_LOSTSHIP: { unsigned int shipid; bs.Read(shipid); for (ShipList::iterator itr = ships_.begin(); itr != ships_.end(); ++itr) { if ((*itr)->GetID() == shipid) { delete *itr; ships_.erase(itr); break; } } } break; case ID_INITIALPOS: break; case ID_MOVEMENT: { unsigned int shipid; float temp; float x,y,w; bs.Read(shipid); for (ShipList::iterator itr = ships_.begin(); itr != ships_.end(); ++itr) { if ((*itr)->GetID() == shipid) { // this portion needs to be changed for it to work #ifdef INTERPOLATEMOVEMENT bs.Read(x); bs.Read(y); bs.Read(w); (*itr)->SetServerLocation( x, y, w ); bs.Read(temp); (*itr)->SetServerVelocityX( temp ); bs.Read(temp); (*itr)->SetServerVelocityY( temp ); bs.Read(temp); (*itr)->SetAngularVelocity( temp ); (*itr)->DoInterpolateUpdate(); #else bs.Read(x); bs.Read(y); bs.Read(w); (*itr)->setLocation( x, y, w ); // Lab 7 Task 1 : Read Extrapolation Data velocity x, velocity y & angular velocity bs.Read(temp); (*itr)->SetVelocityX( temp ); bs.Read(temp); (*itr)->SetVelocityY( temp ); bs.Read(temp); (*itr)->SetAngularVelocity( temp ); #endif break; } } } break; case ID_COLLIDE: { unsigned int shipid; float x, y; bs.Read(shipid); if( shipid == ships_.at(0)->GetID() ) { std::cout << "collided with someone!" << std::endl; bs.Read(x); bs.Read(y); ships_.at(0)->SetX( x ); ships_.at(0)->SetY( y ); bs.Read(x); bs.Read(y); ships_.at(0)->SetVelocityX( x ); ships_.at(0)->SetVelocityY( y ); #ifdef INTERPOLATEMOVEMENT bs.Read(x); bs.Read(y); ships_.at(0)->SetServerVelocityX( x ); ships_.at(0)->SetServerVelocityY( y ); #endif } } break; // Lab 13 Task 10 : new cases to handle missile on application side case ID_NEWMISSILE: { float x, y, w; int id; bs.Read(id); bs.Read(x); bs.Read(y); bs.Read(w); missiles_.push_back(new Missile("missile.png", x, y, w, id)); } break; case ID_UPDATEMISSILE: { float x, y, w; int id; char deleted; bs.Read(id); bs.Read(deleted); for (MissileList::iterator itr = missiles_.begin(); itr != missiles_.end(); ++itr) { if ((*itr)->GetOwnerID() == id) { if (deleted == 1) { delete*itr; missiles_.erase(itr); } else { bs.Read(x); bs.Read(y); bs.Read(w); (*itr)->UpdateLoc(x, y, w); bs.Read(x); (*itr)->SetVelocityX(x); bs.Read(y); (*itr)->SetVelocityY(y); } break; } } } break; case ID_NEW_ENEMY: { int id, hp; Enemy::ENEMY_TYPE type; float x, y, vel_x, vel_y, speed; bs.Read(id); bs.Read(type); bs.Read(x); bs.Read(y); bs.Read(vel_x); bs.Read(vel_y); bs.Read(speed); bs.Read(hp); Enemy* e = FindEnemyByID(id); if (e) { float w = CalcW(Vector2(vel_x, vel_y)); e->Init(type, x, y, w); e->SetVelocityX(vel_x); e->SetVelocityY(vel_y); e->SetSpeed(speed); e->SetHP(hp); } } break; case ID_UPDATE_ENEMY: { int id; bs.Read(id); Enemy* e = FindEnemyByID(id); if (e) { float x, y; bs.Read(x); bs.Read(y); e->SetX(x); e->SetY(y); } } break; case ID_INJURE_ENEMY: { int id, hp; bs.Read(id); Enemy* e = FindEnemyByID(id); if (e && e->GetActive()) { bs.Read(hp); e->SetHP(hp); } } break; case ID_DESTROY_ENEMY: { int id; bs.Read(id); Enemy* e = FindEnemyByID(id); DestroyEnemy(e); } break; case ID_SHOOT: { int id, damage, owner, target; Projectile::PROJECTILE_TYPE type; float x, y, w, vel_x, vel_y, speed; bs.Read(id); Projectile* p = FindProjectileByID(id); if (p) { bs.Read(type); bs.Read(x); bs.Read(y); bs.Read(w); bs.Read(vel_x); bs.Read(vel_y); bs.Read(speed); bs.Read(damage); bs.Read(owner); bs.Read(target); Ship* sOwner = FindShipByID(owner); if (sOwner) { p->Init(sOwner, type, x, y, w); p->SetVelocityX(vel_x); p->SetVelocityY(vel_y); p->SetSpeed(speed); p->SetDamage(damage); if (target != -1) { Enemy* sTarget = FindEnemyByID(target); if (sTarget) { p->SetTarget(sTarget); } } } } } break; case ID_UPDATE_PROJECTILE: { int id, damage, owner, target; Projectile::PROJECTILE_TYPE type; float x, y, vel_x, vel_y, speed; bool active; bs.Read(id); Projectile* p = FindProjectileByID(id); if (p) { bs.Read(active); bs.Read(type); bs.Read(x); bs.Read(y); bs.Read(vel_x); bs.Read(vel_y); bs.Read(speed); bs.Read(damage); bs.Read(owner); bs.Read(target); Ship* sOwner = FindShipByID(owner); if (sOwner) { p->SetOwner(sOwner); p->SetType(type); p->SetX(x); p->SetY(y); p->SetActive(active); p->SetVelocityX(vel_x); p->SetVelocityY(vel_y); p->SetSpeed(speed); p->SetDamage(damage); if (target != -1) { Enemy* sTarget = FindEnemyByID(target); if (sTarget) { p->SetTarget(sTarget); } } } } } break; case ID_DESTROY_PROJECTILE: { int id; bs.Read(id); Projectile* p = FindProjectileByID(id); if (p && p->GetActive()) { // Reset projectile //DestroyProjectile(p); p->Reset(); } } break; case ID_UPDATE_BASE: { bs.Read(base_hp); } break; case ID_UPDATE_SCORE: { int id, score; bs.Read(id); Ship* s = FindShipByID(id); if (s) { bs.Read(score); s->SetScore(score); } } break; case ID_CHAT_SEND: { char cMsg[256]; bs.Read(cMsg); chatList.push_back(cMsg); chatShowTimer = 5.f; } break; default: std::cout << "Unhandled Message Identifier: " << (int)msgid << std::endl; } rakpeer_->DeallocatePacket(packet); } if (base_hp <= 0) { return true; } // Send projectile updates /*static const int SYNCS_PER_SEC = 24; static const float TIME_PER_SYNC = 1 / SYNCS_PER_SEC; static float projSendTimer = TIME_PER_SYNC; if (projSendTimer < TIME_PER_SYNC) { projSendTimer += timedelta; } else { for (vector<Projectile*>::iterator it = projectileList.begin(); it != projectileList.end(); ++it) { Projectile* p = *it; if (p->GetActive() && p->GetOwner() == ships_.at(0)) { RakNet::BitStream sendProj; sendProj.Write((unsigned char)ID_UPDATE_PROJECTILE); sendProj.Write(p->GetID()); sendProj.Write(p->GetActive()); sendProj.Write(p->GetType()); sendProj.Write(p->GetX()); sendProj.Write(p->GetY()); sendProj.Write(p->GetVelocityX()); sendProj.Write(p->GetVelocityY()); sendProj.Write(p->GetSpeed()); sendProj.Write(p->GetDamage()); sendProj.Write(p->GetOwner()->GetID()); // Send target id if available if (p->GetTarget()) { sendProj.Write(p->GetTarget()->GetID()); } else { sendProj.Write(-1); } rakpeer_->Send(&sendProj, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true); std::cout << p->GetX() << " | " << p->GetY() << std::endl; } } projSendTimer = 0.f; }*/ // Send data float timeToSync = 1000 / 24; // Sync 24 times in a second (Millisecond) if (RakNet::GetTime() - timer_ > timeToSync) { timer_ = RakNet::GetTime(); // Store previous time RakNet::BitStream bs2; unsigned char msgid = ID_MOVEMENT; bs2.Write(msgid); #ifdef INTERPOLATEMOVEMENT bs2.Write(ships_.at(0)->GetID()); bs2.Write(ships_.at(0)->GetServerX()); bs2.Write(ships_.at(0)->GetServerY()); bs2.Write(ships_.at(0)->GetServerW()); bs2.Write(ships_.at(0)->GetServerVelocityX()); bs2.Write(ships_.at(0)->GetServerVelocityY()); bs2.Write(ships_.at(0)->GetAngularVelocity()); #else bs2.Write(ships_.at(0)->GetID()); bs2.Write(ships_.at(0)->GetX()); bs2.Write(ships_.at(0)->GetY()); bs2.Write(ships_.at(0)->GetW()); // Lab 7 Task 1 : Add Extrapolation Data velocity x, velocity y & angular velocity bs2.Write(ships_.at(0)->GetVelocityX()); bs2.Write(ships_.at(0)->GetVelocityY()); bs2.Write(ships_.at(0)->GetAngularVelocity()); #endif rakpeer_->Send(&bs2, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true); // Lab 13 Task 11 : send missile update /*if (mymissile) { RakNet::BitStream bs3; unsigned char msgid2 = ID_UPDATEMISSILE; unsigned char deleted = 0; bs3.Write(msgid2); bs3.Write(mymissile->GetOwnerID()); bs3.Write(deleted); bs3.Write(mymissile->GetX()); bs3.Write(mymissile->GetY()); bs3.Write(mymissile->GetW()); bs3.Write(mymissile->GetVelocityX()); bs3.Write(mymissile->GetVelocityY()); rakpeer_->Send(&bs3, HIGH_PRIORITY, UNRELIABLE_SEQUENCED, 0, UNASSIGNED_SYSTEM_ADDRESS, true); }*/ // Send update projectile /*for (int i = 0; i < projectileUpdateList.size(); ++i) { Projectile* p = projectileList[i]; if (p && p->GetActive()) { RakNet::BitStream sendProj; sendProj.Write((unsigned char)ID_UPDATE_PROJECTILE); sendProj.Write(p->GetID()); sendProj.Write(p->GetActive()); sendProj.Write(p->GetType()); sendProj.Write(p->GetX()); sendProj.Write(p->GetY()); sendProj.Write(p->GetVelocityX()); sendProj.Write(p->GetVelocityY()); sendProj.Write(p->GetSpeed()); sendProj.Write(p->GetDamage()); sendProj.Write(p->GetOwner()->GetID()); // Send target id if available if (p->GetTarget()) { sendProj.Write(p->GetTarget()->GetID()); } else { sendProj.Write(-1); } rakpeer_->Send(&sendProj, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true); } } projectileUpdateList.clear();*/ } return false; }