Distributed Computing Systems - WPI

Distributed Computing Systems - WPI

Distributed Computing Systems Project 4 Dragonfly Wings Extending the Dragonfly Game Engine with Networking Due date: Sunday, February 28th, 11:59pm Overview network One game world the pitch But more than one copy each client has own!

Each client does own computations (ball moves left) How to keep game world synchronized? (Advanced: what about latency? scalability? cheating?) Project 4 Synopsis Goals Understand implications of distributing shared, virtual world on multiple computers Realize implementation of distributed system Acquire familiarity with networking for game engine Gain experience using fundamental networking code Objectives Implement distribution of state in virtual world Extend single player game to two player, networked game with clientserver architecture Design and implemented network functionality for game engine Implement networking (TCP/IP) socket code from scratch

Extend Dragonfly with network support Create two player, 2d game using game engine Outline Overview Project Game engine Dragonfly extensions Hints

Experiments Hand In Grading Dragonfly Overview Text-based game engine Primarily to teach about game engine development But full-featured (graphics animation, collisions, audio, input/output) can make real games! Does not provide networking support (Thats the goal of this project!) (High-level architecture slide next) Dragonfly Overview Saucer: hit()

Hero: kbd() GAME CODE Star: eventHandler() GameOver: step() DrawCharacter InsertObject LoadSprite DRAGONFLY GetKey MoveObject SendEvent

Allocate memory Clear display COMPUTER PLATFORM File open/close Get keystroke \ ~== /

Tutorial Overview ____ /_o__\ Good overview of Dragonfly through tutorial Setup development environment for building Work through tutorial making game Saucer Shoot Get used to Dragonfly 2D (text-based graphics) game engine From game programmers perspective In this project, you both game programmer (Saucer Shoot 2) and engine programmer (networking) Learn enough about game to extend to two-player version

What is a Text-based Game? Why Text-based Graphics? Conceptually easy (x,y) location, all cells Platform independent (mostly) Simple Fast Multimedia Library (SFML) ported many platforms Linux, Mac (homebrew and XCode), Windows (Visual Studio) Reduce temptation to spend time on art Programmer art is ok! Text-based Graphics - Sprites Animations stored in Sprite file

Read in by engine before use Sprite file with fixed format Note, must be exact (spaces) Included sprites (sprites.zip) all work with tutorial Note, if doing your own may need to debug art If doesnt load, see dragonfly.log for messages Dragonfly does 30 updates/second ( can potentially change frame each update) Use Object setSpriteSlowDown() if slower Tutorial Saucer Shoot

Online: http://dragonfly.wpi.edu/tutorial/ Work through start to finish Cook-book like, but with some explanations Need resources/assets Sprite package (sprites.zip) Sound package (sounds.zip) Also available is source code if stuck (gameX.zip) Internal understanding not necessarily needed That is whole other class! Basic external understanding expected Needed when extending Saucer Shoot game A 10,000-Foot View of Game Code

Startup game engine Initialize graphics, input devices, file logging Populate world with objects Player object (Hero), Enemies (Saucers), Decorations (Stars) Run game Move objects, get input, send events to objects (e.g., collisions), draw screen (objects draw themselves) Game engine does most of this work! Shutdown Core Attributes of Engine in Tutorial Startup Managers how invoked

Objects these need to by synchronized across computers! Made once (Hero, Stars) Made many times (Saucers, Bullets, Explosions) Events Built-in: Keyboard, Collision Custom: Nuke Not explicit, but also Debugging (own code) Reading (and using) logfiles Development Platforms Can be developed on common desktop development environments Linux (Debian-based has SFML package)

Note: Can use CCC cs4513 machine Windows (Visual Studio 2013) Note, if have VS 2015 can use VS 2013 project MacOS (homebrew or XCode) Development Environment Tools and Libraries Environment C++ compiler Project development software (e.g., make or IDE) Standard C++ libraries Simple and Fast Multimedia Debugger (e.g., gdb or ddd) Library (SFML)

Dragonfly Engine Download zip and extract SFML Linux sudo apt-get install libsfmldev Windows Download zip and extract Mac Documentation Dragonfly Documentation http://dragonfly.wpi.edu/documentation/ Outline

