# HG changeset patch # User terom # Date 1226267473 0 # Node ID af75a1894a32dbba57940f94369427500648e0b5 # Parent b81cb670e6b2ebb68324d7a8184dc8b273cf8bcb simple proto *almost* works diff -r b81cb670e6b2 -r af75a1894a32 src/proto2/Application.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; diff -r b81cb670e6b2 -r af75a1894a32 src/proto2/Dimension.hh --- 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); diff -r b81cb670e6b2 -r af75a1894a32 src/proto2/Drawer.cc.disabled --- 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::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::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; diff -r b81cb670e6b2 -r af75a1894a32 src/proto2/Engine.cc --- 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); - } } diff -r b81cb670e6b2 -r af75a1894a32 src/proto2/Engine.hh --- 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 */ diff -r b81cb670e6b2 -r af75a1894a32 src/proto2/GameState.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) { diff -r b81cb670e6b2 -r af75a1894a32 src/proto2/Graphics.cc --- /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::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(); +} diff -r b81cb670e6b2 -r af75a1894a32 src/proto2/Graphics.hh --- /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 +#include +#include + +#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 */ diff -r b81cb670e6b2 -r af75a1894a32 src/proto2/Network.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, diff -r b81cb670e6b2 -r af75a1894a32 src/proto2/NetworkClient.cc --- 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 + 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) { diff -r b81cb670e6b2 -r af75a1894a32 src/proto2/NetworkClient.hh --- 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); diff -r b81cb670e6b2 -r af75a1894a32 src/proto2/NetworkServer.cc --- 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);