simple proto *almost* works
authorterom
Sun, 09 Nov 2008 21:51:13 +0000
changeset 25 af75a1894a32
parent 24 b81cb670e6b2
child 26 5685602aeb9c
simple proto *almost* works
src/proto2/Application.cc
src/proto2/Dimension.hh
src/proto2/Drawer.cc.disabled
src/proto2/Engine.cc
src/proto2/Engine.hh
src/proto2/GameState.hh
src/proto2/Graphics.cc
src/proto2/Graphics.hh
src/proto2/Network.hh
src/proto2/NetworkClient.cc
src/proto2/NetworkClient.hh
src/proto2/NetworkServer.cc
--- a/src/proto2/Application.cc	Sun Nov 09 20:40:46 2008 +0000
+++ b/src/proto2/Application.cc	Sun Nov 09 21:51:13 2008 +0000
@@ -23,25 +23,29 @@
     private:
         // arguments
         CL_CommandLine args;
-
+        
+        bool arg_graphics;
         std::string arg_port;
-        bool arg_dedicated;
+        bool arg_server;
         std::string arg_connect;
 
         void parse_args (int argc, char **argv) {
             // set up the options
             args.add_option('p', "port", "PORT", "set network port used", true);
-            args.add_option('D', "dedicated", "", "act as a network server", true);
-            args.add_option('c', "connect", "SERVERHOST", "act as a network client", true);
+            args.add_option('s', "server", "", "act as a network server", true);
+            args.add_option('c', "client", "SERVERHOST", "act as a network client", true);
+            args.add_option('g', "graphics", "", "run graphics/local input. Implied with --connect", true);
 
             // set defaults
+            arg_graphics = false;
             arg_port = NETWORK_PORT_STR;
-            arg_dedicated = false;
+            arg_server = false;
             arg_connect = "";
             
             try {
                 // parse args
                 args.parse_args(argc, argv);
+
             } catch (CL_Error &e) {
                 throw ArgumentError(e.message);
             }
@@ -52,12 +56,17 @@
                         arg_port = args.get_argument();
                         break;
 
-                    case 'D':
-                        arg_dedicated = true;
+                    case 's':
+                        arg_server = true;
                         break;
 
                     case 'c':
                         arg_connect = args.get_argument();
+                        arg_graphics = true;
+                        break;
+
+                    case 'g':
+                        arg_graphics = true;
                         break;
 
                     case CL_CommandLine::REST_ARG:
@@ -70,31 +79,41 @@
             }
             
             // check for valid combinations of arugments