Overview (done) Dragonfly extensions (next) Network Manager Network Events Hints Experiments Hand In Grading

+ Sound, Music Dragonfly Classes Add Manager Add Event (Add Sentry) Managers Support systems that manage crucial tasks Handling input, Rendering graphics, Logging data Networking Startup and shutdown

explicitly GameManager NetworkManager Only makes sense to have one Singleton df::NetworkManager Managers: C++ Singletons Idea Generally only 1 makes sense Need global access Singleton (design pattern) Compiler wont allow creation (so have only 1)

Singleton s; // not allowed Instead: Singleton &s= Singleton::getInstance(); Guarantees only 1 copy of Singleton will exist Use for Network Manager class Singleton { private: Singleton(); Singleton(Singleton const ©); Singleton&(Singleton const &assign); public:

static Singleton &getInstance();. }; // Return the one and only instance of the class. Singleton &Singleton::getInstance() { // A static variable persists after method ends. static Singleton single; return single; }; namespace df { class Manager { private: std::string type; // Manager type identifier . bool is_started; // True when started successfully. protected: // Set type identifier of Manager.

void setType(std::string type); public: Manager(); virtual ~Manager(); // Get type identifier of Manager. std::string getType() const; // Startup Manager. // Return 0 if ok, else negative number. virtual int startUp(); // Shutdown Manager. virtual void shutDown(); // Return true when startUp() was executed ok, else false. bool isStarted() const; }; } // end of namespace df Manager.h

Notes: Base class Other managers inherit (e.g., Network Manager) virtual ensures derived calls used // NetworkManager.h // Manage network connections to/from engine. // System includes. #include // Engine includes. #include "Manager.h" #define DRAGONFLY_PORT "PICK NUMBER HERE" // Default port. namespace df {

class NetworkManager : public Manager { private: NetworkManager(); // Private since a singleton. NetworkManager(NetworkManager const&); // Don't allow copy. void operator=(NetworkManager const&); // Don't allow assignment. int sock; // Connected network socket. public: // Get the one and only instance of the NetworkManager. static NetworkManager &getInstance(); // Start up NetworkManager. int startUp(); // Shut down NetworkManager. void shutDown(); // Accept only network events. // Returns false for other engine events. bool isValid(std::string event_type) const;

Network Manager (1 of 2) #ifndef __NETWORK_MANAGER_H__ #define __NETWORK_MANAGER_H__ // Block, waiting to accept network connection. int accept(std::string port = DRAGONFLY_PORT); // Close network connection. // Return 0 if success, else -1. int close(); // Return true if network connected, else false. bool isConnected() const; // Return socket. int getSocket() const; // Send buffer to connected network. // Return 0 if success, else -1.

int send(void *buffer, int bytes); // Receive from connected network (no more than nbytes). // If peek is true, leave data in socket, else remove. // Return number of bytes received, else -1 if error. int receive(void *buffer, int nbytes, bool peek = false); // Check if network data. // Return amount of data (0 if no data), -1 if not connected or error. int isData() const; }; } // end of namespace df #endif // __NETWORK_MANAGER_H__ Network Manager (2 of 2) // Make network connection. // Return 0 if success, else -1. int connect(std::string host, std::string port =

DRAGONFLY_PORT); Dragonfly Events Built-in events derive from base class Game programmer can define others e.g., nuke Use for network event (EventNetwork) df::EventNetwork #include const std::string UNDEFINED_EVENT "df::undefined";

