// // scene_test.cxx // engine-test // // Created by Sam Jaffe on 7/12/19. // Copyright © 2019 Sam Jaffe. All rights reserved. // #include #include "game/engine/entity.hpp" #include "game/engine/game_dispatch.hpp" #include "game/engine/scene.hpp" #include "mock_renderer.h" struct test_scene : engine::scene { using engine::scene::scene; void update(float) override { check_collisions(); } void render(graphics::renderer &) override {} void handle_key_event(engine::event::key_event) override {} void handle_mouse_event(engine::event::mouse_event) override {} void add_with(engine::collision_t t, engine::collidable & c) { colliders[t].push_back(&c); } void add_as(engine::collision_t t, engine::collidable & c) { collidables[t].push_back(&c); } }; struct mock_collidable : engine::collidable { mock_collidable(math::dim2::rectangle bounds) : engine::collidable({bounds, bounds, cast(1), {}}) {} MOCK_METHOD1(collide, void(engine::collidable const &)); }; class SceneTest : public testing::Test { protected: void SetUp() override; void TearDown() override; test_scene & scene() const { return *scene_; } engine::game_dispatch & game() const { return *dispatch_; } std::shared_ptr renderer_; std::shared_ptr dispatch_; std::shared_ptr scene_; }; void SceneTest::SetUp() { renderer_.reset(new stub_renderer); dispatch_.reset(new engine::game_dispatch(renderer_)); scene_.reset(new test_scene("test", dispatch_)); } void SceneTest::TearDown() { scene_.reset(); dispatch_.reset(); renderer_.reset(); } using testing::Ref; TEST_F(SceneTest, WillCollideOverlappingObjects) { math::dim2::rectangle bnds{{{0.f, 0.f}}, {{1.f, 1.f}}}; mock_collidable one{bnds}, two{bnds}; scene().add_with(1, one); scene().add_as(1, two); EXPECT_CALL(one, collide(Ref(two))).Times(1); scene().update(0.f); } TEST_F(SceneTest, NonOverlappingDontCollide) { mock_collidable one{{{{0.f, 0.f}}, {{1.f, 1.f}}}}; mock_collidable two{{{{2.f, 2.f}}, {{1.f, 1.f}}}}; scene().add_with(1, one); scene().add_as(1, two); EXPECT_CALL(one, collide(Ref(two))).Times(0); scene().update(0.f); } TEST_F(SceneTest, CollisionIsOneWay) { math::dim2::rectangle bnds{{{0.f, 0.f}}, {{1.f, 1.f}}}; mock_collidable one{bnds}, two{bnds}; scene().add_with(1, one); scene().add_as(1, two); EXPECT_CALL(one, collide(Ref(two))).Times(1); EXPECT_CALL(two, collide(Ref(one))).Times(0); scene().update(0.f); } TEST_F(SceneTest, ObjectCannotCollideSelf) { math::dim2::rectangle bnds{{{0.f, 0.f}}, {{1.f, 1.f}}}; mock_collidable one{bnds}; scene().add_with(1, one); scene().add_as(1, one); EXPECT_CALL(one, collide(Ref(one))).Times(0); scene().update(0.f); } TEST_F(SceneTest, CollisionMatchesAsWithKeys) { math::dim2::rectangle bnds{{{0.f, 0.f}}, {{1.f, 1.f}}}; mock_collidable one{bnds}, two{bnds}, three{bnds}; scene().add_with(2, one); scene().add_as(1, two); scene().add_as(2, three); EXPECT_CALL(one, collide(Ref(two))).Times(0); EXPECT_CALL(one, collide(Ref(three))).Times(1); scene().update(0.f); } TEST_F(SceneTest, ObjectCanBeInMultipleCollidesWithGroups) { math::dim2::rectangle bnds{{{0.f, 0.f}}, {{1.f, 1.f}}}; mock_collidable one{bnds}, two{bnds}, three{bnds}; scene().add_with(1, one); scene().add_with(2, one); scene().add_as(1, two); scene().add_as(2, three); EXPECT_CALL(one, collide(Ref(two))).Times(1); EXPECT_CALL(one, collide(Ref(three))).Times(1); scene().update(0.f); } TEST_F(SceneTest, ObjectCanBeInMultipleCollidableAsGroups) { math::dim2::rectangle bnds{{{0.f, 0.f}}, {{1.f, 1.f}}}; mock_collidable one{bnds}, two{bnds}, three{bnds}; scene().add_with(1, one); scene().add_with(2, three); scene().add_as(1, two); scene().add_as(2, two); EXPECT_CALL(one, collide(Ref(two))).Times(1); EXPECT_CALL(three, collide(Ref(two))).Times(1); scene().update(0.f); } TEST_F(SceneTest, DoubleCollisionCanOccur) { math::dim2::rectangle bnds{{{0.f, 0.f}}, {{1.f, 1.f}}}; mock_collidable one{bnds}, two{bnds}; scene().add_with(1, one); scene().add_with(2, one); scene().add_as(1, two); scene().add_as(2, two); EXPECT_CALL(one, collide(Ref(two))).Times(1); scene().update(0.f); }