Objects on a grid in c++ - c++

I'm trying to make objects move on a chessboard (a coordinate grid). I've defined these object as Vehicles. They have a position (x,y) on the plane and a direction. Being forced to move only North-South-East-West possible directions could be
North: (0, 1)
South: (0, -1)
East: (1, 0)
West: (-1, 0)
Vehicles can proceed only step by step (x+1, y), (x, y+1), where x, y are integers. Two vehicles cannot stand in the same position. A vehicle maintains its direction while it is possible, that is while it encounters an occupied position.
So I have to create a void move function which has as arguments the positions of the nearby vehicles (North South East West). Such a function should:
Check if the vehicle can maintain its direction and, if it can, refresh the vehicle position with the new position;
If the cell is occupied, go for another direction, check if the cell in that direction is free...
If every cell surrounding the vehicle is occupied, stay still.
I wrote a code that accomplish point 1 but I have difficulties with point 2. In particular, I can't think about an effective way to change the Vehicle's direction. Here's my code so far:
class Vehicle {
private:
int x, y;
int vx, vy;
public:
int getx() { return x;}
int gety() { return y;}
int getvx() { return vx;}
int getvy() { return vy;}
void sety(int a) { y = a;}
void setx(int a) { x = a;}
void setvx(int a) {
if (a != 0) {
vx = a / abs(a);
}else { vx = a;}
}
void setvy(int a) {
if (a != 0) {
vy = a / abs(a);
}else { vy = a;}
}
void move(Vehicle * v) {
int big = 0;
while(big<4) {
int cont=0;
for(int i=0; i<4; i++) {
if (x+vx != v[i].getx() or y+vy != v[i].gety()) {
cont ++;
}
}
if(cont==4) {
x = x + vx;
y = y + vy;
break;
} else {
big ++;
// CHANGE DIRECTION in PROPER WAY
}
}
}
void print() {
// prints the private members
}
};
How could I improve the while?

Related

C++/SDL - Rectangle Coordinates Mapping

I am working on a 2D game using SDL. Recently I implemented various functions that put objects (and their rectangles) into motion, but encountered performance issues that are most likely caused by inefficient mapping of rectangle coordinates. Please see below:
2D coordinates of the rectangle are stored in an integer array whenever move() is called. For example, coordinate[0] is the first point on the x axis and coordinate[1] is the last point on the x axis. Coordinates [2] and [3] work for points on the y axis.
The map() function takes the coordinates of a rectangle and stores them in static std::map (Status class). Each x and y pair is either 0 or 1, depending on whether a rectangle is present or not. Player's coordinates are not mapped.
When the player moves, the bool function collide() checks whether the player's rectangle is adjacent to another recantgle in a particular direction. If there is no rectangle blocking the way, the player is allowed to move.
Everything works well, but it seems like all these for loops in the map() function are very CPU-heavy. When rectangles are being moved on the screen, the program lags horribly. How can I map rectangle coordinates more efficiently?
void move(int x, int y) {
dstRect.x = x;
dstRect.y = y;
coordinate[0] = dstRect.x;
coordinate[1] = dstRect.x + dstRect.w;
coordinate[2] = dstRect.y;
coordinate[3] = dstRect.y + dstRect.h;
}
void map() {
for (int x = coordinate[0]; x != coordinate[1]; x++) {
for (int y = coordinate[2]; y != coordinate[3]; y++) {
Status::map().insert(std::pair<std::vector<int>, int>({ x, y }, 1));
}
}
}
bool collide(DIRECTION direction) {
if (direction == UP || direction == DOWN) {
for (int x = texture.coordinate[0]; x != texture.coordinate[1]; x++) {
if (direction == UP) {
if (Status::map().find({ x, texture.coordinate[2] - 1 })->second == 1) { return true; }
}
if (direction == DOWN) {
if (Status::map().find({ x, texture.coordinate[3] + 1 })->second == 1) { return true; }
}
}
}
if (direction == RIGHT || direction == LEFT) {
for (int y = texture.coordinate[2]; y != texture.coordinate[3]; y++) {
if (direction == RIGHT) {
if (Status::map().find({ texture.coordinate[1] + 1, y })->second == 1) { return true; }
}
if (direction == LEFT) {
if (Status::map().find({ texture.coordinate[0] - 1, y })->second == 1) { return true; }
}
}
}
return false;
}
void moveRight() {
for (int i = 0; i < speed; i ++) {
if (!collide(RIGHT)) {
int x = texture.dstRect.x + 1;
int y = texture.dstRect.y;
texture.move(x, y);
}
}
}
Followed #FrançoisAndrieux advice and created multidimensional vector for storing the coordinates.