class Event { // Holds event type. public: // Create base event. Event(); // Destructor. virtual ~Event(); // Set event type. void setType(std::string new_type); // Get event type. std::string getType() const; }; Event.h

private: std::string event_type; // A "network" event, generated when a network packet arrives. #ifndef __EVENT_NETWORK_H__ #define __EVENT_NETWORK_H__ #include "Event.h" const std::string NETWORK_EVENT = "df::network"; class EventNetwork : public Event { private: int bytes; // Number of bytes available public:

// Default constructor. EventNetwork(); // Create object with initial bytes. EventNetwork(int initial_bytes); // Set number of bytes available. void setBytes(int new_bytes); // Get number of bytes available. int getBytes() const; }; EventNetwork.h namespace df { Using Events Objects register with appropriate Manager Engine knows about built-in events

All user-defined events go to World Manager But! engine wont know about network events Build special Sentry object that checks network (Next Slide) When network data, create network event using onEvent() method Any interested game Objects get event Objects must explicitly register with NetworkManager NetworkManager &network_manager = NetworkManager::getInstance(); network_manager.registerInterest(this, df::NETWORK_EVENT) // // Sentry //

// Poll NetworkManager for incoming messages, generating network // events (onEvent()) when there are complete messages available. #ifndef __SENTRY_H__ #define __SENTRY_H__ namespace df { class Sentry : public Object { private: void doStep(); // Called for each step event. public: Sentry(); int eventHandler(const df::Event *p_e); }; } // end of namespace df #endif // __SENTRY_H__

Sentry.h #include "Object.h" Using Sentry After starting up NetworkManager, create Sentry object new df::Sentry Sentry polls NetworkManager for network data When int of data, check if amount == total data Expects first byte of message to be message size (see Messages slides below) If so, send EventNetwork to interested Objects NetworkManager &network_manager = NetworkManager::getInstance();

EventNetwork en; network_manager.onEvent(&en); Client and Host Objects Host object (derived from Object) runs on server Client object (derived from Object) runs on client Host game started first, whereupon Host (using the NetworkManager) readies computer for connection Client game started next, where Client (also using NetworkManager) starts after and connects to Host Each game step, Host checks all game objects to see which ones are new (their Object id's are modified) Synchronized via NetworkManager Client receives object data over network, updating Objects Host receives keystrokes sent by Client, generating network events to game objects (e.g., the Client Hero) to handle

Two-player Game Startup Start Dragonfly GameManager startUp() Start NetworkManager NetworkManager startUp() Start Sentry new Sentry() If host Start Host new Host Else Start Client new Client

Extending Tutorial Game Saucer Shoot 2 (1 of 3) Need core gameplay only (e.g., hunting Saucers) No GameStart and GameOver Nukes also optional Once connected, can go right to gameplay Once Hero dies, can exit Note: additional features (e.g., GameStart) for Miscellaneous points (below) Add additional code (and sprites/sounds, if needed) Networking from independent computers (a distributed system) Two-player (one can play on Host) Extending Tutorial Game Saucer Shoot 2 (2 of 3)

Possible functionality Simultaneous Heroes (same side, opposite sides) Second player controls Saucer(s) Your own clever idea! Many decisions for multiplayer game How player actions are transmitted to the server How inconsistencies between client and server game states are resolved What Objects are synchronized and how often Key aspect how to send an Object from one computer to another (next topic, after screenshot) Extending Tutorial Game Saucer Shoot 2 (3 of 3)

Serializing (Marshalling) Objects // Object class methods to support serialization // Serialize Object attributes to single string. // e.g., "id:110,is_active:true, ... // Only modified attributes are serialized (unless all is true). // Clear modified[] array. virtual string serialize(bool all = false); // Deserialize string to become Object attributes. // Return 0 if no errors, else -1. virtual int deserialize(std::string s); // Return true if attribute modified since last serialize. bool isModified(enum ObjectAttribute attribute) const; Derived classes (e.g., game objects) need to (de)serialize own attributes. (See helper functions next slide) Note! You may not need to do this only if derived objects have attributes

that need synchronizing Call parent methods Utility Functions for Serializing // Convert integer to string, returning string. std::string toString(int i); // Convert float to string, returning string. std::string toString(float f); // Convert character to string, returning string. std::string toString(char c); // Convert boolean to string, returning string. std::string toString(bool b); // Match key:value pair in string in str, returning value. // If str is empty, use previously parsed string str. // Return empty string if no match. std::string match(std::string str, std::string

find); Synchronizing Objects (1 of 2) Only synchronize important objects and events (e.g., Hero destruction vs. Stars moving) Synchronizing Objects (2 of 2) Generally, only Host creates/destroys Except for Explosion Generally, Host and Client move and animate Except for Client Hero (see below) Client player Hero get player 2 input Could update ship and synchronize But if not allowed, need to roll back state

Instead, send keystrokes to server Let server move all Objects and send to client Messages Suggested message structure First item is int Has size of entire message (including int) Client can peek at data, not pulling all from socket until size bytes available At least one complete message After pulling message, Host/Client can check type and take appropriate actions Host Client format different than Client Host

Messages Host to Client Host sends game objects to Client Objects are one of New (need to be created) Updated (some attributes changed) Deleted Client will take action appropriate to type delete new Object (check type) For new and update deserialize() based on attributes Could add game over type

HEADER (HC_HEADER_SIZE): + size is one int + message type is another int if NEW then + next int is object type else UPDATE + next int is object id REST is serialized Object data (string) Note, if Object not modified, nothing to send #define HC_HEADER_SIZE 3 * sizeof(int) // Types of messages from Host to Client enum HostMessageType { ADD_OBJECT, UPDATE_OBJECT, DELETE_OBJECT,

}; Messages Client to Host Client sends player commands to Host Messages are one of Keyboard Mouse Client will take action appropriate to type If KEY invoke kbd() on Client Hero If MOUSE invoke mouse() on Client Hero

