|
@@ -8,7 +8,9 @@
|
|
|
// TODO: menu - 1/2 players, audio levels
|
|
|
// TODO: menu - gore level (in case become olympic sport),
|
|
|
//
|
|
|
-// TODO: menu - hoboplayer
|
|
|
+// TODO: menu - hoboplayer, with broadcast discovery
|
|
|
+//
|
|
|
+// from game fade away to main menu if no input, form main menu fade away to program.end() if no input
|
|
|
|
|
|
/*
|
|
|
#canvas {
|
|
@@ -163,8 +165,12 @@ struct complayer
|
|
|
|
|
|
struct eye_t
|
|
|
{
|
|
|
- float2 position;
|
|
|
- float2 velocity;
|
|
|
+ constexpr static auto size = float2::one(0.035f);
|
|
|
+
|
|
|
+ float2 position = {};
|
|
|
+ float2 velocity = {};
|
|
|
+ float2 drift = {};
|
|
|
+ unsigned pop_damage = 100;
|
|
|
};
|
|
|
|
|
|
struct boxa
|
|
@@ -181,7 +187,8 @@ struct boxa
|
|
|
std::optional<keymap> controls{};
|
|
|
std::optional<complayer> brainz;
|
|
|
|
|
|
- eye_t eye = {position};
|
|
|
+ std::array<eye_t,2> eyes = {{ {position + float2::j() * eye_t::size * 1.2f}, {position - float2::j() * eye_t::size * 1.2f} }};
|
|
|
+ melody<movement<float, quadratic_out>, movement<float, motion::quadratic_curve>> eye_drift = { {1s, 0, 1}, {1s, 1, 0}};
|
|
|
|
|
|
float punch = 0.0f;
|
|
|
bool hit = false;
|
|
@@ -256,7 +263,7 @@ struct boxa
|
|
|
void draw(frame& f, auto delta_time)
|
|
|
{
|
|
|
const auto direction = this->direction();
|
|
|
- const auto normal = common::rotate(this->direction(), common::protractor<>::tau(1/4.f));
|
|
|
+ const auto normal = common::rotate(direction, common::protractor<>::tau(1/4.f));
|
|
|
const auto facingdom = float2x2{direction, normal};
|
|
|
auto body = this->body();
|
|
|
{
|
|
@@ -331,17 +338,59 @@ struct boxa
|
|
|
glove_sketch.fill(cola);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ { // move eyes, techincally physics but purely visual and need the visually augmented body geometry
|
|
|
+ auto drift_ratio = 0.f;
|
|
|
+ if(motion::loop(drift_ratio, eye_drift, delta_time))
|
|
|
+ for(auto&& eye : eyes)
|
|
|
+ eye.drift = (trand_float2() - 0.5f);
|
|
|
+
|
|
|
+ auto eye_difference = eyes[0].position - eyes[1].position;
|
|
|
+ const auto overlapance = eye_t::size.x() * eye_t::size.x() - eye_difference.quadrance();
|
|
|
+ if(overlapance > 0)
|
|
|
+ {
|
|
|
+ auto impact_surface = common::rotate(eye_difference, common::protractor<>::tau(1/4.f));
|
|
|
+ float side = 1;
|
|
|
+ for(auto&& eye : eyes)
|
|
|
+ {
|
|
|
+ eye.drift = common::reflect(eye.drift, impact_surface);
|
|
|
+ eye.position += side * common::normalize(eye_difference) * support::root2(overlapance)/2;
|
|
|
+ side = -side;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ float side = 1;
|
|
|
+ for(auto&& eye : eyes)
|
|
|
+ {
|
|
|
+ const auto socket_position = body.position + eye_t::size/2 * (direction + side * normal * 1.2f); // +20% seperation
|
|
|
+ auto eye_offset = socket_position - eye.position;
|
|
|
+ eye.velocity = 10 * eye_offset;
|
|
|
+ eye.position += (eye.velocity + drift_ratio * eye.drift) * delta_time.count();
|
|
|
+ side = -side;
|
|
|
+ if(damage < eye.pop_damage)
|
|
|
+ eye.position = socket_position;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const auto look_direction = common::normalize(target->position - position);
|
|
|
+ for(auto&& eye : eyes)
|
|
|
{
|
|
|
- const auto eye_direction = eye.velocity != float2::zero() ? -common::normalize(eye.velocity) : this->direction();
|
|
|
+ bool eye_popped = damage >= eye.pop_damage;
|
|
|
+ const auto eye_direction = (eye.velocity != float2::zero() && eye_popped) ? -common::normalize(eye.velocity) : look_direction;
|
|
|
const auto eye_normal = common::rotate(eye_direction, common::protractor<>::tau(1/4.f));
|
|
|
- const auto eye_facingdom = float2x2{eye_direction * (1+eye.velocity.quadrance()), eye_normal};
|
|
|
- auto scaled_eye = scale(rect{float2::one(0.04f), eye.position}, ring);
|
|
|
+ const auto eye_stretch = eye_popped ? 1+eye.velocity.quadrance() : 1;
|
|
|
+ const auto eye_facingdom = float2x2{eye_direction * eye_stretch, eye_normal};
|
|
|
+ auto scaled_eye = scale(rect{eye_t::size, eye.position}, ring);
|
|
|
+ auto scaled_pupil = scale(rect{eye_t::size/2, eye.position + eye_direction * eye_t::size * 0.45f}, ring);
|
|
|
+ f.begin_sketch()
|
|
|
+ .ellipse(scaled_pupil.position, eye_facingdom * geom::column(scaled_pupil.size/2))
|
|
|
+ .fill(rgb::white(0.f)) // hmm...
|
|
|
+ ;
|
|
|
f.begin_sketch()
|
|
|
.ellipse(scaled_eye.position, eye_facingdom * geom::column(scaled_eye.size/2))
|
|
|
.fill(rgb::white())
|
|
|
;
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
void move(auto delta_time)
|
|
@@ -397,17 +446,10 @@ struct boxa
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- {
|
|
|
- auto eye_offset = position - eye.position;
|
|
|
- eye.velocity = 10 * eye_offset;
|
|
|
- eye.position += eye.velocity * delta_time.count();
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
void update(frame& f, auto delta_time)
|
|
|
{
|
|
|
-
|
|
|
move(delta_time);
|
|
|
draw(f, delta_time);
|
|
|
}
|
|
@@ -476,8 +518,14 @@ void start(Program& program)
|
|
|
boxas[1].brainz = complayer{};
|
|
|
// boxas[0].brainz = complayer{};
|
|
|
|
|
|
- boxas[0].idle.advance(trand_float() * boxas[0].idle.total);
|
|
|
- boxas[1].idle.advance(trand_float() * boxas[0].idle.total);
|
|
|
+ for(auto&& boxa : boxas)
|
|
|
+ {
|
|
|
+ boxa.idle.advance(trand_float() * boxa.idle.total);
|
|
|
+ auto last_pop = trand_int({70,91});
|
|
|
+ auto last_eye = trand_int({0,2});
|
|
|
+ boxa.eyes[last_eye].pop_damage = last_pop;
|
|
|
+ boxa.eyes[not last_eye].pop_damage = last_pop - trand_int({10,21});
|
|
|
+ }
|
|
|
|
|
|
if(program.argc > 2)
|
|
|
{
|