Unable to change private variables using member functions

#include <iostream>
#include <string>
using namespace std;
struct Point {
private:
int xCord,yCord;
public:
void setX(int x);
void setY(int y);
int getX();
int getY();
int rotate(int x, int y, Point p1);
int moveHorizontally(int x, int a, int b);
int moveVertically(int y, int a, int b);
};
int main() {
Point p1;
p1.setX(1); //sets X
p1.setY(2); //sets Y
cout << p1.getX() << ", " << p1.getY() << endl; //prints current value of X & Y
p1.rotate(p1.getX(), p1.getY(), p1);
cout << p1.getX() << ", " << p1.getY() << endl;
return 0;
}
void Point::setX(int newX) {
xCord = newX;
}
void Point::setY(int newY) {
yCord = newY;
}
int Point::getY() { //This will just return the y Cord.
return yCord;
}
int Point::getX() { //This will just return the x Cord.
return xCord;
}
int Point::moveHorizontally(int x, int tempX, int tempY) {
//Move the point to the right if positive.
//Move the point to the left if negative.
int newX = tempX + (x);
return newX;
}
int Point::moveVertically(int y, int tempX, int tempY) {
//Move the point up if positive.
//Move the point down if negative.
int newY = tempY + (y);
return newY;
}
int Point::rotate(int tempX, int tempY, Point p1){
//(1,2) -->> (-2,1)
int tempX_DNC = tempX;
int tempY_DNC = tempY;
int quadrant;
if((tempX > 0) && (tempY > 0)) { //Quadrant 1: x(positive), y(positive) Then rotates to Quad 2
quadrant = 1;
tempX = -(tempY);
tempY = tempX_DNC;
} else if ((tempX < 0) && (tempY > 0)) { //Quadrant 2: x(negative), y(positive) Then rotates to Quad 3
quadrant = 2;
tempX = -(tempY_DNC);
tempY = tempX_DNC;
} else if ((tempX < 0) && (tempY < 0)) { //Quadrant 3: x(negative), y(negative) Then rotates to Quad 4
quadrant = 3;
tempX = -(tempY_DNC);
tempY = tempX_DNC;
} else if ((tempX > 0) && (tempY < 0)) { //Quadrant 4: x(positive), y(negative) Then rotates to Quad 1
quadrant = 4;
tempX = -(tempY_DNC);
tempY = tempX_DNC;
} else {
quadrant = 0;
}
//This will rotate the points 90* to the left.
//(1,2) will then become (-2,1)
//I could have if in quadrant1, all are positive, if in quadrant 2 the x would be negative and y would be positive
//If in quadrant 3 the x and y will both be negative, if in quadrant 4 the x would be positive and the y would be negative
cout << tempX << ", " << tempY << endl;
p1.setX(tempX);
p1.setY(tempY);
cout <<"x is: " <<p1.getX() <<endl;
cout <<"Y is: " <<p1.getY() <<endl;
}
Code is above.
So I am creating a class Point. Point has 2 private variables xCord, yCord. I want to call the rotate function and have that be able to modify the xCord, yCord but it does not. I am not sure why. I tried passing the Point p1 to the function and to see if that would fix the issue but it did not, I also tried without passing the Point p1 and just having Point p1 inside the function definition.
p1.setX(VARIABLE);
works when it is in main(). but not when I call p1.setX(VARIABLE) inside another member function.
You are passing a copy of p1 to the rotate function. Only this copy is modified.
You pass the point by value:
int rotate(int x, int y, Point p1);
^^--------pass-by-value
ie. the p1 inside the function is a copy of p1 in main that gets deleted once the function returns. If you want to change the point that is passed as parameter inside the function then pass it by reference:
int rotate(int x, int y, Point& p1);
^^--------pass-by-reference
PS: ... However, as rotate is a member function of Point you should probably rather rotate the instance on which you are calling it, change its signature to
int rotate(int x, int y);
and instead of changing the coordinates of some point passed as parameter do this:
this->setX(tempX); // this-> not really necessary, just added for clarity
this->setY(tempY);
Alternatively you keep it as is and pass the point that is supposed to be rotated as parameter, but then you should consider making the method static.
PPS: If you want to change it to pass-by-reference, you have to change the signature in the class declaration to:
int rotate(int x, int y, Point& p1);
and the definition you have to change to:
int Point::rotate(int tempX, int tempY, Point& p1) { /*...*/ }
void point::rotate() {
xcord = ycord;
ycord = xcord;
}
is all you need for basic rotation