HEADER (CH_HEADER_SIZE): + size is one int + message type is another int if KEYBOARD then + next int is key else MOUSE + next int is mouse-x + next int is mouse-y #define CH_HEADER_SIZE 2 * sizeof(int) // Types of messages from Host to Client enum ClientHostMessageType { KEY, MOUSE, };

Outline Overview (done) Dragonfly extensions (done) Hints (next) Experiments Hand In Grading

Dragonfly Question-Answer http://alpheus.wpi.edu/dqa/ The LogManager - Functionality Manages output to log file (dragonfly.log) Upon startup opens file (erasing old content) Upon shutdown closes file Printf() style output via writeLog(). E.g., writelog(Player is moving) writelog(Player is moving to (%d,%d), x, y) Can set log level of LogManager (via setLogLevel()) and messages to control verbosity when logging. E.g.,

writelog(3, Player is moving) Using the LogManager (1 of 2) // Get singleton instance of LogManager. LogManager &log_manager = LogManager::getInstance(); // Example call with 1 arg. log_manager.writeLog( NetworkManager::connect(): Socket is open"); // Example call with 2 args. log_manager.writeLog( NetworkManager::receive(): read %d bytes, bytes); // Call with 3 args. log_manager.writeLog( Hero::kbd(): Hero is at is position (%d, %d)", x, y); Using the LogManager (2 of 2)

Tip #2! When calling writeLog() include information: Class name Method name // Sample logfile output: 07:53:30 Log Manager started 07:53:31 GraphicsManager::startUp(): Current window set 07:53:31 GraphicsManager::startUp(): max X is 80, max Y is 24 Once-only Header Files "Redeclaration of class ClassName...? When header included first time, all is normal Defines FILE_FOO_SEEN

When header included second time, FILE_FOO_SEEN defined Conditional is then false So, preprocessor skips entire contents compiler will not see it twice // File foo.h #ifndef FILE_FOO_SEEN #define FILE_FOO_SEEN // The entire foo file appears next. class Foo{ }; #endif // !FILE_FOO_SEEN Protocols and Sockets (recommended) TCP stream oriented, may have part of a message Check that header arrives, header has message size, then check that full

message arrives (optional) UDP frame boundaries (e.g., message) preserved, but message may be lost If matters (could ignore), use sequence numbers to detect Non-blocking Dont want to hang Get byte count (peek) before pulling examining Windows versus Mac/Linux? Mostly same, but some exceptions (next slide) Linux/Mac vs. Windows Linux/Mac Windows

// Header files #include #include #include // for ioctl() #include // for close() #include // Header files #include #include // System calls close() ioctl() // check num bytes, non-block sigaction() // if do signals // Flags

