diff --git a/README.md b/README.md index 67a3c74..29b0677 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ The Massive Mobile Multiuser Framework is a software platform designed to enable # Setup and Installation - - Install necessary dependencies on server: SFML2, python3; if you use a Raspberry Pi, a special fork of SFML2 (e.g https://github.com/mickelson/sfml) needs to be compiled + - Install necessary dependencies on server: SFML, python3. If you use a Raspberry Pi, you previously needed a special fork of SFML (e.g https://github.com/mickelson/sfml), which is now no longer necessary by installing it from the official package repositories: ```sudo apt install libsfml-dev``` - Install a web server and make its root directory point to the www_root symlink in the project's root directory - Connect the server to a network from which it is reachable for client devices, or open a Wifi network yourself (see troubleshooting section for hints) - Paste the server's IP address to the frontend WebSocket configuration file: frontend/configuration/configuration.js @@ -21,23 +21,6 @@ The Massive Mobile Multiuser Framework is a software platform designed to enable - T. Weißker, A. Berst, J. Hartmann, and F. Echtler. 2016. The Massive Mobile Multiuser Framework: Enabling Ad-hoc Realtime Interaction on Public Displays with Mobile Devices. In Proceedings of the 5th International Symposium on Pervasive Displays (PerDis '16). ACM, New York, NY, USA, 168-174. DOI: http://dx.doi.org/10.1145/2914920.2915004 # Troubleshooting -## Compilation of mickelson's version of SFML -As outline by mickelson himself, the following steps need to be executed in order to get the Raspberry-Pi-version of SFML running. - -Install necessary dependencies: -``` -sudo apt-get install cmake libx11-dev libx11-xcb-dev libflac-dev libogg-dev libvorbis-dev libopenal-dev libjpeg8-dev libfreetype6-dev libxcb-randr0-dev libxcb-image0-dev libxcb-util0-dev libxcb-ewmh-dev libxcb-keysyms1-dev libxcb-icccm4-dev libudev-dev libavutil-dev libavcodec-dev libavformat-dev libavfilter-dev libswscale-dev libavresample-dev libfontconfig1-dev -``` - -Configure and compile SFML: -``` -git clone -b rpi https://github.com/mickelson/SFML sfml-pi -mkdir sfml-pi/build;cd sfml-pi/build -cmake -DEGL_INCLUDE_DIR=/opt/vc/include -DEGL_LIBRARY=/opt/vc/lib/libEGL.so -DFREETYPE_INCLUDE_DIR_freetype2=/usr/include -DFREETYPE_INCLUDE_DIR_ft2build=/usr/include/freetype2 -DGLES_INCLUDE_DIR=/opt/vc/include -DGLES_LIBRARY=/opt/vc/lib/libGLESv1_CM.so -DSFML_BCMHOST=1 .. -sudo make install -sudo ldconfig -``` - ## Wireless network and DHCP server We have used and tested two platforms on which we opened a Wifi network and assigned IP addresses to the connecting client devices. Therefore, we assigned the IP address 29.4.93.1 to the respective server and gave out an address range of 29.4.93.10 to 29.4.93.254 to connecting client devices. diff --git a/backend/dictionary_builder/create_dictionary.py b/backend/dictionary_builder/create_dictionary.py index 4e158e4..f813367 100644 --- a/backend/dictionary_builder/create_dictionary.py +++ b/backend/dictionary_builder/create_dictionary.py @@ -1,3 +1,4 @@ +import os import sys # Command line parameters @@ -9,6 +10,7 @@ def start(): # get filenames and load files config_file_name = sys.argv[1] + config_file_abs_path = os.path.abspath(config_file_name) output_file_name = sys.argv[2] config_file = open(config_file_name, 'r') @@ -25,7 +27,7 @@ def start(): output_file.write('#include \n') output_file.write('\n') output_file.write('const std::string configuration_file("' + - config_file_name + '");\n') + config_file_abs_path + '");\n') output_file.write('std::map eventDictionary;\n') output_file.write('\n') output_file.write('void fillDictionary()\n') diff --git a/backend/main.cpp b/backend/main.cpp index 59152e8..e7a0d96 100644 --- a/backend/main.cpp +++ b/backend/main.cpp @@ -251,6 +251,7 @@ int main() { //parse message formats: EVENT_TYPE EVENT_CODE VALUE // [EV_ABS | EV_REL] VALUE1 VALUE2 VALUE3 ... + //std::cout << message << std::endl; std::stringstream messageStream(message); std::string typeString; @@ -299,7 +300,8 @@ int main() else { //illegal use of multiple values - std::cout << "[Server] Multiple values only allowed for EV_ABS and EV_REL." << std::endl; + std::cout << message << std::endl; + std::cout << "[Server] Multiple values only allowed for EV_ABS and EV_REL." << std::endl; } } else diff --git a/frontend/configuration/configuration.js b/frontend/configuration/configuration.js index 294deeb..7e78ec1 100644 --- a/frontend/configuration/configuration.js +++ b/frontend/configuration/configuration.js @@ -1,5 +1,5 @@ var configuration = { - server_ip: '29.4.93.1', // the IP adress to open the WebSocket connection to + server_ip: '29.4.29.1', // the IP adress to open the WebSocket connection to server_port: '53000' // the port to use for the WebSocket connection // if you didn't change anything in backend/, the default is 53000 -} \ No newline at end of file +} diff --git a/frontend/controller.html b/frontend/controller.html index 4b52084..577266e 100644 --- a/frontend/controller.html +++ b/frontend/controller.html @@ -14,7 +14,6 @@
-
diff --git a/frontend/js/controller.js b/frontend/js/controller.js index 1c618bb..5633b60 100644 --- a/frontend/js/controller.js +++ b/frontend/js/controller.js @@ -1,6 +1,7 @@ /**************************************************************************************************************** OnLoad ****************************************************************************************************************/ +redirectOnError = true; checkLogin(); window.addEventListener('load', function(){ @@ -9,29 +10,36 @@ window.addEventListener('load', function(){ button = document.getElementById('button'); wrapper = document.getElementById('canvas-wrap'); canvas = document.getElementById('sadstick'); - circle = document.getElementById('circle'); hint = document.getElementById('mmmturn'); - colorbase = 'grey'; idletimer = setTimeout(logout, 3000000); context = null; socket = null; startx = null; starty = null; socket = null; + normalizedStickCoords = [0.0, 0.0]; + + stickRadius = 40; + stickMaxDistance = 2 * stickRadius; + teamColor = '#bbbbbb'; + stickIsDragged = false; + sendInputMaxValue = 255; initSocket(); - initView(); - window.addEventListener('resize', updateBasicView, false); + window.addEventListener('resize', onWindowResize, false); + onWindowResize(); button.addEventListener('touchstart', pushButton, false); button.addEventListener('touchend', releaseButton, false); - circle.addEventListener('touchstart', pushCircle, false); - circle.addEventListener('touchmove', moveCircle, false); - circle.addEventListener('touchend', releaseCircle, false); + canvas.addEventListener('touchstart', touchCanvas, false); + canvas.addEventListener('touchmove', moveTouchOnCanvas, false); + canvas.addEventListener('touchend', releaseCanvasTouch, false); + socketSendRate = 50; // updates per second + window.setInterval(intervalUpdate, (1.0/socketSendRate)*1000); }, false) @@ -39,46 +47,33 @@ window.addEventListener('load', function(){ Controller Basic View, Functions ****************************************************************************************************************/ - function isLandscape() { - var width = window.innerWidth; - var height = window.innerHeight; - - if (width < height) { - hint.style.display="block"; - button.style.display="none"; - circle.style.display="none"; - canvas.style.display="none"; - socketSend(socket, 'V * '+ 0 + ' ' + 0); - } else { - hint.style.display="none"; - button.style.display="inline"; - circle.style.display="block"; - canvas.style.display="inline"; - } - - + var width = window.innerWidth; + var height = window.innerHeight; + + if (width < height) { + hint.style.display="block"; + button.style.display="none"; + canvas.style.display="none"; + socketSend(socket, 'V * '+ 0 + ' ' + 0); + } else { + hint.style.display="none"; + button.style.display="inline"; + canvas.style.display="inline"; + } } -function initView() { - isLandscape(); - context = canvas.getContext('2d'); - canvas.width = window.innerWidth/2; - canvas.height = window.innerHeight; - var canvasCenterX = canvas.width /2; - var canvasCenterY = canvas.height /2; - circle.style.left = canvasCenterX - circle.offsetWidth/2; - circle.style.top = canvasCenterY - circle.offsetHeight/2; +function onWindowResize() { + isLandscape(); + setCanvasSize(); + clearCanvas(); } -function updateBasicView() { - isLandscape(); - canvas.width = window.innerWidth/2; - canvas.height = window.innerHeight; - var canvasCenterX = canvas.width /2; - var canvasCenterY = canvas.height /2; - circle.style.left = canvasCenterX - circle.offsetWidth/2; - circle.style.top = canvasCenterY - circle.offsetHeight/2; +function setCanvasSize() { + context = canvas.getContext('2d'); + canvas.width = window.innerWidth/2; + canvas.height = window.innerHeight; + canvasCenter = [canvas.width/2, canvas.height/2]; } function colorBackground(object, color) { @@ -93,36 +88,37 @@ function resetTimer() { /**************************************************************************************************************** Canvas Draw ****************************************************************************************************************/ -function drawControllerStick(currx, curry) { - clearCanvas(); - drawLineFromCenterTo(currx, curry); - drawCircleAtPos(currx,curry); +function drawControllerStick(pos, color) { + clearCanvas(); + drawLineFromCenterTo(pos); + drawCircleAtPos(pos, stickRadius, color); } -function drawLineFromCenterTo(currx, curry) { - var canvasCenterX = canvas.width /2; - var canvasCenterY = canvas.height /2; - context.beginPath(); - context.moveTo(canvasCenterX ,canvasCenterY); - context.lineTo(currx, curry); - context.closePath(); - context.stroke(); +function drawLineFromCenterTo(pos) { + context.beginPath(); + context.moveTo(canvasCenter[0],canvasCenter[1]); + context.lineTo(pos[0], pos[1]); + context.closePath(); + context.stroke(); } -function drawCircleAtPos(currx, curry) { - context.beginPath(); - context.arc(currx, curry, 50, 0, 2 * Math.PI, false); - context.fillStyle = 'black'; - context.fill(); - context.lineWidth = 5; - context.closePath(); - context.stroke(); +function drawCircleAtPos(pos, radius, color) { + context.beginPath(); + context.arc(pos[0], pos[1], radius, 0, 2 * Math.PI, false); + context.fillStyle = color; + context.fill(); + context.lineWidth = 3; + context.closePath(); + context.stroke(); } function clearCanvas() { - context.clearRect(0, 0, canvas.width, canvas.height); - context.lineWidth = 4; - context.shadowColor = "transparent"; + context.clearRect(0, 0, canvas.width, canvas.height); + context.lineWidth = 4; + context.shadowColor = "transparent"; + drawCircleAtPos(canvasCenter, stickRadius*0.25, '#bbbbbb'); + if (!stickIsDragged) drawCircleAtPos(canvasCenter, stickRadius, teamColor); + drawCircleAtPos(canvasCenter, stickMaxDistance, "transparent"); } @@ -132,49 +128,71 @@ function clearCanvas() { function pushButton(e) { e.preventDefault(); - colorBackground(button,'#000000'); + colorBackground(button,'#ffffff'); resetTimer(); socketSend(socket, 'K A 1'); socketSend(socket, 'K A 0'); } function releaseButton() { - colorBackground(button, colorbase); + colorBackground(button, teamColor); } -function pushCircle(e) { +function touchCanvas(e) { e.preventDefault(); var touchobj = e.changedTouches[0]; - startx = parseInt(touchobj.clientX); - starty = parseInt(touchobj.clientX); - circle.style.display ="none"; - - var canvasCenterX = canvas.width /2; - var canvasCenterY = canvas.height /2; - drawControllerStick(canvasCenterX,canvasCenterY); + var touchCoords = [parseInt(touchobj.clientX), parseInt(touchobj.clientY)]; + var touchToCenter = [canvasCenter[0]-touchCoords[0], canvasCenter[1]-touchCoords[1]]; + var touchDistance = Math.sqrt(touchToCenter[0]*touchToCenter[0] + touchToCenter[1]*touchToCenter[1]); + + if (touchDistance < stickRadius) + { + stickIsDragged = true; + stickDraggingOffset = touchToCenter; + drawControllerStick(canvasCenter, teamColor); + socketSend(socket, 'V * '+ 0 + ' ' + 0); + } - socketSend(socket, 'V * '+ 0 + ' ' + 0); resetTimer(); } -function moveCircle(e) { - e.preventDefault(); - var touchobj = e.changedTouches[0]; - var currx = parseInt(touchobj.clientX); - var curry = parseInt(touchobj.clientY); - drawControllerStick(currx,curry); - - diffx = currx - startx; - diffy = curry - starty; +function moveTouchOnCanvas(e) { + + if (stickIsDragged) + { + var touchobj = e.changedTouches[0]; + var touchCoords = [parseInt(touchobj.clientX), parseInt(touchobj.clientY)]; + var stickCoords = [touchCoords[0]+stickDraggingOffset[0], touchCoords[1]+stickDraggingOffset[1]]; + var centerToStick = [stickCoords[0]-canvasCenter[0], stickCoords[1]-canvasCenter[1]]; + var centerToStickMag = Math.sqrt(centerToStick[0]*centerToStick[0] + centerToStick[1]*centerToStick[1]); + + if (centerToStickMag > stickMaxDistance) + { + var shorteningFactor = stickMaxDistance/centerToStickMag; + centerToStick = [centerToStick[0]*shorteningFactor, centerToStick[1]*shorteningFactor]; + centerToStickMag = stickMaxDistance; + stickCoords = [canvasCenter[0]+centerToStick[0], canvasCenter[1]+centerToStick[1]]; + } + drawControllerStick(stickCoords, teamColor); + normalizedStickCoords = [centerToStick[0]/stickMaxDistance, centerToStick[1]/stickMaxDistance]; + } resetTimer(); - socketSend(socket, 'V * '+ diffx + ' ' + diffy); } -function releaseCircle(e) { - circle.style.display = ""; - clearCanvas(); +function releaseCanvasTouch(e) { + stickIsDragged = false; + normalizedStickCoords = [0.0, 0.0]; socketSend(socket, 'V * '+ 0 + ' ' + 0); + clearCanvas(); +} + +function intervalUpdate() { + if (stickIsDragged) + { + var inputToSend = [Math.round(normalizedStickCoords[0]*sendInputMaxValue), Math.round(normalizedStickCoords[1]*sendInputMaxValue)]; + socketSend(socket, 'V * ' + inputToSend[0] + ' ' + inputToSend[1]); + } } /**************************************************************************************************************** @@ -185,12 +203,11 @@ function initSocket() { socket = new WebSocket('ws://' + configuration.server_ip + ':' + configuration.server_port) socket.onerror = function(error) { - window.location.href = './goodbye.html'; + if (redirectOnError) window.location.href = './goodbye.html'; }; socket.onopen = function() { socketSend(socket, 'NAME '+sessionStorage.getItem('playername')); - window.sessionStorage.removeItem('playername'); } socket.onmessage = function(evt) { @@ -200,20 +217,21 @@ function initSocket() { window.sessionStorage.setItem("number", splitted_string[2]); if(sessionStorage.getItem('team') == "RED") { - colorbase = 'red'; - button.style.backgroundColor = colorbase; - circle.style.backgroundColor = colorbase; - + teamColor = 'red'; + button.style.backgroundColor = teamColor; } else if(sessionStorage.getItem('team') == "BLUE") { - colorbase = 'blue'; - button.style.backgroundColor = colorbase; - circle.style.backgroundColor = colorbase; - } + teamColor = 'blue'; + button.style.backgroundColor = teamColor; + } + + button.innerHTML = "
Name: " + sessionStorage.getItem('playername') + "

Number: " + sessionStorage.getItem('number') + "
"; + clearCanvas(); } } function socketSend(socket, message) { messageToSend = '^' + message + '$'; + //console.log(messageToSend); if (socket.readyState == 1) { socket.send(messageToSend); } @@ -230,7 +248,7 @@ function closeSocket() { ****************************************************************************************************************/ function checkLogin() { if(sessionStorage.getItem('playername') === null) { - window.location.href = './goodbye.html'; + if (redirectOnError) window.location.href = './goodbye.html'; } } @@ -238,5 +256,5 @@ function logout(){ window.sessionStorage.removeItem('team'); window.sessionStorage.removeItem('number'); closeSocket(); - window.location.href = './goodbye.html'; + if (redirectOnError) window.location.href = './goodbye.html'; } diff --git a/frontend/style.css b/frontend/style.css index d287b5d..04df175 100644 --- a/frontend/style.css +++ b/frontend/style.css @@ -128,6 +128,19 @@ body { -o-user-select: none; } +.status-text +{ + font-size: medium; + text-align: center; + color: white; + margin: 5%; +} + +#bold +{ + font-weight: bold; +} + #sadstick { position:absolute; width: 100%; @@ -159,7 +172,7 @@ body { position: relative; top: 50; left: 50; - background: red; + background: #cccccc; border-radius: 50%; padding: 20%; -moz-user-select: none; diff --git a/game/include/Game.hpp b/game/include/Game.hpp index de981f6..5ee3aac 100644 --- a/game/include/Game.hpp +++ b/game/include/Game.hpp @@ -4,7 +4,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -52,6 +54,7 @@ class Game //game logic methods void performEndOfGameAnimation(); + void resetGame(); void resetScore(); void checkForGoal(); void resetPlayers(); diff --git a/game/include/PhysicalCircle.hpp b/game/include/PhysicalCircle.hpp index e66bc58..a6d8b42 100644 --- a/game/include/PhysicalCircle.hpp +++ b/game/include/PhysicalCircle.hpp @@ -3,9 +3,13 @@ #include #include +#include #include #include +typedef std::chrono::high_resolution_clock Clock; +typedef std::chrono::milliseconds milliseconds; + #define MAX_SPEED 6.0 class PhysicalCircle @@ -15,7 +19,7 @@ class PhysicalCircle virtual ~PhysicalCircle(); virtual void render(sf::RenderWindow* window) const; - virtual void frameFrictionUpdate(); + virtual void frameFrictionUpdate(float timeFactor); virtual void frameUpdate(); virtual void setPosition(float x, float y); virtual void clampPosition() = 0; @@ -45,6 +49,8 @@ class PhysicalCircle float mass_; float radius_; float frictionCoefficient_; + + Clock::time_point lastFrameTime_; }; #endif //PHYSICAL_CIRCLE_HPP diff --git a/game/include/Player.hpp b/game/include/Player.hpp index 5c688db..5021b50 100644 --- a/game/include/Player.hpp +++ b/game/include/Player.hpp @@ -15,7 +15,7 @@ class Player : public PhysicalCircle { public: - Player(int startX, int startY, sf::Color border, sf::Color center, std::string const& name, int number); + Player(int startX, int startY, sf::Color border, sf::Color center, std::string const& name, int number, std::string resourcesPath); /* virtual */ void render(sf::RenderWindow* window) const; /* virtual */ void frameUpdate(); @@ -54,6 +54,7 @@ class Player : public PhysicalCircle int startX_; int startY_; + std::string resourcesPath_; sf::Text numberText_; sf::Text nameText_; sf::Font font_; diff --git a/game/main.cpp b/game/main.cpp index 8ed90c7..b99f284 100644 --- a/game/main.cpp +++ b/game/main.cpp @@ -14,8 +14,8 @@ int main(int argc, char* argv[]) srand (time(NULL)); sf::Clock Clock; - sf::RenderWindow window(sf::VideoMode(sf::VideoMode::getDesktopMode().width,sf::VideoMode::getDesktopMode().width,20), "MMMBall", sf::Style::Fullscreen); //sf::RenderWindow window(sf::VideoMode(sf::VideoMode::getDesktopMode().width,sf::VideoMode::getDesktopMode().width,20), "MMMBall"); + sf::RenderWindow window(sf::VideoMode(sf::VideoMode::getDesktopMode().width,sf::VideoMode::getDesktopMode().width,20), "MMMBall", sf::Style::Fullscreen); window.setVerticalSyncEnabled(true); std::string programName(argv[0]); @@ -182,6 +182,11 @@ int main(int argc, char* argv[]) // input handling inputHandler.processAddRemoveQueries(); inputHandler.processDeviceInputs(); + + if (sf::Keyboard::isKeyPressed(sf::Keyboard::R)) + { + game->resetGame(); + } // application logic diff --git a/game/src/Game.cpp b/game/src/Game.cpp index 81fb3ad..8153954 100644 --- a/game/src/Game.cpp +++ b/game/src/Game.cpp @@ -83,7 +83,7 @@ Player* Game::addNewPlayer(std::string const& name) redNumbersInUse_[number] = true; } - Player* newPlayer = new Player(spawnPosition.x, spawnPosition.y, sf::Color(0,0,0), teamColor, name, number); + Player* newPlayer = new Player(spawnPosition.x, spawnPosition.y, sf::Color(0,0,0), teamColor, name, number, resourcesPath_); //adjust player radius to other players float newRadius; @@ -188,7 +188,9 @@ void Game::renderScoreLine(sf::RenderWindow* window) void Game::renderFpsDisplay(sf::RenderWindow* window, float value) { - fpsString_.setString(std::to_string(value) + " fps"); + std::stringstream stream; + stream << std::fixed << std::setprecision(2) << value; + fpsString_.setString(stream.str() + " fps"); window->draw(fpsString_); } @@ -206,22 +208,22 @@ void Game::renderTime(sf::RenderWindow* window) if (pointsRedTeam_ > pointsBlueTeam_) { - goalTextOne_.setColor(sf::Color(255,0,0)); + goalTextOne_.setFillColor(sf::Color(255,0,0)); goalTextOne_.setString("red wins"); - goalTextTwo_.setColor(sf::Color(255,0,0)); + goalTextTwo_.setFillColor(sf::Color(255,0,0)); } else if (pointsBlueTeam_ > pointsRedTeam_) { - goalTextOne_.setColor(sf::Color(0,0,255)); + goalTextOne_.setFillColor(sf::Color(0,0,255)); goalTextOne_.setString("blue wins"); - goalTextTwo_.setColor(sf::Color(0,0,255)); + goalTextTwo_.setFillColor(sf::Color(0,0,255)); } else { - goalTextOne_.setColor(sf::Color(0,0,0)); + goalTextOne_.setFillColor(sf::Color(0,0,0)); goalTextOne_.setString("draw"); - goalTextTwo_.setColor(sf::Color(0,0,0)); + goalTextTwo_.setFillColor(sf::Color(0,0,0)); } goalTextTwo_.setString(std::to_string(pointsBlueTeam_) + " to " + std::to_string(pointsRedTeam_)); @@ -247,11 +249,11 @@ void Game::renderTime(sf::RenderWindow* window) if (remainingSeconds <= 10) { - time_.setColor(sf::Color(255,255,0)); + time_.setFillColor(sf::Color(255,255,0)); } else { - time_.setColor(sf::Color(255,255,255)); + time_.setFillColor(sf::Color(255,255,255)); } if (inEndAnimation_) @@ -411,11 +413,7 @@ void Game::performEndOfGameAnimation() if (elapsedMilliseconds > END_ANIMATION_DURATION_SEC * 1000) { - ball_->resetToStart(); - resetPlayers(); - resetScore(); - clock_.restart(); - inEndAnimation_ = false; + resetGame(); } else { @@ -442,6 +440,15 @@ void Game::performEndOfGameAnimation() } } +void Game::resetGame() +{ + ball_->resetToStart(); + resetPlayers(); + resetScore(); + clock_.restart(); + inEndAnimation_ = false; +} + void Game::resetScore() { @@ -461,8 +468,8 @@ void Game::checkForGoal() ball_->setColor(sf::Color(0,0,0)); goalTextOne_.setString(ball_->getLastPlayerTouchName() + " scores"); - goalTextOne_.setColor(sf::Color(255, 0, 0)); - goalTextTwo_.setColor(sf::Color(255, 0, 0)); + goalTextOne_.setFillColor(sf::Color(255, 0, 0)); + goalTextTwo_.setFillColor(sf::Color(255, 0, 0)); celebratingTeam_ = sf::Color(255,0,0); goalTextTwo_.setString(std::to_string(pointsRedTeam_-1)); @@ -477,8 +484,8 @@ void Game::checkForGoal() ball_->setColor(sf::Color(0,0,0)); goalTextOne_.setString(ball_->getLastPlayerTouchName() + " scores"); - goalTextOne_.setColor(sf::Color(0, 0, 255)); - goalTextTwo_.setColor(sf::Color(0, 0, 255)); + goalTextOne_.setFillColor(sf::Color(0, 0, 255)); + goalTextTwo_.setFillColor(sf::Color(0, 0, 255)); celebratingTeam_ = sf::Color(0,0,255); goalTextTwo_.setString(std::to_string(pointsBlueTeam_-1)); @@ -818,8 +825,9 @@ void Game::createFpsDisplay() fpsString_.setFont(font_); fpsString_.setCharacterSize(screenHeight_*0.03); + fpsString_.setFillColor(sf::Color(50,50,50)); - fpsString_.move(0.85*screenWidth_,0.94*screenHeight_); + fpsString_.move(0.88*screenWidth_,0.94*screenHeight_); } diff --git a/game/src/InputDevice.cpp b/game/src/InputDevice.cpp index cfcd8ce..b726f06 100644 --- a/game/src/InputDevice.cpp +++ b/game/src/InputDevice.cpp @@ -83,8 +83,9 @@ void InputDevice::mapValuesAndApply() { if (inputValueX_ != 0 || inputValueY_ != 0) { - double inputToVelFactor = 12.0; - playerFigure_->addVelocityOffset(inputValueX_ * inputToVelFactor, inputValueY_ * inputToVelFactor); + double inputToVelFactor = 6.0 / 255.0; + //playerFigure_->addVelocityOffset(inputValueX_ * inputToVelFactor, inputValueY_ * inputToVelFactor); + playerFigure_->setVelocity(inputValueX_ * inputToVelFactor, inputValueY_ * inputToVelFactor); } if (inputButtonA_) diff --git a/game/src/InputHandler.cpp b/game/src/InputHandler.cpp index 664a06a..9d32641 100644 --- a/game/src/InputHandler.cpp +++ b/game/src/InputHandler.cpp @@ -234,6 +234,7 @@ std::map::iterator InputHandler::removeDevice(int deviceID) currentInputDevicesMutex_.unlock(); return nextIterator; } + return currentInputDevices_.end(); } void InputHandler::processAddRemoveQueries() diff --git a/game/src/PhysicalCircle.cpp b/game/src/PhysicalCircle.cpp index ddb9314..84b7033 100644 --- a/game/src/PhysicalCircle.cpp +++ b/game/src/PhysicalCircle.cpp @@ -1,7 +1,7 @@ #include "PhysicalCircle.hpp" PhysicalCircle::PhysicalCircle(float mass, float posX, float posY, float radius, float frictionCoefficient) : - mass_(mass), posX_(posX), posY_(posY), velX_(0.0), velY_(0.0), radius_(radius), frictionCoefficient_(frictionCoefficient) {} + mass_(mass), posX_(posX), posY_(posY), velX_(0.0), velY_(0.0), radius_(radius), frictionCoefficient_(frictionCoefficient), lastFrameTime_(Clock::now()) {} /* virtual */ PhysicalCircle::~PhysicalCircle() {} @@ -10,9 +10,9 @@ PhysicalCircle::PhysicalCircle(float mass, float posX, float posY, float radius, window->draw(shape_); } -/* virtual */ void PhysicalCircle::frameFrictionUpdate() +/* virtual */ void PhysicalCircle::frameFrictionUpdate(float timeFactor) { - float frictionDecrement = frictionCoefficient_; + float frictionDecrement = frictionCoefficient_ * timeFactor; float currentSpeed = computeCurrentSpeed(); @@ -35,8 +35,12 @@ PhysicalCircle::PhysicalCircle(float mass, float posX, float posY, float radius, /* virtual */ void PhysicalCircle::frameUpdate() { - frameFrictionUpdate(); - setPosition(posX_ + velX_, posY_ + velY_); + Clock::time_point nowTime = Clock::now(); + int elapsedMilliseconds = (std::chrono::duration_cast(nowTime - lastFrameTime_)).count(); + float timeFactor = (elapsedMilliseconds/1000.0)*100.0; + frameFrictionUpdate(timeFactor); + setPosition(posX_ + velX_ * timeFactor, posY_ + velY_ * timeFactor); + lastFrameTime_ = nowTime; } /* virtual */ void PhysicalCircle::setPosition(float x, float y) diff --git a/game/src/Player.cpp b/game/src/Player.cpp index fbe4ded..ce6cefd 100644 --- a/game/src/Player.cpp +++ b/game/src/Player.cpp @@ -1,8 +1,8 @@ #include "Player.hpp" -Player::Player(int startX, int startY, sf::Color border, sf::Color center, std::string const& name, int number) : +Player::Player(int startX, int startY, sf::Color border, sf::Color center, std::string const& name, int number, std::string resourcesPath) : PhysicalCircle(10.2, startX, startY, 35.0, 1.0), borderColor_(border), centerColor_(center), - blockShootFrames_(0), startX_(startX), startY_(startY), name_(name), shirtNumber_(number) + blockShootFrames_(0), startX_(startX), startY_(startY), resourcesPath_(resourcesPath), name_(name), shirtNumber_(number) { shootCircleRadius_ = computeShootCircleRadius(); @@ -22,7 +22,7 @@ Player::Player(int startX, int startY, sf::Color border, sf::Color center, std:: shootCircle_.setOrigin(shootCircleRadius_, shootCircleRadius_); shootCircle_.setPosition(startX, startY); - if (!font_.loadFromFile("resources/font.ttf")) + if (!font_.loadFromFile(resourcesPath_ + std::string("/font.ttf"))) { std::cout << "[Player.cpp] Error loading font." << std::endl; } @@ -33,7 +33,7 @@ Player::Player(int startX, int startY, sf::Color border, sf::Color center, std:: nameText_.setFont(font_); nameText_.setString(name_); - nameText_.setColor(sf::Color(0,0,0)); + nameText_.setFillColor(sf::Color(0,0,0)); nameText_.setCharacterSize(6.0/7.0 * radius_); }