I have the following problem already longer time. The point ist that I have read a bit on stackoverflow and I have used a typedef, but I doesnt help me.
Looking forward to get some help :)
Align_vector.h :
#include <utils/vector_2d.h>
class Vector_2d;
namespace Utils {
class Align_vector : public Vector_2d {
protected:
bool check_range(int x, int y);
public:
typedef enum {left, right, up, down} Alignment;
Align_vector(Alignment alignment);
void set_alignment(Alignment alignment);
Alignment get_alignment();
};
} /* namespace Utils */
Align_vector.cc :
#include <utils/align_vector.h>
namespace Utils {
Align_vector::Align_vector(Alignment alignment) {
this->alignment = alignment;
}
void set_alignment(Alignment alignment) {
Align_vector::alignment = alignment;
}
Alignment get_alignment() {
return Align_vector::alignment ;
}
bool check_range(int x, int y) {
switch ( Align_vector::alignment ) {
case Align_vector::left:
if (x == -1 && y == 0) {
return true;
} else {
return false;
}
break;
case Align_vector::right:
if (x == 1 && y == 0) {
return true;
} else {
return false;
}
break;
case Align_vector::down:
if (x == 0 && y == -1) {
return true;
} else {
return false;
}
break;
case Align_vector::up:
if (x == 0 && y == 1) {
return true;
} else {
return false;
}
break;
default:
return false;
break;
}
}
} /* namespace Utils */
Here is the error:
/utils/align_vector.cc:14:47: error: no matching function for call to ‘Utils::Vector_2d::Vector_2d()’
Align_vector::Align_vector(Alignment alignment) {
This code has numerous issues. First of all, you have defined an
enum called Alignment, but you did not declare a member
of that type. To do so, add this line after the definition of the enum:
Alignment alignment;
Your definitions of methods are also incorrect, the alignment is
supposed to belong to a specific object, while you are using it in
several functions as if it were a static member of the class. Here
are the fixed versions of method definitions:
namespace Utils {
Align_vector::Align_vector(Alignment alignment) {
this->alignment = alignment;
}
void Align_vector::set_alignment(Alignment alignment) {
this->alignment = alignment;
}
Align_vector::Alignment Align_vector::get_alignment() {
return this->alignment;
}
bool Align_vector::check_range(int x, int y) {
switch(this->alignment) {
case Align_vector::left:
if(x == -1 && y == 0) {
return true;
}
else {
return false;
}
break;
case Align_vector::right:
if(x == 1 && y == 0) {
return true;
}
else {
return false;
}
break;
case Align_vector::down:
if(x == 0 && y == -1) {
return true;
}
else {
return false;
}
break;
case Align_vector::up:
if(x == 0 && y == 1) {
return true;
}
else {
return false;
}
break;
default:
return false;
break;
}
}
} /* namespace Utils */
Finally, you are missing a definition of a default constructor for base
class Vector_2d (your comments suggest that you did not define that class
at all, you just declared its existance using statement class Vector_2d;).
Judging by your overall implementation, I think user #molbdnilo was correct
when suggesting you should learn more about C++ programming in general.
Hope this helps!
Related
By the below link to Compiler Explorer you get two versions of the same finite state machine: one as a switch-statement
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#define MORE
//#define ENTER
volatile uint8_t r = 0;
volatile uint8_t x = 0;
namespace {
struct FSM {
enum class State : uint8_t {Test0, Test1, Test2, Test3, Test4
#ifdef MORE
, Test5, Test6, Test7
#endif
};
inline static void process(const uint8_t b) {
const auto oldState = mState;
switch(mState) {
case State::Test0:
if (b == 0) {
mState = State::Test1;
}
break;
case State::Test1:
if (b == 1) {
mState = State::Test2;
}
break;
case State::Test2:
if (b == 2) {
mState = State::Test3;
}
break;
case State::Test3:
if (b == 3) {
mState = State::Test4;
}
break;
case State::Test4:
if (b == 4) {
#ifdef MORE
mState = State::Test5;
#else
mState = State::Test0;
#endif
}
break;
#ifdef MORE
case State::Test5:
if (b == 5) {
mState = State::Test6;
}
break;
case State::Test6:
if (b == 6) {
mState = State::Test7;
}
break;
case State::Test7:
if (b == 7) {
mState = State::Test0;
}
break;
#endif
}
#ifdef ENTER
if (oldState != mState) {
switch(mState) {
case State::Test0:
x = 40;
break;
case State::Test1:
x = 41;
break;
case State::Test2:
x = 42;
break;
case State::Test3:
x = 43;
break;
case State::Test4:
x = 44;
break;
#ifdef MORE
case State::Test5:
x = 45;
break;
case State::Test6:
x = 46;
break;
case State::Test7:
x = 47;
break;
#endif
}
}
#endif
}
private:
inline static State mState{State::Test0};
};
using fsm = FSM;
}
int main() {
while(true) {
const uint8_t b = r;
fsm::process(b);
}
}
and one as equivalent if-statments.
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#define MORE
//#define ENTER
volatile uint8_t r = 0;
volatile uint8_t x = 0;
namespace {
struct FSM {
enum class State : uint8_t {Test0, Test1, Test2, Test3, Test4
#ifdef MORE
, Test5, Test6, Test7
#endif
};
inline static void process(const uint8_t b) {
const auto oldState = mState;
if (mState == State::Test0) {
if (b == 0) {
mState = State::Test1;
}
}
else {
if (mState == State::Test1) {
if (b == 1) {
mState = State::Test2;
}
}
else {
if (mState == State::Test2) {
if (b == 2) {
mState = State::Test3;
}
}
else {
if (mState == State::Test3) {
if (b == 3) {
mState = State::Test4;
}
}
else {
if (mState == State::Test4) {
if (b == 4) {
#ifndef MORE
mState = State::Test0;
#else
mState = State::Test5;
}
}
else {
if (mState == State::Test5) {
if (b == 5) {
mState = State::Test6;
}
}
else {
if (mState == State::Test6) {
if (b == 6) {
mState = State::Test7;
}
}
else {
if (mState == State::Test7) {
if (b == 7) {
mState = State::Test0;
}
}
}
#endif
}
}
}
}
}
}
#ifdef ENTER
if (oldState != mState) {
if (mState == State::Test1) {
x = 41;
}
else {
if (mState == State::Test2) {
x = 42;
}
else {
if (mState == State::Test3) {
x = 43;
}
else {
if (mState == State::Test4) {
x = 44;
}
#ifdef MORE
else {
if (mState == State::Test5) {
x = 45;
}
else {
if (mState == State::Test6) {
x = 46;
}
else {
if (mState == State::Test7) {
x = 47;
}
}
}
}
#endif
}
}
}
}
#endif
}
private:
inline static State mState{State::Test0};
};
using fsm = FSM;
}
int main() {
while(true) {
const uint8_t b = r;
fsm::process(b);
}
}
https://godbolt.org/z/7TdEo31KE
Side note: this is a stripped down version of some tests I made to implement the finite-state-machine with template-metaprogramming, which is quite straight forward and fundamentally gives the same copy as the if-statement example by template-recursion.
First I found that gcc starts to generate a jump-table for the switch-implementation using more than 5 states, the same occurs in the if-statement example with more than 7 states.
But even with more than 7 states the code is fundamentally different: the if-statement example uses a 7-entry jump-table whereas the switch-statement example uses a jump-table with 8 entries. This is also true for x86 backend and also for clang.
My assembler skills are limited, therefore two questions arise:
which one is more performant?
can some changes to the code make the two version look the same in assembler?
i try to sort a vector which element-type is a class like following:
void sort_test() {
class A{
public:
A(float x, float y, float z):score_(x),rerank_score_(y),ranking_score_(z) {};
float score_;
float rerank_score_;
float ranking_score_;
};
using A_ptr = std::shared_ptr<A>;
auto CompareA_ptr = [](A_ptr x, A_ptr y) {
if (x == nullptr && y != nullptr) {
return false;
} else if (x == nullptr && y == nullptr) {
return false;
} else if (x != nullptr && y == nullptr) {
return true;
} else {
if (x->rerank_score_ > y->rerank_score_) {
return true;
} else if (x->rerank_score_ < y->rerank_score_) {
return false;
} else {
if (x->score_ > y->score_) {
return true;
} else if (x->score_ < y->score_) {
return false;
} else {
return x->ranking_score_ >= y->ranking_score_;
}
}
}
};
std::vector<A_ptr> X;
for (int i = 0; i < 7; ++i) {
X.push_back(std::make_shared<A>(A(0.1, 0.1, 0.1)));
}
std::sort(X.begin(), X.end(), CompareA_ptr);
}
int main(){
sort_test();
return 0;
}
I run the code in Xcode and get the Xcode error "Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)"in memory.cpp:
I found that the code runs correctly when the vector size is less than 7, and an error is reported when the vector size is greater than 7. It bothers me a lot.
Appreciate for any reply.
Testing your code in Visual Studio revelas that CompareA_ptr doesn't define a strict weak ordering as required for a comparator. This causes undefined behaviour.
The culprit seems to be
return x->ranking_score_ >= y->ranking_score_;
where >= should be changed to >
return x->ranking_score_ > y->ranking_score_;
void Map::Movement()
{
int ch;
switch (ch = _getch())
{
case KEY_W: //up
if (Player::posy != 1)
{
if (AboveM == false)
{
Player::posy--;
DisplayMap();
}
}
break;
case KEY_S: //down
if (Player::posy != 20)
{
if (BelowM == false)
{
Player::posy++;
DisplayMap();
}
}
break;
case KEY_A: //left
if (Player::posx != 1)
{
if (LeftM == false)
{
Player::posx--;
DisplayMap();
}
}
break;
case KEY_D: //right
if (Player::posx != 20)
{
if (RightM == false)
{
Player::posx++;
DisplayMap();
}
}
break;
I can't for the life of me figure out where to put this so that the borders for the mob will work correctly (first question I know it isn't asked well since I haven't added the rest of the code but it should be simple to figure out)I've been putting it every place I could think of the last week or so as well as trying out everything else I could that would run I either get weird random errors or it runs as if the monster as no borders at all.
if ((Player::posy = Enemy::enemyBuild::posy) && (Player::posx = Enemy::enemyBuild::posx +1))
{
bool RightM = true;
}
if ((Player::posy = Enemy::enemyBuild::posy) && (Player::posx = Enemy::enemyBuild::posx -1))
{
bool LeftM = true;
}
if ((Player::posx = Enemy::enemyBuild::posx) && (Player::posy = Enemy::enemyBuild::posy +1))
{
bool BelowM = true;
}
if ((Player::posx = Enemy::enemyBuild::posx) && (Player::posy = Enemy::enemyBuild::posy -1))
{
bool AboveM = true;
}
I'm having a really bad time here looking for the error in my code.
My collision detection won't work here even the algorithm I searched in Google.
void PollEvents()
{
for (int i = 0;i < NUMBER_OF_BLOCKS; ++i)
{
Rectangle& a = blocks[i];
if (mouse.state == GLFW_PRESS)
{
//look for any block to grab
if (mouse.leftClick && !blocks[selectedBlock].Grab() &&
a.Hover(mouse.pos.x, mouse.pos.y))
{
//prevent grabbing another block
if (i != selectedBlock) {
selectedBlock = i;
}
a.Grab() = true;
if (a.IsTypeHorizontal()) {
diff = mouse.pos.x - a.Left();
} else {
diff = mouse.pos.y - a.Top();
}
}
if (a.Grab())
{
for (int j = 0;j < NUMBER_OF_BLOCKS; ++j)
{
//skip for any self-checking
if (i == j) continue;
Rectangle& b = blocks[j];
//check for rectangle collision
if (!a.Collide(b) || b.Collide(a)) {
//j++;
//how does this block will move.
if (a.IsTypeVertical()) {
a.SetY(mouse.pos.y - diff);
} else {
a.SetX(mouse.pos.x - diff);
}
} else {
switch (a.sideHit)
{
case UP:
//a.SetY(b.Bottom());
printf("UP\n");
break;
case DOWN:
//a.SetY(b.Top() + a.GetHeight());
printf("DOWN\n");
break;
case LEFT:
//a.SetX(b.Right());
printf("LEFT\n");
break;
case RIGHT:
//a.SetX(b.Left() - a.GetWidth());
printf("RIGHT\n");
break;
}
}
//check for bound collision
a.BoundCheck(1.f);
}
}
} else {
a.Grab() = false;
}
}
}
Collision detection:
bool Rectangle::Collide(const Rectangle& r) {
if (IsTypeHorizontal()) {
if (r.Hover(Left(), Top()) && r.Hover(Right(), Top())) {
sideHit = UP;
return true;
} else if (r.Hover(Right(), Bottom()) && r.Hover(Left(), Bottom())) {
sideHit = DOWN;
return true;
}
// } else if (r.Hover(Left(), Top())) {
// sideHit = UP;
// return true;
// } else if (r.Hover(Right(), Top())) {
// sideHit = UP;
// return true;
// } else if (r.Hover(Right(), Bottom())) {
// sideHit = DOWN;
// return true;
// } else if (r.Hover(Left(), Bottom())) {
// sideHit = DOWN;
// return true;
// }
} else {
if (r.Hover(Left(), Top()) && r.Hover(Left(), Bottom())) {
sideHit = LEFT;
return true;
} else if (r.Hover(Right(), Top()) && r.Hover(Right(), Bottom())) {
sideHit = RIGHT;
return true;
}
// } else if (r.Hover(Left(), Top())) {
// sideHit = LEFT;
// return true;
// } else if (r.Hover(Left(), Bottom())) {
// sideHit = LEFT;
// return true;
// } else if (r.Hover(Right(), Top())) {
// sideHit = RIGHT;
// return true;
// } else if (r.Hover(Right(), Bottom())) {
// sideHit = RIGHT;
// return true;
// }
}
return false;
}
Code for Hover:
inline float Hover(float X, float Y) const {
return X >= Left() &&
X <= Right() &&
Y >= Bottom() &&
Y <= Top();
}
I'm trying to make my own unblockme.
Please help me on my collision-detection. It's been 3 days now since I got stuck in this problem.
UPDATE
I have found out the problem why all rect-rect collision detection won't work in my program.
Bug:
if (!a.Collide(b)) {
//Move()
} else {
//Resolve collision
}
This one should be
if (!Rectangle::Collide(a, b)) {
//Move()
} else {
//Resolve collision
}
Making the Collide() a static member of Rectangle because, as you can see in my implementation of Collide(), it bases its decision on its own member so a.Hover(b.x, b.y) doesn't make any sense.
Hope this helps a little bit to all newbies like me.
To do rect/rect collision detection, if any of one (edges parallel to x and y axis) rect's four points is inside the other rect, we have a collision.
An easier way than to check each of the four points is to check if one X edge is between both the other rect's X edges, and if one Y edge is between both the other rect's Y edges - if both are true, we have a collision (because the two edges must meet at a point inside of the other rect). So we just check this in both directions:
bool isclamped(float mid, float A, float B)
{
if (A > B)
{
return mid >= B && mid <= A;
}
return mid >= A && mid <= B;
}
bool checkcollisiononeway(rect rectA, rect rectB)
{
if (isclamped(rectA.left, rectB.left, rectB.right)
|| isclamped(rectA.right, rectB.left, rectB.right))
&& (isclamped(rectA.bottom, rectB.bottom, rectB.top)
|| isclamped(rectA.top, rectB.bottom, rectB.top))
{
return true;
}
return false;
}
bool checkcollisionbothways(rect rectA, rect rectB)
{
return checkcollisiononeway(rectA, rectB) || checkcollisiononeway(rectB, rectA);
}
To determine the angle of collision after detecting a collision, find the angle between their two centers using atan2(rectA.y - rectB.y, rectA.x - rectB.x) (the angle is returned in radians, not in degrees)
The many repetitious switch statements seems like it needs to be DRY'd. Any suggestions? (Including doing nothing!)
AnimMapIter _iter;
_iter = _animations->find(name);
if(_iter == _animations->end()) return;
if(_curName != name) {
_curName = name;
switch(dir) {
case DIR_FORWARD_LOOPING: /* Fall through to DIR_FORWARD_NONLOOPING */
case DIR_FORWARD_NONLOOPING:
_iter->second->First();
break;
case DIR_REVERSE_LOOPING: /* Fall through to DIR_REVERSE_NONLOOPING */
case DIR_REVERSE_NONLOOPING:
_iter->second->Last();
break;
}
} else {
switch(dir) {
case DIR_FORWARD_LOOPING: /* Fall through to DIR_FORWARD_NONLOOPING */
case DIR_FORWARD_NONLOOPING:
_iter->second->Next();
break;
case DIR_REVERSE_LOOPING: /* Fall through to DIR_REVERSE_NONLOOPING */
case DIR_REVERSE_NONLOOPING:
_iter->second->Previous();
break;
}
switch(dir) {
case DIR_FORWARD_LOOPING:
if(_iter->second->IsAtEnd())
_iter->second->First();
break;
case DIR_FORWARD_NONLOOPING:
if(_iter->second->IsAtEnd())
_iter->second->Last();
break;
case DIR_REVERSE_LOOPING:
if(_iter->second->IsAtFront())
_iter->second->Last();
break;
case DIR_REVERSE_NONLOOPING:
if(_iter->second->IsAtFront())
_iter->second->First();
break;
}
}
Everything under the else should collapse into a single switch to bring the related steps closer; e.g.
case DIR_FORWARD_LOOPING:
_iter->second->Next();
if (_iter->second->IsAtEnd()) {
_iter->second->First();
}
break;
...all in that one case. Repetition of a couple of function calls is not a big deal when it makes the overall sequence of actions more clear.
Push the logic into whatever _iter->second is, along these lines (assuming the methods you've already shown exist):
class WhateverItIs
{
public:
void Start() { if (m_forward) First(); else Last(); }
void Stop() { if (m_forward) Last(); else First(); }
void Advance()
{
if (m_forward)
Next();
else
Previous();
if (IsLast())
{
if (m_loop)
Start();
else
Stop();
}
}
private:
bool IsLast() const
{
return m_forward ? IsAtEnd() : IsAtFront();
}
// Direction and looping are independent concepts.
bool m_forward;
bool m_loop;
};
Then you can write:
AnimMapIter _iter;
_iter = _animations->find(name);
if(_iter == _animations->end()) return;
if(_curName != name) {
_curName = name;
_iter->second->Start();
} else {
_iter->second->Advance();
}
Edit: Example using free functions and keeping the constants.
void Start(Strip* s, bool forward)
{ if (forward) s->First(); else s->Last(); }
void Stop(Strip* s, bool forward)
{ if (forward) s->Last() else s->First(); }
void Advance(Strip* s, bool forward, bool loop)
{
if (forward)
s->Next();
else
s->Previous();
if (IsLast(s, forward))
{
if (loop)
Start(s);
else
Stop(s);
}
}
bool IsLast(const Strip* s, bool forward) const
{
return forward ? s->IsAtEnd() : s->IsAtFront();
}
bool Projector::IsForward() const
{
return dir == DIR_FORWARD_LOOPING || dir == DIR_FORWARD_NONLOOPING;
}
bool Projector::IsLooping() const
{
return dir == DIR_REVERSE_LOOPING || dir == DIR_FORWARD_LOOPING;
}
if(_curName != name) {
_curName = name;
Start(_iter->second, IsForward());
} else {
Advance(_iter->second, IsForward(), IsLooping());
}