MSG_DONTWAIT // peek recv() // Types socklen_t // System calls closesocket() ioctlsocket() // check num // bytes, non-blocking Multi-platform? (Optional can be misc points) #if defined(_WIN32) || defined(_WIN64) Should be able to isolate all in NetworkManager Single-host Testing Can test via localhost Both games will record keystrokes (Dragonfly notes when key is pressed)

Instead, game can check if mouse inside window (focus follow mouse) // Check if mouse outside game window. sf::RenderWindow *p_win = df::GraphicsManager::getInstance().getWindow(); sf::Vector2i lp = sf::Mouse::getPosition(*p_win); if (lp.x > df::Config::getInstance().getWindowHorizontalPixels() || lp.x < 0 || lp.y > df::Config::getInstance().getWindowVerticalPixels() || lp.y < 0) { // Outside window so don't capture input. } else { // Inside window so don't capture input. } Defined Roles Host or Client Helpful for single code-base game to know if Host or Client

// Role class - Indicate whether game is Host or Client. #ifndef __ROLE_H__ #define __ROLE_H__ class Role { private: Role(); // Private since a singleton. Role (Role const&); // Don't allow copy. void operator=(Role const&); // Don't allow assignment. bool is_host; // True if hosting game. public: // Get the one and only instance of the Role. static Role &getInstance(); // Set host. void setHost(bool is_host = true); // Return true if host. bool isHost() const; };

#endif // __ROLE_H__ Dragonfly Book The book Dragonfly - Program a Game Engine from Scratch guides programmers through the implementation of a fullfeatured, 2d, text-based game engine. If interested: Order for cost (see me) Borrow from IMGD student Outline

Overview (done) Dragonfly extensions (done) Hints (done) Experiments (next) Hand In Grading Experiments (1 of 3) When done (networking and Saucer Shoot 2) Measure: 1) network data rate from server to client

2) network data rate from client to server 3) in-game round trip time Note! Want for game traffic, not X Consider in-game aspects Data rate over time (e.g., game beginning, middle, end) Gameplay during measurements Number of Objects in game (e.g., more saucers as time progresses) Player actions (e.g., frantic moving and shooting) Experiments (2 of 3) Network data rates Instrumenting code to write data out to logfile each packet sent/ received Analysis on packet sizes, packet rates and bitrates

At least one graph of network bitrate (e.g., Kb/s) over time In-game round trip time Timing when player inputs a key until action on screen Logfile messages placed at right points in client code Analysis on average, min and max System call gettimeofday() for system time Multiple measurements Experiments (3 of 3) Design - describe experiments a) how instrumented/measured b) number of runs c) system conditions d) any other relevant details

Results - depict results clearly Tables and/or graphs Statistical analysis where appropriate Analysis - interpret results What the results mean e.g., scalability to more players? Playability over networks? Any subjective analysis Outline

Overview (done) Dragonfly extensions (done) Hints (done) Experiments (done) Hand In (next) Grading Hand In (1 of 2) Source code package All code necessary to build your engine modification (well-structured,

commented) Any other support files, including .h files. Makefile or Project file You do NOT need to turn in any Dragonfly headers or libraries Game code for Saucer Shoot 2: All code necessary to build your game (well-structured, commented) Sprites (including all default sprites) A Makefile README.txt file explaining: Platform How to compile and run Where extra points Experiment document (PDF)

Hand In (2 of 2) Clean and zip up Turn in via Instruct Assist Due at mid-night (11:59pm) Grading Networking Support 30% Socket-based code Integrated with Dragonfly as Manager Saucer Shoot 2 60% Networking Distributed Object synchronization Enhanced gameplay for 2nd player Experiments 5% Design, Results, Analysis

Miscellaneous 5% Flexibility in grading Extra points can apply to any section See detailed grading guide on project Webpage for detailed breakdown Grading Rubric 90-100 The submission clearly exceeds requirements. The functionality is fully implemented and is provided in a robust, bug-free fashion. Full client-host synchronization is evident in the game. Gameplay is effective and fun for two players. All code is well-structured and clearly commented. Experiments effectively test all required measurements. Experimental writeup has the three required sections, with each clearly written and the results clearly depicted. 89-80 The submission meets requirements. The basic functionality is implemented and runs as expected without any critical bugs. Client-host synchronization is effective, but there may be occasional visual glitches that are not critical to gameplay. Gameplay is effective for two players. Code is well-structured and clearly commented. Experimental writeup has the three required sections, with details on the methods used and informative results. 79-70 The submission barely meets requirements. Functionality is mostly implemented, but may not be fully

