[Opentnl-cvs] tnl/zap CTFGame.cpp,1.2,1.3 game.cpp,1.2,1.3 game.h,1.2,1.3 gameConnection.cpp,1.2,1.3
Brought to you by:
mark_frohnmayer,
s_alanet
From: Ben G. <s_a...@us...> - 2004-04-20 19:26:02
|
Update of /cvsroot/opentnl/tnl/zap In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3186/zap Modified Files: CTFGame.cpp game.cpp game.h gameConnection.cpp gameType.cpp item.cpp moveObject.cpp projectile.cpp sfx.cpp sfx.h ship.cpp teleporter.cpp Log Message: Assorted fixes and cleanups. Team chat works now. Fixed messed up linebreaks. Redid sound engine. Index: moveObject.cpp =================================================================== RCS file: /cvsroot/opentnl/tnl/zap/moveObject.cpp,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** moveObject.cpp 20 Apr 2004 18:55:58 -0000 1.3 --- moveObject.cpp 20 Apr 2004 19:25:48 -0000 1.4 *************** *** 299,304 **** { // Make a noise... ! //SFXHandle h = new SFXObject(SFXBounceWall, collisionPoint, Point()); ! //h->play(); Color bumpC(scale/3, scale/3, scale); --- 299,303 ---- { // Make a noise... ! SFXObject::play(SFXBounceWall, collisionPoint, Point()); Color bumpC(scale/3, scale/3, scale); *************** *** 340,346 **** shipHit->mMoveState[stateIndex].vel += collisionVector * (v2f - v2i); ! //SFXHandle h = new SFXObject(SFXBounceObject, shipHit->mMoveState[stateIndex].pos, Point()); ! //h->play(); ! } --- 339,343 ---- shipHit->mMoveState[stateIndex].vel += collisionVector * (v2f - v2i); ! SFXObject::play(SFXBounceObject, shipHit->mMoveState[stateIndex].pos, Point()); } Index: gameType.cpp =================================================================== RCS file: /cvsroot/opentnl/tnl/zap/gameType.cpp,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** gameType.cpp 20 Apr 2004 18:40:19 -0000 1.2 --- gameType.cpp 20 Apr 2004 19:25:48 -0000 1.3 *************** *** 1,278 **** ! //----------------------------------------------------------------------------------- ! // ! // Torque Network Library - ZAP example multiplayer vector graphics space game ! // Copyright (C) 2004 GarageGames.com, Inc. ! // For more information see http://www.opentnl.org ! // ! // This program is free software; you can redistribute it and/or modify ! // it under the terms of the GNU General Public License as published by ! // the Free Software Foundation; either version 2 of the License, or ! // (at your option) any later version. ! // ! // For use in products that are not compatible with the terms of the GNU ! // General Public License, alternative licensing options are available ! // from GarageGames.com. ! // ! // This program is distributed in the hope that it will be useful, ! // but WITHOUT ANY WARRANTY; without even the implied warranty of ! // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! // GNU General Public License for more details. ! // ! // You should have received a copy of the GNU General Public License ! // along with this program; if not, write to the Free Software ! // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! // ! //------------------------------------------------------------------------------------ ! ! #include "gameType.h" ! #include "ship.h" ! #include "UIGame.h" ! #include "gameNetInterface.h" ! ! namespace Zap ! { ! ! TNL_IMPLEMENT_NETOBJECT(GameType); ! ! GameType::GameType() ! { ! mNetFlags.set(Ghostable); ! } ! ! void GameType::processArguments(S32 argc, const char **argv) ! { ! ! } ! ! void GameType::onAddedToGame(Game *theGame) ! { ! theGame->setGameType(this); ! setInterface(theGame->getNetInterface()); ! if(!isGhost()) ! setScopeAlways(); ! } ! ! bool GameType::processLevelItem(S32 argc, const char **argv) ! { ! if(!stricmp(argv[0], "Team")) ! { ! if(argc < 5) ! return false; ! Team t; ! t.numPlayers = 0; ! ! t.name.set(argv[1]); ! t.color.read(argv + 2); ! mTeams.push_back(t); ! } ! else if(!stricmp(argv[0], "Spawn")) ! { ! if(argc < 4) ! return false; ! S32 teamIndex = atoi(argv[1]); ! Point p; ! p.read(argv + 2); ! p *= getGame()->getGridSize(); ! if(teamIndex >= 0 && teamIndex < mTeams.size()) ! mTeams[teamIndex].spawnPoints.push_back(p); ! } ! else ! return false; ! return true; ! } ! ! S32 GameType::findClientIndexByConnection(GameConnection *theConnection) ! { ! for(S32 clientIndex = 0; clientIndex < mClientList.size(); clientIndex++) ! if(mClientList[clientIndex].clientConnection == theConnection) ! return clientIndex; ! return -1; ! } ! ! S32 GameType::findClientIndexById(U32 clientId) ! { ! for(S32 clientIndex = 0; clientIndex < mClientList.size(); clientIndex++) ! if(mClientList[clientIndex].clientId == clientId) ! return clientIndex; ! return -1; ! } ! ! void GameType::spawnShip(GameConnection *theClient) ! { ! S32 clientIndex = findClientIndexByConnection(theClient); ! S32 teamIndex = mClientList[clientIndex].teamId; ! ! Point spawnPoint; ! S32 spawnIndex = Random::readI() % mTeams[teamIndex].spawnPoints.size(); ! spawnPoint = mTeams[teamIndex].spawnPoints[spawnIndex]; ! ! Ship *newShip = new Ship(spawnPoint, mTeams[teamIndex].color); ! newShip->addToGame(getGame()); ! theClient->setControlObject(newShip); ! } ! ! void GameType::serverAddClient(GameConnection *theClient) ! { ! ClientRef cref; ! cref.clientId = theClient->mClientId; ! cref.name = theClient->playerName; ! ! cref.clientConnection = theClient; ! U32 minPlayers = mTeams[0].numPlayers; ! S32 minTeamIndex = 0; ! for(S32 i = 1; i < mTeams.size(); i++) ! { ! if(mTeams[i].numPlayers < minPlayers) ! { ! minTeamIndex = i; ! minPlayers = mTeams[i].numPlayers; ! } ! } ! cref.teamId = minTeamIndex; ! mClientList.push_back(cref); ! ! mTeams[cref.teamId].numPlayers++; ! ! s2cAddClient(cref.clientId, cref.name, false); ! s2cClientJoinedTeam(cref.clientId, cref.teamId); ! spawnShip(theClient); ! } ! ! void GameType::controlObjectForClientKilled(GameConnection *theClient) ! { ! spawnShip(theClient); ! } ! ! void GameType::addClientGameMenuOptions(Vector<const char *> &menuOptions) ! { ! if(mTeams.size() > 1) ! menuOptions.push_back("CHANGE TEAMS"); ! } ! ! void GameType::processClientGameMenuOption(U32 index) ! { ! if(index == 0) ! c2sChangeTeams(); ! } ! ! TNL_IMPLEMENT_NETOBJECT_RPC(GameType, s2cAddClient, (U32 id, StringTableEntry name, bool isMyClient), ! NetClassGroupGameMask, RPCGuaranteedOrdered, RPCToGhost, 0) ! { ! ClientRef cref; ! cref.clientId = id; ! cref.name = name; ! cref.teamId = 0; ! mClientList.push_back(cref); ! ! if(isMyClient) ! mThisClientId = id; ! gGameUserInterface.displayMessage(Color(0.6f, 0.6f, 0.8f), "%s joined the game.", name.getString()); ! } ! ! void GameType::serverRemoveClient(GameConnection *theClient) ! { ! S32 clientIndex = findClientIndexByConnection(theClient); ! mTeams[mClientList[clientIndex].teamId].numPlayers--; ! mClientList.erase(clientIndex); ! ! GameObject *theControlObject = theClient->getControlObject(); ! if(theControlObject) ! delete theControlObject; ! ! s2cRemoveClient(theClient->mClientId); ! } ! ! TNL_IMPLEMENT_NETOBJECT_RPC(GameType, s2cRemoveClient, (U32 id), ! NetClassGroupGameMask, RPCGuaranteedOrdered, RPCToGhost, 0) ! { ! S32 clientIndex = findClientIndexById(id); ! mClientList.erase(clientIndex); ! } ! ! TNL_IMPLEMENT_NETOBJECT_RPC(GameType, s2cAddTeam, (StringTableEntry teamName, F32 r, F32 g, F32 b), ! NetClassGroupGameMask, RPCGuaranteedOrdered, RPCToGhost, 0) ! { ! Team team; ! team.name = teamName; ! team.color.r = r; ! team.color.g = g; ! team.color.b = b; ! mTeams.push_back(team); ! } ! ! TNL_IMPLEMENT_NETOBJECT_RPC(GameType, s2cSetTeamScore, (U32 teamIndex, U32 score), ! NetClassGroupGameMask, RPCGuaranteedOrdered, RPCToGhost, 0) ! { ! mTeams[teamIndex].score = score; ! } ! ! TNL_IMPLEMENT_NETOBJECT_RPC(GameType, s2cClientJoinedTeam, (U32 clientId, U32 teamIndex), ! NetClassGroupGameMask, RPCGuaranteedOrdered, RPCToGhost, 0) ! { ! S32 clientIndex = findClientIndexById(clientId); ! mClientList[clientIndex].teamId = teamIndex; ! gGameUserInterface.displayMessage(Color(0.6f, 0.6f, 0.8f), "%s joined team %s.", mClientList[clientIndex].name.getString(), mTeams[teamIndex].name.getString()); ! } ! ! TNL_IMPLEMENT_NETOBJECT_RPC(GameType, c2sChangeTeams, (), ! NetClassGroupGameMask, RPCGuaranteedOrdered, RPCToGhostParent, 0) ! { ! if(mTeams.size() <= 1) ! return; ! ! GameConnection *source = (GameConnection *) NetObject::getRPCSourceConnection(); ! S32 clientIndex = findClientIndexByConnection(source); ! ! // destroy the old ship ! GameObject *co = source->getControlObject(); ! if(co) ! getGame()->deleteObject(co, 0); ! ! U32 newTeamId = (mClientList[clientIndex].teamId + 1) % mTeams.size(); ! mClientList[clientIndex].teamId = newTeamId; ! s2cClientJoinedTeam(mClientList[clientIndex].clientId, newTeamId); ! spawnShip(source); ! } ! ! void GameType::onGhostAvailable(GhostConnection *theConnection) ! { ! NetObject::setRPCDestConnection(theConnection); ! ! for(S32 i = 0; i < mTeams.size(); i++) ! { ! s2cAddTeam(mTeams[i].name, mTeams[i].color.r, mTeams[i].color.g, mTeams[i].color.b); ! s2cSetTeamScore(i, mTeams[i].score); ! } ! ! // add all the client and team information ! for(S32 i = 0; i < mClientList.size(); i++) ! { ! s2cAddClient(mClientList[i].clientId, mClientList[i].name, mClientList[i].clientConnection == theConnection); ! s2cClientJoinedTeam(mClientList[i].clientId, mClientList[i].teamId); ! } ! NetObject::setRPCDestConnection(NULL); ! } ! ! TNL_IMPLEMENT_NETOBJECT_RPC(GameType, c2sSendChat, (bool global, const char *message), ! NetClassGroupGameMask, RPCGuaranteedOrdered, RPCToGhostParent, 0) ! { ! GameConnection *source = (GameConnection *) getRPCSourceConnection(); ! ! RefPtr<NetEvent> theEvent = TNL_RPC_CONSTRUCT_NETEVENT(this, ! s2cDisplayChatMessage, (global, source->playerName, message)); ! for(S32 i = 0; i < mClientList.size(); i++) ! mClientList[i].clientConnection->postNetEvent(theEvent); ! } ! ! extern Color gGlobalChatColor; ! extern Color gTeamChatColor; ! ! TNL_IMPLEMENT_NETOBJECT_RPC(GameType, s2cDisplayChatMessage, (bool global, StringTableEntry clientName, const char *message), ! NetClassGroupGameMask, RPCGuaranteedOrdered, RPCToGhost, 0) ! { ! Color theColor = global ? gGlobalChatColor : gTeamChatColor; ! ! gGameUserInterface.displayMessage(theColor, "%s: %s", clientName.getString(), message); ! } ! }; \ No newline at end of file --- 1,289 ---- ! //----------------------------------------------------------------------------------- ! // ! // Torque Network Library - ZAP example multiplayer vector graphics space game ! // Copyright (C) 2004 GarageGames.com, Inc. ! // For more information see http://www.opentnl.org ! // ! // This program is free software; you can redistribute it and/or modify ! // it under the terms of the GNU General Public License as published by ! // the Free Software Foundation; either version 2 of the License, or ! // (at your option) any later version. ! // ! // For use in products that are not compatible with the terms of the GNU ! // General Public License, alternative licensing options are available ! // from GarageGames.com. ! // ! // This program is distributed in the hope that it will be useful, ! // but WITHOUT ANY WARRANTY; without even the implied warranty of ! // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! // GNU General Public License for more details. ! // ! // You should have received a copy of the GNU General Public License ! // along with this program; if not, write to the Free Software ! // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! // ! //------------------------------------------------------------------------------------ ! ! #include "gameType.h" ! #include "ship.h" ! #include "UIGame.h" ! #include "gameNetInterface.h" ! ! namespace Zap ! { ! ! TNL_IMPLEMENT_NETOBJECT(GameType); ! ! GameType::GameType() ! { ! mNetFlags.set(Ghostable); ! } ! ! void GameType::processArguments(S32 argc, const char **argv) ! { ! ! } ! ! void GameType::onAddedToGame(Game *theGame) ! { ! theGame->setGameType(this); ! setInterface(theGame->getNetInterface()); ! if(!isGhost()) ! setScopeAlways(); ! } ! ! bool GameType::processLevelItem(S32 argc, const char **argv) ! { ! if(!stricmp(argv[0], "Team")) ! { ! if(argc < 5) ! return false; ! Team t; ! t.numPlayers = 0; ! ! t.name.set(argv[1]); ! t.color.read(argv + 2); ! mTeams.push_back(t); ! } ! else if(!stricmp(argv[0], "Spawn")) ! { ! if(argc < 4) ! return false; ! S32 teamIndex = atoi(argv[1]); ! Point p; ! p.read(argv + 2); ! p *= getGame()->getGridSize(); ! if(teamIndex >= 0 && teamIndex < mTeams.size()) ! mTeams[teamIndex].spawnPoints.push_back(p); ! } ! else ! return false; ! return true; ! } ! ! S32 GameType::findClientIndexByConnection(GameConnection *theConnection) ! { ! for(S32 clientIndex = 0; clientIndex < mClientList.size(); clientIndex++) ! if(mClientList[clientIndex].clientConnection == theConnection) ! return clientIndex; ! return -1; ! } ! ! S32 GameType::findClientIndexById(U32 clientId) ! { ! for(S32 clientIndex = 0; clientIndex < mClientList.size(); clientIndex++) ! if(mClientList[clientIndex].clientId == clientId) ! return clientIndex; ! return -1; ! } ! ! void GameType::spawnShip(GameConnection *theClient) ! { ! S32 clientIndex = findClientIndexByConnection(theClient); ! S32 teamIndex = mClientList[clientIndex].teamId; ! ! Point spawnPoint; ! S32 spawnIndex = Random::readI() % mTeams[teamIndex].spawnPoints.size(); ! spawnPoint = mTeams[teamIndex].spawnPoints[spawnIndex]; ! ! Ship *newShip = new Ship(spawnPoint, mTeams[teamIndex].color); ! newShip->addToGame(getGame()); ! theClient->setControlObject(newShip); ! } ! ! void GameType::serverAddClient(GameConnection *theClient) ! { ! ClientRef cref; ! cref.clientId = theClient->mClientId; ! cref.name = theClient->playerName; ! ! cref.clientConnection = theClient; ! U32 minPlayers = mTeams[0].numPlayers; ! S32 minTeamIndex = 0; ! for(S32 i = 1; i < mTeams.size(); i++) ! { ! if(mTeams[i].numPlayers < minPlayers) ! { ! minTeamIndex = i; ! minPlayers = mTeams[i].numPlayers; ! } ! } ! cref.teamId = minTeamIndex; ! mClientList.push_back(cref); ! ! mTeams[cref.teamId].numPlayers++; ! ! s2cAddClient(cref.clientId, cref.name, false); ! s2cClientJoinedTeam(cref.clientId, cref.teamId); ! spawnShip(theClient); ! } ! ! void GameType::controlObjectForClientKilled(GameConnection *theClient) ! { ! spawnShip(theClient); ! } ! ! void GameType::addClientGameMenuOptions(Vector<const char *> &menuOptions) ! { ! if(mTeams.size() > 1) ! menuOptions.push_back("CHANGE TEAMS"); ! } ! ! void GameType::processClientGameMenuOption(U32 index) ! { ! if(index == 0) ! c2sChangeTeams(); ! } ! ! TNL_IMPLEMENT_NETOBJECT_RPC(GameType, s2cAddClient, (U32 id, StringTableEntry name, bool isMyClient), ! NetClassGroupGameMask, RPCGuaranteedOrdered, RPCToGhost, 0) ! { ! ClientRef cref; ! cref.clientId = id; ! cref.name = name; ! cref.teamId = 0; ! mClientList.push_back(cref); ! ! if(isMyClient) ! mThisClientId = id; ! gGameUserInterface.displayMessage(Color(0.6f, 0.6f, 0.8f), "%s joined the game.", name.getString()); ! } ! ! void GameType::serverRemoveClient(GameConnection *theClient) ! { ! S32 clientIndex = findClientIndexByConnection(theClient); ! mTeams[mClientList[clientIndex].teamId].numPlayers--; ! mClientList.erase(clientIndex); ! ! GameObject *theControlObject = theClient->getControlObject(); ! if(theControlObject) ! delete theControlObject; ! ! s2cRemoveClient(theClient->mClientId); ! } ! ! TNL_IMPLEMENT_NETOBJECT_RPC(GameType, s2cRemoveClient, (U32 id), ! NetClassGroupGameMask, RPCGuaranteedOrdered, RPCToGhost, 0) ! { ! S32 clientIndex = findClientIndexById(id); ! mClientList.erase(clientIndex); ! } ! ! TNL_IMPLEMENT_NETOBJECT_RPC(GameType, s2cAddTeam, (StringTableEntry teamName, F32 r, F32 g, F32 b), ! NetClassGroupGameMask, RPCGuaranteedOrdered, RPCToGhost, 0) ! { ! Team team; ! team.name = teamName; ! team.color.r = r; ! team.color.g = g; ! team.color.b = b; ! mTeams.push_back(team); ! } ! ! TNL_IMPLEMENT_NETOBJECT_RPC(GameType, s2cSetTeamScore, (U32 teamIndex, U32 score), ! NetClassGroupGameMask, RPCGuaranteedOrdered, RPCToGhost, 0) ! { ! mTeams[teamIndex].score = score; ! } ! ! TNL_IMPLEMENT_NETOBJECT_RPC(GameType, s2cClientJoinedTeam, (U32 clientId, U32 teamIndex), ! NetClassGroupGameMask, RPCGuaranteedOrdered, RPCToGhost, 0) ! { ! S32 clientIndex = findClientIndexById(clientId); ! mClientList[clientIndex].teamId = teamIndex; ! gGameUserInterface.displayMessage(Color(0.6f, 0.6f, 0.8f), "%s joined team %s.", mClientList[clientIndex].name.getString(), mTeams[teamIndex].name.getString()); ! } ! ! TNL_IMPLEMENT_NETOBJECT_RPC(GameType, c2sChangeTeams, (), ! NetClassGroupGameMask, RPCGuaranteedOrdered, RPCToGhostParent, 0) ! { ! if(mTeams.size() <= 1) ! return; ! ! GameConnection *source = (GameConnection *) NetObject::getRPCSourceConnection(); ! S32 clientIndex = findClientIndexByConnection(source); ! ! // destroy the old ship ! GameObject *co = source->getControlObject(); ! if(co) ! getGame()->deleteObject(co, 0); ! ! U32 newTeamId = (mClientList[clientIndex].teamId + 1) % mTeams.size(); ! mClientList[clientIndex].teamId = newTeamId; ! s2cClientJoinedTeam(mClientList[clientIndex].clientId, newTeamId); ! spawnShip(source); ! } ! ! void GameType::onGhostAvailable(GhostConnection *theConnection) ! { ! NetObject::setRPCDestConnection(theConnection); ! ! for(S32 i = 0; i < mTeams.size(); i++) ! { ! s2cAddTeam(mTeams[i].name, mTeams[i].color.r, mTeams[i].color.g, mTeams[i].color.b); ! s2cSetTeamScore(i, mTeams[i].score); ! } ! ! // add all the client and team information ! for(S32 i = 0; i < mClientList.size(); i++) ! { ! s2cAddClient(mClientList[i].clientId, mClientList[i].name, mClientList[i].clientConnection == theConnection); ! s2cClientJoinedTeam(mClientList[i].clientId, mClientList[i].teamId); ! } ! NetObject::setRPCDestConnection(NULL); ! } ! ! TNL_IMPLEMENT_NETOBJECT_RPC(GameType, c2sSendChat, (bool global, const char *message), ! NetClassGroupGameMask, RPCGuaranteedOrdered, RPCToGhostParent, 0) ! { ! GameConnection *source = (GameConnection *) getRPCSourceConnection(); ! ! RefPtr<NetEvent> theEvent = TNL_RPC_CONSTRUCT_NETEVENT(this, ! s2cDisplayChatMessage, (global, source->playerName, message)); ! ! S32 teamId = 0; ! ! if(!global) ! for(S32 i = 0; i < mClientList.size(); i++) ! if(mClientList[i].clientId == source->mClientId) ! teamId = mClientList[i].teamId; ! ! for(S32 i = 0; i < mClientList.size(); i++) ! { ! if(global || mClientList[i].teamId == teamId) ! mClientList[i].clientConnection->postNetEvent(theEvent); ! } ! } ! ! extern Color gGlobalChatColor; ! extern Color gTeamChatColor; ! ! TNL_IMPLEMENT_NETOBJECT_RPC(GameType, s2cDisplayChatMessage, (bool global, StringTableEntry clientName, const char *message), ! NetClassGroupGameMask, RPCGuaranteedOrdered, RPCToGhost, 0) ! { ! Color theColor = global ? gGlobalChatColor : gTeamChatColor; ! ! gGameUserInterface.displayMessage(theColor, "%s: %s", clientName.getString(), message); ! } ! }; \ No newline at end of file Index: projectile.cpp =================================================================== RCS file: /cvsroot/opentnl/tnl/zap/projectile.cpp,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** projectile.cpp 20 Apr 2004 18:40:19 -0000 1.2 --- projectile.cpp 20 Apr 2004 19:25:48 -0000 1.3 *************** *** 1,223 **** ! //----------------------------------------------------------------------------------- ! // ! // Torque Network Library - ZAP example multiplayer vector graphics space game ! // Copyright (C) 2004 GarageGames.com, Inc. ! // For more information see http://www.opentnl.org ! // ! // This program is free software; you can redistribute it and/or modify ! // it under the terms of the GNU General Public License as published by ! // the Free Software Foundation; either version 2 of the License, or ! // (at your option) any later version. ! // ! // For use in products that are not compatible with the terms of the GNU ! // General Public License, alternative licensing options are available ! // from GarageGames.com. ! // ! // This program is distributed in the hope that it will be useful, ! // but WITHOUT ANY WARRANTY; without even the implied warranty of ! // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! // GNU General Public License for more details. ! // ! // You should have received a copy of the GNU General Public License ! // along with this program; if not, write to the Free Software ! // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! // ! //------------------------------------------------------------------------------------ ! ! #include "projectile.h" ! #include "ship.h" ! #include "sparkManager.h" ! #include "sfx.h" ! ! #include "glutInclude.h" ! ! namespace Zap ! { ! ! TNL_IMPLEMENT_NETOBJECT(Projectile); ! ! ! Projectile::Projectile(Point p, Point v, U32 t, Ship *shooter) ! { ! mNetFlags.set(Ghostable); ! pos = p; ! velocity = v; ! liveTime = t; ! collided = false; ! mShooter = shooter; ! } ! ! U32 Projectile::packUpdate(GhostConnection *connection, U32 updateMask, BitStream *stream) ! { ! stream->write(pos.x); ! stream->write(pos.y); ! stream->write(velocity.x); ! stream->write(velocity.y); ! S32 index = -1; ! if(mShooter.isValid()) ! index = connection->getGhostIndex(mShooter); ! if(stream->writeFlag(index != -1)) ! stream->writeInt(index, GhostConnection::GhostIdBitSize); ! ! return 0; ! } ! ! void Projectile::unpackUpdate(GhostConnection *connection, BitStream *stream) ! { ! stream->read(&pos.x); ! stream->read(&pos.y); ! stream->read(&velocity.x); ! stream->read(&velocity.y); ! ! if(stream->readFlag()) ! mShooter = (Ship *) connection->resolveGhost(stream->readInt(GhostConnection::GhostIdBitSize)); ! ! Rect newExtent(pos,pos); ! setExtent(newExtent); ! process(connection->getOneWayTime()); ! ! SFXObject::play(0, pos, velocity); ! } ! ! enum { ! NumSparkColors = 4, ! }; ! ! Color SparkColors[NumSparkColors] = { ! Color(1, 0, 1), ! Color(1, 1, 1), ! Color(0, 0, 1), ! Color(1, 0, 0), ! }; ! void Projectile::handleCollision(GameObject *hitObject, Point collisionPoint) ! { ! collided = true; ! ! if(!isGhost()) ! { ! DamageInfo theInfo; ! theInfo.collisionPoint = collisionPoint; ! theInfo.damageAmount = 1; ! theInfo.damageType = 0; ! theInfo.damagingObject = this; ! theInfo.impulseVector = velocity; ! ! hitObject->damageObject(&theInfo); ! } ! liveTime = 0; ! ! // Do some particle spew... ! if(isGhost()) ! { ! SparkManager::emitExplosion(collisionPoint, 0.4, SparkColors, NumSparkColors); ! SFXObject::play(SFXPhaserImpact, pos, velocity); ! } ! } ! ! void Projectile::process(U32 deltaT) ! { ! if(collided) ! return; ! ! Point endPos = pos + velocity * deltaT * 0.001; ! static Vector<GameObject *> disableVector; ! ! Rect queryRect(pos, endPos); ! ! float collisionTime; ! disableVector.clear(); ! ! if(mShooter.isValid()) ! { ! disableVector.push_back(mShooter); ! mShooter->disableCollision(); ! } ! ! GameObject *hitObject; ! for(;;) ! { ! hitObject = findObjectLOS(MoveableType | BarrierType, MoveObject::RenderState, pos, endPos, collisionTime); ! if(!hitObject || hitObject->collide(this)) ! break; ! disableVector.push_back(hitObject); ! hitObject->disableCollision(); ! } ! ! for(S32 i = 0; i < disableVector.size(); i++) ! disableVector[i]->enableCollision(); ! ! if(hitObject) ! { ! Point collisionPoint = pos + (endPos - pos) * collisionTime; ! handleCollision(hitObject, collisionPoint); ! } ! else ! pos = endPos; ! ! Rect newExtent(pos,pos); ! setExtent(newExtent); ! } ! ! void Projectile::processServer(U32 deltaT) ! { ! process(deltaT); ! if(liveTime) ! { ! if(liveTime <= deltaT) ! { ! getGame()->deleteObject(this, 500); ! liveTime = 0; ! } ! else ! liveTime -= deltaT; ! } ! } ! ! void Projectile::processClient(U32 deltaT) ! { ! process(deltaT); ! liveTime += deltaT; ! } ! ! void Projectile::render() ! { ! if(collided) ! return; ! ! glColor3f(1,0,0.5); ! glPushMatrix(); ! glTranslatef(pos.x, pos.y, 0); ! ! glPushMatrix(); ! glRotatef((liveTime % 720) * 0.5, 0, 0, 1); ! ! glBegin(GL_LINE_LOOP); ! glVertex2f(-2, 2); ! glVertex2f(0, 6); ! glVertex2f(2, 2); ! glVertex2f(6, 0); ! glVertex2f(2, -2); ! glVertex2f(0, -6); ! glVertex2f(-2, -2); ! glVertex2f(-6, 0); ! glEnd(); ! ! glPopMatrix(); ! ! glRotatef(180 - (liveTime % 360), 0, 0, 1); ! glColor3f(0.5,0,1); ! glBegin(GL_LINE_LOOP); ! glVertex2f(-2, 2); ! glVertex2f(0, 8); ! glVertex2f(2, 2); ! glVertex2f(8, 0); ! glVertex2f(2, -2); ! glVertex2f(0, -8); ! glVertex2f(-2, -2); ! glVertex2f(-8, 0); ! glEnd(); ! ! glPopMatrix(); ! } ! }; \ No newline at end of file --- 1,223 ---- ! //----------------------------------------------------------------------------------- ! // ! // Torque Network Library - ZAP example multiplayer vector graphics space game ! // Copyright (C) 2004 GarageGames.com, Inc. ! // For more information see http://www.opentnl.org ! // ! // This program is free software; you can redistribute it and/or modify ! // it under the terms of the GNU General Public License as published by ! // the Free Software Foundation; either version 2 of the License, or ! // (at your option) any later version. ! // ! // For use in products that are not compatible with the terms of the GNU ! // General Public License, alternative licensing options are available ! // from GarageGames.com. ! // ! // This program is distributed in the hope that it will be useful, ! // but WITHOUT ANY WARRANTY; without even the implied warranty of ! // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! // GNU General Public License for more details. ! // ! // You should have received a copy of the GNU General Public License ! // along with this program; if not, write to the Free Software ! // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! // ! //------------------------------------------------------------------------------------ ! ! #include "projectile.h" ! #include "ship.h" ! #include "sparkManager.h" ! #include "sfx.h" ! ! #include "glutInclude.h" ! ! namespace Zap ! { ! ! TNL_IMPLEMENT_NETOBJECT(Projectile); ! ! ! Projectile::Projectile(Point p, Point v, U32 t, Ship *shooter) ! { ! mNetFlags.set(Ghostable); ! pos = p; ! velocity = v; ! liveTime = t; ! collided = false; ! mShooter = shooter; ! } ! ! U32 Projectile::packUpdate(GhostConnection *connection, U32 updateMask, BitStream *stream) ! { ! stream->write(pos.x); ! stream->write(pos.y); ! stream->write(velocity.x); ! stream->write(velocity.y); ! S32 index = -1; ! if(mShooter.isValid()) ! index = connection->getGhostIndex(mShooter); ! if(stream->writeFlag(index != -1)) ! stream->writeInt(index, GhostConnection::GhostIdBitSize); ! ! return 0; ! } ! ! void Projectile::unpackUpdate(GhostConnection *connection, BitStream *stream) ! { ! stream->read(&pos.x); ! stream->read(&pos.y); ! stream->read(&velocity.x); ! stream->read(&velocity.y); ! ! if(stream->readFlag()) ! mShooter = (Ship *) connection->resolveGhost(stream->readInt(GhostConnection::GhostIdBitSize)); ! ! Rect newExtent(pos,pos); ! setExtent(newExtent); ! process(connection->getOneWayTime()); ! ! SFXObject::play(0, pos, velocity); ! } ! ! enum { ! NumSparkColors = 4, ! }; ! ! Color SparkColors[NumSparkColors] = { ! Color(1, 0, 1), ! Color(1, 1, 1), ! Color(0, 0, 1), ! Color(1, 0, 0), ! }; ! void Projectile::handleCollision(GameObject *hitObject, Point collisionPoint) ! { ! collided = true; ! ! if(!isGhost()) ! { ! DamageInfo theInfo; ! theInfo.collisionPoint = collisionPoint; ! theInfo.damageAmount = 1; ! theInfo.damageType = 0; ! theInfo.damagingObject = this; ! theInfo.impulseVector = velocity; ! ! hitObject->damageObject(&theInfo); ! } ! liveTime = 0; ! ! // Do some particle spew... ! if(isGhost()) ! { ! SparkManager::emitExplosion(collisionPoint, 0.4, SparkColors, NumSparkColors); ! SFXObject::play(SFXPhaserImpact, pos, velocity); ! } ! } ! ! void Projectile::process(U32 deltaT) ! { ! if(collided) ! return; ! ! Point endPos = pos + velocity * deltaT * 0.001; ! static Vector<GameObject *> disableVector; ! ! Rect queryRect(pos, endPos); ! ! float collisionTime; ! disableVector.clear(); ! ! if(mShooter.isValid()) ! { ! disableVector.push_back(mShooter); ! mShooter->disableCollision(); ! } ! ! GameObject *hitObject; ! for(;;) ! { ! hitObject = findObjectLOS(MoveableType | BarrierType, MoveObject::RenderState, pos, endPos, collisionTime); ! if(!hitObject || hitObject->collide(this)) ! break; ! disableVector.push_back(hitObject); ! hitObject->disableCollision(); ! } ! ! for(S32 i = 0; i < disableVector.size(); i++) ! disableVector[i]->enableCollision(); ! ! if(hitObject) ! { ! Point collisionPoint = pos + (endPos - pos) * collisionTime; ! handleCollision(hitObject, collisionPoint); ! } ! else ! pos = endPos; ! ! Rect newExtent(pos,pos); ! setExtent(newExtent); ! } ! ! void Projectile::processServer(U32 deltaT) ! { ! process(deltaT); ! if(liveTime) ! { ! if(liveTime <= deltaT) ! { ! getGame()->deleteObject(this, 500); ! liveTime = 0; ! } ! else ! liveTime -= deltaT; ! } ! } ! ! void Projectile::processClient(U32 deltaT) ! { ! process(deltaT); ! liveTime += deltaT; ! } ! ! void Projectile::render() ! { ! if(collided) ! return; ! ! glColor3f(1,0,0.5); ! glPushMatrix(); ! glTranslatef(pos.x, pos.y, 0); ! ! glPushMatrix(); ! glRotatef((liveTime % 720) * 0.5, 0, 0, 1); ! ! glBegin(GL_LINE_LOOP); ! glVertex2f(-2, 2); ! glVertex2f(0, 6); ! glVertex2f(2, 2); ! glVertex2f(6, 0); ! glVertex2f(2, -2); ! glVertex2f(0, -6); ! glVertex2f(-2, -2); ! glVertex2f(-6, 0); ! glEnd(); ! ! glPopMatrix(); ! ! glRotatef(180 - (liveTime % 360), 0, 0, 1); ! glColor3f(0.5,0,1); ! glBegin(GL_LINE_LOOP); ! glVertex2f(-2, 2); ! glVertex2f(0, 8); ! glVertex2f(2, 2); ! glVertex2f(8, 0); ! glVertex2f(2, -2); ! glVertex2f(0, -8); ! glVertex2f(-2, -2); ! glVertex2f(-8, 0); ! glEnd(); ! ! glPopMatrix(); ! } ! }; \ No newline at end of file Index: sfx.cpp =================================================================== RCS file: /cvsroot/opentnl/tnl/zap/sfx.cpp,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** sfx.cpp 20 Apr 2004 18:40:19 -0000 1.4 --- sfx.cpp 20 Apr 2004 19:25:49 -0000 1.5 *************** *** 1,454 **** ! //----------------------------------------------------------------------------------- ! // ! // Torque Network Library - ZAP example multiplayer vector graphics space game ! // Copyright (C) 2004 GarageGames.com, Inc. ! // For more information see http://www.opentnl.org ! // ! // This program is free software; you can redistribute it and/or modify ! // it under the terms of the GNU General Public License as published by ! // the Free Software Foundation; either version 2 of the License, or ! // (at your option) any later version. ! // ! // For use in products that are not compatible with the terms of the GNU ! // General Public License, alternative licensing options are available ! // from GarageGames.com. ! // ! // This program is distributed in the hope that it will be useful, ! // but WITHOUT ANY WARRANTY; without even the implied warranty of ! // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! // GNU General Public License for more details. ! // ! // You should have received a copy of the GNU General Public License ! // along with this program; if not, write to the Free Software ! // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! // ! //------------------------------------------------------------------------------------ ! ! #include "sfx.h" ! #include "tnl.h" ! #include "tnlLog.h" ! ! #if defined (TNL_OS_WIN32) ! ! #include "alInclude.h" ! ! using namespace TNL; ! ! namespace Zap ! { ! ! static SFXProfile gSFXProfiles[] = { ! { "phaser.wav", false, 0.45f, false, 150, 600 }, ! { "phaser_impact.wav", false, 0.7f, false, 150, 600 }, ! { "ship_explode.wav", false, 1.0, false, 300, 1000 }, ! { "flag_capture.wav", true, 0.45f, false, 0, 0 }, ! { "flag_drop.wav", true, 0.45f, false, 0, 0 }, ! { "flag_return.wav", true, 0.45f, false, 0, 0 }, ! { "flag_snatch.wav", true, 0.45f, false, 0, 0 }, ! { "teleport_in.wav", false, 1.0, false, 200, 500 }, ! { "teleport_out.wav", false, 1.0, false, 200, 500 }, ! { NULL, false, 0, false, 0, 0 }, ! }; ! ! static ALCdevice *gDevice = NULL; ! static ALCcontext *gContext = NULL; ! static bool gSFXValid = false; ! ! enum { ! NumSources = 16, ! }; ! ! static ALuint gSources[NumSources]; ! static bool gSourceActive[NumSources]; ! Point SFXObject::mListenerPosition; ! Point SFXObject::mListenerVelocity; ! F32 SFXObject::mMaxDistance = 500; ! ! static ALuint gBuffers[NumSFXBuffers]; ! static Vector<SFXHandle> gPlayList; ! ! SFXObject::SFXObject(U32 profileIndex, F32 gain, Point position, Point velocity) ! { ! mSFXIndex = profileIndex; ! mProfile = gSFXProfiles + profileIndex; ! mGain = gain; ! mPosition = position; ! mVelocity = velocity; ! mSourceIndex = -1; ! mPriority = 0; ! } ! ! RefPtr<SFXObject> SFXObject::play(U32 profileIndex, F32 gain) ! { ! RefPtr<SFXObject> ret = new SFXObject(profileIndex, gain, Point(), Point()); ! ret->play(); ! return ret; ! } ! ! RefPtr<SFXObject> SFXObject::play(U32 profileIndex, Point position, Point velocity, F32 gain) ! { ! RefPtr<SFXObject> ret = new SFXObject(profileIndex, gain, position, velocity); ! ret->play(); ! return ret; ! } ! ! SFXObject::~SFXObject() ! { ! ! } ! ! void SFXObject::updateGain() ! { ! ALuint source = gSources[mSourceIndex]; ! F32 gain = mGain; ! ! if(!mProfile->isRelative) ! { ! F32 distance = (mListenerPosition - mPosition).len(); ! if(distance > mProfile->fullGainDistance) ! { ! if(distance < mProfile->zeroGainDistance) ! gain *= (mProfile->fullGainDistance - distance) / ! (mProfile->zeroGainDistance - mProfile->fullGainDistance); ! else ! gain = 0.0f; ! } ! else ! gain = 1.0f; ! } ! else ! gain = 1.0f; ! ! alSourcef(source, AL_GAIN, gain * mProfile->gainScale); ! } ! ! void SFXObject::updateMovementParams() ! { ! ALuint source = gSources[mSourceIndex]; ! if(mProfile->isRelative) ! { ! alSourcei(source, AL_SOURCE_RELATIVE, true); ! alSource3f(source, AL_POSITION, 0, 0, 0); ! //alSource3f(source, AL_VELOCITY, 0, 0, 0); ! } ! else ! { ! alSourcei(source, AL_SOURCE_RELATIVE, false); ! alSource3f(source, AL_POSITION, mPosition.x, mPosition.y, 0); ! //alSource3f(source, AL_VELOCITY, mVelocity.x, mVelocity.y, 0); ! } ! } ! ! void SFXObject::playOnSource() ! { ! ALuint source = gSources[mSourceIndex]; ! alSourceStop(source); ! alSourcei(source, AL_BUFFER, gBuffers[mSFXIndex]); ! alSourcei(source, AL_LOOPING, mProfile->isLooping); ! updateMovementParams(); ! ! updateGain(); ! alSourcePlay(source); ! } ! ! void SFXObject::setGain(F32 gain) ! { ! mGain = gain; ! if(mSourceIndex != -1) ! updateGain(); ! } ! ! void SFXObject::setMovementParams(Point position, Point velocity) ! { ! mPosition = position; ! mVelocity = velocity; ! if(mSourceIndex != -1) ! updateMovementParams(); ! } ! ! void SFXObject::play() ! { ! if(mSourceIndex != -1) ! return; ! else ! { ! // see if it's on the play list: ! S32 i; ! for(i = 0; i < gPlayList.size(); i++) ! if(gPlayList[i] == this) ! return; ! gPlayList.push_back(this); ! } ! } ! ! void SFXObject::stop() ! { ! // remove from the play list, if this sound is playing: ! if(mSourceIndex != -1) ! { ! alSourceStop(gSources[mSourceIndex]); ! mSourceIndex = -1; ! } ! for(S32 i = 0; i < gPlayList.size(); i++) ! { ! if(gPlayList[i] == this) ! { ! gPlayList.erase(i); ! return; ! } ! } ! } ! ! void SFXObject::init() ! { ! gDevice = alcOpenDevice((ALubyte *) "DirectSound3D"); ! if(!gDevice) ! { ! logprintf("Failed to intitialize OpenAL."); ! return; ! } ! ! static int contextData[][2] = ! { ! {ALC_FREQUENCY, 11025}, ! {0,0} // Indicate end of list... ! }; ! ! gContext = alcCreateContext(gDevice, (ALCint*)contextData); ! alcMakeContextCurrent(gContext); ! ! alGetError(); ! ! alDistanceModel(AL_NONE); ! ! // load up all the sound buffers ! alGenBuffers(NumSFXBuffers, gBuffers); ! ! if(alGetError() != AL_NO_ERROR) ! return; ! ! alGenSources(NumSources, gSources); ! ! for(U32 i = 0; i < NumSFXBuffers; i++) ! { ! if(!gSFXProfiles[i].fileName) ! break; ! ! ALsizei size,freq; ! ALenum format; ! ALvoid *data; ! ALboolean loop; ! ! alutLoadWAVFile((ALbyte *) gSFXProfiles[i].fileName, &format, &data, &size, &freq, &loop); ! if(alGetError() != AL_NO_ERROR) ! return; ! alBufferData(gBuffers[i], format, data, size, freq); ! alutUnloadWAV(format, data, size, freq); ! if(alGetError() != AL_NO_ERROR) ! return; ! } ! gSFXValid = true; ! } ! ! void SFXObject::process() ! { ! if(!gSFXValid) ! return; ! ! // ok, so we have a list of currently "playing" sounds, which is ! // unbounded in length, but only the top NumSources actually have sources ! // associtated with them. Sounds are prioritized on a 0-1 scale ! // based on type and distance. ! // Each time through the main loop, newly played sounds are placed ! // on the process list. When SFXProcess is called, any finished sounds ! // are retired from the list, and then it prioritizes and sorts all ! // the remaining sounds. For any sounds from 0 to NumSources that don't ! // have a current source, they grab one of the sources not used by the other ! // top sounds. At this point, any sound that is not looping, and is ! // not in the active top list is retired. ! ! // ok, look through all the currently playing sources and see which ! // ones need to be retired: ! ! for(S32 i = 0; i < NumSources; i++) ! { ! ALint state; ! alGetSourcei(gSources[i], AL_SOURCE_STATE, &state); ! gSourceActive[i] = state != AL_STOPPED && state != AL_INITIAL; ! } ! for(S32 i = 0; i < gPlayList.size(); ) ! { ! SFXHandle &s = gPlayList[i]; ! if(s->mSourceIndex != -1 && !gSourceActive[s->mSourceIndex]) ! { ! // this sound was playing; now it is stopped, ! // so remove it from the list. ! s->mSourceIndex = -1; ! gPlayList.erase_fast(i); ! } ! else ! { ! // compute a priority for this sound. ! if(!s->mProfile->isRelative) ! s->mPriority = (500 - (s->mPosition - mListenerPosition).len()) / 500.0f; ! else ! s->mPriority = 1.0; ! i++; ! } ! } ! // now, bubble sort all the sounds up the list: ! // we choose bubble sort, because the list should ! // have a lot of frame-to-frame coherency, making the ! // sort most often O(n) ! for(S32 i = 1; i < gPlayList.size(); i++) ! { ! F32 priority = gPlayList[i]->mPriority; ! for(S32 j = i - 1; j >= 0; j--) ! { ! if(priority > gPlayList[j]->mPriority) ! { ! SFXHandle temp = gPlayList[j]; ! gPlayList[j] = gPlayList[j+1]; ! gPlayList[j+1] = temp; ! } ! } ! } ! // last, release any sources and get rid of non-looping sounds ! // outside our max sound limit ! for(S32 i = NumSources; i < gPlayList.size(); ) ! { ! SFXHandle &s = gPlayList[i]; ! if(s->mSourceIndex != -1) ! { ! gSourceActive[s->mSourceIndex] = false; ! s->mSourceIndex = -1; ! } ! if(!s->mProfile->isLooping) ! gPlayList.erase_fast(i); ! else ! i++; ! } ! // now assign sources to all our sounds that need them: ! S32 firstFree = 0; ! S32 max = NumSources; ! if(max > gPlayList.size()) ! max = gPlayList.size(); ! ! for(S32 i = 0; i < max; i++) ! { ! SFXHandle &s = gPlayList[i]; ! if(s->mSourceIndex == -1) ! { ! while(gSourceActive[firstFree]) ! firstFree++; ! s->mSourceIndex = firstFree; ! gSourceActive[firstFree] = true; ! s->playOnSource(); ! } ! else ! { ! // for other sources, just attenuate the gain. ! s->updateGain(); ! } ! } ! } ! ! void SFXObject::setListenerParams(Point pos, Point velocity) ! { ! if(!gSFXValid) ! return; ! ! mListenerPosition = pos; ! mListenerVelocity = velocity; ! alListener3f(AL_POSITION, pos.x, pos.y, -mMaxDistance/2); ! } ! ! void SFXObject::shutdown() ! { ! if(!gSFXValid) ! return; ! ! alDeleteBuffers(NumSFXBuffers, gBuffers); ! alcMakeContextCurrent(NULL); ! alcDestroyContext(gContext); ! alcCloseDevice(gDevice); ! } ! ! }; ! ! #else ! ! using namespace TNL; ! ! namespace Zap ! { ! ! Point SFXObject::mListenerPosition; ! Point SFXObject::mListenerVelocity; ! F32 SFXObject::mMaxDistance = 500; ! ! SFXObject::SFXObject(U32 sfxIndex, F32 gain, bool looping) ! { ! } ! ! SFXObject::SFXObject(U32 sfxIndex, Point position, Point velocity, F32 gain, bool looping) ! { ! } ! ! SFXObject::~SFXObject() ! { ! ! } ! ! void SFXObject::updateGain() ! { ! } ! ! void SFXObject::updateMovementParams() ! { ! } ! ! void SFXObject::playOnSource() ! { ! } ! ! void SFXObject::setGain(F32 gain) ! { ! } ! ! void SFXObject::setLooping(bool looping) ! { ! } ! ! void SFXObject::setMovementParams(Point position, Point velocity) ! { ! } ! ! void SFXObject::play() ! { ! } ! ! void SFXObject::stop() ! { ! } ! ! void SFXObject::init() ! { ! logprintf("No OpenAL support on this platform."); ! } ! ! void SFXObject::process() ! { ! } ! ! void SFXObject::setListenerParams(Point pos, Point velocity) ! { ! } ! ! void SFXObject::shutdown() ! { ! }; ! ! }; ! ! #endif \ No newline at end of file --- 1,456 ---- ! //----------------------------------------------------------------------------------- ! // ! // Torque Network Library - ZAP example multiplayer vector graphics space game ! // Copyright (C) 2004 GarageGames.com, Inc. ! // For more information see http://www.opentnl.org ! // ! // This program is free software; you can redistribute it and/or modify ! // it under the terms of the GNU General Public License as published by ! // the Free Software Foundation; either version 2 of the License, or ! // (at your option) any later version. ! // ! // For use in products that are not compatible with the terms of the GNU ! // General Public License, alternative licensing options are available ! // from GarageGames.com. ! // ! // This program is distributed in the hope that it will be useful, ! // but WITHOUT ANY WARRANTY; without even the implied warranty of ! // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! // GNU General Public License for more details. ! // ! // You should have received a copy of the GNU General Public License ! // along with this program; if not, write to the Free Software ! // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! // ! //------------------------------------------------------------------------------------ ! ! #include "sfx.h" ! #include "tnl.h" ! #include "tnlLog.h" ! ! #if defined (TNL_OS_WIN32) || defined (TNL_OS_LINUX) ! ! #include "alInclude.h" ! ! using namespace TNL; ! ! namespace Zap ! { ! ! static SFXProfile gSFXProfiles[] = { ! { "phaser.wav", false, 0.45f, false, 150, 600 }, ! { "phaser_impact.wav", false, 0.7f, false, 150, 600 }, ! { "ship_explode.wav", false, 1.0, false, 300, 1000 }, ! { "flag_capture.wav", true, 0.45f, false, 0, 0 }, ! { "flag_drop.wav", true, 0.45f, false, 0, 0 }, ! { "flag_return.wav", true, 0.45f, false, 0, 0 }, ! { "flag_snatch.wav", true, 0.45f, false, 0, 0 }, ! { "teleport_in.wav", false, 1.0, false, 200, 500 }, ! { "teleport_out.wav", false, 1.0, false, 200, 500 }, ! { "bounce_wall.wav", false, 0.7f, false, 150, 600 }, ! { "bounce_obj.wav", false, 0.7f, false, 150, 600 }, ! { NULL, false, 0, false, 0, 0 }, ! }; ! ! static ALCdevice *gDevice = NULL; ! static ALCcontext *gContext = NULL; ! static bool gSFXValid = false; ! ! enum { ! NumSources = 16, ! }; ! ! static ALuint gSources[NumSources]; ! static bool gSourceActive[NumSources]; ! Point SFXObject::mListenerPosition; ! Point SFXObject::mListenerVelocity; ! F32 SFXObject::mMaxDistance = 500; ! ! static ALuint gBuffers[NumSFXBuffers]; ! static Vector<SFXHandle> gPlayList; ! ! SFXObject::SFXObject(U32 profileIndex, F32 gain, Point position, Point velocity) ! { ! mSFXIndex = profileIndex; ! mProfile = gSFXProfiles + profileIndex; ! mGain = gain; ! mPosition = position; ! mVelocity = velocity; ! mSourceIndex = -1; ! mPriority = 0; ! } ! ! RefPtr<SFXObject> SFXObject::play(U32 profileIndex, F32 gain) ! { ! RefPtr<SFXObject> ret = new SFXObject(profileIndex, gain, Point(), Point()); ! ret->play(); ! return ret; ! } ! ! RefPtr<SFXObject> SFXObject::play(U32 profileIndex, Point position, Point velocity, F32 gain) ! { ! RefPtr<SFXObject> ret = new SFXObject(profileIndex, gain, position, velocity); ! ret->play(); ! return ret; ! } ! ! SFXObject::~SFXObject() ! { ! ! } ! ! void SFXObject::updateGain() ! { ! ALuint source = gSources[mSourceIndex]; ! F32 gain = mGain; ! ! if(!mProfile->isRelative) ! { ! F32 distance = (mListenerPosition - mPosition).len(); ! if(distance > mProfile->fullGainDistance) ! { ! if(distance < mProfile->zeroGainDistance) ! gain *= (mProfile->fullGainDistance - distance) / ! (mProfile->zeroGainDistance - mProfile->fullGainDistance); ! else ! gain = 0.0f; ! } ! else ! gain = 1.0f; ! } ! else ! gain = 1.0f; ! ! alSourcef(source, AL_GAIN, gain * mProfile->gainScale); ! } ! ! void SFXObject::updateMovementParams() ! { ! ALuint source = gSources[mSourceIndex]; ! if(mProfile->isRelative) ! { ! alSourcei(source, AL_SOURCE_RELATIVE, true); ! alSource3f(source, AL_POSITION, 0, 0, 0); ! //alSource3f(source, AL_VELOCITY, 0, 0, 0); ! } ! else ! { ! alSourcei(source, AL_SOURCE_RELATIVE, false); ! alSource3f(source, AL_POSITION, mPosition.x, mPosition.y, 0); ! //alSource3f(source, AL_VELOCITY, mVelocity.x, mVelocity.y, 0); ! } ! } ! ! void SFXObject::playOnSource() ! { ! ALuint source = gSources[mSourceIndex]; ! alSourceStop(source); ! alSourcei(source, AL_BUFFER, gBuffers[mSFXIndex]); ! alSourcei(source, AL_LOOPING, mProfile->isLooping); ! updateMovementParams(); ! ! updateGain(); ! alSourcePlay(source); ! } ! ! void SFXObject::setGain(F32 gain) ! { ! mGain = gain; ! if(mSourceIndex != -1) ! updateGain(); ! } ! ! void SFXObject::setMovementParams(Point position, Point velocity) ! { ! mPosition = position; ! mVelocity = velocity; ! if(mSourceIndex != -1) ! updateMovementParams(); ! } ! ! void SFXObject::play() ! { ! if(mSourceIndex != -1) ! return; ! else ! { ! // see if it's on the play list: ! S32 i; ! for(i = 0; i < gPlayList.size(); i++) ! if(gPlayList[i] == this) ! return; ! gPlayList.push_back(this); ! } ! } ! ! void SFXObject::stop() ! { ! // remove from the play list, if this sound is playing: ! if(mSourceIndex != -1) ! { ! alSourceStop(gSources[mSourceIndex]); ! mSourceIndex = -1; ! } ! for(S32 i = 0; i < gPlayList.size(); i++) ! { ! if(gPlayList[i] == this) ! { ! gPlayList.erase(i); ! return; ! } ! } ! } ! ! void SFXObject::init() ! { ! gDevice = alcOpenDevice((ALubyte *) "DirectSound3D"); ! if(!gDevice) ! { ! logprintf("Failed to intitialize OpenAL."); ! return; ! } ! ! static int contextData[][2] = ! { ! {ALC_FREQUENCY, 11025}, ! {0,0} // Indicate end of list... ! }; ! ! gContext = alcCreateContext(gDevice, (ALCint*)contextData); ! alcMakeContextCurrent(gContext); ! ! alGetError(); ! ! alDistanceModel(AL_NONE); ! ! // load up all the sound buffers ! alGenBuffers(NumSFXBuffers, gBuffers); ! ! if(alGetError() != AL_NO_ERROR) ! return; ! ! alGenSources(NumSources, gSources); ! ! for(U32 i = 0; i < NumSFXBuffers; i++) ! { ! if(!gSFXProfiles[i].fileName) ! break; ! ! ALsizei size,freq; ! ALenum format; ! ALvoid *data; ! ALboolean loop; ! ! alutLoadWAVFile((ALbyte *) gSFXProfiles[i].fileName, &format, &data, &size, &freq, &loop); ! if(alGetError() != AL_NO_ERROR) ! return; ! alBufferData(gBuffers[i], format, data, size, freq); ! alutUnloadWAV(format, data, size, freq); ! if(alGetError() != AL_NO_ERROR) ! return; ! } ! gSFXValid = true; ! } ! ! void SFXObject::process() ! { ! if(!gSFXValid) ! return; ! ! // ok, so we have a list of currently "playing" sounds, which is ! // unbounded in length, but only the top NumSources actually have sources ! // associtated with them. Sounds are prioritized on a 0-1 scale ! // based on type and distance. ! // Each time through the main loop, newly played sounds are placed ! // on the process list. When SFXProcess is called, any finished sounds ! // are retired from the list, and then it prioritizes and sorts all ! // the remaining sounds. For any sounds from 0 to NumSources that don't ! // have a current source, they grab one of the sources not used by the other ! // top sounds. At this point, any sound that is not looping, and is ! // not in the active top list is retired. ! ! // ok, look through all the currently playing sources and see which ! // ones need to be retired: ! ! for(S32 i = 0; i < NumSources; i++) ! { ! ALint state; ! alGetSourcei(gSources[i], AL_SOURCE_STATE, &state); ! gSourceActive[i] = state != AL_STOPPED && state != AL_INITIAL; ! } ! for(S32 i = 0; i < gPlayList.size(); ) ! { ! SFXHandle &s = gPlayList[i]; ! if(s->mSourceIndex != -1 && !gSourceActive[s->mSourceIndex]) ! { ! // this sound was playing; now it is stopped, ! // so remove it from the list. ! s->mSourceIndex = -1; ! gPlayList.erase_fast(i); ! } ! else ! { ! // compute a priority for this sound. ! if(!s->mProfile->isRelative) ! s->mPriority = (500 - (s->mPosition - mListenerPosition).len()) / 500.0f; ! else ! s->mPriority = 1.0; ! i++; ! } ! } ! // now, bubble sort all the sounds up the list: ! // we choose bubble sort, because the list should ! // have a lot of frame-to-frame coherency, making the ! // sort most often O(n) ! for(S32 i = 1; i < gPlayList.size(); i++) ! { ! F32 priority = gPlayList[i]->mPriority; ! for(S32 j = i - 1; j >= 0; j--) ! { ! if(priority > gPlayList[j]->mPriority) ! { ! SFXHandle temp = gPlayList[j]; ! gPlayList[j] = gPlayList[j+1]; ! gPlayList[j+1] = temp; ! } ! } ! } ! // last, release any sources and get rid of non-looping sounds ! // outside our max sound limit ! for(S32 i = NumSources; i < gPlayList.size(); ) ! { ! SFXHandle &s = gPlayList[i]; ! if(s->mSourceIndex != -1) ! { ! gSourceActive[s->mSourceIndex] = false; ! s->mSourceIndex = -1; ! } ! if(!s->mProfile->isLooping) ! gPlayList.erase_fast(i); ! else ! i++; ! } ! // now assign sources to all our sounds that need them: ! S32 firstFree = 0; ! S32 max = NumSources; ! if(max > gPlayList.size()) ! max = gPlayList.size(); ! ! for(S32 i = 0; i < max; i++) ! { ! SFXHandle &s = gPlayList[i]; ! if(s->mSourceIndex == -1) ! { ! while(gSourceActive[firstFree]) ! firstFree++; ! s->mSourceIndex = firstFree; ! gSourceActive[firstFree] = true; ! s->playOnSource(); ! } ! else ! { ! // for other sources, just attenuate the gain. ! s->updateGain(); ! } ! } ! } ! ! void SFXObject::setListenerParams(Point pos, Point velocity) ! { ! if(!gSFXValid) ! return; ! ! mListenerPosition = pos; ! mListenerVelocity = velocity; ! alListener3f(AL_POSITION, pos.x, pos.y, -mMaxDistance/2); ! } ! ! void SFXObject::shutdown() ! { ! if(!gSFXValid) ! return; ! ! alDeleteBuffers(NumSFXBuffers, gBuffers); ! alcMakeContextCurrent(NULL); ! alcDestroyContext(gContext); ! alcCloseDevice(gDevice); ! } ! ! }; ! ! #else ! ! using namespace TNL; ! ! namespace Zap ! { ! ! Point SFXObject::mListenerPosition; ! Point SFXObject::mListenerVelocity; ! F32 SFXObject::mMaxDistance = 500; ! ! SFXObject::SFXObject(U32 sfxIndex, F32 gain, bool looping) ! { ! } ! ! SFXObject::SFXObject(U32 sfxIndex, Point position, Point velocity, F32 gain, bool looping) ! { ! } ! ! SFXObject::~SFXObject() ! { ! ! } ! ! void SFXObject::updateGain() ! { ! } ! ! void SFXObject::updateMovementParams() ! { ! } ! ! void SFXObject::playOnSource() ! { ! } ! ! void SFXObject::setGain(F32 gain) ! { ! } ! ! void SFXObject::setLooping(bool looping) ! { ! } ! ! void SFXObject::setMovementParams(Point position, Point velocity) ! { ! } ! ! void SFXObject::play() ! { ! } ! ! void SFXObject::stop() ! { ! } ! ! void SFXObject::init() ! { ! logprintf("No OpenAL support on this platform."); ! } ! ! void SFXObject::process() ! { ! } ! ! void SFXObject::setListenerParams(Point pos, Point velocity) ! { ! } ! ! void SFXObject::shutdown() ! { ! }; ! ! }; ! ! #endif Index: game.h =================================================================== RCS file: /cvsroot/opentnl/tnl/zap/game.h,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** game.h 20 Apr 2004 18:40:19 -0000 1.2 --- game.h 20 Apr 2004 19:25:48 -0000 1.3 *************** *** 1,189 **** ! //----------------------------------------------------------------------------------- ! // ! // Torque Network Library - ZAP example multiplayer vector graphics space game ! // Copyright (C) 2004 GarageGames.com, Inc. ! // For more information see http://www.opentnl.org ! // ! // This program is free software; you can redistribute it and/or modify ! // it under the terms of the GNU General Public License as published by ! // the Free Software Foundation; either version 2 of the License, or ! // (at your option) any later version. ! // ! // For use in products that are not compatible with the terms of the GNU ! // General Public License, alternative licensing options are available ! // from GarageGames.com. ! // ! // This program is distributed in the hope that it will be useful, ! // but WITHOUT ANY WARRANTY; without even the implied warranty of ! // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! // GNU General Public License for more details. ! // ! // You should have received a copy of the GNU General Public License ! // along with this program; if not, write to the Free Software ! // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! // ! //------------------------------------------------------------------------------------ ! ! #ifndef _GAME_H_ ! #define _GAME_H_ ! ! #include "point.h" ! #include "gameConnection.h" ! #include "../tnl/tnlNetObject.h" ! #include "gridDB.h" ! ! /// ! /// Zap - a 2D space game demonstrating the full capabilities of the ! /// Torque Network Library. ! /// ! /// The Zap example game is a 2D vector-graphics game that utilizes ! /// some of the more advanced features of the TNL. Zap also demonstrates ! /// the use of client-side prediction, and interpolation to present ! /// a consistent simulation to clients over a connection with perceptible ! /// latency. ! /// ! /// Zap can run in 3 modes - as a client, a client and server, or a dedicated ! /// server. The dedicated server option is available only as a launch ! /// parameter from the command line. ! /// ! /// If it is run as a client, Zap uses the GLUT library to perform ! /// cross-platform window intialization, event processing and OpenGL setup. ! /// ! /// Zap implements a simple game framework. The GameObject class is ! /// the root class for all of the various objects in the Zap world, including ! /// Ship, Barrier and Projectile instances. The Game class, which is instanced ! /// once for the client and once for the server, manages the current ! /// list of GameObject instances. ! /// ! /// Zap clients can connect to servers directly that are on the same LAN ! /// or for which the IP address is known. Zap is also capable of talking ! /// to the TNL master server and using its arranged connection functionality ! /// to talk to servers. ! /// ! /// The simplified user interface for Zap is managed entirely through ! /// subclasses of the UserInterface class. Each UserInterface subclass ! /// represents one "screen" in the UI. The GameUserInterface is the most complicated, ! /// being responsible for the user interface while the client is actually ! /// playing a game. The only other somewhat complicated UI is the ! /// QueryServersUserInterface class, which implements a full server browser ! /// for choosing from a list of LAN and master server queried servers. ! /// ! /// ! namespace Zap ! { ! ! class MasterServerConnection; ! class GameNetInterface; ! class GameType; ! ! /// Base class for server and client Game subclasses. The Game ! /// base class manages all the objects in the game simulation on ! /// either the server or the client, and is responsible for ! /// managing the passage of time as well as rendering. ! class Game ! { ! protected: ! U32 mLastIdleTime; ! U32 mNextMasterTryTime; ! F32 mGridSize; ! ! struct DeleteRef ! { ! GameO... [truncated message content] |