1
Fork 0
This repository has been archived on 2025-04-09. You can view files and clone it, but cannot push or open issues or pull requests.
beats-motor-client/src/Base.hpp
Joshua Moerman c3be4d5d12 first commit
2013-03-13 13:49:30 +01:00

171 lines
5.8 KiB
C++

#pragma once
#include <iostream>
#include <memory>
#include <SDL/SDL.h>
#include <moggle/xxx/mesh.hpp>
#include <motor/basic/body.hpp>
#include <motor/basic/scene.hpp>
#include <motor/core/fbo.hpp>
#include <astrant-extensions/algorithm.hpp>
#include "globals.hpp"
//! Returns (f(ax, bx) && f(ay, by)) || (f(ax, by) && f(ay, bx))
//! Useful for instance when you want to compare two pairs if they contain the same elements, but don't care about the order
//! (and we provide an overload for that of course)
template <typename First, typename Second, typename Third, typename Fourth, typename CompareFunction>
bool order_agnostic_compare(First const& ax, Second const& ay, Third const& bx, Fourth const& by, CompareFunction const& f){
return
(f(ax, bx) && f(ay, by))
||
(f(ax, by) && f(ay, bx));
}
//TODO: Figure out what the syntax of this was, then express equal, less{,or equal}, greater{, or equal}.
//using order_agnostic_equalness<First, Second, Third, Fourth> = order_agnostic_compare<First, Second, Third, Fourth, std::eq>;
template <typename First, typename Second, typename Third, typename Fourth>
bool order_agnostic_equal(First const& ax, Second const& ay, Third const& bx, Fourth const& by){
return ((ax == bx && ay == by) || (ax == by && ay == bx));
}
template <typename First, typename Second, typename Third, typename Fourth>
bool order_agnostic_equal(std::pair<First, Second> const& a, std::pair<Third, Fourth> const& b){
return order_agnostic_equalness(a.first, a.second, b.first, b.second);
}
namespace games {
using namespace motor;
struct Base {
static ResourceCache resource_cache;
std::shared_ptr<Scene> scene = std::make_shared<Scene>();
int window_width;
int window_height;
Fbo fbo{window_width, window_height};
float time = 0.0;
// So all this is needed to set up Bullet!
// You pay for modularity with a lot of code, but perhaps we can wrap this in our own motor::world or something.
std::unique_ptr<btDefaultCollisionConfiguration> collison_configuration{new btDefaultCollisionConfiguration()};
std::unique_ptr<btCollisionDispatcher> collision_dispatcher{new btCollisionDispatcher(collison_configuration.get())};
btVector3 const world_minimum = btVector3(-1000,-1000,-1000);
btVector3 const world_maximum = btVector3(1000,1000,1000);
std::unique_ptr<btBroadphaseInterface> overlapping_pair_cache{new btAxisSweep3(world_minimum, world_maximum)};
std::unique_ptr<btConstraintSolver> constraint_solver{new btSequentialImpulseConstraintSolver()};
std::unique_ptr<btDynamicsWorld> dynamics_world{new btDiscreteDynamicsWorld(collision_dispatcher.get(), overlapping_pair_cache.get(), constraint_solver.get(), collison_configuration.get())};
Base(int window_width, int window_height);
virtual ~Base();
virtual bool has_ended();
private:
// Contains objects that were colliding in the previous update
std::vector<std::pair<btCollisionObject const*, btCollisionObject const*>> bullet_objects_in_collision_previous_frame{};
public:
virtual void update(float const dt, std::map<SDLKey, bool> keys_went_down, std::map<SDLKey, bool> is_pressed, std::map<SDLKey, bool> keys_went_up);
void update_bullet(float const dt);
void check_collisions();
//! A callback for when a collision between two objects occurs.
//! TODO: Expand to N-objects?
//! The pointers aren't const here so we can call f with the two arguments
struct dual_collision_callback {
//! The constructor.
//! CallbackFunctor must be a valid ctor-parameter for @member f
template <typename CallbackFunctor>
dual_collision_callback(std::shared_ptr<Body> first_, std::shared_ptr<Body> second_, CallbackFunctor&& c)
: first(first_)
, second(second_)
, f(c)
{}
std::shared_ptr<Body> first;
std::shared_ptr<Body> second;
std::function<void(decltype(first), decltype(second))> f;
void operator()() {
f(first, second);
}
};
struct single_collision_callback {
template <typename CallbackFunctor>
single_collision_callback(std::shared_ptr<Body> b_, CallbackFunctor&& c)
: b(b_)
, f(c)
{}
std::shared_ptr<Body> b;
std::function<void(decltype(b))> f;
void operator()() {
f(b);
}
};
void register_on_enter_collision_callback(dual_collision_callback&& c){
on_enter_dual_collision_callback.emplace_back(std::move(c));
}
void register_on_exit_collision_callback(dual_collision_callback&& c){
on_exit_dual_collision_callback.emplace_back(std::move(c));
}
void register_on_enter_collision_callback(single_collision_callback&& c){
on_enter_single_collision_callback.emplace_back(std::move(c));
}
void register_on_exit_collision_callback(single_collision_callback&& c){
on_exit_single_collision_callback.emplace_back(std::move(c));
}
private:
std::vector<dual_collision_callback> on_enter_dual_collision_callback{};
std::vector<dual_collision_callback> on_exit_dual_collision_callback{};
std::vector<single_collision_callback> on_enter_single_collision_callback{};
std::vector<single_collision_callback> on_exit_single_collision_callback{};
void bullet_objects_entered_collision(btCollisionObject const* x, btCollisionObject const* y){
for(auto& c : on_enter_dual_collision_callback){
if(order_agnostic_equal(c.first->get_physical_body(), c.second->get_physical_body(), x, y)){
c();
}
}
for(auto& c : on_enter_single_collision_callback){
if(c.b->get_physical_body() == x || c.b->get_physical_body() == y){
c();
}
}
}
void bullet_objects_exited_collision(btCollisionObject const* x, btCollisionObject const* y){
for(auto& c : on_exit_dual_collision_callback){
if(order_agnostic_equal(c.first->get_physical_body(), c.second->get_physical_body(), x, y)){
c();
}
}
for(auto& c : on_exit_single_collision_callback){
if(c.b->get_physical_body() == x || c.b->get_physical_body() == y){
c();
}
}
}
public:
virtual void draw();
};
} // namespace games