From a94557f5119ca5cac0ecf970b02180152af83f5d Mon Sep 17 00:00:00 2001 From: jonas Date: Mon, 4 Mar 2019 00:47:23 +0100 Subject: Started collision detection, working progress Move now triggers CheckCollision for every move action Hit direction detection still missing --- Makefile | 9 ++- cObject.h | 20 ++++++- cObjectHandler.cpp | 66 ++++++++++++++++++++- cObjectHandler.h | 12 +++- collision.txt | 11 ++++ test.cpp | 48 ++++------------ test_old.cpp | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 289 insertions(+), 42 deletions(-) create mode 100644 collision.txt create mode 100644 test_old.cpp diff --git a/Makefile b/Makefile index 14a7242..ee0f6d2 100644 --- a/Makefile +++ b/Makefile @@ -37,9 +37,12 @@ clean: rm -df $(OBJ) test.o version.h rm -Rdf $(BUILDDIR)/lib $(BUILDDIR)/inc $(BUILDDIR)/test doc/ -run: test +run: gentest ./$(BUILDDIR)/test/test +memleak: gentest + valgrind ./$(BUILDDIR)/test/test + genversion: @echo Building Version @echo "//Generated by MAKEFILE. DO NOT Edit." > version.h @@ -50,9 +53,11 @@ genversion: @echo "#define DATE \"`date +'%d.%m.20%y'`\"" >> version.h @echo "#define TIME \"`date +'%H:%M:%S'`\"" >> version.h -test: genversion test.o $(OBJ) +gentest: genversion test.o $(OBJ) mkdir -p $(BUILDDIR)/test $(CC) $(DEBUGFLAGS) -o $(BUILDDIR)/test/test test.o $(OBJ) $(LDFLAGS) + +test: gentest ./$(BUILDDIR)/test/test test doc: diff --git a/cObject.h b/cObject.h index d0947da..50b9d18 100644 --- a/cObject.h +++ b/cObject.h @@ -3,8 +3,12 @@ #include "cRender.h" -struct sObject +#define _HIT_TOP 1 +#define _HIT_BOTTOM 2 +#define _HIT_LEFT 3 +#define _HIT_RIGHT 4 +struct sObject { sPos pos; WORD **wColor; @@ -60,6 +64,20 @@ public: */ virtual void onChar(unsigned char _c){} + + /** Called by cObjectHandler if Object hits another during move operation + * return true to abort move, false to continue and allow overlap + */ + virtual bool onCollisionActive(unsigned int _hit, int _passiveObject) { return false; } + + /** Called by cObjectHandler if Object is hit by another object + * return any integer value to be identified by hitting object + */ + virtual int onCollisionPassive(unsigned int _hit) { return 0; } + + + + protected: //For child classes cObject(); /** For inheriting classes: sets size of framebuffer diff --git a/cObjectHandler.cpp b/cObjectHandler.cpp index ee47226..5f2782b 100644 --- a/cObjectHandler.cpp +++ b/cObjectHandler.cpp @@ -26,11 +26,33 @@ int cObjectHandler::moveObject(int _object, sPos _pos, int _mode) return 1; sPos objPosition = objects[_object]->getPosition(); + sPos newPosition; if (_mode == _MOVE_RELATIVE) - objects[_object]->setPosition(sPos{ objPosition.x + _pos.x, objPosition.y + _pos.y }); + newPosition = { objPosition.x + _pos.x, objPosition.y + _pos.y }; else if (_mode == _MOVE_ABSOLUTE) + newPosition = _pos; + else if (_mode == _MOVE_FORCE_ABSOLUTE) + { objects[_object]->setPosition(_pos); + return 0; + } + + sCollision coll = checkCollision(newPosition, objects[_object]->getSize()); + + bool abort = false; + + if(coll.idc) + { + for(int i = 0; i < coll.idc; i++) + { + if(coll.idv[i] != _object) + abort += objects[_object]->onCollisionActive(0, objects[coll.idv[0]]->onCollisionPassive(0)); + } + } + + if(!abort) + objects[_object]->setPosition(newPosition); buildHitmap(); return 0; @@ -256,3 +278,45 @@ sPos cObjectHandler::getCameraPosition() { return cameraPosition; } + +sCollision cObjectHandler::checkCollision(sPos _pos, sPos _size) +{ + sCollision ret; + vector collisions; + vector hitTypes; + ret.idc = 0; + + int sizeX, sizeY; + + sizeX = render->getSize().x; + sizeY = render->getSize().y; + + //No collision for offscreen objects + if( (_pos.x < cameraPosition.x && _pos.x + _size.x + cameraPosition.x < 0) || + (_pos.x - cameraPosition.x >= iHitMap.size() && _pos.x + _size.x - cameraPosition.x >= iHitMap.size()) || + (_pos.y < cameraPosition.y && _pos.y + _size.y + cameraPosition.y < 0) || + (_pos.y - cameraPosition.y >= iHitMap[0].size() && _pos.y + _size.y - cameraPosition.y >= iHitMap[0].size()) ) + return ret; + + for(int x = _pos.x - cameraPosition.x; x < _pos.x + _size.x - cameraPosition.x; x++) + { + for(int y = _pos.y - cameraPosition.y; y < _pos.y + _size.y - cameraPosition.y; y++) + { + if(!(x >= sizeX || x < 0 || y >= sizeY || y < 0)) + { + if(iHitMap[x][y]) + collisions.push_back(iHitMap[x][y]); + } + } + } + + ret.idc = collisions.size(); + ret.idv = (unsigned int*) malloc( sizeof(*ret.idv) * ret.idc ); + + for(int i = 0; i < ret.idc; i++) + { + ret.idv[i] = collisions[i]; + } + + return ret; +} diff --git a/cObjectHandler.h b/cObjectHandler.h index 0e7750c..1e872b3 100644 --- a/cObjectHandler.h +++ b/cObjectHandler.h @@ -8,9 +8,16 @@ //movemodes #define _MOVE_RELATIVE 0 #define _MOVE_ABSOLUTE 1 +#define _MOVE_FORCE_ABSOLUTE 2 using namespace std; +struct sCollision +{ + unsigned int *idv; + int *hitv; + unsigned int idc; +}; /** * Manages cObject and cWiremesh and writes them to a cRender framebuffer. @@ -32,7 +39,8 @@ public: /** * Alters position of _object by _pos either relative to old position or Absolute - * Depending on selected _mode (_MOVE_RELATIVE / _MOVE_ABSOLUTE). + * Depending on selected _mode (_MOVE_RELATIVE / _MOVE_ABSOLUTE / _MOVE_ABSOLUTE). + * _MOVE_ABSOLUTE not recommended: Collision is only checked at destination. To ensure initialisation, use _MOVE_FORCE_ABSOLUTE! */ int moveObject(int _object, sPos _pos, int _mode); @@ -89,6 +97,8 @@ public: private: + sCollision checkCollision(sPos _pos, sPos _size); + void buildHitmap(); vector objects; diff --git a/collision.txt b/collision.txt new file mode 100644 index 0000000..509e1bd --- /dev/null +++ b/collision.txt @@ -0,0 +1,11 @@ +collision check by using object map from click registering +collision passed as returns +cObject::collision? for both objects? + +bool onCollisionActive(unsigned int _hit, onCollisionPassice(_hit)) +_hit: TOP,BOTTOM,LEFT,RIGHT +return true: abort move ; false: continue move + +int onCollisionPassive(unsigned int _hit) +_hit: TOP,BOTTOM,LEFT,RIGHT +return: Maybe object type to tell object what it hit diff --git a/test.cpp b/test.cpp index 313b632..7d0c9b9 100644 --- a/test.cpp +++ b/test.cpp @@ -32,6 +32,11 @@ public: drawPoint('Q', _pos, true, _COL_YELLOW); } + virtual bool onCollisionActive(unsigned int _hit, int _passiveObject){ + drawPoint('K', {0,0}, true, _COL_RED); + return true; + } + virtual void onChar(unsigned char _c) { drawPoint(_c, {1,1},true, _COL_BLUE); } private: int cc; @@ -42,7 +47,6 @@ int main(int argc, char* argv[]) cRender render(' ', _COL_DEFAULT, 30,30); cObjectHandler handler(&render); cObject ver(45,1); - cWiremesh obj; testobject obj2; cInput input; @@ -60,37 +64,15 @@ int main(int argc, char* argv[]) ver.drawText(DATE, {20,0}, _COL_WHITE); ver.drawText(VERSTRING, {0,0}, _COL_WHITE); int iver = handler.createObject(&ver); - handler.moveObject(iver, {0,0}, _MOVE_ABSOLUTE); - - int x = 15; - int y = 15; - int z = 30; - - obj.addVector({-x,-y,z}, {2*x,0,0}, '+', _COL_RED); - obj.addVector({-x,-y,z}, {0,2*y,0}, '+', _COL_RED); - obj.addVector({-x,y,z}, {2*x,0,0}, '+', _COL_RED); - obj.addVector({x,-y,z}, {0,2*y,0}, '+', _COL_RED); - - obj.addVector({-x,-y,0}, {0,0,z}, ':', _COL_RED); - obj.addVector({x,-y,0}, {0,0,z}, ':', _COL_RED); - obj.addVector({-x,y,0}, {0,0,z}, ':', _COL_RED); - obj.addVector({x,y,0}, {0,0,z}, ':', _COL_RED); - - obj.addVector({-x,-y,0}, {2*x,0,0}, ',', _COL_RED); - obj.addVector({-x,-y,0}, {0,2*y,0}, ',', _COL_RED); - obj.addVector({-x,y,0}, {2*x,0,0}, ',', _COL_RED); - obj.addVector({x,-x,0}, {0,2*y,0}, ',', _COL_RED); - int imesh = handler.createWiremesh(&obj); + handler.moveObject(iver, {0,0}, _MOVE_FORCE_ABSOLUTE); int iobj2 = handler.createObject((cObject*)&obj2); - handler.moveObject(iobj2, {3,3}, _MOVE_ABSOLUTE); + handler.moveObject(iobj2, {3,3}, _MOVE_FORCE_ABSOLUTE); sPos middle = render.getSize(); middle.x /= 2; middle.y /= 2; - handler.moveWiremesh(imesh,{middle.x,middle.y,0}, _MOVE_ABSOLUTE); - while( loop ) { sInputEvent ie = input.poll(); @@ -126,22 +108,16 @@ int main(int argc, char* argv[]) switch(ie.c) { case 'w': - handler.rotateWiremesh(imesh,{-10,0,0}); + handler.moveObject(iobj2, {0,-1}, _MOVE_RELATIVE); break; case 's': - handler.rotateWiremesh(imesh,{10,0,0}); + handler.moveObject(iobj2, {0,1}, _MOVE_RELATIVE); break; case 'a': - handler.rotateWiremesh(imesh,{0,-10,0}); + handler.moveObject(iobj2, {-1,0}, _MOVE_RELATIVE); break; case 'd': - handler.rotateWiremesh(imesh,{0,10,0}); - break; - case 'q': - handler.rotateWiremesh(imesh,{0,0,-10}); - break; - case 'e': - handler.rotateWiremesh(imesh,{0,0,10}); + handler.moveObject(iobj2, {1,0}, _MOVE_RELATIVE); break; }; } @@ -151,8 +127,6 @@ int main(int argc, char* argv[]) } } - handler.rotateWiremesh(imesh,{1,1,1}); - handler.write(); render.render(); framecounter++; diff --git a/test_old.cpp b/test_old.cpp new file mode 100644 index 0000000..313b632 --- /dev/null +++ b/test_old.cpp @@ -0,0 +1,165 @@ +#include +#include + +#include "version.h" + +#include "cRender.h" +#include "cObject.h" +#include "cObjectHandler.h" +#include "cInput.h" +#include "cWiremesh.h" + +//#include "testobject.h" + +class testobject : cObject +{ +public: + testobject() + { + setSize(10,5); + cc = 0; + + drawRectangle('#', NULL, {0,0}, {9,4}, _COL_GREEN, _COL_DEFAULT); + } + + ~testobject() { destruct(); } + + virtual void onClick(sPos _pos, unsigned int _button) + { + cc++; + drawText(std::to_string(cc), {2,2}, _COL_RED); + + drawPoint('Q', _pos, true, _COL_YELLOW); + } + + virtual void onChar(unsigned char _c) { drawPoint(_c, {1,1},true, _COL_BLUE); } +private: + int cc; +}; + +int main(int argc, char* argv[]) +{ + cRender render(' ', _COL_DEFAULT, 30,30); + cObjectHandler handler(&render); + cObject ver(45,1); + cWiremesh obj; + testobject obj2; + + cInput input; + + unsigned int framecounter = 0; + bool loop = true; + + if(argc > 1) + { + loop = false; + } + + render.render(); + + ver.drawText(DATE, {20,0}, _COL_WHITE); + ver.drawText(VERSTRING, {0,0}, _COL_WHITE); + int iver = handler.createObject(&ver); + handler.moveObject(iver, {0,0}, _MOVE_ABSOLUTE); + + int x = 15; + int y = 15; + int z = 30; + + obj.addVector({-x,-y,z}, {2*x,0,0}, '+', _COL_RED); + obj.addVector({-x,-y,z}, {0,2*y,0}, '+', _COL_RED); + obj.addVector({-x,y,z}, {2*x,0,0}, '+', _COL_RED); + obj.addVector({x,-y,z}, {0,2*y,0}, '+', _COL_RED); + + obj.addVector({-x,-y,0}, {0,0,z}, ':', _COL_RED); + obj.addVector({x,-y,0}, {0,0,z}, ':', _COL_RED); + obj.addVector({-x,y,0}, {0,0,z}, ':', _COL_RED); + obj.addVector({x,y,0}, {0,0,z}, ':', _COL_RED); + + obj.addVector({-x,-y,0}, {2*x,0,0}, ',', _COL_RED); + obj.addVector({-x,-y,0}, {0,2*y,0}, ',', _COL_RED); + obj.addVector({-x,y,0}, {2*x,0,0}, ',', _COL_RED); + obj.addVector({x,-x,0}, {0,2*y,0}, ',', _COL_RED); + int imesh = handler.createWiremesh(&obj); + + int iobj2 = handler.createObject((cObject*)&obj2); + handler.moveObject(iobj2, {3,3}, _MOVE_ABSOLUTE); + + sPos middle = render.getSize(); + middle.x /= 2; + middle.y /= 2; + + handler.moveWiremesh(imesh,{middle.x,middle.y,0}, _MOVE_ABSOLUTE); + + while( loop ) + { + sInputEvent ie = input.poll(); + + if(ie.type != _EVENT_NULL) + { + if(ie.type == _EVENT_KEY) + { + switch (ie.c) + { + case 'A'://up + handler.setCameraPosition({0,-1}, _MOVE_RELATIVE); + break; + case 'B'://down + handler.setCameraPosition({0,1}, _MOVE_RELATIVE); + break; + case 'C'://right + handler.setCameraPosition({1,0}, _MOVE_RELATIVE); + break; + case 'D'://left + handler.setCameraPosition({-1,0}, _MOVE_RELATIVE); + break; + }; + } + else if (ie.type == _EVENT_MOUSE) + { + if(ie.b == 0) + handler.clickEvent({ie.x, ie.y}, 0); + } + else if (ie.type == _EVENT_CHAR) + { + //handler.charEvent(ie.c); + switch(ie.c) + { + case 'w': + handler.rotateWiremesh(imesh,{-10,0,0}); + break; + case 's': + handler.rotateWiremesh(imesh,{10,0,0}); + break; + case 'a': + handler.rotateWiremesh(imesh,{0,-10,0}); + break; + case 'd': + handler.rotateWiremesh(imesh,{0,10,0}); + break; + case 'q': + handler.rotateWiremesh(imesh,{0,0,-10}); + break; + case 'e': + handler.rotateWiremesh(imesh,{0,0,10}); + break; + }; + } + else if (ie.type == _EVENT_TERM) + { + return 0; + } + } + + handler.rotateWiremesh(imesh,{1,1,1}); + + handler.write(); + render.render(); + framecounter++; + + if(loop) + usleep(10*1000); + } + + return 0; +} -- cgit v1.2.3