A* pathfinding find path that player need to walk, c++ in Qt - c++

I'm trying to implement the A* algorithm for finding the fastest path to the destination. I can find the path when the destination is not far away from the player. But it's freezes when I take a position that is far away from the player. Can anyone help me out with this? Can't find it anyway.
int Controller::findPathfindingNodes(int xdes, int ydes)
{
std::vector<std::shared_ptr<Tile>> tiles = model->getAllLimitTiles(); //all the tiles where we can move
std::shared_ptr<Protagonist> prota = model->getAllProtagonist(); //get data from protagonist
int currentX = prota->getXPos(); //get xpos of prota
int currentY = prota->getYPos(); //get ypos of prota
openList.clear();
closedList.clear();
mylist.clear();
//return 50;
std::shared_ptr<Tile> endPoint = model->getCoordinate(QPointF(xdes,ydes));
std::shared_ptr<Tile> startPoint = model->getCoordinate(QPointF(currentX,currentY));
int sumtotal = abs((currentX - xdes) + (currentY - ydes));
//we insert our start position, we have no parrent yet
PathFinding* start = new PathFinding(startPoint,currentX, currentY, 0, sumtotal,nullptr);
//this value we insert in our openList
openList.insert(start->getXCoord() + (model->getCols()+1)*start->getYCoord(), start);
bool pathFound = false;
int i = 0;
int pathcost;
//do whil path is found
while(!pathFound){
QHashIterator<int, PathFinding*> iterator(openList);
PathFinding* parent;
iterator.next();
parent = iterator.value();
//we take the next tile, and we take the one with the lowest value
while(iterator.hasNext()){
iterator.next();
//checking lowest f value
if((iterator.value()->getGcost() + iterator.value()->getHcost()) < (parent->getGcost() + parent->getHcost())){
parent = iterator.value();
}
}
//here we check if we are at the destionation. if we are we return our pathcost.
if(atDestionation(parent,endPoint)){
pathFound = true;
while(parent->hasParent()){
mylist.append(parent);
parent = parent->getParent();
}
//we calculate what the pathcost is and return it
pathcost = calculatePathCost(mylist);
return pathcost;
}else{
int parent_x = parent->getXCoord();
int parent_y = parent->getYCoord();
i++;
clearLists(parent);
filllists(parent,endPoint);
}
}
}
To put the values of the nodes in the open & closed list I do with this:
void Controller::filllists(PathFinding *parent,std::shared_ptr<Tile> endPoint)
{
int xPosNode = parent->getXPos();
int yPosNode = parent->getYPos();
//while found location
for(int x = -1; x < 2; x++) {
for(int y = -1; y <2; y++) {
int p_x = xPosNode + x;
int p_y = yPosNode + y;
// Is this coordinate within the world?
if(p_x >= 0 && p_x < model->getCols() && p_y >= 0 && p_y < model->getRows()) {
//we check if the tile exist (if it's no infinity tile)
if(model->tileExist(QPointF(p_x,p_y))){
// Already in open list > Check if current node is a better parent
if((!openList.value(p_x))+ (model->getCols() + 1)*(p_y)){
// Not in open and not in closed list > Possible candidate
if((!closedList.value(p_x))+ (model->getCols() + 1)*(p_y)){
int h_value = calculateHvalue(parent->getXCoord(),parent->getYCoord(),endPoint->getXPos(),endPoint->getYPos());
//int g_value = parent->getGcost() + calculateTileCost(parent->getXCoord(),parent->getYCoord(),p_x,p_y);
int g_value = calculateGvalue(parent, p_x, p_y);
std::shared_ptr<Tile> tile = model->getCoordinate(QPointF(p_x,p_y));
PathFinding* move = new PathFinding(tile,p_x, p_y, g_value, h_value, parent);
int number = move->getXCoord() + (model->getCols()+1)*move->getYCoord();
openList.insert(move->getXCoord() + (model->getCols()+1)*move->getYCoord(), move);
}
}
}
}
}
}
}
My header file looks like:
class Controller : public QObject
{
Q_OBJECT
public:
Controller(std::shared_ptr<Model> &modelPtr,std::shared_ptr<View> &viewPtr);
// void checkTile(QString position,PathFinding *parent, std::shared_ptr<Tile> endPoint, int pos);
void checkAboveTile(PathFinding *parent, std::shared_ptr<Tile> endPoint, int pos);
void checkBelowTile(PathFinding *parent, std::shared_ptr<Tile> endPoint, int pos);
void checkLeftTile(PathFinding *parent, std::shared_ptr<Tile> endPoint, int pos);
void checkRightTile(PathFinding *parent, std::shared_ptr<Tile> endPoint, int pos);
bool atDestionation(PathFinding *parent, std::shared_ptr<Tile> endPoint);
float calculateTileCost(int xposnew,int yposnew, int xpos, int ypos);
int calculateHvalue(int p_x,int p_y, int des_x, int des_y);
int calculateGvalue(PathFinding *parent, int x, int y);
void filllists(PathFinding *parent, std::shared_ptr<Tile> endPoint);
//QPair<QList<QPointF>, float> generatePath(Tile* endPoint);
//Openlist contains the nodes to be examined
QHash <int, PathFinding *> openList;
//ClosedList has the nodes that are already examined
QHash <int, PathFinding *> closedList;
QList<QPointF> pathlist;
void clearLists(PathFinding *parent);
QList<PathFinding*> mylist;
int calculatePathCost(QList<PathFinding*> mylist);
int findPathfindingNodes(int xdes, int ydes);
private:
std::shared_ptr<Model> model;
std::shared_ptr<View> view;
int heurCost;
signals:
void atDestination(int xPos,int yPos);
void gotoview(int xPos,int yPos);
public slots :
void goToDestination(int xDestination, int yDestination);
};
#endif // CONTROLLER_H
When I try to output the path which is travelled the I can see that it put sometimes the same position in mylist.
X1 value : 2 Y1 value : 3
X1 value : 1 Y1 value : 3
X1 value : 0 Y1 value : 3
X1 value : 1 Y1 value : 3
X1 value : 1 Y1 value : 3
X1 value : 2 Y1 value : 3
X1 value : 2 Y1 value : 4
X1 value : 3 Y1 value : 4
X1 value : 3 Y1 value : 4
X1 value : 3 Y1 value : 5
X1 value : 2 Y1 value : 6
X1 value : 2 Y1 value : 6
X1 value : 1 Y1 value : 6
X1 value : 0 Y1 value : 6
X1 value : 0 Y1 value : 7
X1 value : 0 Y1 value : 6
X1 value : 0 Y1 value : 5
This is how the player walked, can see that he sometimes uses the same parent over again.

