--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/build/mkcmake.sh Tue Nov 18 22:58:50 2008 +0000
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+cmake ../ -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/tmp
+
--- a/plan/diagram.dot Mon Nov 10 21:58:38 2008 +0000
+++ b/plan/diagram.dot Tue Nov 18 22:58:50 2008 +0000
@@ -19,7 +19,7 @@
subgraph cluster1 {
label = "Game Engine";
- {rank=min; gs; physics; }
+ {rank=min; gs; physics;}
gs;
physics;
color = black;
--- a/plan/test.ps Mon Nov 10 21:58:38 2008 +0000
+++ b/plan/test.ps Tue Nov 18 22:58:50 2008 +0000
@@ -410,3 +410,4 @@
end
restore
%%EOF
+
--- a/src/proto2/Application.cc Mon Nov 10 21:58:38 2008 +0000
+++ b/src/proto2/Application.cc Tue Nov 18 22:58:50 2008 +0000
@@ -78,9 +78,9 @@
}
}
- // check for valid combinations of arugments
- if (!(arg_server xor !arg_connect.empty()))
- throw ArgumentError("must supply *exactly* one of --server/--client");
+ // check for invalid combinations of arugments
+ if (arg_server and !arg_connect.empty())
+ throw ArgumentError("cannot be both server and client");
}
public:
@@ -102,15 +102,16 @@
if (arg_graphics)
engine.setupGraphics();
- // setup either network server or client
+ // setup either network server, client or singleplayer
if (arg_server) {
engine.setupNetworkServer(arg_port);
} else if (!arg_connect.empty()) {
engine.setupNetworkClient(arg_connect, arg_port);
- } else
- assert(false);
+ } else {
+ engine.setupSinglePlayer();
+ }
// run the main loop
engine.run();
--- a/src/proto2/Dimension.cc Mon Nov 10 21:58:38 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-#include "Dimension.hh"
-
-std::ostream& operator<< (std::ostream &s, const Coordinate &c) {
- s << "(" << c.x << ", " << c.y << ")";
-
- return s;
-}
-
-std::ostream& operator<< (std::ostream &s, const PositionDelta &c) {
- s << "(" << c.dx << ", " << c.dy << ")";
-
- return s;
-}
-
--- a/src/proto2/Dimension.hh Mon Nov 10 21:58:38 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-#ifndef DIMENSION_HH
-#define DIMENSION_HH
-
-#include <iostream>
-
-class Dimension {
- public:
- uint32_t w;
- uint32_t h;
-
- Dimension (uint32_t w, uint32_t h) : w(w), h(h) { }
-};
-
-class PositionDelta {
- public:
- int32_t dx;
- int32_t dy;
-
- PositionDelta (int32_t dx, int32_t dy) : dx(dx), dy(dy) { }
-};
-
-class Coordinate {
- public:
- uint32_t x;
- uint32_t y;
-
- Coordinate (uint32_t x, uint32_t y) : x(x), y(y) { }
-
- Coordinate &operator+= (const PositionDelta &d) {
- this->x += d.dx;
- this->y += d.dy;
-
- return *this;
- }
-
- Coordinate operator+ (const PositionDelta &d) {
- return Coordinate(x + d.dx, y + d.dy);
- }
-
- // 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);
-std::ostream& operator<< (std::ostream &s, const PositionDelta &c);
-
-#endif
--- a/src/proto2/Engine.cc Mon Nov 10 21:58:38 2008 +0000
+++ b/src/proto2/Engine.cc Tue Nov 18 22:58:50 2008 +0000
@@ -2,6 +2,7 @@
#include "Engine.hh"
#include "NetworkServer.hh"
#include "NetworkClient.hh"
+#include "SinglePlayer.hh"
#include <iostream>
@@ -27,6 +28,14 @@
net_client = new NetworkClient(game_state, connect_addr);
}
+void Engine::setupSinglePlayer (void) {
+ // create player directly
+ LocalPlayer* lp = new SinglePlayer(game_state);
+
+ // add to gamestate
+ game_state.newLocalPlayer(lp);
+}
+
void Engine::stop (void) {
is_running = false;
}
@@ -39,7 +48,7 @@
// if I can't find some better way to do this in ClanLib by next thursday, then it f*%!ing sucks
// 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(20);
+ CL_System::sleep(10);
}
}
--- a/src/proto2/Engine.hh Mon Nov 10 21:58:38 2008 +0000
+++ b/src/proto2/Engine.hh Tue Nov 18 22:58:50 2008 +0000
@@ -37,6 +37,7 @@
// 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);
+ void setupSinglePlayer (void);
// run the main loop
void run (void);
--- a/src/proto2/GameState.cc Mon Nov 10 21:58:38 2008 +0000
+++ b/src/proto2/GameState.cc Tue Nov 18 22:58:50 2008 +0000
@@ -1,18 +1,24 @@
#include "GameState.hh"
-bool Player::updatePosition (Coordinate p) {
- if (!state.isValidCoordinate(p)) {
- // out-of-bounds
- return false;
+void LocalPlayer::handleMove (PlayerInput_Move input) {
+ float fx = 0, fy = 0;
- } else {
- // valid
- position = p;
+ // handle up/down/left/right
+ if (input & INPUT_MOVE_UP)
+ fy -= PLAYER_MOVE_FORCE;
+
+ if (input & INPUT_MOVE_DOWN)
+ fy += PLAYER_MOVE_FORCE;
- return true;
+ if (input & INPUT_MOVE_LEFT)
+ fx -= PLAYER_MOVE_FORCE;
+
+ if (input & INPUT_MOVE_RIGHT)
+ fx += PLAYER_MOVE_FORCE;
+
+ if (fx || fy) {
+ // apply force
+ applyForce(Vector(fx, fy), INPUT_INTERVAL_MS);
}
}
-
-
-
--- a/src/proto2/GameState.hh Mon Nov 10 21:58:38 2008 +0000
+++ b/src/proto2/GameState.hh Tue Nov 18 22:58:50 2008 +0000
@@ -1,88 +1,60 @@
#ifndef GAMESTATE_HH
#define GAMESTATE_HH
-#include "Dimension.hh"
+#include "Physics.hh"
+#include "Input.hh"
#include <list>
#include <stdexcept>
-enum PlayerType {
- PLAYER_LOCAL,
- PLAYER_REMOTE
-};
-
-#define PLAYER_DIM_W 10
-#define PLAYER_DIM_H 10
-#define MAP_DIM_W 800
-#define MAP_DIM_H 640
+// in meters/kg
+const float MAP_WIDTH = 100.0;
+const float MAP_HEIGHT = 100.0;
+const float MAP_GRAVITY = 9.81;
+const float PLAYER_MASS = 10.0;
+const float PLAYER_MOVE_FORCE = 500.0;
+const float PLAYER_INITIAL_X = 50.0;
+const float PLAYER_INITIAL_Y = 40.0;
// forward-declare GameState
class GameState;
-class Player {
+class Player : public PhysicsObject {
protected:
- Coordinate position;
-
GameState &state;
+ bool visible;
public:
- Player(GameState &state, Coordinate c, bool visible) : position(c), state(state), dimensions(PLAYER_DIM_W, PLAYER_DIM_H), visible(visible) {}
-
- PlayerType type;
- Dimension dimensions;
- bool visible;
-
- Coordinate getPosition (void) const {
- return position;
- }
-
- protected:
- /*
- * 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);
+ Player(GameState &state, Vector position, bool visible) :
+ PhysicsObject((PhysicsWorld &) state, PLAYER_MASS, position, Vector(0, 0)), state(state), visible(visible) { }
};
class LocalPlayer : public Player {
protected:
- LocalPlayer (GameState &state, Coordinate c, bool visible) : Player(state, c, visible) { }
+ LocalPlayer (GameState &state, Vector pos, bool visible) : Player(state, pos, visible) { }
public:
- virtual bool move (PositionDelta d) {
- return updatePosition(position + d);
- }
+ virtual void handleMove (PlayerInput_Move input);
};
class RemotePlayer : public Player {
protected:
- RemotePlayer (GameState &state, Coordinate c, bool visible) : Player(state, c, visible) { }
-
+ RemotePlayer (GameState &state, Vector pos, bool visible) : Player(state, pos, visible) { }
};
-class GameState {
+class GameState : public PhysicsWorld {
public:
- Dimension map_dimensions;
std::list<Player*> player_list;
// only one local player is supported
LocalPlayer *local_player;
- GameState (void) : map_dimensions(MAP_DIM_W, MAP_DIM_H), local_player(NULL) {
+ GameState (void) : PhysicsWorld(Vector(0, MAP_GRAVITY), Vector(MAP_WIDTH, MAP_HEIGHT)), local_player(NULL) {
}
-
- /*
- * Check if the given coordinate is valid
- */
- bool isValidCoordinate (const Coordinate &p) {
- // unsigned...
- return !(p.x > map_dimensions.w || p.y > map_dimensions.h);
- }
-
+
/*
* This will return NULL if we don't have a local player - yet
*/
--- a/src/proto2/Graphics.cc Mon Nov 10 21:58:38 2008 +0000
+++ b/src/proto2/Graphics.cc Tue Nov 18 22:58:50 2008 +0000
@@ -5,7 +5,7 @@
engine(engine),
state(state),
update_timer(GRAPHICS_UPDATE_INTERVAL_MS),
- win(GRAPHICS_WINDOW_TITLE, MAP_DIM_W, MAP_DIM_H),
+ win(GRAPHICS_WINDOW_TITLE, GRAPHICS_RESOLUTION_WIDTH, GRAPHICS_RESOLUTION_HEIGHT),
keyboard(win.get_ic()->get_keyboard()) {
// connect timer signal
@@ -17,7 +17,7 @@
void Graphics::check_input (void) {
LocalPlayer *player;
- int dx = 0, dy = 0;
+ PlayerInput_Move input_move = 0;
// stop on escape
if (keyboard.get_keycode(CL_KEY_ESCAPE)) {
@@ -32,20 +32,20 @@
// handle up/down/left/right
if (keyboard.get_keycode(CL_KEY_UP))
- dy -= 3;
+ input_move |= INPUT_MOVE_UP;
if (keyboard.get_keycode(CL_KEY_DOWN))
- dy += 3;
+ input_move |= INPUT_MOVE_DOWN;
if (keyboard.get_keycode(CL_KEY_LEFT))
- dx -= 3;
+ input_move |= INPUT_MOVE_LEFT;
if (keyboard.get_keycode(CL_KEY_RIGHT))
- dx += 3;
+ input_move |= INPUT_MOVE_RIGHT;
// apply movement if applicable
- if (dx || dy)
- player->move(PositionDelta(dx, dy));
+ if (input_move)
+ player->handleMove(input_move);
}
void Graphics::do_redraw (void) {
@@ -54,6 +54,9 @@
// white background
gc->clear(CL_Color::white);
+ const float factorX = GRAPHICS_RESOLUTION_WIDTH / MAP_WIDTH;
+ const float factorY = GRAPHICS_RESOLUTION_HEIGHT / MAP_HEIGHT;
+
// draw players
for (std::list<Player*>::iterator it = state.player_list.begin(); it != state.player_list.end(); it++) {
Player *p = *it;
@@ -61,8 +64,8 @@
// draw square
gc->fill_rect(
CL_Rect(
- p->getPosition().x - 5, p->getPosition().y - 5,
- p->getPosition().x + 5, p->getPosition().y + 5
+ p->getPosition().x * factorX - 5, p->getPosition().y * factorY - 5,
+ p->getPosition().x * factorX + 5, p->getPosition().y * factorY + 5
), CL_Color::black
);
}
--- a/src/proto2/Graphics.hh Mon Nov 10 21:58:38 2008 +0000
+++ b/src/proto2/Graphics.hh Tue Nov 18 22:58:50 2008 +0000
@@ -11,8 +11,10 @@
#include <ClanLib/gl.h>
#include <ClanLib/display.h>
-#define GRAPHICS_WINDOW_TITLE "Kisna Glista"
-#define GRAPHICS_UPDATE_INTERVAL_MS 100
+const std::string GRAPHICS_WINDOW_TITLE = "Kisna Glista";
+const uint32_t GRAPHICS_RESOLUTION_WIDTH = 800;
+const uint32_t GRAPHICS_RESOLUTION_HEIGHT = 600;
+const uint16_t GRAPHICS_UPDATE_INTERVAL_MS = 20;
class Graphics {
private:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/proto2/Input.hh Tue Nov 18 22:58:50 2008 +0000
@@ -0,0 +1,15 @@
+#ifndef INPUT_HH
+#define INPUT_HH
+
+const uint16_t INPUT_INTERVAL_MS = 20;
+
+enum {
+ INPUT_MOVE_UP = 0x01,
+ INPUT_MOVE_DOWN = 0x02,
+ INPUT_MOVE_LEFT = 0x04,
+ INPUT_MOVE_RIGHT = 0x08,
+};
+
+typedef uint16_t PlayerInput_Move;
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/proto2/Network.cc Tue Nov 18 22:58:50 2008 +0000
@@ -0,0 +1,41 @@
+
+#include "Network.hh"
+#include "Engine.hh"
+
+void writeVector (CL_NetPacket &pkt, const Vector &vec) {
+ pkt.output.write_float32(vec.x);
+ pkt.output.write_float32(vec.y);
+
+/*
+ int32_t x = vec.x * COORDINATE_MAX / MAP_WIDTH;
+ int32_t y = vec.y * COORDINATE_MAX / MAP_HEIGHT;
+
+ Engine::log(DEBUG, "network.write_vector")
+ << "vec=" << vec << " -> x=" << x << ", y=" << y;
+
+ pkt.output.write_int32(x);
+ pkt.output.write_int32(y);
+*/
+}
+
+Vector readVector (CL_NetPacket &pkt) {
+ float fx = pkt.input.read_float32();
+ float fy = pkt.input.read_float32();
+
+ Vector vec(fx, fy);
+
+/*
+ int32_t x = pkt.input.read_int32();
+ int32_t y = pkt.input.read_int32();
+
+ float fx = x * MAP_WIDTH / COORDINATE_MAX;
+ float fy = y * MAP_HEIGHT / COORDINATE_MAX;
+
+ Vector vec(fx, fy);
+
+ Engine::log(DEBUG, "network.read_vector") << "x=" << x << ", y=" << y << " -> " << vec;
+*/
+
+ return vec;
+}
+
--- a/src/proto2/Network.hh Mon Nov 10 21:58:38 2008 +0000
+++ b/src/proto2/Network.hh Tue Nov 18 22:58:50 2008 +0000
@@ -6,6 +6,8 @@
#include <ClanLib/network.h>
+const int32_t COORDINATE_MAX = 1 << 30;
+
class NetworkCore {
protected:
GameState &state;
@@ -14,24 +16,28 @@
// constructor
NetworkCore (GameState &state) : state(state) { }
+
+
};
+// XXX: util methods
+void writeVector (CL_NetPacket &pkt, const Vector &vec);
+Vector readVector (CL_NetPacket &pkt);
+
enum NetworkMessage {
NETMSG_PACKET_INVALID = 0x00,
/*
* You have joined the game:
*
- * uint32_t x
- * uint32_t y
+ * Vector initial_position
*/
NETMSG_SERVER_HELLO = 0x0100,
/*
* New client has connected to server:
- *
- * uint32_t x
- * uint32_t y
+ *
+ * Vector initial_position
*/
NETMSG_PLAYER_JOIN = 0x0101,
@@ -44,24 +50,23 @@
/*
* Client has moved
*
- * int32_t dx
- * int32_t dy
+ * Vector impulse_force
+ * uint16_t impulse_ms
*/
NETMSG_CLIENT_MOVE = 0x0201,
/*
* Initial player info
*
- * uint32_t x
- * uint32_t y
+ * Vector initial_position
*/
NETMSG_PLAYER_INFO = 0x0300,
/*
* Player position update
*
- * uint32_t x
- * uint32_t y
+ * Vector position
+ * Vector velocity
*/
NETMSG_PLAYER_POSITION = 0x0301,
};
--- a/src/proto2/NetworkClient.cc Mon Nov 10 21:58:38 2008 +0000
+++ b/src/proto2/NetworkClient.cc Tue Nov 18 22:58:50 2008 +0000
@@ -38,15 +38,12 @@
void NetworkClient::on_server_hello (CL_NetObject_Client &obj, CL_NetPacket &pkt) {
// read the packet
- uint32_t x = pkt.input.read_uint32();
- uint32_t y = pkt.input.read_uint32();
-
- Coordinate initial_position(x, y);
+ Vector position = readVector(pkt);
- Engine::log(INFO, "client.on_server_hello") << "obj=" << obj << ", pos=" << initial_position;
+ Engine::log(INFO, "client.on_server_hello") << "obj=" << obj << ", pos=" << position;
// create the LocalPlayer object
- NetworkClientLocalPlayer *player = new NetworkClientLocalPlayer(*this, obj, initial_position);
+ NetworkClientLocalPlayer *player = new NetworkClientLocalPlayer(*this, obj, position);
// inform state
state.newLocalPlayer(player);
@@ -54,15 +51,12 @@
void NetworkClient::on_player_info (CL_NetObject_Client &obj, CL_NetPacket &pkt) {
// read the packet
- uint32_t x = pkt.input.read_uint32();
- uint32_t y = pkt.input.read_uint32();
+ Vector position = readVector(pkt);
- Coordinate initial_position(x, y);
-
- Engine::log(INFO, "client.on_player_info") << "obj=" << obj << ", pos=" << initial_position;
+ Engine::log(INFO, "client.on_player_info") << "obj=" << obj << ", pos=" << position;
// create the LocalPlayer object
- NetworkClientRemotePlayer *player = new NetworkClientRemotePlayer(*this, obj, initial_position);
+ NetworkClientRemotePlayer *player = new NetworkClientRemotePlayer(*this, obj, position);
// inform state
state.newRemotePlayer(player);
@@ -71,15 +65,12 @@
void NetworkClient::on_player_join (CL_NetObject_Client &obj, CL_NetPacket &pkt) {
// read the packet
- uint32_t x = pkt.input.read_uint32();
- uint32_t y = pkt.input.read_uint32();
+ Vector position = readVector(pkt);
- Coordinate initial_position(x, y);
-
- Engine::log(INFO, "client.on_player_join") << "obj=" << obj << ", pos=" << initial_position;
+ Engine::log(INFO, "client.on_player_join") << "obj=" << obj << ", pos=" << position;
// create the RemotePlayer object
- NetworkClientRemotePlayer *player = new NetworkClientRemotePlayer(*this, obj, initial_position);
+ NetworkClientRemotePlayer *player = new NetworkClientRemotePlayer(*this, obj, position);
// inform state
state.newRemotePlayer(player);
@@ -94,38 +85,36 @@
// delete player;
}
-NetworkClientLocalPlayer::NetworkClientLocalPlayer (NetworkClient &client, CL_NetObject_Client &obj, Coordinate initial_position) :
- LocalPlayer(client.state, initial_position, true), client(client), obj(obj) {
+NetworkClientLocalPlayer::NetworkClientLocalPlayer (NetworkClient &client, CL_NetObject_Client &obj, Vector position) :
+ LocalPlayer(client.state, position, true), client(client), obj(obj) {
// receive messages
slots.connect(obj.sig_received_message(NETMSG_PLAYER_POSITION), this, &NetworkClientLocalPlayer::on_position);
}
-bool NetworkClientLocalPlayer::move (PositionDelta d) {
+void NetworkClientLocalPlayer::applyForce (Vector force, uint16_t dt) {
// always send move, in all cases
CL_NetPacket pkt;
- pkt.output.write_int32(d.dx);
- pkt.output.write_int32(d.dy);
+ writeVector(pkt, force);
+ pkt.output.write_uint16(dt);
obj.send(NETMSG_CLIENT_MOVE, pkt, false);
-
- // return validity
- return LocalPlayer::move(d);
+
+ // do not handle locally
}
void NetworkClientLocalPlayer::on_position (CL_NetPacket &pkt) {
- uint32_t x = pkt.input.read_uint32();
- uint32_t y = pkt.input.read_uint32();
+ Vector position = readVector(pkt);
+ Vector velocity = readVector(pkt);
- Coordinate pos (x, y);
-
- Engine::log(INFO, "client_player.on_position") << "obj=" << obj << ", pos=" << pos;
+ Engine::log(INFO, "client_player.on_position") << "obj=" << obj << ", position=" << position << ", velocity=" << velocity;
- assert(updatePosition(pos));
+ // just update...
+ updatePhysics(position, velocity);
}
-NetworkClientRemotePlayer::NetworkClientRemotePlayer (NetworkClient &client, CL_NetObject_Client &obj, Coordinate initial_position) :
- RemotePlayer(client.state, initial_position, true), client(client), obj(obj) {
+NetworkClientRemotePlayer::NetworkClientRemotePlayer (NetworkClient &client, CL_NetObject_Client &obj, Vector position) :
+ RemotePlayer(client.state, position, true), client(client), obj(obj) {
// receive messages
slots.connect(obj.sig_received_message(NETMSG_PLAYER_POSITION), this, &NetworkClientRemotePlayer::on_position);
@@ -133,14 +122,13 @@
}
void NetworkClientRemotePlayer::on_position (CL_NetPacket &pkt) {
- uint32_t x = pkt.input.read_uint32();
- uint32_t y = pkt.input.read_uint32();
+ Vector position = readVector(pkt);
+ Vector velocity = readVector(pkt);
+
+ Engine::log(INFO, "client_player.on_position") << "obj=" << obj << ", position=" << position << ", velocity=" << velocity;
- Coordinate pos (x, y);
-
- Engine::log(INFO, "client_player.on_position") << "obj=" << obj << ", pos=" << pos;
-
- assert(updatePosition(pos));
+ // just update...
+ updatePhysics(position, velocity);
}
void NetworkClientRemotePlayer::on_quit (CL_NetPacket &pkt) {
--- a/src/proto2/NetworkClient.hh Mon Nov 10 21:58:38 2008 +0000
+++ b/src/proto2/NetworkClient.hh Tue Nov 18 22:58:50 2008 +0000
@@ -38,9 +38,9 @@
CL_NetObject_Client obj;
public:
- NetworkClientLocalPlayer (NetworkClient &client, CL_NetObject_Client &obj, Coordinate initial_position);
+ NetworkClientLocalPlayer (NetworkClient &client, CL_NetObject_Client &obj, Vector initial_position);
- virtual bool move (PositionDelta d);
+ virtual void applyForce (Vector force, uint16_t dt);
private:
void on_position (CL_NetPacket &pkt);
@@ -55,7 +55,7 @@
CL_NetObject_Client obj;
public:
- NetworkClientRemotePlayer (NetworkClient &client, CL_NetObject_Client &obj, Coordinate initial_position);
+ NetworkClientRemotePlayer (NetworkClient &client, CL_NetObject_Client &obj, Vector initial_position);
private:
void on_position (CL_NetPacket &pkt);
--- a/src/proto2/NetworkServer.cc Mon Nov 10 21:58:38 2008 +0000
+++ b/src/proto2/NetworkServer.cc Tue Nov 18 22:58:50 2008 +0000
@@ -48,7 +48,7 @@
}
NetworkServerPlayer::NetworkServerPlayer (NetworkServer &server, CL_NetComputer &computer, uint16_t pid) :
- RemotePlayer(server.state, Coordinate(100, 100), true), server(server), computer(computer), obj(&server.netobjs), pid(pid) {
+ RemotePlayer(server.state, Vector(PLAYER_INITIAL_X, PLAYER_INITIAL_Y), true), server(server), computer(computer), obj(&server.netobjs), pid(pid) {
// log
Engine::log(INFO, "server_player.connected") << "computer=" << computer << ", obj=" << obj;
@@ -58,8 +58,7 @@
// the initial NETMSG_PLAYER_HELLO
CL_NetPacket hello_pkt;
- hello_pkt.output.write_uint32(position.x);
- hello_pkt.output.write_uint32(position.y);
+ writeVector(hello_pkt, position);
obj.send(computer, NETMSG_SERVER_HELLO, hello_pkt, true);
@@ -71,8 +70,7 @@
// player is not in players list yet
assert(player != this);
- player_pkt.output.write_uint32(player->position.x);
- player_pkt.output.write_uint32(player->position.y);
+ writeVector(player_pkt, player->position);
player->obj.send(computer, NETMSG_PLAYER_INFO, player_pkt, true);
}
@@ -95,17 +93,13 @@
if (!(from == computer))
return;
- // read packet
- int32_t dx = pkt.input.read_int32();
- int32_t dy = pkt.input.read_int32();
+ Vector impulse_force = readVector(pkt);
+ uint16_t impulse_ms = pkt.input.read_uint16();
- // movement delta
- PositionDelta delta(dx, dy);
-
- Engine::log(INFO, "server_player.on_move") << "obj=" << obj << ", old_pos=" << position << ", delta=" << delta;
-
- // apply movement
- position += delta;
+ Engine::log(INFO, "server_player.on_move") << "obj=" << obj << ", old_pos=" << position << ", impulse=" << impulse_force << "@" << impulse_ms << "ms";
+
+ // apply force
+ applyForce(impulse_force, impulse_ms);
// send position update
send_position_update();
@@ -113,10 +107,10 @@
void NetworkServerPlayer::send_position_update (void) {
CL_NetPacket pkt;
- pkt.output.write_uint32(position.x);
- pkt.output.write_uint32(position.y);
+ writeVector(pkt, position);
+ writeVector(pkt, velocity);
- Engine::log(INFO, "server_player.send_position_update") << "obj=" << obj << " -> " << position;
+ Engine::log(INFO, "server_player.send_position_update") << "obj=" << obj << " -> " << position << "+" << velocity;
obj.send(server.netsession.get_all(), NETMSG_PLAYER_POSITION, pkt, false);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/proto2/Physics.cc Tue Nov 18 22:58:50 2008 +0000
@@ -0,0 +1,114 @@
+
+#include "Physics.hh"
+#include "Engine.hh"
+
+#include <algorithm>
+#include <functional>
+
+PhysicsWorld::PhysicsWorld (Vector gravity, Vector dimensions)
+ : tick_timer(PHYSICS_TICK_MS), gravity(gravity), dimensions(dimensions) {
+
+ slots.connect(tick_timer.sig_timer(), this, &PhysicsWorld::tick);
+ tick_timer.enable();
+}
+
+void PhysicsWorld::addObject (PhysicsObject *object) {
+ objects.push_back(object);
+}
+
+void PhysicsWorld::tick () {
+// Engine::log(DEBUG, "physics.apply_force") << "*tick*";
+
+ for (std::vector<PhysicsObject*>::iterator i = objects.begin(); i != objects.end(); i++) {
+ (*i)->tick();
+ }
+}
+
+PhysicsObject::PhysicsObject (PhysicsWorld &world, float mass, Vector position, Vector velocity)
+ : world(world), mass(mass), position(position), velocity(velocity) {
+
+ world.addObject(this);
+}
+
+void PhysicsObject::updatePosition () {
+
+ // Check if the player is moving on the ground
+ /*if (this->velocity.y == 0 && (position.y >= world.dimensions.y - 3)) {
+ position.x += 50 * velocity.x * (PHYSICS_TICK_MS / 1000.0);
+ velocity.x = 0;
+ return;
+ }*/
+
+ // If not moving on the ground, apply normal physics
+
+ // Calculate gravity's influence on the velocity vector
+ this->velocity += world.gravity * (PHYSICS_TICK_MS / 1000.0);
+
+ Vector newPosition = position + velocity * (PHYSICS_TICK_MS / 1000.0);
+
+ //TODO Handle the object as a square or a polygon
+
+// Engine::log(DEBUG, "physics.update_position") << "position=" << newPosition << ", velocity=" << velocity;
+
+ bool collided = false;
+
+ if (newPosition.x < 0 || (newPosition.x > world.dimensions.x)) {
+ // CRASH!
+ this->velocity.x *= -0.5;
+
+ // If the velocity drops under some fixed constant we decide it is zero.
+ // This is to prevent the object from bouncing eternally.
+ if (abs(this->velocity.x) < 0.1)
+ this->velocity.x = 0;
+
+ collided = true;
+ } else {
+ this->position.x = newPosition.x;
+ }
+
+ if (newPosition.y <= 0 || (newPosition.y >= world.dimensions.y)) {
+ this->velocity.y *= -0.3;
+
+
+
+ if (abs(this->velocity.y) < 0.1) {
+ this->velocity.y = 0;
+ // Friction
+ this->velocity.x *= 0.95;
+ } else {
+ // Bigger friction
+ this->velocity.x *= 0.75;
+ }
+
+ collided = true;
+ } else {
+ this->position.y = newPosition.y;
+ }
+
+ if(!collided) {
+ this->position = newPosition;
+ }
+}
+
+void PhysicsObject::applyForce (Vector force, uint16_t dt) {
+ Vector oldVelocity = velocity;
+
+ this->velocity += force * dt / 1000 / mass; // The last factor denotes the time.
+ // It should be scaled somehow.
+
+// Engine::log(DEBUG, "physics.apply_force") << "force=" << force << ", velocity " << oldVelocity << " -> " << velocity;
+}
+
+void PhysicsObject::updatePhysics (Vector position, Vector velocity) {
+ this->position = position;
+ this->velocity = velocity;
+}
+
+Vector PhysicsObject::getPosition () {
+ return this->position;
+}
+
+void PhysicsObject::tick () {
+ this->updatePosition();
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/proto2/Physics.hh Tue Nov 18 22:58:50 2008 +0000
@@ -0,0 +1,55 @@
+#ifndef PHYSICS_HH
+#define PHYSICS_HH
+
+#include "Vector.hh"
+
+#include <ClanLib/core.h>
+
+const uint16_t PHYSICS_TICK_MS = 10;
+
+// forward-declare
+class PhysicsObject;
+
+class PhysicsWorld {
+ friend class PhysicsObject;
+
+ private:
+ CL_Timer tick_timer;
+
+ protected:
+ std::vector<PhysicsObject*> objects;
+ Vector gravity;
+ Vector dimensions;
+
+ CL_SlotContainer slots;
+
+ PhysicsWorld (Vector gravity, Vector dimensions);
+
+ public:
+ void addObject (PhysicsObject *object);
+
+ void tick (void);
+};
+
+class PhysicsObject {
+ protected:
+ PhysicsWorld &world;
+ float mass;
+ Vector position;
+ Vector velocity;
+
+ PhysicsObject (PhysicsWorld &world, float mass, Vector position, Vector velocity);
+
+ virtual void applyForce (Vector force, uint16_t dt);
+ void updatePhysics (Vector position, Vector velocity);
+
+ private:
+ void updatePosition (void);
+
+ public:
+ Vector getPosition (void);
+
+ void tick (void);
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/proto2/SinglePlayer.hh Tue Nov 18 22:58:50 2008 +0000
@@ -0,0 +1,11 @@
+#ifndef SINGLE_PLAYER_HH
+#define SINGLE_PLAYER_HH
+
+#include "GameState.hh"
+
+class SinglePlayer : public LocalPlayer {
+ public:
+ SinglePlayer (GameState &state) : LocalPlayer(state, Vector(PLAYER_INITIAL_X, PLAYER_INITIAL_Y), true) { }
+};
+
+#endif /* SINGLE_PLAYER_HH */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/proto2/Vector.hh Tue Nov 18 22:58:50 2008 +0000
@@ -0,0 +1,76 @@
+#ifndef COOR_H
+#define COOR_H
+
+#include <iostream>
+
+/**
+ * 2D Vector class. Implements standard vector operations.
+ */
+template <typename T>
+class _Vector {
+public:
+ T x;
+ T y;
+
+ _Vector() : x(0), y(0){}
+ /**
+ * @param x Initial x-coordinate.
+ * @param y Initial y-coordinate.
+ */
+ _Vector(T x, T y) : x(x), y(y) {}
+ /**
+ * @param v Other vector to be copied.
+ */
+ _Vector(const _Vector &v) : x(v.x), y(v.y) {}
+
+ void operator=(const _Vector &v) {
+ this->x = v.x;
+ this->y = v.y;
+ }
+ _Vector operator+(const _Vector &v) const {
+ return _Vector(this->x+v.x, this->y+v.y);
+ }
+ _Vector operator-(const _Vector &v) const {
+ return _Vector(this->x-v.x, this->y-v.y);
+ }
+ _Vector operator*(const T &d) const {
+ return _Vector(this->x*d, this->y*d);
+ }
+ _Vector operator/(const T &d) const {
+ return _Vector(this->x/d, this->y/d);
+ }
+ void operator+=(const _Vector &v) {
+ this->x += v.x;
+ this->y += v.y;
+ }
+ void operator-=(const _Vector &v) {
+ this->x -= v.x;
+ this->y -= v.y;
+ }
+ void operator*=(const T &f) {
+ this->x *= f;
+ this->y *= f;
+ }
+ void operator/=(const T &d) {
+ this->x /= d;
+ this->y /= d;
+ }
+};
+
+template<typename T>
+bool operator==(const _Vector<T> &v1, const _Vector<T> &v2) {
+ return ((v1.x == v2.x) && (v1.y == v2.y));
+}
+template<typename T>
+bool operator!=(const _Vector<T> &v1, const _Vector<T> &v2) {
+ return !(v1 == v2);
+}
+
+template<typename T>
+std::ostream& operator<<(std::ostream &s, const _Vector<T> &v) {
+ return s<<"("<<v.x<<", "<<v.y<<")";
+}
+
+typedef _Vector<float> Vector;
+
+#endif