Changeset e62b56c in network-game
- Timestamp:
- Dec 23, 2013, 4:56:22 PM (11 years ago)
- Branches:
- master
- Children:
- ad1e2fc
- Parents:
- 35f6097
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
common/MessageContainer.h
r35f6097 re62b56c 38 38 #define MSG_TYPE_JOIN_GAME_ACK 23 39 39 #define MSG_TYPE_PLAYER_JOIN_GAME 24 40 #define MSG_TYPE_FINISH_GAME 25 40 41 41 42 typedef struct -
design/multipleGameDesign.txt
r35f6097 re62b56c 7 7 There should be a new LOBBY state the player goes to after logging in, which lets him create a game and view all created games. There should also be a button to let him go to the current "global" game. 8 8 9 The client only has one game object, which is the game the client is currently in (or MILL if the client is in the lobby). The mapGames of the client maps game names to number of players in each game. 9 The client only has one game object, which is the game the client is currently in (or NULL if the client is in the lobby). The mapGames of the client maps game names to number of players in each game. 10 11 There should be code that ends a game when a team scores 3 points and shows each participant a screen saying which team won, what the final score was, and a button back to the lobby. More info can be added to that screen in the future. As far as the server is concerned, when a player is viewing this screen, they are already at the lobby and no longer in their game. 12 13 When a game ends, everyone not in the game should get a GAME_INFO message with 0 players so they delete the game. Everyone in the game will instead get a GAME_FINISH message which will have the winner and the final score (and possibly other info in the future, such as kills, deaths, assists, and flag turn-ins per player). Once these messages are sent, the server will delete the game from its list. The player who got the FINISH_GAME message will go to the lobby state, but save the game results in a new GameResult object and display it in the afore-mentioned screen with the results. -
server/server.cpp
r35f6097 re62b56c 227 227 // process players currently in a game 228 228 FLOAT_POSITION oldPos; 229 for (it = mapPlayers.begin(); it != mapPlayers.end(); it++) 230 { 231 Player* p = it->second; 232 if (p->currentGame == NULL) 233 continue; 234 235 cout << "moving player" << endl; 236 bool broadcastMove = false; 237 238 // xompute playersInGame here 239 240 // move player and perform associated tasks 241 oldPos = p->pos; 242 if (p->move(p->currentGame->getMap())) { 243 244 cout << "player moved" << endl; 245 if (p->currentGame->processPlayerMovement(p, oldPos)) 246 broadcastMove = true; 247 cout << "player move processed" << endl; 248 249 map<unsigned int, Player*>& playersInGame = p->currentGame->getPlayers(); 250 251 WorldMap::ObjectType flagType; 252 POSITION pos; 253 bool flagTurnedIn = false; 254 bool flagReturned = false; 255 bool ownFlagAtBase = false; 256 257 // need to figure out how to move this to a different file 258 // while still sending back flag type and position 259 WorldMap* playerMap = p->currentGame->getMap(); 260 switch(playerMap->getStructure(p->pos.x/25, p->pos.y/25)) 261 { 262 case WorldMap::STRUCTURE_BLUE_FLAG: 263 { 264 if (p->team == 0 && p->hasRedFlag) 229 map<string, Game*>::iterator itGames; 230 Game* game = NULL; 231 WorldMap* gameMap = NULL; 232 233 for (itGames = mapGames.begin(); itGames != mapGames.end(); itGames++) { 234 game = itGames->second; 235 gameMap = game->getMap(); 236 map<unsigned int, Player*>& playersInGame = game->getPlayers(); 237 238 for (it = game->getPlayers().begin(); it != game->getPlayers().end(); it++) 239 { 240 Player* p = it->second; 241 242 cout << "moving player" << endl; 243 bool broadcastMove = false; 244 245 // xompute playersInGame here 246 247 // move player and perform associated tasks 248 oldPos = p->pos; 249 if (p->move(gameMap)) { 250 251 cout << "player moved" << endl; 252 if (game->processPlayerMovement(p, oldPos)) 253 broadcastMove = true; 254 cout << "player move processed" << endl; 255 256 257 WorldMap::ObjectType flagType; 258 POSITION pos; 259 bool flagTurnedIn = false; 260 bool flagReturned = false; 261 bool ownFlagAtBase = false; 262 263 // need to figure out how to move this to a different file 264 // while still sending back flag type and position 265 switch(gameMap->getStructure(p->pos.x/25, p->pos.y/25)) 266 { 267 case WorldMap::STRUCTURE_BLUE_FLAG: 265 268 { 266 // check that your flag is at your base 267 pos = playerMap->getStructureLocation(WorldMap::STRUCTURE_BLUE_FLAG); 268 269 vector<WorldMap::Object>* vctObjects = playerMap->getObjects(); 270 vector<WorldMap::Object>::iterator itObjects; 271 272 for (itObjects = vctObjects->begin(); itObjects != vctObjects->end(); itObjects++) 269 if (p->team == 0 && p->hasRedFlag) 273 270 { 274 if (itObjects->type == WorldMap::OBJECT_BLUE_FLAG) 271 // check that your flag is at your base 272 pos = gameMap->getStructureLocation(WorldMap::STRUCTURE_BLUE_FLAG); 273 274 vector<WorldMap::Object>* vctObjects = gameMap->getObjects(); 275 vector<WorldMap::Object>::iterator itObjects; 276 277 for (itObjects = vctObjects->begin(); itObjects != vctObjects->end(); itObjects++) 275 278 { 276 if (itObjects-> pos.x == pos.x*25+12 && itObjects->pos.y == pos.y*25+12)279 if (itObjects->type == WorldMap::OBJECT_BLUE_FLAG) 277 280 { 278 ownFlagAtBase = true; 279 break; 281 if (itObjects->pos.x == pos.x*25+12 && itObjects->pos.y == pos.y*25+12) 282 { 283 ownFlagAtBase = true; 284 break; 285 } 280 286 } 281 287 } 288 289 if (ownFlagAtBase) 290 { 291 p->hasRedFlag = false; 292 flagType = WorldMap::OBJECT_RED_FLAG; 293 pos = gameMap->getStructureLocation(WorldMap::STRUCTURE_RED_FLAG); 294 flagTurnedIn = true; 295 scoreBlue++; 296 } 282 297 } 283 298 284 if (ownFlagAtBase) 299 break; 300 } 301 case WorldMap::STRUCTURE_RED_FLAG: 302 { 303 if (p->team == 1 && p->hasBlueFlag) 285 304 { 286 p->hasRedFlag = false; 287 flagType = WorldMap::OBJECT_RED_FLAG; 288 pos = playerMap->getStructureLocation(WorldMap::STRUCTURE_RED_FLAG); 289 flagTurnedIn = true; 290 scoreBlue++; 305 // check that your flag is at your base 306 pos = gameMap->getStructureLocation(WorldMap::STRUCTURE_RED_FLAG); 307 308 vector<WorldMap::Object>* vctObjects = gameMap->getObjects(); 309 vector<WorldMap::Object>::iterator itObjects; 310 311 for (itObjects = vctObjects->begin(); itObjects != vctObjects->end(); itObjects++) 312 { 313 if (itObjects->type == WorldMap::OBJECT_RED_FLAG) 314 { 315 if (itObjects->pos.x == pos.x*25+12 && itObjects->pos.y == pos.y*25+12) 316 { 317 ownFlagAtBase = true; 318 break; 319 } 320 } 321 } 322 323 if (ownFlagAtBase) 324 { 325 p->hasBlueFlag = false; 326 flagType = WorldMap::OBJECT_BLUE_FLAG; 327 pos = gameMap->getStructureLocation(WorldMap::STRUCTURE_BLUE_FLAG); 328 flagTurnedIn = true; 329 scoreRed++; 330 } 331 } 332 333 break; 334 } 335 } 336 337 if (flagTurnedIn) 338 { 339 // send an OBJECT message to add the flag back to its spawn point 340 pos.x = pos.x*25+12; 341 pos.y = pos.y*25+12; 342 gameMap->addObject(flagType, pos.x, pos.y); 343 344 serverMsg.type = MSG_TYPE_OBJECT; 345 gameMap->getObjects()->back().serialize(serverMsg.buffer); 346 347 map<unsigned int, Player*>::iterator it2; 348 349 for (it2 = playersInGame.begin(); it2 != playersInGame.end(); it2++) 350 { 351 if ( msgProcessor.sendMessage(&serverMsg, sock, &(it2->second->addr), &outputLog) < 0 ) 352 error("sendMessage"); 353 } 354 355 serverMsg.type = MSG_TYPE_SCORE; 356 memcpy(serverMsg.buffer, &scoreBlue, 4); 357 memcpy(serverMsg.buffer+4, &scoreRed, 4); 358 359 for (it2 = playersInGame.begin(); it2 != playersInGame.end(); it2++) 360 { 361 if ( msgProcessor.sendMessage(&serverMsg, sock, &(it2->second->addr), &outputLog) < 0 ) 362 error("sendMessage"); 363 } 364 365 /* 366 if (scoreBlue == 3 || scoreRed == 3) { 367 gameOver = true; 368 369 unsigned int winningTeam; 370 if (scoreBlue == 3) 371 winningTeam = 0; 372 else if (scoreRed == 3) 373 winningTeam = 1; 374 375 serverMsg.type = MSG_TYPE_FINISH_GAME; 376 memcpy(serverMsg.buffer+4, &winningTeam, 4); 377 memcpy(serverMsg.buffer+4, &scoreBlue, 4); 378 memcpy(serverMsg.buffer+8, &scoreRed, 4); 379 380 for (it2 = playersInGame.begin(); it2 != playersInGame.end(); it2++) 381 { 382 if ( msgProcessor.sendMessage(&serverMsg, sock, &(it2->second->addr), &outputLog) < 0 ) 383 error("sendMessage"); 384 } 385 386 // send a GAME_INFO message with 0 players to force clients to delete the game 387 int numPlayers = 0; 388 serverMsg.type = MSG_TYPE_GAME_INFO; 389 memcpy(serverMsg.buffer, &numPlayers, 4); 390 391 for (it2 = playersInGame.begin(); it2 != playersInGame.end(); it2++) 392 { 393 if ( msgProcessor.sendMessage(&serverMsg, sock, &(it2->second->addr), &outputLog) < 0 ) 394 error("sendMessage"); 291 395 } 292 396 } 293 294 break; 295 } 296 case WorldMap::STRUCTURE_RED_FLAG: 297 { 298 if (p->team == 1 && p->hasBlueFlag) 397 */ 398 399 // this means a PLAYER message will be sent 400 broadcastMove = true; 401 } 402 403 // go through all objects and check if the player is close to one and if its their flag 404 vector<WorldMap::Object>* vctObjects = gameMap->getObjects(); 405 vector<WorldMap::Object>::iterator itObjects; 406 POSITION structPos; 407 408 for (itObjects = vctObjects->begin(); itObjects != vctObjects->end(); itObjects++) 409 { 410 POSITION pos = itObjects->pos; 411 412 if (posDistance(p->pos, pos.toFloat()) < 10) 299 413 { 300 // check that your flag is at your base 301 pos = playerMap->getStructureLocation(WorldMap::STRUCTURE_RED_FLAG); 302 303 vector<WorldMap::Object>* vctObjects = playerMap->getObjects(); 304 vector<WorldMap::Object>::iterator itObjects; 305 306 for (itObjects = vctObjects->begin(); itObjects != vctObjects->end(); itObjects++) 414 if (p->team == 0 && 415 itObjects->type == WorldMap::OBJECT_BLUE_FLAG) 307 416 { 308 if (itObjects->type == WorldMap::OBJECT_RED_FLAG) 309 { 310 if (itObjects->pos.x == pos.x*25+12 && itObjects->pos.y == pos.y*25+12) 311 { 312 ownFlagAtBase = true; 313 break; 314 } 315 } 417 structPos = gameMap->getStructureLocation(WorldMap::STRUCTURE_BLUE_FLAG); 418 flagReturned = true; 419 break; 316 420 } 317 318 if (ownFlagAtBase)421 else if (p->team == 1 && 422 itObjects->type == WorldMap::OBJECT_RED_FLAG) 319 423 { 320 p->hasBlueFlag = false; 321 flagType = WorldMap::OBJECT_BLUE_FLAG; 322 pos = playerMap->getStructureLocation(WorldMap::STRUCTURE_BLUE_FLAG); 323 flagTurnedIn = true; 324 scoreRed++; 424 structPos = gameMap->getStructureLocation(WorldMap::STRUCTURE_RED_FLAG); 425 flagReturned = true; 426 break; 325 427 } 326 428 } 327 328 break; 429 } 430 431 if (flagReturned) 432 { 433 itObjects->pos.x = structPos.x*25+12; 434 itObjects->pos.y = structPos.y*25+12; 435 436 serverMsg.type = MSG_TYPE_OBJECT; 437 itObjects->serialize(serverMsg.buffer); 438 439 map<unsigned int, Player*>::iterator it2; 440 for (it2 = playersInGame.begin(); it2 != playersInGame.end(); it2++) 441 { 442 if ( msgProcessor.sendMessage(&serverMsg, sock, &(it2->second->addr), &outputLog) < 0 ) 443 error("sendMessage"); 444 } 445 } 446 447 if (broadcastMove) 448 { 449 cout << "broadcasting player move" << endl; 450 serverMsg.type = MSG_TYPE_PLAYER; 451 p->serialize(serverMsg.buffer); 452 453 // only broadcast message to other players in the same game 454 cout << "about to broadcast move" << endl; 455 456 map<unsigned int, Player*>::iterator it2; 457 for (it2 = playersInGame.begin(); it2 != playersInGame.end(); it2++) 458 { 459 if ( msgProcessor.sendMessage(&serverMsg, sock, &(it2->second->addr), &outputLog) < 0 ) 460 error("sendMessage"); 461 } 462 cout << "done broadcasting player move" << endl; 329 463 } 330 464 } 331 465 332 if (flagTurnedIn) 466 cout << "processing player attack" << endl; 467 468 // check if the player's attack animation is complete 469 if (p->isAttacking && p->timeAttackStarted+p->attackCooldown <= getCurrentMillis()) 333 470 { 334 // send an OBJECT message to add the flag back to its spawn point 335 pos.x = pos.x*25+12; 336 pos.y = pos.y*25+12; 337 playerMap->addObject(flagType, pos.x, pos.y); 338 339 serverMsg.type = MSG_TYPE_OBJECT; 340 playerMap->getObjects()->back().serialize(serverMsg.buffer); 471 p->isAttacking = false; 472 cout << "Attack animation is complete" << endl; 473 474 //send everyone an ATTACK message 475 cout << "about to broadcast attack" << endl; 476 477 serverMsg.type = MSG_TYPE_ATTACK; 478 memcpy(serverMsg.buffer, &p->id, 4); 479 memcpy(serverMsg.buffer+4, &p->targetPlayer, 4); 341 480 342 481 map<unsigned int, Player*>::iterator it2; 343 344 482 for (it2 = playersInGame.begin(); it2 != playersInGame.end(); it2++) 345 483 { … … 348 486 } 349 487 350 serverMsg.type = MSG_TYPE_SCORE; 351 memcpy(serverMsg.buffer, &scoreBlue, 4); 352 memcpy(serverMsg.buffer+4, &scoreRed, 4); 353 488 if (p->attackType == Player::ATTACK_MELEE) 489 { 490 cout << "Melee attack" << endl; 491 492 Player* target = playersInGame[p->targetPlayer]; 493 damagePlayer(target, p->damage); 494 495 if (target->isDead) 496 { 497 WorldMap::ObjectType flagType = WorldMap::OBJECT_NONE; 498 if (target->hasBlueFlag) 499 flagType = WorldMap::OBJECT_BLUE_FLAG; 500 else if (target->hasRedFlag) 501 flagType = WorldMap::OBJECT_RED_FLAG; 502 503 if (flagType != WorldMap::OBJECT_NONE) { 504 addObjectToMap(flagType, target->pos.x, target->pos.y, gameMap, playersInGame, msgProcessor, sock, outputLog); 505 } 506 } 507 508 serverMsg.type = MSG_TYPE_PLAYER; 509 target->serialize(serverMsg.buffer); 510 } 511 else if (p->attackType == Player::ATTACK_RANGED) 512 { 513 cout << "Ranged attack" << endl; 514 515 Projectile proj(p->pos.x, p->pos.y, p->targetPlayer, p->damage); 516 game->assignProjectileId(&proj); 517 game->addProjectile(proj); 518 519 int x = p->pos.x; 520 int y = p->pos.y; 521 522 serverMsg.type = MSG_TYPE_PROJECTILE; 523 memcpy(serverMsg.buffer, &proj.id, 4); 524 memcpy(serverMsg.buffer+4, &x, 4); 525 memcpy(serverMsg.buffer+8, &y, 4); 526 memcpy(serverMsg.buffer+12, &p->targetPlayer, 4); 527 } 528 else 529 cout << "Invalid attack type: " << p->attackType << endl; 530 531 // broadcast either a PLAYER or PROJECTILE message 532 cout << "Broadcasting player or projectile message" << endl; 354 533 for (it2 = playersInGame.begin(); it2 != playersInGame.end(); it2++) 355 534 { 356 if ( 535 if (msgProcessor.sendMessage(&serverMsg, sock, &(it2->second->addr), &outputLog) < 0 ) 357 536 error("sendMessage"); 358 537 } 359 360 // this means a PLAYER message will be sent 361 broadcastMove = true; 538 cout << "Done broadcasting" << endl; 362 539 } 363 364 // go through all objects and check if the player is close to one and if its their flag365 vector<WorldMap::Object>* vctObjects = playerMap->getObjects();366 vector<WorldMap::Object>::iterator itObjects;367 POSITION structPos;368 369 for (itObjects = vctObjects->begin(); itObjects != vctObjects->end(); itObjects++)370 {371 POSITION pos = itObjects->pos;372 373 if (posDistance(p->pos, pos.toFloat()) < 10)374 {375 if (p->team == 0 &&376 itObjects->type == WorldMap::OBJECT_BLUE_FLAG)377 {378 structPos = playerMap->getStructureLocation(WorldMap::STRUCTURE_BLUE_FLAG);379 flagReturned = true;380 break;381 }382 else if (p->team == 1 &&383 itObjects->type == WorldMap::OBJECT_RED_FLAG)384 {385 structPos = playerMap->getStructureLocation(WorldMap::STRUCTURE_RED_FLAG);386 flagReturned = true;387 break;388 }389 }390 }391 392 if (flagReturned)393 {394 itObjects->pos.x = structPos.x*25+12;395 itObjects->pos.y = structPos.y*25+12;396 397 serverMsg.type = MSG_TYPE_OBJECT;398 itObjects->serialize(serverMsg.buffer);399 400 map<unsigned int, Player*>::iterator it2;401 for (it2 = playersInGame.begin(); it2 != playersInGame.end(); it2++)402 {403 if ( msgProcessor.sendMessage(&serverMsg, sock, &(it2->second->addr), &outputLog) < 0 )404 error("sendMessage");405 }406 }407 408 if (broadcastMove)409 {410 cout << "broadcasting player move" << endl;411 serverMsg.type = MSG_TYPE_PLAYER;412 p->serialize(serverMsg.buffer);413 414 // only broadcast message to other players in the same game415 cout << "about to broadcast move" << endl;416 417 map<unsigned int, Player*>::iterator it2;418 for (it2 = playersInGame.begin(); it2 != playersInGame.end(); it2++)419 {420 if ( msgProcessor.sendMessage(&serverMsg, sock, &(it2->second->addr), &outputLog) < 0 )421 error("sendMessage");422 }423 cout << "done broadcasting player move" << endl;424 }425 }426 427 cout << "processing player attack" << endl;428 429 // check if the player's attack animation is complete430 if (p->isAttacking && p->timeAttackStarted+p->attackCooldown <= getCurrentMillis())431 {432 p->isAttacking = false;433 cout << "Attack animation is complete" << endl;434 435 //send everyone an ATTACK message436 cout << "about to broadcast attack" << endl;437 438 serverMsg.type = MSG_TYPE_ATTACK;439 memcpy(serverMsg.buffer, &p->id, 4);440 memcpy(serverMsg.buffer+4, &p->targetPlayer, 4);441 442 map<unsigned int, Player*>& playersInGame = p->currentGame->getPlayers();443 map<unsigned int, Player*>::iterator it2;444 for (it2 = playersInGame.begin(); it2 != playersInGame.end(); it2++)445 {446 if ( msgProcessor.sendMessage(&serverMsg, sock, &(it2->second->addr), &outputLog) < 0 )447 error("sendMessage");448 }449 450 if (p->attackType == Player::ATTACK_MELEE)451 {452 cout << "Melee attack" << endl;453 454 Player* target = playersInGame[p->targetPlayer];455 damagePlayer(target, p->damage);456 457 if (target->isDead)458 {459 WorldMap::ObjectType flagType = WorldMap::OBJECT_NONE;460 if (target->hasBlueFlag)461 flagType = WorldMap::OBJECT_BLUE_FLAG;462 else if (target->hasRedFlag)463 flagType = WorldMap::OBJECT_RED_FLAG;464 465 if (flagType != WorldMap::OBJECT_NONE) {466 addObjectToMap(flagType, target->pos.x, target->pos.y, p->currentGame->getMap(), playersInGame, msgProcessor, sock, outputLog);467 }468 }469 470 serverMsg.type = MSG_TYPE_PLAYER;471 target->serialize(serverMsg.buffer);472 }473 else if (p->attackType == Player::ATTACK_RANGED)474 {475 cout << "Ranged attack" << endl;476 477 Projectile proj(p->pos.x, p->pos.y, p->targetPlayer, p->damage);478 p->currentGame->assignProjectileId(&proj);479 480 p->currentGame->addProjectile(proj);481 482 int x = p->pos.x;483 int y = p->pos.y;484 485 serverMsg.type = MSG_TYPE_PROJECTILE;486 memcpy(serverMsg.buffer, &proj.id, 4);487 memcpy(serverMsg.buffer+4, &x, 4);488 memcpy(serverMsg.buffer+8, &y, 4);489 memcpy(serverMsg.buffer+12, &p->targetPlayer, 4);490 }491 else492 cout << "Invalid attack type: " << it->second->attackType << endl;493 494 // broadcast either a PLAYER or PROJECTILE message495 cout << "Broadcasting player or projectile message" << endl;496 for (it2 = playersInGame.begin(); it2 != playersInGame.end(); it2++)497 {498 if (msgProcessor.sendMessage(&serverMsg, sock, &(it2->second->addr), &outputLog) < 0 )499 error("sendMessage");500 }501 cout << "Done broadcasting" << endl;502 540 } 503 541 } … … 508 546 // see if this can be moved inside the game class 509 547 // this method can be moved when I add a MessageProcessor to the Game class 510 map<string, Game*>::iterator itGames;511 Game* game;512 548 map<unsigned int, Projectile>::iterator itProj; 513 549 for (itGames = mapGames.begin(); itGames != mapGames.end(); itGames++) { … … 1009 1045 } 1010 1046 1011 Player* p = findPlayerByAddr(mapPlayers, from);1012 p->currentGame = g;1013 1014 1047 serverMsg.type = MSG_TYPE_JOIN_GAME_SUCCESS; 1015 1048 strcpy(serverMsg.buffer, gameName.c_str()); … … 1044 1077 } 1045 1078 1046 p->currentGame = g;1047 1048 1079 serverMsg.type = MSG_TYPE_JOIN_GAME_SUCCESS; 1049 1080 strcpy(serverMsg.buffer, gameName.c_str()); … … 1118 1149 Player* p = findPlayerByAddr(mapPlayers, from); 1119 1150 p->team = rand() % 2; // choose a random team (either 0 or 1) 1120 p->currentGame = g; // should have been done in JOIN_GAME, so not necessary1151 p->currentGame = g; 1121 1152 1122 1153 // tell the new player about all map objects
Note:
See TracChangeset
for help on using the changeset viewer.