I can't see anywhere that you move visited nodes from the open list to the closed list.
This would account for visiting the same place multiple times.
if((!openList.value(p_x)) + (model->getCols() + 1)*(p_y)) is very likely to be true.
(Adding 0 or 1 to (model->getCols() + 1)*p_y is probably non-zero.)
I believe you meant if(!openList.value(p_x + (model->getCols() + 1)*p_y)).
(Same issue with the closed list.)
This would also account for multiple visits, as you repeatedly insert the same nodes in the open list.
I would suggest abstracting out the index calculation:
int index(shared_ptr<Model> model, int x, int y)
{
return x * (model->getCols() + 1)* y;
}
and using that instead of error-prone code reproduction, e.g.
openList.insert(index(model, start->getXCoord(), start->getYCoord()), start);
// ...
if(!openList.value(index(model, p_x, p_y)))
It's also a good idea to add tracing output along the way.

Related

error LNK2019: unresolved external symbol Visual Studio 2013 with openCV

I am using OpenCV 2.4.10 with Visual Studio 2013 for my code. But I am getting the following linking error:
1>Pathfinding.obj : error LNK2019: unresolved external symbol "public:
class cv::Vec & __cdecl cv::Mat::at >(int,int)"
(??$at#V?$Vec#E$02#cv###Mat#cv##QEAAAEAV?$Vec#E$02#1#HH#Z) referenced
in function "private: struct Pathfinding::Point2A * __cdecl
Pathfinding::GetNeighbors(struct Pathfinding::Point2A,int &)"
(?GetNeighbors#Pathfinding##AEAAPEAUPoint2A#1#U21#AEAH#Z)
1>C:\Users\ysingh\Documents\DstarLite\OpenCV\Astar\x64\Debug\Astar.exe
: fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Here is the header file (please see struct Point2A in class definition) where the above error is referring to:
#include<opencv2\core\core.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<string>
class Pathfinding
{
private :
//Two dimensional , integer -based point structure , contains additional variables for pathfinding calculation
**struct Point2A**
{
// x, y the coordinates of the point
//dir is the direction from the previous point . see directions coding below
int x, y, dir;
//level: the cost of route from start to this point
//fscore: the essence of the A* algorithm, value is : [level] + [in air distance from destination] * astar_weight
float fScore, level;
//Constructors
Point2A() : x(0), y(0), fScore(0), dir(0){};
Point2A(int _x, int _y, float _level = 0.f, int _dir = 0) :x(_x), y(_y), level(_level), fScore(0), dir(_dir) {};
//== operator overload
bool operator == (const Point2A other);
};
//CompByPos : struct used in the stl map<Point2A, Point2A> during the pathfinding
//it only contains a comparator function
//we need this, because every point is unique by position, but not by fscore
struct CompByPos
{
bool operator()(const Point2A a, const Point2A b) const;
};
//CompByFScore : contains a comparating function, which works by fscore
//it gives priority for the smaller fScore
//used in stl priority_queue<Point2A>
struct CompByFScore
{
bool operator()(const Point2A a, const Point2A b);
};
//mapimg is the map got, pathmap is the same, but the pixels of the path are colored
//pathmap is only valid after calculate path
//blurmap is matimg blurred with opencv function, its used in keeping away from walls
cv::Mat mapimg, pathmap, blurmap;
//astar_weight is the multiplier of A* coefficient
//wall_weight is used in keeping away from walls features
float astar_weight, wall_weight;
//no comment
Point2A start, dest;
//daigonal decides if a pixel (which is a node) has 4 or 8 neighbours
//see direction coding below
//calculated decides if the Pathfinding object has valid path for current map and settings
bool diagonal, calculated;
//mrows and mcols refers to the size of mapimg
//blursize is used in avaoiding wall avoidance feature
int mrows, mcols, blur_size;
//stores the list of directions for the path
std::string dir;
//calculated Eucledian Distance between two points a and b
float Distance(Point2A a, Point2A b);
//returns an array of the points surrounding point p
//the length of the array is not constant, because the function performs
//OnMap checks too. use arraySize ref variable to get the size of the array returned
Point2A* GetNeighbors(Point2A p, int& arraySize);
// Function sets default values
void InitValues();
//Checks if point p is wall
//Class support black and white maps, where black pixels are wall
bool IsWall(Point2A p);
//Function decides if coordinates of this point are on map or not
bool OnMap(int x, int y);
public:
enum ErrorCodes
{
NoError = 0,
NoMap,
StartIsWall,
DestIsWall,
NoPath,
AlreadyCalculated
};
static const int diagonalDirX[];
static const int diagonalDirY[];
static const int nonDiagonalDirX[];
static const int nonDiagonalDirY[];
//constructor :sets default values diagonal = true, astar coefficient 0.3
Pathfinding();
//constructor, argument map is the map on which algorithm is implemented
Pathfinding(cv::Mat map, bool _diagonal = true);
//Set OpenCV Mat image as the map
void SetMap(cv::Mat map);
////sets the A* pathfinding coefficient. 0.f means Dijkstra's algorithm, anything else is A* (positive values recommended).
//The bigger the value, the more the algorithm steers towards the destination
//but setting it too high can result in suboptimal path
//after changing that, have to call CalculatePath again
void SetAWeight(float weight);
//if set to true, each pixel has 8 connected neighbor, else only 4 - see GetDirections() comment
//after changing that, have to call CalculatePath again
void SetDiagonal(bool _diagonal);
//sets the value of how much the algorithm tries to avoid going near walls.
//weight: the amount the walls push away the route. default 10.f
//0.f disables the feature
//avoidZoneLevel: the size of the zone surrounding the walls, in which the upper effect works. default: 5
void SetWallWeight(float weight, int avoidZoneLevel);
//sets the start point. the coordinate system is the OpenCV/image default, the origin is the upper left corner of the image.
//start and destination points have to be set after the map image!
void SetStart(int x, int y);
void SetDestination(int x, int y);
//returns the map, on which the calculated path is marked red
//call this after CalculatePath(), otherwise returns empty map
cv::Mat GetPathMap();
// returns a std::string of numbers, which represent the directions along the path.Direction coding(relative to p) :
//call after CalculatePath()
//if diagonal is set to true if diagonal == false
// [0] [1] [2] [3]
// [3] [p] [4] [2] [p] [0]
// [5] [6] [7] [1]
std::string GetDirections();
//evaluates the algorithm. It's a separate function because it takes some time
//check out the ErrorCodes enum to decode the returned values
ErrorCodes CalculatePath();
};
I am also attaching the .cpp for this class
#include "Pathfinding.h"
bool Pathfinding::Point2A::operator==(const Point2A other) {
return x == other.x && y == other.y;
}
bool Pathfinding::CompByPos::operator()(const Point2A a, const Point2A b) const
{
if (a.x == b.x)
return a.y > b.y;
else
return a.x > b.x;
}
bool Pathfinding::CompByFScore::operator()(const Point2A a, const Point2A b)
{
return a.fScore > b.fScore;
}
float Pathfinding::Distance(Point2A a, Point2A b)
{
float x = static_cast<float>(a.x - b.x);
float y = static_cast<float>(a.y - b.y);
return sqrtf(x*x + y*y);
}
Pathfinding:: Point2A* Pathfinding::GetNeighbors(Point2A p, int& arraySize)
{
arraySize = 0;
uchar size;
if (diagonal)
size = 8;
else
size = 4;
Point2A* ret = new Point2A[size];
for (int i = 0; i < size; i++) {
int x, y;
if (diagonal)
{
x = p.x + diagonalDirX[i];
y = p.y + diagonalDirY[i];
}
else
{
x = p.x + nonDiagonalDirX[i];
y = p.y + nonDiagonalDirY[i];
}
if (!OnMap(x, y))
continue;
float level = p.level + 1.f + (255 - blurmap.at<cv::Vec3b>(y, x)[2]) / 255.f * wall_weight;
Point2A n = Point2A(x, y, level, i);
if (diagonal && (i == 0 || i == 2 || i == 5 || i == 7))
n.level += 0.414213f;
ret[arraySize] = n;
arraySize++;
}
return ret;
}
void Pathfinding::InitValues()
{
astar_weight = 0.3f;
wall_weight = 10.f;
blur_size = 11;
diagonal = true;
calculated = false;
}
bool Pathfinding::IsWall(Point2A p)
{
if (mapimg.at<cv::Vec3b>(p.y, p.x) == cv::Vec3b(0, 0, 0))
return true;
return false;
}
bool Pathfinding::OnMap(int x, int y)
{
if (x >= 0 && y >= 0 && x < mcols && y < mrows)
return true;
return false;
}
const int Pathfinding::diagonalDirX[] = { -1, 0, 1, -1, 1, -1, 0, 1 };
const int Pathfinding::diagonalDirY[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
const int Pathfinding::nonDiagonalDirX[] = { 1, 0, -1, 0 };
const int Pathfinding::nonDiagonalDirY[] = { 0, 1, 0, -1 };
Pathfinding::Pathfinding()
{
InitValues();
}
Pathfinding::Pathfinding(cv::Mat map, bool _diagonal)
{
InitValues();
SetMap(map);
diagonal = _diagonal;
}
void Pathfinding::SetMap(cv::Mat map)
{
if (!map.empty())
{
mapimg = map;
calculated = false;
mrows = map.rows;
mcols = map.cols;
GaussianBlur(mapimg, blurmap, cv::Size(blur_size, blur_size), 0);
}
}
void Pathfinding::SetAWeight(float weight)
{
if (astar_weight != weight)
{
astar_weight = weight;
calculated = false;
}
}
void Pathfinding::SetDiagonal(bool _diagonal)
{
if (diagonal != _diagonal)
{
diagonal = _diagonal;
calculated = false;
}
}
void Pathfinding::SetWallWeight(float weight, int avoidZoneLevel)
{
if (wall_weight == weight && blur_size == 2 * avoidZoneLevel + 1)
return;
wall_weight = weight;
if (avoidZoneLevel >= 0)
blur_size = 2 * avoidZoneLevel + 1;
calculated = false;
}
void Pathfinding::SetStart(int x, int y)
{
if (!mapimg.empty())
{
if (OnMap(x, y))
{
start = Point2A(x, y);
calculated = false;
}
}
}
void Pathfinding::SetDestination(int x, int y)
{
if (!mapimg.empty())
{
if (OnMap(x, y))
{
dest = Point2A(x, y);
calculated = false;
}
}
}
cv::Mat Pathfinding::GetPathMap()
{
if (calculated) return pathmap;
else return cv::Mat();
}
std::string Pathfinding::GetDirections()
{
if (calculated) return dir;
else return std::string();
}
Pathfinding::ErrorCodes Pathfinding::CalculatePath()
{
if (calculated)
return AlreadyCalculated;
if (mapimg.empty())
return NoMap;
if (IsWall(start))
return StartIsWall;
if (IsWall(dest))
return DestIsWall;
dir = std::string();
mapimg.copyTo(pathmap);
int **closedSet = new int*[mrows];
float **openSet = new float*[mrows];
for (int i = 0; i < mrows; i++) {
closedSet[i] = new int[mcols];
openSet[i] = new float[mcols];
for (int j = 0; j < mcols; j++) {
closedSet[i][j] = 0;
openSet[i][j] = -1.0f;
}
}
std::priority_queue<Pathfinding::Point2A, std::vector<Point2A>, CompByFScore> openSetQue[2];
int osq = 0;
std::map <Pathfinding::Point2A, Pathfinding::Point2A, CompByPos> cameFrom;
start.fScore = Distance(start, dest);
openSetQue[osq].push(start);
openSet[start.y][start.x] = 0.0f;
while (openSetQue[osq].size() != 0) {
Point2A current = openSetQue[osq].top();
if (current == dest) {
while (cameFrom.size() != 0) {
pathmap.at<cv::Vec3b>(current.y, current.x) = cv::Vec3b(0, 0, 255);
dir = std::to_string(current.dir) + dir;
auto it = cameFrom.find(current);
Point2A keytmp = current;
if (it == cameFrom.end()) {
for (int i = 0; i < mrows; i++) {
delete openSet[i];
delete closedSet[i];
}
delete openSet;
delete closedSet;
calculated = true;
dir = dir.substr(1, dir.length() - 1);
return NoError;
}
current = cameFrom[current];
cameFrom.erase(keytmp);
}
}
openSetQue[osq].pop();
closedSet[current.y][current.x] = 1;
int arraySize;
Point2A *neighbors = GetNeighbors(current, arraySize);
for (int i = 0; i < arraySize; i++) {
Point2A neighbor = neighbors[i];
if (closedSet[neighbor.y][neighbor.x] == 1)
continue;
if (IsWall(neighbor)) {
closedSet[neighbor.y][neighbor.x] = 1;
continue;
}
float ngScore = neighbor.level;
if (openSet[neighbor.y][neighbor.x] == -1.0f || ngScore < openSet[neighbor.y][neighbor.x]) {
cameFrom[neighbor] = current;
neighbor.fScore = ngScore + Distance(neighbor, dest) * astar_weight;
if (openSet[neighbor.y][neighbor.x] == -1.0f) {
openSet[neighbor.y][neighbor.x] = ngScore;
openSetQue[osq].push(neighbor);
}
else {
openSet[neighbor.y][neighbor.x] = ngScore;
while (!(neighbor == openSetQue[osq].top())) {
openSetQue[1 - osq].push(openSetQue[osq].top());
openSetQue[osq].pop();
}
openSetQue[osq].pop();
if (openSetQue[osq].size() >= openSetQue[1 - osq].size()) {
osq = 1 - osq;
}
while (!openSetQue[osq].empty()) {
openSetQue[1 - osq].push(openSetQue[osq].top());
openSetQue[osq].pop();
}
osq = 1 - osq;
openSetQue[osq].push(neighbor);
}
}
}
delete neighbors;
}
return NoPath;
}
Here is my main file .cpp too :
#include"Pathfinding.h"
#include<opencv2\highgui\highgui.hpp>
#include<iostream>
Pathfinding pathfinding;
cv::Mat mapimg;
void DisplayMap()
{
cv::Mat tmp;
cv::imshow("Path", tmp);
}
int main()
{
//Open and load the map
mapimg = cv::imread("test.png");
pathfinding.SetMap(mapimg);
pathfinding.SetWallWeight(0.f, 0);
pathfinding.SetStart(1, 1);
pathfinding.SetDestination(39, 53);
pathfinding.SetDiagonal(false);
DisplayMap();
}
I think I am using Pathfinding class twice in the definition of the functions in .cpp ( i.e. Line 29 in .cpp file > Pathfinding:: Point2A* Pathfinding::GetNeighbors(Point2A p, int& arraySize)
My intention is not to throw a bunch of codes at the people but to give them an complete picture for the problem so that people can provide me some useful suggestions. My apologies for this.
My deadlines are near and I am constrained with time. Can someone suggest me some solutions.
I assume your project settings are the problem for this (your write you did a working minimalistic example, so you indeed use right libs and includes).
Please check what the include and lib paths evaluate to (check this inside the configuration site). Maybe you see they are relative paths or a makro was set wrong.
Usually, an "UNRESOLVED EXTERNAL" error means you did not link the right lib (32/64 debug/release these are 4 different combinations!) or the path to the lib is wrong.
See this answer,
If you DID explicitly set up linking with all the necessary libraries,
but linking errors still show, you might be mixing up 64/32 bit
libraries and application.
BUILD -> Configration Manager. check 'platform' is 'x64'
Check that your Project -> Properties -> VC++ Directories -> Library Directories, includes the path where the OpenCV libraries are
And Linker -> General -> Aditional Library Directories
C:\opencv\build\x64\vc11\lib
(on a 64-bit machine running VS2012, it will vary on other setups).

FloodFill: Record distance from Origin?

Short question, I implemented the Flood Fill Algorithm (Basically the first pseudo-code) into my C++ code and it works perfectly only I need to record how many tiles it's removed from the origin like this person accomplished.
I'm not looking for manhattan distance though.
This is my code. I omitted unnecessary code.
class MovementTile
{
public:
int x, y;
bool CanMoveTo;
bool IsPassable;
bool Visited;
MovementTile(int _x, int _y, bool _IsPassable)
{
x = _x;
y = _y;
IsPassable = _IsPassable;
Visited = false;
CanMoveTo = false;
}
};
void Fill(MovementTile* _tile, int _x, int _y)
{
if (!_tile->Visited)
{
if (!_tile->IsPassable)
{
_tile->Visited = true;
}
else
{
_tile->Visited = true;
_tile->CanMoveTo = true;
if (_x - 1 > 0)
{
Fill(TileList[_y][_x - 1], _x - 1, _y);
}
if (_y - 1 > 0)
{
Fill(TileList[_y - 1][_x], _x, _y - 1);
}
if (_y + 1 < TileList[_y].size())
{
Fill(TileList[_y + 1][_x], _x, _y + 1);
}
if (_x + 1 < TileList[_y].size())
{
Fill(TileList[_y][_x + 1], _x + 1, _y);
}
}
}
}

Packing arbitrary triangles into a finite box?

I need to pack triangles into a box as tightly as reasonable, as part of a 3D optimization (I'm stuffing alpha-using segments of different textures into a single different texture, for use with depth-sorting, so textures don't switch with every new tri)
Is there an algorithm for doing this? The triangles themselves can be made to be plyable (transformable to be right angles, effectively making this a box-stuffing algorithm instead), but I would like to avoid this if possible, as it would distort the underlying texture art.
"tight as reasonable" -> Something working is better than nothing.
These code fragments provide a simple solution to stuff shapes (also triangles) band by band into a rectangle.
public abstract class Shape {
protected Point offset = new Point();
public abstract int getHeight();
public abstract int getWidth();
}
public class Triangle extends Shape {
// all points are relative to offset (from Shape)
Point top = new Point(); // top.y is always 0, left.y >= 0 right.y >= 0
Point left = new Point(); // left.x < right.x
Point right = new Point();
public int getHeight() {
return left.y >= right.y ? left.y : right.y;
}
public int getWidth() {
int xmin = left.x <= top.x ? left.x : top.x;
int xmax = right.x >= top.x ? right.x : top.x;
return xmax - xmin;
}
}
public class StuffRectangle extends Shape {
private Point ww = new Point();
private ArrayList<Shape> maintained = new ArrayList<Shape>();
private int insx;
private int insy;
private int maxy;
public int getHeight() {
return ww.y;
}
public int getWidth() {
return ww.x;
}
public void clear() {
insx = 0;
insy = 0;
maxy = 0;
maintained.clear();
}
/**
* Fill the rectangle band by band.
*
* The inserted shapes are removed from the provided shape collection.
*
* #param shapes
* the shapes to insert
* #return the count of inserted shapes.
*/
public int stuff(Collection<Shape> shapes) {
int inserted = 0;
for (;;) {
int insertedInPass = 0;
for (Iterator<Shape> i = shapes.iterator(); i.hasNext();) {
Shape shape = i.next();
// does the shape fit into current band?
int sx = shape.getWidth();
if (insx + sx > getWidth())
continue;
int sy = shape.getHeight();
if (insy + sy > getHeight())
continue;
// does fit
++insertedInPass;
// remove from shapes
i.remove();
// add to maintained and adjust offset
maintained.add(shape);
shape.offset.x = insx;
shape.offset.y = insy;
insx += sx;
if (sy > maxy)
maxy = sy;
}
inserted += insertedInPass;
if (shapes.isEmpty())
break;
// nothing fits current band - try a new band
if (insertedInPass == 0) {
// already a new band - does not fit at all
if (insx == 0)
break;
// start new band
insx = 0;
insy += maxy;
maxy = 0;
continue;
}
}
return inserted;
}
}

How to move a point object on co-ordinates x-y in console - C++ OOP

I am doing my Object oriented programming assignment in which I am asked to create a game of catching numbers for children so that during their enjoyment they also learn counting numbers.
In here , I am supposed to create a Point class and an x-y coordinate. In here , I have to create a shift function which takes P (point object as a parameter). This function shift the first point when user presses key i.e arrow keys.
The problem is I am confused about what are the actual keywords use for arrow keys (like move UP, DOWN, LEFT, RIGHT) in c++ like we use in normal games to move an object or a person! ???
Here below is my code!
Class Point.h
#ifndef POINT_H
#define POINT_H
class Point
{
public:
Point(); // Default Constructor
Point(double, double, int); // Three argument constructor
void initialize(double, double, int);
void shift(Point p); // Shift the first point when user press keys
void setValue(int value);
int getValue() const;
void setX();
double getX() const;
void setY();
double gety() const;
void AddPointValue(Point p2); /*This function add the TWO points value
void displayPoint(); //This will use to display value of point
bool checkCoordinates();
bool checkTime(); // Check time remaining
private:
double x;
double y;
int value;
};
#endif
Implementation File
#include <iostream>
#include <windows.h>
#include "point.h"
using namespace std;
Point::Point() // Default Constructor
{
x = 0;
y = 0;
value = 0;
}
Point::Point(double x1, double y1, int value1){ // Three argument constructor
x = x1;
y = y1;
value = value1;
}
void Point::initialize(double init_x, double init_y, int init_value)
{
x = init_x;
y = init_y;
value = init_value;
}
void Point::shift(Point p){
if(p == VK_LEFT)
{
}else if(p == VK_RIGHT)
{
}else if(p == VK_UP)
{
}else if(p == VK_DOWN)
{
}
}
Its giving me an error right now that no match for an operator==(Operand type 'point' and 'int')
The issue with point and int is because you're trying to compare a 2d coordinate against an ASCII value (VK_*), change that part the following and it should be easier to maintain:
Point Point::shift(Point p, int keyPress)
{
Point maxSize = new Point();
Point minSize = new Point();
maxSize.x=80;
maxSize.y=40;
// Assuming a coordinate system of 0,0 (x,y) at top left of the display
switch (keyPress)
{
case (VK_LEFT): // increment the x coord by 1 to go left
p.x += 1;
if (p.x < minSize.x) p.x = minSize.x;
break;
case (VK_RIGHT): // decrement the x coord by 1 to go right
p.x -= 1;
if (p.x > maxize.x) p.x = maxSize.x;
break;
case (VK_UP): // decrement the y coord by 1 to go up
p.y -= 1;
if (p.y < minSize.y) p.y = minSize.y;
break;
case (VK_DOWN): // increment the y coord by 1 to go down
p.y += 1;
if (p.y > maxize.y) p.y = maxSize.y;
break;
}
return p;
}
you will also have to check that x and y are never smaller than 0 as that would take them off the display/cause an exception depending on how you structure the code and play area.
Hope this helps for your movement issues, but let me know if you need more info:)

C++ Weird function pointer behaviour

It's a simple opengl/sdl program. Generally theres a huge deque in which the program holds the display data for example a triangle will be inserted / readed in/from the dequeue like this ( GL_Begin .... Vertice 1 .... Vertice 2 ... Vertice 3 ... GL_End )
The Item struct
enum Shapes{
LINE,
POLYGON,
TRIANGLE
};
struct Item{
int id;
int type;
Shapes shape;
double x;
double y;
double z;
};
...
void GEngine::CC2D(int id,double x,double y){ // Change Coordinates ... Move the Item
for(int i=0;i<Items.size();i++){
Item* item = &Items[i]; // Pointer to the item INSIDE the deque because we need to edit it, we can not create a new instance of Item
if(item->id == id && item->type == 2){
item->x += x;
item->y += y;
}
}
DrawScene();
}
void GEngine::PollEvents( void (*Event)() ){
int mbpressed = 0; // Mouse button pressed flag
int mouse_xpre = 0;
int mouse_ypre = 0;
int move_id = 0; // TESTING
while(1){
while( SDL_PollEvent( &event ) ){
switch( event.type ){
case SDL_MOUSEMOTION:{
if(mbpressed == 1){
mouse_x = event.motion.x; // X2
mouse_y = event.motion.y; // Y2
// (*Event)();
// CC2D( ( X2 - X1 ),( Y2 - Y1 )
CC2D(move_id,(mouse_x-mouse_xpre),(mouse_y-mouse_ypre)); // The difference between the current and the previous mouse position is equal to the DX and DY which will be used to move the vertices.
mouse_xpre = mouse_x; // X1
mouse_ypre = mouse_y; // Y1
SDL_Delay(20);
}
break;
Now the issue. If i use CC2D(move_id,(mouse_x-mouse_xpre),(mouse_y-mouse_ypre)); it works fine but if I add the CC2D function into the Event one the algorithm fails and instead of the Item moving with the mouse it moves away from the screen.
In other words.
case SDL_MOUSEMOTION:{
if(mbpressed == 1){
mouse_x = event.motion.x; // X2
mouse_y = event.motion.y; // Y2
// (*Event)();
// CC2D( ( X2 - X1 ),( Y2 - Y1 )
CC2D(move_id,(mouse_x-mouse_xpre),(mouse_y-mouse_ypre)); // The difference between the current and the previous mouse position is equal to the DX and DY which will be used to move the vertices.
mouse_xpre = mouse_x; // X1
mouse_ypre = mouse_y; // Y1
SDL_Delay(20);
}
break;
}
^ Works just fine.
But
GEngine gEngine;
void Event(){
gEngine.CC2D(0,(gEngine.mouse_x-gEngine.mouse_xpre),(gEngine.mouse_y-gEngine.mouse_ypre));
}
int main(int argc, char *argv[]){
... code ...
gEngine.PollEvents(&Event);
return 0; // NEVER REACHED
}
with
case SDL_MOUSEMOTION:{
if(mbpressed == 1){
mouse_x = event.motion.x; // X2
mouse_y = event.motion.y; // Y2
(*Event)();
mouse_xpre = mouse_x; // X1
mouse_ypre = mouse_y; // Y1
SDL_Delay(20);
}
break;
}
does not ...
To further simplify things:
Case SDL_MOUSEMOTION: ...... code ..... CC2D( params) ........
works fine but
Event(){ CC2D( params ) } // Main.cpp
Case SDL_MOUSEMOTION: ...... code ..... (*Event)() ........ // GEngine.cpp
fails to work as intended
You are declaring local variables here inside PollEvents:
int mouse_xpre = 0;
int mouse_ypre = 0;
Notice that they are named mouse_xpre and mouse_ypre. Then in the callback you are doing
gEngine.CC2D(0,(gEngine.mouse_x-gEngine.mouse_xpre),(gEngine.mouse_y-gEngine.mouse_ypre));
// ^^^^^^^^^^ ^^^^^^^^^^
which accesses member variables. You need to remove the declaration of the local variables so that they don't hide the member variables and you'll be using member variables in both places.