Why is my ball using acceleration as velocity?

I got an object of type ball which is a subclass of the class Particle. This class has three members position, velocity and acceleration of type Vector.
On each frame, when myball.update is called, its velocity is summed to the position and the acceleration is summed to the velocity. Then the ball is drawn on the screen. Anyway for some unclear motive whatever value I give as a velocity the ball doesn't move, but it moves in non - accelerated uniform movement if I give a value as the acceleration.
Here are my classes Vector:
class Vector {
private:
void updateC() {
x = cos(a) * l;
y = sin(a) * l;
}
void updateT() {
a = atan2(y, x);
l = sqrt(x * x + y * y);
}
public:
float x = 0, y = 0;
float a = 0, l = 0;
Vector() {
}
Vector(float nx, float ny): x(nx), y(ny) {
updateT();
}
void X(float nx) {
x = nx;
updateT();
}
void Y(float ny) {
y = ny;
updateT();
}
void A(float na) {
a = na;
updateC();
}
void L(float nl) {
l = nl;
updateC();
}
Vector operator +(Vector other) {
return Vector(x + other.x, y + other.y);
}
Vector operator -(Vector other) {
return Vector(x - other.x, y - other.y);
}
Vector operator *(float m) {
Vector result(x, y);
result.L(l * m);
return result;
}
void operator +=(Vector other) {
x += other.x;
y += other.y;
updateT();
}
void operator -=(Vector other) {
x -= other.x;
y -= other.y;
updateT();
}
void operator *=(float m) {
l *= m;
updateC();
}
};
Particle:
class Particle {
public:
Vector position;
Vector velocity;
Vector gravity;
Particle() {}
Particle(Vector np, Vector nv = Vector(0, 0), Vector na = Vector(0, 0)): position(np), velocity(na), gravity(na) {}
void accelerate(Vector a) {
velocity += a;
}
void update() {
position += velocity;
velocity += gravity;
}
};
And ball:
class ball: public Particle {
public:
ball(Vector p, Vector v, Vector a): Particle(p, v, a) {}
void update() {
Particle::update();
graphics.circle("fill", position.x, position.y, 10);
}
};
So, as I said before, if I initialize myball with a velocity different than 0, the ball still won't move, but it will move if I inititialize it with an acceleration different than 0 using acceleration as velocity.
What did I do wrong?
You have a typo in the Particle constructor:
Particle(Vector np, Vector nv = Vector(0, 0), Vector na = Vector(0, 0)): position(np), velocity(na), gravity(na) {}
It must be:
Particle(Vector np, Vector nv = Vector(0, 0), Vector na = Vector(0, 0)): position(np), velocity(nv), gravity(na) {}

How can I use a class object in another function? c++

