| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- //
- // scene_test.cxx
- // engine-test
- //
- // Created by Sam Jaffe on 7/12/19.
- // Copyright © 2019 Sam Jaffe. All rights reserved.
- //
- #include "game/engine/scene.hpp"
- #include <game/util/env.hpp>
- #include <testing/xcode_gtest_helper.h>
- #include "game/engine/entity.hpp"
- #include "game/engine/game_dispatch.hpp"
- #include "mock_renderer.h"
- using testing::Values;
- struct test_scene : engine::scene {
- using engine::scene::scene;
- void update(float) override { check_collisions(); }
- void render() override {}
- void handle_key_event(engine::event::key_event) override {}
- void handle_mouse_event(engine::event::mouse_event) override {}
- bool in_bounds(math::dim2::point c) const {
- return engine::scene::in_bounds(c);
- }
- bool in_bounds(engine::collidable * c) const {
- return engine::scene::in_bounds(c);
- }
- graphics::manager const & graphics_manager() const {
- return engine::scene::graphics_manager();
- }
- 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<graphics::material>(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<stub_renderer> renderer_;
- std::shared_ptr<engine::game_dispatch> dispatch_;
- std::shared_ptr<test_scene> scene_;
- };
- void SceneTest::SetUp() {
- renderer_.reset(new stub_renderer);
- math::vec2 screen{{1600.f, 900.f}};
- env::resize_screen(math::vec2i(screen));
- dispatch_.reset(new engine::game_dispatch(renderer_));
- scene_.reset(new test_scene("test", screen, dispatch_));
- }
- void SceneTest::TearDown() {
- scene_.reset();
- dispatch_.reset();
- renderer_.reset();
- }
- using testing::Eq;
- using testing::Ref;
- TEST_F(SceneTest, SharedGraphicsManagerWithDispatch) {
- EXPECT_THAT(&scene().graphics_manager(), &game().graphics_manager());
- }
- 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);
- }
- // TODO: Solve double-collision bug?
- 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(2);
- scene().update(0.f);
- }
- struct BoundsTest : SceneTest, testing::WithParamInterface<math::vec2> {};
- TEST_F(BoundsTest, BoundsCheckIsPointInScreenZone) {
- // Confirm that the size is as expected...
- EXPECT_THAT(scene().size(), Eq(math::vec2(1600.f, 900.f)));
- // Lower-Left Corner
- EXPECT_FALSE(scene().in_bounds(math::vec2(-1.f, 0.f)));
- EXPECT_FALSE(scene().in_bounds(math::vec2(0.f, -1.f)));
- EXPECT_TRUE(scene().in_bounds(math::vec2(0.f, 0.f)));
- // Lower-Right Corner
- EXPECT_FALSE(scene().in_bounds(math::vec2(1600.f, -1.f)));
- EXPECT_FALSE(scene().in_bounds(math::vec2(1601.f, 0.f)));
- EXPECT_TRUE(scene().in_bounds(math::vec2(1600.f, 0.f)));
- // Upper-Right Corner
- EXPECT_FALSE(scene().in_bounds(math::vec2(1601.f, 900.f)));
- EXPECT_FALSE(scene().in_bounds(math::vec2(1600.f, 901.f)));
- EXPECT_TRUE(scene().in_bounds(math::vec2(1600.f, 900.f)));
- // Upper-Left Corner
- EXPECT_FALSE(scene().in_bounds(math::vec2(0.f, 901.f)));
- EXPECT_FALSE(scene().in_bounds(math::vec2(-1.f, 900.f)));
- EXPECT_TRUE(scene().in_bounds(math::vec2(0.f, 900.f)));
- }
- TEST_P(BoundsTest, BoundsCheckOnCollidableIsAnyPointInBounds) {
- math::dim2::square bounds = {GetParam(), 2.f};
- engine::collidable collide{{{}, bounds, cast<graphics::material>(1), {}}};
- EXPECT_TRUE(scene().in_bounds(&collide));
- }
- INSTANTIATE_TEST_SUITE_P(Collidable, BoundsTest,
- Values(math::vec2(-1.f, -1.f),
- math::vec2(1599.f, -1.f),
- math::vec2(1599.f, 899.f),
- math::vec2(-1.f, 899.f)));
|