Skip to content

Commit

Permalink
net curve initial sketch
Browse files Browse the repository at this point in the history
  • Loading branch information
VelorumS committed Oct 10, 2016
1 parent 7c14465 commit dd6aa96
Show file tree
Hide file tree
Showing 9 changed files with 288 additions and 0 deletions.
1 change: 1 addition & 0 deletions libopenage/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pxdgen(
add_subdirectory("audio")
add_subdirectory("console")
add_subdirectory("coord")
add_subdirectory("curve")
add_subdirectory("cvar")
add_subdirectory("datastructure")
add_subdirectory("gui")
Expand Down
4 changes: 4 additions & 0 deletions libopenage/curve/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
add_sources(libopenage
entities_conductor.cpp
entities_conductor_interpolator.cpp
)
48 changes: 48 additions & 0 deletions libopenage/curve/entities_conductor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright 2015-2016 the openage authors. See copying.md for legal info.

#include "entities_conductor.h"

#include <algorithm>

#include "../error/error.h"

namespace openage {
namespace curve {

EntitiesConductor::EntitiesConductor(std::function<void(int, int, coord::phys2)> emerge, std::function<void(int)> vanish) {
}

void EntitiesConductor::jump(GameClock::time_point from, GameClock::time_point to) {
// this->jump_to(interpolator.to_frame_boundary(time_point));
}

EntitiesConductor::Prediction EntitiesConductor::predict_migration(GameClock::time_point current_time, GameClock::time_point other_time) const {
const auto prior = std::min(current_time, other_time);
const auto forth = std::max(current_time, other_time);

const auto cmp_start_cp = [](const OccurenceCurve &c, GameClock::time_point p) { return c.time < p; };
const auto cmp_start_pc = [](GameClock::time_point p, const OccurenceCurve &c) { return p < c.time; };

const auto cmp_end_ip = [this](size_t index, GameClock::time_point p) { return end_time(this->history[index]) < p; };
const auto cmp_end_pi = [this](GameClock::time_point p,size_t index) { return p < end_time(this->history[index]); };

ENSURE(this->history.size() == this->history_sorted_by_ends.size(), "index array out of sync");

const auto occurencesWithStartsInsideBeginIt = std::lower_bound(std::begin(this->history), std::end(this->history), prior, cmp_start_cp);
const auto occurencesWithStartsInsideEndIt = std::upper_bound(std::begin(this->history), std::end(this->history), forth, cmp_start_pc);

const auto occurencesWithEndsInsideBeginIt = std::lower_bound(std::begin(this->history_sorted_by_ends), std::end(this->history_sorted_by_ends), prior, cmp_end_ip);
const auto occurencesWithEndsInsideEndIt = std::upper_bound(std::begin(this->history_sorted_by_ends), std::end(this->history_sorted_by_ends), forth, cmp_end_pi);

decltype(this->history_sorted_by_ends) occurencesWithOnlyEndsInside;
const size_t completelyInsideBeginIndex = std::distance(std::begin(this->history), occurencesWithStartsInsideBeginIt);

std::copy_if(occurencesWithEndsInsideBeginIt, occurencesWithEndsInsideEndIt, std::back_inserter(occurencesWithOnlyEndsInside), [completelyInsideBeginIndex](size_t index) { return index < completelyInsideBeginIndex; });

}

void EntitiesConductor::converge(GameClock::time_point current_time)
{
}

}} // namespace openage::curve
54 changes: 54 additions & 0 deletions libopenage/curve/entities_conductor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2015-2016 the openage authors. See copying.md for legal info.

#pragma once

#include <functional>
#include <vector>
#include <utility>

#include "../coord/phys2.h"

#include "game_clock.h"
#include "occurence_curve.h"

namespace openage {
namespace curve {

class EntitiesConductor
{
public:
using Prediction = std::vector<std::pair<GameClock::time_point, OccurenceCurve>>;

EntitiesConductor(std::function<void(int, int, coord::phys2)> emerge, std::function<void(int)> vanish);

/**
* Immediately mutate the world to the given time point.
*
* @param current_time current time of the world
* @param to desired time
*/
void jump(GameClock::time_point current_time, GameClock::time_point to);

/**
* Output what happens between two time points.
*
* @param current_time current time of the world
* @param other_time other point in time
* @return sorted timed occurrences from the past to the future
*/
Prediction predict_migration(GameClock::time_point current_time, GameClock::time_point other_time) const;

/**
* Update the history and mutate the world to eliminate the divergence.
*
* @param current_time current time of the world
*/
void converge(GameClock::time_point current_time);

private:
std::vector<OccurenceCurve> history;
std::vector<size_t> history_sorted_by_ends;
std::vector<OccurenceCurve> unapplied_history;
};

}} // namespace openage::curve
61 changes: 61 additions & 0 deletions libopenage/curve/entities_conductor_interpolator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2016-2016 the openage authors. See copying.md for legal info.

#include "entities_conductor_interpolator.h"

#include "../error/error.h"

namespace openage {
namespace curve {

EntitiesConductorInterpolator::EntitiesConductorInterpolator(
GameClock::duration min_frame_duration,
std::function<void(int, int, coord::phys2)> emerge,
std::function<void(int, Occurence)> operate,
std::function<void(int)> vanish)
:
min_frame_duration{min_frame_duration},
current_logic_frame_start{},
current_logic_frame_end{},
current_time{},
conductor{emerge, vanish}
{
}

void EntitiesConductorInterpolator::migrate_to(GameClock::time_point time_point) {

auto to_next_frame = [this, time_point](GameClock::time_point &behind, GameClock::time_point &infront)
{
const auto delta = ((time_point - infront) / this->min_frame_duration + 1) * this->min_frame_duration;
const auto new_infront = behind + delta > std::decay<decltype(behind)>::type{} ? behind + delta : std::decay<decltype(behind)>::type{};
static_assert(std::is_signed<decltype(delta)::rep>::value, "time representation must be a signed number");

this->conductor.converge(this->current_time);

behind = this->current_time;
infront = new_infront;
this->predictions_since_current_logic_frame_start = this->conductor.predict_migration(behind, infront);

this->play(time_point);
};

if (time_point > this->current_logic_frame_end)
to_next_frame(this->current_logic_frame_start, this->current_logic_frame_end);
else if (time_point < this->current_logic_frame_start)
to_next_frame(this->current_logic_frame_end, this->current_logic_frame_start);
else
this->play(time_point);
}

void EntitiesConductorInterpolator::jump_to(GameClock::time_point time_point) {
this->conductor.converge(this->current_time);

this->conductor.jump(this->current_time, time_point);
this->predictions_since_current_logic_frame_start.clear();
this->current_logic_frame_start = this->current_logic_frame_end = time_point;
}

void EntitiesConductorInterpolator::play(GameClock::time_point time_point)
{
}

}} // namespace openage::curve
40 changes: 40 additions & 0 deletions libopenage/curve/entities_conductor_interpolator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2016-2016 the openage authors. See copying.md for legal info.

#pragma once

#include <functional>

#include "game_clock.h"
#include "entities_conductor.h"

namespace openage {
namespace curve {

class EntitiesConductorInterpolator
{
public:
explicit EntitiesConductorInterpolator(
GameClock::duration min_frame_duration,
std::function<void(int, int, coord::phys2)> emerge,
std::function<void(int, Occurence)> operate,
std::function<void(int)> vanish
);

void migrate_to(GameClock::time_point time_point);
void jump_to(GameClock::time_point time_point);

private:
void play(GameClock::time_point time_point);

GameClock::duration min_frame_duration;

GameClock::time_point current_logic_frame_start;
GameClock::time_point current_logic_frame_end;

GameClock::time_point current_time;

EntitiesConductor conductor;
EntitiesConductor::Prediction predictions_since_current_logic_frame_start;
};

}} // namespace openage::curve
18 changes: 18 additions & 0 deletions libopenage/curve/game_clock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2016-2016 the openage authors. See copying.md for legal info.

#pragma once

#include <chrono>

namespace openage {
namespace curve {

struct GameClock {
typedef std::chrono::milliseconds duration;
typedef duration::rep rep;
typedef duration::period period;
typedef std::chrono::time_point<GameClock> time_point;
static const bool is_steady = false;
};

}} // namespace openage::curve
23 changes: 23 additions & 0 deletions libopenage/curve/occurence.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2016-2016 the openage authors. See copying.md for legal info.

#pragma once

namespace openage {
namespace curve {

class Occurence
{
public:
enum class kind
{
SPAWN,
MOVE,
ATTACK,
GATHER,
BUILD,
PRODUCE,
DIE
};
};

}} // namespace openage::curve
39 changes: 39 additions & 0 deletions libopenage/curve/occurence_curve.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2016-2016 the openage authors. See copying.md for legal info.

#pragma once

#include "../coord/phys2.h"

#include "game_clock.h"
#include "occurence.h"

namespace openage {
namespace curve {

struct OccurenceCurve
{
GameClock::time_point time;

Occurence::kind kind;

union {
struct {
int unit_id;

union {
struct {
GameClock::time_point end_time;

union {
coord::phys2 pos;
int health;
} property;
} span;
} par;
} u;
} desc;
};

GameClock::time_point end_time(const OccurenceCurve& c);

}} // namespace openage::curve

0 comments on commit dd6aa96

Please sign in to comment.