How can i use the x and y values of lastLoc object in another function like in the following code. I get no errors but when i print the values of lastLoc in the getPosLoc function I get a long number(possibly address):
class solveMaze {
private:
maze maze;
mouse m;
stack<coords> coordStack;
int x;
int y;
int posLocCount = 0;
coords lastLoc;
};
solveMaze::solveMaze() {
x = m.x;
y = m.y;
coords c(x, y);
coords lastLoc(c.x, c.y);
coordStack.push(c);
}
void solveMaze::getPosLoc() {
if((mazeLayout[x][y-1] == 0) && (x != lastLoc.x) && (y-1 != lastLoc.y)) {
posLocCount++;
putUp();
}
this is the coords.h removed irrelevant functions to shorten the code:
class coords {
public:
coords(){};
coords(int, int);
int x;
int y;
friend ostream &operator<<(ostream &output, const coords &c);
bool operator==(coords);
void operator=(const coords &b);
};
coords::coords(int a, int b) {
x = a;
y = b;
}
this is mouse.h:
class mouse {
private:
maze maze;
public:
mouse();
int x;
int y;
};
mouse::mouse() {
for (int i=0; i<12; i++) {
for (int j=0; j<29; j++) {
if (mazeLayout[i][j] == 8){
x = j;
y = i;
}
}
}
}
There are a couple of evident problems:
coords lastLoc(c.x, c.y);
This statement declares and initialize a local variable named lastLoc... it is not referring to the member lastLoc. For that the code needs to be
lastLoc = coords(c.x, c.y);
x = m.x; and y = m.y;
These statements use m that has not been explicitly initialized, how is that class defined?
You should make getters and setters for x and y, because it's better practise. But if you want refer to coord's x or y. You should write:
lastLoc->x

Was not declared in this scope issue

I'm checking to see and understand someone else's code... The code worked in his computer, however when I tried to edit it in mine, it doesn't seem to work. The lib files are all connected properly thou...
#include "play.h"
#include "Lib110ct/Lib110ct.h"
#include <ctime>
int main(int argc, char** argv)
{
Win110ct win;
Turtle * t = win.getTurtle();
win.hideTurtle();
const int NumOfBook = 7;
Player You(512,384);
Book B[NumOfBook];
int pts = 0;
char in;
time_t ti;
while (in != 'x')
{
for (int i = 0; i<NumOfBook; i++)
{
if (A[i].isReadBy(You))
{
B[i].setPosition(rand() % 1024 + 1,rand() % 768 + 1);
pts++;
}
B[i].move();
B[i].draw(t);
}
You.draw(t);
win << "Points: " << pts << "\n";
win.render();
win.setPosition(-1,-1);
in = win.getchar();
win.clearBack();
win.clear();
win.setPosition(0,0);
if (in == 'w')
You.moveRelative(0,-50);
else if (in == 's')
You.moveRelative(0,50);
else if (in == 'a')
You.moveRelative(-50,0);
else if (in == 'd')
You.moveRelative(50,0);
}
return 0;
}
However I run into the error... "Book" was not declared in this scope.
The header play.h file's code is as follows..
#include "Lib110ct/Lib110ct.h"
#include <cstdlib>
//Player class, used to create the controllable character.
class Player
{
protected:
double xpos, ypos;
public:
Player(){};
//constructor, user input variables stored as xpos and ypos, then player is drawn
Player(double x, double y)
{
xpos = x;
ypos = y;
}
//draws the new position of the turtle
void draw(Turtle* t)
{
t->setPosition(xpos,ypos);
t->penDown();
for (int i = 0; i < 180; i++ )
{
t->turn(2);
t->moveForward(1);
}
}
double getX(){ return xpos; } //returns the x position of the player
double getY(){ return ypos; } //returns the y position of the player
//moves the player by x increment and y increment (leave x or y as 0 to not move along the respective axis)
//relative to current position
void moveRelative(double xadd, double yadd)
{
if (xpos+xadd > 0 && xpos+xadd < 1024 && ypos+yadd > 0 && ypos+yadd < 768)
{
xpos += xadd;
ypos += yadd;
}
}
};
//Food class. Not controlled by player
class Food
{
protected:
double xpos, ypos, xdir, ydir;
public:
//constructor, random x and y co-ordinates stored as xpos and ypos. food is drawn in those co-ordinates
//random xdir and ydir, food initially moves in this direction
Food()
{
xpos = rand() % 1024 + 1;
ypos = rand() % 768 + 1;
xdir = rand() % 41 - 20;
ydir = rand() % 41 - 20;
}
//draws the food
void draw(Turtle* t)
{
t->setPosition(xpos,ypos);
t->penDown();
for (int i = 0; i < 4; i++ )
{
t->turn(90);
t->moveForward(20);
}
}
double getX(){ return xpos; } //returns the x position of the player
double getY(){ return ypos; } //returns the y position of the player
//moves the food to a specific location, not relative to current position
void setPosition(double x,double y)
{
xpos = x;
ypos = y;
}
//moves the food in the specified directions, given by the variables xdir and ydir
void move()
{
if (!(xpos+xdir>0 && xpos+xdir<1024 && ypos+ydir>0 && ypos+ydir<768))
{
xdir = -xdir;
ydir = -ydir;
}
xpos += xdir;
ypos += ydir;
}
//returns TRUE if the player is in a close proximity to the food, otherwise false
bool isEatenBy(Player Play)
{
double pX = Play.getX();
double pY = Play.getY();
double fX = getX();
double fY = getY();
return pX+60>fX && pX-20<fX & pY+40>fY && pY-40<fY;
}
};
You are trying to use an array of type 'Book', which is probably a class you intended to define:
Book B[NumOfBook];
However, you have not defined this in the code you posted above, or in the code you put in Dropbox.
Either add a definition for class Book to play.h, or create a new header file, perhaps called book.h, with the definition and then #include "book.h" in your cpp file. Your Book class will need methods to setPosition, move and draw.