implemented and/or may not run as expected. Client-host synchronization provides occasional visual glitches, some may be critical to gameplay. Gameplay supports two players, but to a limited extent. Code is only somewhat well-structured and commented. Experiments are incomplete and/or the writeup does not provide clarity on the methods or results. 69-60 The project fails to meet requirements in some places. Networking support is missing critical functionality or robustness. The engine may crash occasionally. The game does not support complete or robust gameplay for two players. Code is lacking in structure or comments. Experiments are incomplete and the writeup does not provide clarity on the methods or results. 59-0 The project does not meet core requirements. The networking extensions cannot compile, crashes consistently, or is lacking many functional features. The game does not compile or does not support two player interaction. Code is only lacking structure and comments. Experiments are incomplete with a minimal writeup. Previous Results CS4513 D-term 2014

Mark Claypool. Teaching Network Game Programming with the Dragonfly Game Eng ine , Syllabus Journal - Special Issue on Teaching with and about Video Games, Vol. 4, No. 1, 2015. Online at: http://www.cs.wpi.edu/~claypool/papers/dragonfly-networking/ Grades Distributed Systems Game Engines Networking C++

Hours Spent

Recently Viewed Presentations

  • Stroke is bad, but worsening is worse

    Stroke is bad, but worsening is worse

    The CT scan of the brain was reported to show a cluster of subcentimeter hypodensities which has developed in the right corona read out and centrum semiovale. Impression was that this was consistent with evolving changes related to recent infarct...
  • 2016 Statistical Report Training 2016 Statistical Report Training

    2016 Statistical Report Training 2016 Statistical Report Training

    Money spent on the church's own programs (i.e. Education, music, church dinners, or VBS) Do Not include Subsidiary Organization Expenses. Defined as local church programs that has its own structure. (i.e. Preschool, adult daycare, food pantry, or . cemetery) These...
  • Kantian Ethics Exam Questions - Weebly

    Kantian Ethics Exam Questions - Weebly

    Kantian ethics is based upon the teachings of the philosopher, Immanuel Kant (1724-1804) consisting of the importance of duty, good will and the categorical imperative. Kant's theory of ethics is . deontological. meaning that an action is good or bad,...
  • CUNYfirst Genesis

    CUNYfirst Genesis

    CUNYfirst is… Largest ERP implementation in higher education. 250,000 students and 50,000 employees daily. 24 community, senior and professional/honors colleges with diverse academic calendars and requirements
  • La explicación científica

    La explicación científica

    El explanans ofrece credibilidad racional al explanandum. La explicación de leyes. El modelo de cobertura legal es aplicable también para la explicación de regularidades o leyes. A diferencia de las explicaciones de hechos o sucesos particulares, en las explicaciones de...
  • Stafford Afternoons - LANG-LIT A LEVEL

    Stafford Afternoons - LANG-LIT A LEVEL

    and flowering nettles gathered spit in their throats. Within the first line the writer knows of the danger present, however, the feeling of being thrilled drives their curiosity. Again the writer uses the personification of nature to describe her environment,...
  • Building Buddies with a Bee Bop - flmusiced.org

    Building Buddies with a Bee Bop - flmusiced.org

    Building Buddies with a Bee Bop. Meeting the Needs of the Young Child With Autism Through Music. What is Autism Spectrum Disorder? As defined by Autism Speaks, Autism spectrum disorder (ASD) and autism are both general terms for a group...
  • General Chemistry 1 Sections 7-12

    General Chemistry 1 Sections 7-12

    The First Three Quantum Numbers n, l, and ml are integers n = principal quantum # = 1, 2, 3, … n tells us the size/energy of the orbital l = angular momentum quantum # = 0, 1, 2, …,...