-            if (arg_dedicated && !arg_connect.empty())
-                throw ArgumentError("-D and -c are mutually exclusive");
-            
-            if (!arg_dedicated && arg_connect.empty())
-                throw ArgumentError("nothing to do");
+            if (!(arg_server xor !arg_connect.empty()))
+                throw ArgumentError("must supply *exactly* one of --server/--client");
         }
 
     public:
         virtual int main (int argc, char **argv) {
-            // initialize core
+            // initialize the ClanLib components that we use
             CL_SetupCore setup_core;
-            
+            CL_SetupNetwork setup_network;
+            CL_SetupDisplay setup_disp;
+            CL_SetupGL setup_gl;
+
             try {
                 // parse arugments
                 parse_args(argc, argv);
+
+                // our engine
+                Engine engine;
                 
-                // run engine based on args
-                if (arg_dedicated) {
-                    Engine::runNetworkServer(arg_port);
+                // setup graphics
+                if (arg_graphics)
+                    engine.setupGraphics();
+
+                // setup either network server or client
+                if (arg_server) {
+                    engine.setupNetworkServer(arg_port);
 
                 } else if (!arg_connect.empty()) {
-                    Engine::runNetworkClient(arg_connect, arg_port);
+                    engine.setupNetworkClient(arg_connect, arg_port);
                 
                 } else
                     assert(false);
+
+                // run the main loop
+                engine.run();
                 
                 // succesful return
                 return 0;
--- a/src/proto2/Dimension.hh	Sun Nov 09 20:40:46 2008 +0000
+++ b/src/proto2/Dimension.hh	Sun Nov 09 21:51:13 2008 +0000
@@ -5,18 +5,18 @@
 
 class Dimension {
     public:
-        uint32_t width;
-        uint32_t height;
+        uint32_t w;
+        uint32_t h;
 
-        Dimension (uint32_t width, uint32_t height) : width(width), height(height) { }
+        Dimension (uint32_t w, uint32_t h) : w(w), h(h) { }
 };
 
 class PositionDelta {
     public:
-        uint32_t dx;
-        uint32_t dy;
+        int32_t dx;
+        int32_t dy;
 
-        PositionDelta (uint32_t dx, uint32_t dy) : dx(dx), dy(dy) { }
+        PositionDelta (int32_t dx, int32_t dy) : dx(dx), dy(dy) { }
 };
 
 class Coordinate {
@@ -33,15 +33,14 @@
             return *this;
         }
 
-        uint32_t scaledX() {
-            // Scale the coordinate so that it 
-            // matches the pixel resolution
-            return this->x/1;
+        Coordinate operator+ (const PositionDelta &d) {
+            return Coordinate(x + d.dx, y + d.dy);
         }
 
-        uint32_t scaledY() {
-            return this->y/1;
-        }
+        // Scale the coordinate so that it matches the pixel resolution
+        uint32_t scaledX() { return x; }
+
+        uint32_t scaledY() { return y; }
 };
 
 std::ostream& operator<< (std::ostream &s, const Coordinate &c);
--- a/src/proto2/Drawer.cc.disabled	Sun Nov 09 20:40:46 2008 +0000
+++ b/src/proto2/Drawer.cc.disabled	Sun Nov 09 21:51:13 2008 +0000
@@ -7,70 +7,70 @@
 
 class CL_Game : public CL_ClanApplication {
 private:
-	bool keep_going;
-	void check_input() {
-		if(CL_Keyboard::get_keycode(CL_KEY_ESCAPE))
-			keep_going = false;
-			
+        bool keep_going;
+        void check_input() {
+                if(CL_Keyboard::get_keycode(CL_KEY_ESCAPE))
+                        keep_going = false;
+                        
         LocalPlayer& lp = gs.getLocalPlayer();
 
-		if(CL_Keyboard::get_keycode(CL_KEY_UP)) {
-			lp.doMovement(PositionDelta(0,3));
-		}
-		if(CL_Keyboard::get_keycode(CL_KEY_DOWN)) {
-			lp.doMovement(PositionDelta(0,-3));
-		}
-		if(CL_Keyboard::get_keycode(CL_KEY_LEFT)) {
-			lp.doMovement(PositionDelta(-3,0));
-		}
-		if(CL_Keyboard::get_keycode(CL_KEY_RIGHT)) {
-			lp.doMovement(PositionDelta(3,0));
-		}
-	}
+                if(CL_Keyboard::get_keycode(CL_KEY_UP)) {
+                        lp.doMovement(PositionDelta(0,3));
+                }
+                if(CL_Keyboard::get_keycode(CL_KEY_DOWN)) {
+                        lp.doMovement(PositionDelta(0,-3));
+                }
+                if(CL_Keyboard::get_keycode(CL_KEY_LEFT)) {
+                        lp.doMovement(PositionDelta(-3,0));
+                }
+                if(CL_Keyboard::get_keycode(CL_KEY_RIGHT)) {
+                        lp.doMovement(PositionDelta(3,0));
+                }
+        }
 
 public:
-	GameState gs;
-
-	CL_Game() : keep_going(true) {}
-	virtual int main(int argc, char **argv) {
-		CL_SetupCore setup_init;
-		CL_SetupDisplay setup_disp;
-		CL_SetupGL setup_gl;
-		
-		//gs.player_list.push(Player(Coordinate()));
+        GameState gs;
 
-		CL_DisplayWindow win("ikkuna", 640, 480);
-//		CL_Surface bg(CL_PNGProvider("image.png");
+        CL_Game() : keep_going(true) {}
+        virtual int main(int argc, char **argv) {
+                CL_SetupCore setup_init;
+                CL_SetupDisplay setup_disp;
+                CL_SetupGL setup_gl;
+                
+                //gs.player_list.push(Player(Coordinate()));
 
-		unsigned int last_draw = CL_System::get_time();
-		int r = 100, g = 100, b = 100;
-		unsigned int frame_count = 0;
-		bool R = false, G = false, B = false;
+                CL_DisplayWindow win("ikkuna", 640, 480);
+//              CL_Surface bg(CL_PNGProvider("image.png");
 
-		while(keep_going) { //not good idea to put infinite loop
-			CL_Display::clear(CL_Color(r, g, b));
+                unsigned int last_draw = CL_System::get_time();
+                int r = 100, g = 100, b = 100;
+                unsigned int frame_count = 0;
+                bool R = false, G = false, B = false;
+
+                while(keep_going) { //not good idea to put infinite loop
+                        CL_Display::clear(CL_Color(r, g, b));
             
-			int colorIdx = 0;
-			for(std::list<Player>::iterator it = gs.player_list.begin(); it != gs.player_list.end(); ++it) {
-
-				CL_Display::fill_rect(CL_Rect(it->getPosition().scaledX()-10, it->getPosition().scaledY()-10, 
-					it->getPosition().scaledX()+10, it->getPosition().scaledY()+10), CL_Color((colorIdx*30)%255, (colorIdx*30)%255, (colorIdx*30)%255));
+                        int colorIdx = 0;
+                        for(std::list<Player>::iterator it = gs.player_list.begin(); it != gs.player_list.end(); ++it) {
 
-				colorIdx++;
-			}
- 			
-			CL_Display::flip(1);
-			frame_count++;
-			unsigned int cur_draw = CL_System::get_time();
-		
-			check_input();
+                                CL_Display::fill_rect(CL_Rect(it->getPosition().scaledX()-10, it->getPosition().scaledY()-10, 
+                                        it->getPosition().scaledX()+10, it->getPosition().scaledY()+10), CL_Color((colorIdx*30)%255, (colorIdx*30)%255, (colorIdx*30)%255));
 
-			last_draw = cur_draw;
-			CL_System::keep_alive();
-//			sleep(10); //flip already wait a short amount of time
-		}
-		return 0;
-	}
+                                colorIdx++;
+                        }
+                        
+                        CL_Display::flip(1);
+                        frame_count++;
+                        unsigned int cur_draw = CL_System::get_time();
+                
+                        check_input();
+
+                        last_draw = cur_draw;
+                        CL_System::keep_alive();
+//                      sleep(10); //flip already wait a short amount of time
+                }
+                return 0;
+        }
 };
 
 CL_Game inst;
--- a/src/proto2/Engine.cc	Sun Nov 09 20:40:46 2008 +0000
+++ b/src/proto2/Engine.cc	Sun Nov 09 21:51:13 2008 +0000
@@ -1,6 +1,5 @@
 
 #include "Engine.hh"
-#include "GameState.hh"
 #include "NetworkServer.hh"
 #include "NetworkClient.hh"
 
@@ -10,53 +9,29 @@
 
 }
 
-void Engine::runNetworkServer (const std::string &listen_port) {
-    // the engine
-    Engine engine;
-    
-    // setup network
-    CL_SetupNetwork setup_network;
-
-    try {
-        // create the server
-        engine.net_server = new NetworkServer(engine.game_state, listen_port);
-
-        // run the main loop
-        engine.main_loop();
-    
-    } catch (CL_Error &e) {
-        std::cerr << "NetworkServer::main: CL_Error:" << e.message << std::endl;
-
-        throw;
-    }
+void Engine::setupGraphics (void) {
+    // create the graphics
+    graphics = new Graphics(*this, game_state);
 }
 
-void Engine::runNetworkClient (const std::string &connect_host, const std::string &connect_port) {
-    // the engine
-    Engine engine;
-    
-    // setup network
-    CL_SetupNetwork setup_network;
+void Engine::setupNetworkServer (const std::string &listen_port) {
+    // create the server
+    net_server = new NetworkServer(game_state, listen_port);
+}
 
+void Engine::setupNetworkClient (const std::string &connect_host, const std::string &connect_port) {
     // connect_to
     CL_IPAddress connect_addr(connect_host, connect_port);
 
-    try {
-        // create the server
-        engine.net_client = new NetworkClient(engine.game_state, connect_addr);
-
-        // run the main loop
-        engine.main_loop();
-    
-    } catch (CL_Error &e) {
-        std::cerr << "NetworkServer::main: CL_Error:" << e.message << std::endl;
-
-        throw;
-    }
-
+    // create the client
+    net_client = new NetworkClient(game_state, connect_addr);
 }
 
-void Engine::main_loop (void) {
+void Engine::stop (void) {
+    is_running = false;
+}
+
+void Engine::run (void) {
     while (is_running) {
         // this does.... magical things
         CL_System::keep_alive();
@@ -65,7 +40,6 @@
         // ideally, we should be able to have a main loop that does timed waits on I/O, fufilling some set of timers
         // but as far as I can tell, ClanLib doesn't have anything like that
         CL_System::sleep(100);
-
     }
 }
 
--- a/src/proto2/Engine.hh	Sun Nov 09 20:40:46 2008 +0000
+++ b/src/proto2/Engine.hh	Sun Nov 09 21:51:13 2008 +0000
@@ -1,4 +1,11 @@
+#ifndef ENGINE_HH
+#define ENGINE_HH
 
+// XXX: forward-declare Engine for other components
+class Engine;
+
+#include "GameState.hh"
+#include "Graphics.hh"
 #include "NetworkServer.hh"
 #include "NetworkClient.hh"
 
@@ -9,25 +16,38 @@
         // game state
         GameState game_state;
         
+        // Graphics/Input
+        Graphics *graphics;
+
         // network server/client
         NetworkServer *net_server;
         NetworkClient *net_client;
 
         // to exit the mainloop
         bool is_running;
-        
+    
+    public:    
         // default constructor
         Engine (void);
 
-    public:
-        static void runNetworkServer (const std::string &listen_port);
-        static void runNetworkClient (const std::string &connect_host, const std::string &connect_port);
+        // setup graphics
+        void setupGraphics (void);
         
-                // logging utility
+        // set up network server/client
+        // setting up both of these will lead to odd behaviour :)
+        void setupNetworkServer (const std::string &listen_port);
+        void setupNetworkClient (const std::string &connect_host, const std::string &connect_port);
+        
+        // run the main loop
+        void run (void);
+
+        // terminate the main loop
+        void stop (void);
+
+    public:
+        // logging utility
         static Logger log (enum LogLevel level, const char *type);
 
-    private:
-        void main_loop (void);
-
 };
 
+#endif /* ENGINE_HH */
--- a/src/proto2/GameState.hh	Sun Nov 09 20:40:46 2008 +0000
+++ b/src/proto2/GameState.hh	Sun Nov 09 21:51:13 2008 +0000
@@ -29,12 +29,26 @@
         bool visible;
 
         Coordinate getPosition (void) const {
-            return this->position;
+            return position;
         }
     
     protected:
-        void updatePosition (Coordinate p) {
-            this->position = p;
+        /*
+         * Update position to the given value.
+         *
+         * Returns true if valid move (not out of bounds), false otherwise (doesn't change position)
+         */
+        bool updatePosition (Coordinate p) {
+            // unsigned...
+            if (p.x > dimensions.w || p.y > dimensions.h) {
+                // out-of-bounds
+                return false;
+            }
+
+            // valid
+            position = p;
+
+            return true;
         }
 
 };
@@ -44,8 +58,10 @@
         LocalPlayer (Coordinate c, bool visible) : Player(c, visible) { }
     
     public:
-        virtual void move (PositionDelta d) {
-            this->position += d;
+        virtual bool move (PositionDelta d) {
+            return true;
+
+            //return updatePosition(position + d);
         }
 };
 
@@ -66,12 +82,12 @@
         GameState (void) : map_dimensions(MAP_DIM_W, MAP_DIM_H), local_player(NULL) {
 
         }
-
-        LocalPlayer &getLocalPlayer (void) {
-            if (!local_player)
-                throw std::logic_error("getLocalPlayer called with no local player");
-            
-            return *local_player;
+        
+        /*
+         * This will return NULL if we don't have a local player - yet
+         */
+        LocalPlayer *getLocalPlayer (void) {
+            return local_player;
         }
         
         void newLocalPlayer (LocalPlayer *player) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/proto2/Graphics.cc	Sun Nov 09 21:51:13 2008 +0000
@@ -0,0 +1,80 @@
+
+#include "Graphics.hh"
+
+Graphics::Graphics (Engine &engine, GameState &state) :
+    engine(engine), 
+    state(state), 
+    update_timer(GRAPHICS_UPDATE_INTERVAL_MS),
+    win(GRAPHICS_WINDOW_TITLE, MAP_DIM_W, MAP_DIM_H), 
+    keyboard(win.get_ic()->get_keyboard()) {
+    
+    // connect timer signal
+    slots.connect(update_timer.sig_timer(), this, &Graphics::on_update);
+
+    // enable
+    update_timer.enable();
+}
+
+void Graphics::check_input (void) {
+    LocalPlayer *player;
+    int dx = 0, dy = 0;
+    
+    // stop on escape
+    if (keyboard.get_keycode(CL_KEY_ESCAPE)) {
+            engine.stop();
+
+            return;
+    }
+     
+    // ignore if we don't have a local player
+    if ((player = state.getLocalPlayer()) == NULL)
+        return;
+    
+    // handle up/down/left/right
+    if (keyboard.get_keycode(CL_KEY_UP))
+            dy -= 3;
+
+    if (keyboard.get_keycode(CL_KEY_DOWN))
+            dy += 3;
+
+    if (keyboard.get_keycode(CL_KEY_LEFT))
+            dx -= 3;
+
+    if (keyboard.get_keycode(CL_KEY_RIGHT))
+            dx += 3;
+    
+    // apply movement if applicable
+    if (dx || dy)
+        player->move(PositionDelta(dx, dy));
+}
+
+void Graphics::do_redraw (void) {
+    CL_GraphicContext *gc = win.get_gc();
+    
+    // white background
+    gc->clear(CL_Color::white);
+
+    // draw players
+    for (std::list<Player*>::iterator it = state.player_list.begin(); it != state.player_list.end(); it++) {
+        Player *p = *it;
+        
+        // draw square
+        gc->fill_rect(
+            CL_Rect(
+                p->getPosition().x - 5, p->getPosition().y - 5,
+                p->getPosition().x + 5, p->getPosition().y + 5
+            ), CL_Color::black
+        );
+    }
+
+    // flip window buffer, LIEK NAO
+    win.flip(0);
+}
+
+void Graphics::on_update (void) {
+    // check keyboard input
+    check_input();
+
+    // redraw display
+    do_redraw();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/proto2/Graphics.hh	Sun Nov 09 21:51:13 2008 +0000
@@ -0,0 +1,40 @@
+#ifndef GRAPHICS_HH
+#define GRAPHICS_HH
+
+// XXX: forward-declare for Engine
+class Graphics;
+
+#include "GameState.hh"
+#include "Engine.hh"
+
+#include <ClanLib/core.h>
+#include <ClanLib/gl.h>
+#include <ClanLib/display.h>
+
+#define GRAPHICS_WINDOW_TITLE "Kisna Glista"
+#define GRAPHICS_UPDATE_INTERVAL_MS 100
+
+class Graphics {
+    private:
+        Engine &engine;
+        GameState &state;
+    
+        CL_SlotContainer slots;
+
+        CL_Timer update_timer;
+        
+        CL_DisplayWindow win;
+        CL_InputDevice &keyboard;
+    
+    public:
+        Graphics (Engine &engine, GameState &state);
+
+    private:
+        void check_input (void);
+        void do_redraw (void);
+
+        void on_update (void);
+
+};
+
+#endif /* GRAPHICS_HH */
--- a/src/proto2/Network.hh	Sun Nov 09 20:40:46 2008 +0000
+++ b/src/proto2/Network.hh	Sun Nov 09 21:51:13 2008 +0000
@@ -48,8 +48,8 @@
     /*
      * Client has moved
      *
-     *  uint32_t dx
-     *  uint32_t dy
+     *  int32_t dx
+     *  int32_t dy
      */
     NETMSG_CLIENT_MOVE  = 0x0201,
     
--- a/src/proto2/NetworkClient.cc	Sun Nov 09 20:40:46 2008 +0000
+++ b/src/proto2/NetworkClient.cc	Sun Nov 09 21:51:13 2008 +0000
@@ -3,6 +3,8 @@
 #include "Engine.hh"
 #include "Logger.hh"
 
+#include <cassert>
+
 NetworkClient::NetworkClient (GameState &state, const CL_IPAddress &connect_to) : 
     NetworkCore(state), server(netsession.connect(connect_to)) {
     
@@ -99,12 +101,16 @@
     slots.connect(obj.sig_received_message(NETMSG_PLAYER_POSITION), this, &NetworkClientLocalPlayer::on_position);
 }
         
-void NetworkClientLocalPlayer::move (PositionDelta d) {
+bool NetworkClientLocalPlayer::move (PositionDelta d) {
+    // always send move, in all cases
     CL_NetPacket pkt;
-    pkt.output.write_uint32(d.dx);
-    pkt.output.write_uint32(d.dy);
+    pkt.output.write_int32(d.dx);
+    pkt.output.write_int32(d.dy);
 
     obj.send(NETMSG_CLIENT_MOVE, pkt, false);
+
+    // return validity
+    return LocalPlayer::move(d);
 }
         
 void NetworkClientLocalPlayer::on_position (CL_NetPacket &pkt) {
@@ -134,7 +140,7 @@
 
     Engine::log(INFO, "client_player.on_position") << "obj=" << obj << ", pos=" << pos;
     
-    updatePosition(pos);
+    assert(updatePosition(pos));
 }
 
 void NetworkClientRemotePlayer::on_quit (CL_NetPacket &pkt) {
--- a/src/proto2/NetworkClient.hh	Sun Nov 09 20:40:46 2008 +0000
+++ b/src/proto2/NetworkClient.hh	Sun Nov 09 21:51:13 2008 +0000
@@ -36,7 +36,7 @@
     public:
         NetworkClientLocalPlayer (NetworkClient &client, CL_NetObject_Client &obj, Coordinate initial_position);
         
-        virtual void move (PositionDelta d);
+        virtual bool move (PositionDelta d);
     
     private:
         void on_position (CL_NetPacket &pkt);
--- a/src/proto2/NetworkServer.cc	Sun Nov 09 20:40:46 2008 +0000
+++ b/src/proto2/NetworkServer.cc	Sun Nov 09 21:51:13 2008 +0000
@@ -48,7 +48,7 @@
 }
         
 NetworkServerPlayer::NetworkServerPlayer (NetworkServer &server, CL_NetComputer &computer, uint16_t pid) : 
-    RemotePlayer(Coordinate(0, 0), true), server(server), computer(computer), obj(&server.netobjs), pid(pid) {
+    RemotePlayer(Coordinate(100, 100), true), server(server), computer(computer), obj(&server.netobjs), pid(pid) {
     
     // log
     Engine::log(INFO, "server_player.connected") << "computer=" << computer << ", obj=" << obj;
@@ -96,8 +96,8 @@
         return;
     
     // read packet
-    uint32_t dx = pkt.input.read_uint32();
-    uint32_t dy = pkt.input.read_uint32();
+    int32_t dx = pkt.input.read_int32();
+    int32_t dy = pkt.input.read_int32();
 
     // movement delta
     PositionDelta delta(dx, dy);