physics is starting to work
authorterom
Tue, 18 Nov 2008 21:17:14 +0000
changeset 60 26571fd9a8d1
parent 59 5b9b85489ef6
child 61 d7999511b103
physics is starting to work
src/proto2/Engine.cc
src/proto2/GameState.cc
src/proto2/GameState.hh
src/proto2/Graphics.cc
src/proto2/Graphics.hh
src/proto2/Input.hh
src/proto2/NetworkClient.cc
src/proto2/NetworkClient.hh
src/proto2/NetworkServer.cc
src/proto2/Physics.cc
src/proto2/Physics.hh
src/proto2/SinglePlayer.hh
src/proto2/Vector.hh
--- a/src/proto2/Engine.cc	Tue Nov 18 20:00:04 2008 +0000
+++ b/src/proto2/Engine.cc	Tue Nov 18 21:17:14 2008 +0000
@@ -30,7 +30,7 @@
 
 void Engine::setupSinglePlayer (void) {
     // create player directly
- 	LocalPlayer* lp = new SinglePlayer();
+ 	LocalPlayer* lp = new SinglePlayer(game_state);
 
     // add to gamestate
 	game_state.newLocalPlayer(lp);
@@ -48,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/GameState.cc	Tue Nov 18 20:00:04 2008 +0000
+++ b/src/proto2/GameState.cc	Tue Nov 18 21:17:14 2008 +0000
@@ -1,22 +1,22 @@
 
 #include "GameState.hh"
 
-bool LocalPlayer::handleMove (PlayerInput_Move input) {
-    int dx = 0, dy = 0;
+void LocalPlayer::handleMove (PlayerInput_Move input) {
+    float fx = 0, fy = 0;
 
     // handle up/down/left/right
     if (input & INPUT_MOVE_UP)
-            dy -= PLAYER_MOVE_FORCE;
+            fy -= PLAYER_MOVE_FORCE;
     
     if (input & INPUT_MOVE_DOWN)
-            dy += PLAYER_MOVE_FORCE;
+            fy += PLAYER_MOVE_FORCE;
 
     if (input & INPUT_MOVE_LEFT)
-            dx -= PLAYER_MOVE_FORCE;
+            fx -= PLAYER_MOVE_FORCE;
 
     if (input & INPUT_MOVE_RIGHT)
-            dx += PLAYER_MOVE_FORCE;
+            fx += PLAYER_MOVE_FORCE;
     
     // apply force
-    applyForce(Vector(dx, dy));
+    applyForce(Vector(fx, fy), INPUT_INTERVAL_MS);
 }
--- a/src/proto2/GameState.hh	Tue Nov 18 20:00:04 2008 +0000
+++ b/src/proto2/GameState.hh	Tue Nov 18 21:17:14 2008 +0000
@@ -7,37 +7,41 @@
 #include <list>
 #include <stdexcept>
 
-const uint16_t PLAYER_MASS = 100;
-const uint16_t PLAYER_DIM_W = 10;
-const uint16_t PLAYER_DIM_H = 10;
-const uint16_t MAP_DIM_W = 800;
-const uint16_t MAP_DIM_H = 640;
+const uint32_t COORDINATE_MAX = 1 << 31;
+
+// 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 = 20.0;
 
 // forward-declare GameState
 class GameState;
 
 class Player : public PhysicsObject {
     protected:
+        GameState &state;
+        bool visible;
 
     public:
 
-        Player(Vector position, bool visible) : 
-            PhysicsObject(PLAYER_MASS, position, Vector(0, 0), Vector(0, 0)), visible(visible) { }
+        Player(GameState &state, Vector position, bool visible) : 
+            PhysicsObject((PhysicsWorld &) state, PLAYER_MASS, position, Vector(0, 0)), state(state), visible(visible) { }
 
-        bool visible;
 };
 
 class LocalPlayer : public Player {
     protected:
-        LocalPlayer (Vector pos, bool visible) : Player(pos, visible) { }
+        LocalPlayer (GameState &state, Vector pos, bool visible) : Player(state, pos, visible) { }
     
     public:
-        virtual bool handleMove (PlayerInput_Move input);
+        virtual void handleMove (PlayerInput_Move input);
 };
 
 class RemotePlayer : public Player {
     protected:
-        RemotePlayer (Vector pos, bool visible) : Player(pos, visible) { }
+        RemotePlayer (GameState &state, Vector pos, bool visible) : Player(state, pos, visible) { }
 };
 
 class GameState : public PhysicsWorld {
@@ -47,7 +51,7 @@
         // only one local player is supported
         LocalPlayer *local_player;
 
-        GameState (void) : PhysicsWorld(Vector(MAP_DIM_W, MAP_DIM_H)), local_player(NULL) {
+        GameState (void) : PhysicsWorld(Vector(0, MAP_GRAVITY), Vector(MAP_WIDTH, MAP_HEIGHT)), local_player(NULL) {
 
         }
        
@@ -63,14 +67,12 @@
                 throw std::logic_error("newLocalPlayer called even though we already have a local player");
 
             player_list.push_back(player);
-            addObject(player);
 
             local_player = player;
         }
 
         void newRemotePlayer (RemotePlayer *player) {
             player_list.push_back(player);
-            addObject(player);
         }
 
         void removePlayer (Player *player) {
--- a/src/proto2/Graphics.cc	Tue Nov 18 20:00:04 2008 +0000
+++ b/src/proto2/Graphics.cc	Tue Nov 18 21:17:14 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
@@ -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	Tue Nov 18 20:00:04 2008 +0000
+++ b/src/proto2/Graphics.hh	Tue Nov 18 21:17:14 2008 +0000
@@ -12,7 +12,9 @@
 #include <ClanLib/display.h>
 
 const std::string GRAPHICS_WINDOW_TITLE = "Kisna Glista";
-const uint16_t GRAPHICS_UPDATE_INTERVAL_MS = 100;
+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:
--- a/src/proto2/Input.hh	Tue Nov 18 20:00:04 2008 +0000
+++ b/src/proto2/Input.hh	Tue Nov 18 21:17:14 2008 +0000
@@ -1,7 +1,7 @@
 #ifndef INPUT_HH
 #define INPUT_HH
 
-const uint16_t PLAYER_MOVE_FORCE = 5;
+const uint16_t INPUT_INTERVAL_MS = 20;
 
 enum {
     INPUT_MOVE_UP     = 0x01,
--- a/src/proto2/NetworkClient.cc	Tue Nov 18 20:00:04 2008 +0000
+++ b/src/proto2/NetworkClient.cc	Tue Nov 18 21:17:14 2008 +0000
@@ -95,13 +95,13 @@
 }
 
 NetworkClientLocalPlayer::NetworkClientLocalPlayer (NetworkClient &client, CL_NetObject_Client &obj, Vector initial_position) :
-    LocalPlayer(initial_position, true), client(client), obj(obj) {
+    LocalPlayer(client.state, initial_position, true), client(client), obj(obj) {
     
     // receive messages
     slots.connect(obj.sig_received_message(NETMSG_PLAYER_POSITION), this, &NetworkClientLocalPlayer::on_position);
 }
         
-bool NetworkClientLocalPlayer::handleMove (PlayerInput_Move move) {
+void NetworkClientLocalPlayer::handleMove (PlayerInput_Move move) {
     // always send move, in all cases
     CL_NetPacket pkt;
     pkt.output.write_uint16(move);
@@ -109,7 +109,7 @@
     obj.send(NETMSG_CLIENT_MOVE, pkt, false);
     
     // handle locally
-    return LocalPlayer::handleMove(move);
+    LocalPlayer::handleMove(move);
 }
         
 void NetworkClientLocalPlayer::on_position (CL_NetPacket &pkt) {
@@ -121,11 +121,11 @@
     Engine::log(INFO, "client_player.on_position") << "obj=" << obj << ", pos=" << pos;
     
     // XXX: transmit velocity/force    
-    updatePhysics(pos, Vector(0, 0), Vector(0, 0));
+    updatePhysics(pos, Vector(0, 0));
 }
         
 NetworkClientRemotePlayer::NetworkClientRemotePlayer (NetworkClient &client, CL_NetObject_Client &obj, Vector initial_position) :
-    RemotePlayer(initial_position, true), client(client), obj(obj) {
+    RemotePlayer(client.state, initial_position, true), client(client), obj(obj) {
     
     // receive messages
     slots.connect(obj.sig_received_message(NETMSG_PLAYER_POSITION), this, &NetworkClientRemotePlayer::on_position);
@@ -141,7 +141,7 @@
     Engine::log(INFO, "client_player.on_position") << "obj=" << obj << ", pos=" << pos;
     
     // XXX: transmit velocity/force    
-    updatePhysics(pos, Vector(0, 0), Vector(0, 0));
+    updatePhysics(pos, Vector(0, 0));
 }
 
 void NetworkClientRemotePlayer::on_quit (CL_NetPacket &pkt) {
--- a/src/proto2/NetworkClient.hh	Tue Nov 18 20:00:04 2008 +0000
+++ b/src/proto2/NetworkClient.hh	Tue Nov 18 21:17:14 2008 +0000
@@ -40,7 +40,7 @@
     public:
         NetworkClientLocalPlayer (NetworkClient &client, CL_NetObject_Client &obj, Vector initial_position);
         
-        virtual bool handleMove (PlayerInput_Move input);
+        virtual void handleMove (PlayerInput_Move input);
     
     private:
         void on_position (CL_NetPacket &pkt);
--- a/src/proto2/NetworkServer.cc	Tue Nov 18 20:00:04 2008 +0000
+++ b/src/proto2/NetworkServer.cc	Tue Nov 18 21:17:14 2008 +0000
@@ -48,7 +48,7 @@
 }
         
 NetworkServerPlayer::NetworkServerPlayer (NetworkServer &server, CL_NetComputer &computer, uint16_t pid) : 
-    RemotePlayer(Vector(100, 100), true), server(server), computer(computer), obj(&server.netobjs), pid(pid) {
+    RemotePlayer(server.state, Vector(100, 100), true), server(server), computer(computer), obj(&server.netobjs), pid(pid) {
     
     // log
     Engine::log(INFO, "server_player.connected") << "computer=" << computer << ", obj=" << obj;
--- a/src/proto2/Physics.cc	Tue Nov 18 20:00:04 2008 +0000
+++ b/src/proto2/Physics.cc	Tue Nov 18 21:17:14 2008 +0000
@@ -5,8 +5,8 @@
 #include <algorithm>
 #include <functional>
 
-PhysicsWorld::PhysicsWorld (Vector dimensions)
-    : tick_timer(PHYSICS_TICK_MS), dimensions(dimensions) {
+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();
@@ -17,31 +17,31 @@
 }
 
 void PhysicsWorld::tick () {
-    Engine::log(DEBUG, "physics.apply_force") << "*tick*";
+//    Engine::log(DEBUG, "physics.apply_force") << "*tick*";
 
-	for(std::vector<PhysicsObject*>::iterator i = objects.begin(); i != objects.end(); i++) {
+	for (std::vector<PhysicsObject*>::iterator i = objects.begin(); i != objects.end(); i++) {
        	(*i)->tick(); 
   	}
-	//std::for_each(objects.begin(), objects.end(), );
 }
 
-PhysicsObject::PhysicsObject (uint16_t mass, Vector position, Vector velocity, Vector force)
-    : mass(mass), position(position), velocity(velocity), force(force) {}
+PhysicsObject::PhysicsObject (PhysicsWorld &world, float mass, Vector position, Vector velocity)
+    : world(world), mass(mass), position(position), velocity(velocity) {
+
+    world.addObject(this);
+}
     
 void PhysicsObject::updatePosition () {
 
     // Calculate gravity's influence on the velocity vector
-    this->velocity += (GRAVITY_FORCE / this->mass) * PHYSICS_TICK_MS;
+    this->velocity += world.gravity * (PHYSICS_TICK_MS / 1000.0);
         
-    Vector newPosition = position + velocity * PHYSICS_TICK_MS;
+    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;
+    Engine::log(DEBUG, "physics.update_position") << "position=" << newPosition << ", velocity=" << velocity;
 
-    if(newPosition.x < 0 || (newPosition.x > PHYSICS_WORLD_WIDTH)
-       || (newPosition.y < 0) || (newPosition.y >= PHYSICS_WORLD_HEIGHT)) {
-        
+    if (newPosition.x < 0 || (newPosition.x > world.dimensions.x) || (newPosition.y < 0) || (newPosition.y >= world.dimensions.y)) {
         // CRASH!
         this->velocity *= -1;
 
@@ -50,19 +50,18 @@
     }
 }
 
-void PhysicsObject::applyForce (Vector force) {
+void PhysicsObject::applyForce (Vector force, uint16_t dt) {
     Vector oldVelocity = velocity;
 
-    this->velocity += (force * PHYSICS_TICK_MS) / mass;  // The last factor denotes the time.
+    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;
+//    Engine::log(DEBUG, "physics.apply_force") << "force=" << force << ", velocity " << oldVelocity << " -> " << velocity;
 }
 
-void PhysicsObject::updatePhysics (Vector position, Vector velocity, Vector force) {
+void PhysicsObject::updatePhysics (Vector position, Vector velocity) {
     this->position = position;
     this->velocity = velocity;
-    this->force = force;
 }
     
 Vector PhysicsObject::getPosition () {
--- a/src/proto2/Physics.hh	Tue Nov 18 20:00:04 2008 +0000
+++ b/src/proto2/Physics.hh	Tue Nov 18 21:17:14 2008 +0000
@@ -5,25 +5,25 @@
 
 #include <ClanLib/core.h>
 
-const uint16_t PHYSICS_TICK_MS = 50;
-const uint16_t PHYSICS_WORLD_WIDTH = 800;
-const uint16_t PHYSICS_WORLD_HEIGHT = 600;
-const Vector GRAVITY_FORCE(0, -5); 
+const uint16_t PHYSICS_TICK_MS = 100;
 
 // 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 dimensions);
+        PhysicsWorld (Vector gravity, Vector dimensions);
 
     public:
         void addObject (PhysicsObject *object);
@@ -33,19 +33,19 @@
 
 class PhysicsObject {
     protected:
-        uint16_t mass;
+        PhysicsWorld &world;
+        float mass;
         Vector position;
         Vector velocity;
-        Vector force;
     
-        PhysicsObject (uint16_t mass, Vector position, Vector velocity, Vector force);
+        PhysicsObject (PhysicsWorld &world, float mass, Vector position, Vector velocity);
     
     private:
         void updatePosition (void);
 
     protected:
-        void applyForce (Vector force);
-        void updatePhysics (Vector position, Vector velocity, Vector force);
+        void applyForce (Vector force, uint16_t dt);
+        void updatePhysics (Vector position, Vector velocity);
     
     public:
         Vector getPosition (void);
@@ -53,6 +53,4 @@
         void tick (void);
 };
 
-void tickObject(PhysicsObject* obj);
-
 #endif
--- a/src/proto2/SinglePlayer.hh	Tue Nov 18 20:00:04 2008 +0000
+++ b/src/proto2/SinglePlayer.hh	Tue Nov 18 21:17:14 2008 +0000
@@ -5,7 +5,7 @@
 
 class SinglePlayer : public LocalPlayer {
     public:
-        SinglePlayer (void) : LocalPlayer(Vector(400, 400), true) { }
+        SinglePlayer (GameState &state) : LocalPlayer(state, Vector(50.0, 50.0), true) { }
 };
 
 #endif /* SINGLE_PLAYER_HH */
--- a/src/proto2/Vector.hh	Tue Nov 18 20:00:04 2008 +0000
+++ b/src/proto2/Vector.hh	Tue Nov 18 21:17:14 2008 +0000
@@ -71,6 +71,6 @@
     return s<<"("<<v.x<<", "<<v.y<<")";
 }
 
-typedef _Vector<int32_t> Vector;
+typedef _Vector<float> Vector;
 
 #endif