I'm making a simple game of catching the fruit, but I've been having troubles with the collision logic and/or using the variables from the classes.
class row
{
public:
int x,y;
void setpoint (int xi, int yi)
{
x=xi;
y=yi;
}
float DownSpeed = 5;
void down () {
y = y+DownSpeed;
if (y==1000) {
y=0;
}
}
};
class fruit:public row
{
public:
void draw()
{
setcolor(11);
circle(x,y,20);
}
};
Then I have other classes to create the catcher, like so:
class catcher
{
protected:
float moveSpeed = 5;
public:
float catchX, catchY;
void setpoint (int xi, int yi)
{
catchX=xi;
catchY=yi;
}
void MoveLeft () {
catchX = catchX - moveSpeed;}
void MoveRight () {
catchX = catchX + moveSpeed;}
};
class character:public catcher
{
public:
void draw()
{
setcolor(15);
circle(catchX,catchY,50);
}
};
How do I call the variables of both circles into creating a collision function? I'm sorry if the codes are messy and ineffective, I'm just starting out and I'm stuck. Thanks!
Since both sets of variables are in the public part of the class, you should be able to create a function independent of either class and should be able to access the variables as long as they are declared.
void CheckCollision(float x, float y, float catchX, float catchY)
{
If(y =< catchY + 5)
{
//y resets
}
}
You’d want to check if it’s within a certain x range too though. I hope this solves your problem.
Since all the functions and variables are public. return the values of x, catchX from the functions modifying them. use the draw functions after you have the modified values.
for example modify your down function like this
int down()
{
y = y+DownSpeed;
if (y==1000)
{
y=0;
}
return y;
}
Modify the other function like wise and you will end up having your x,y and catchX, catchY values. create you collison function with these values.
Related
I am new to OOP and I am probably misusing some terminologies here (in which case suggestion or edits are most welcome). I would like to know how to design classes so that under some pre-defined criteria, an update to a data member automatically triggers a change in some state in the overall object.
Let's consider the following pseudocode for a concrete but over-simplistic example. It is so simple that I don't need classes here but I hope it describes the type of problem.
class X {
private:
int x;
public:
void update_x(int);
};
class Y {
private:
std::set<X> xs;
bool max_xs_at_least_10 = false;
public:
void expand_xs() { xs.insert(X()); }
void change_an_element_in_xs(){ call X::update_x on some element in xs }
};
Is it possible to implement X::update_x as follows?
void X::update_x(int y)
{
x = y;
if (x >= 10) {
tell the instance of Y that contains this instance of X to
change max_xs_at_least_10 to true
}
}
In simple case, when you sure that only one object should be notified about the change, you can simply hold a reference to the desired Y object:
class Y;
class X {
private:
int x;
Y& _y;
public:
X(Y& y);
void update_x(int val);
bool operator<(const X& o) const {
// Objects has to be comparable to be used in std::set
return x < o.x;
}
};
class Y {
private:
std::set<X> xs;
bool max_xs_at_least_10 = false;
public:
void expand_xs() { xs.insert(X(*this)); }
void change_an_element_in_xs(){ /*call X::update_x on some element in xs*/ }
void some_x_changed(int val) {
if (val >= 10) {
max_xs_at_least_10 = true;
}
}
};
X::X(Y& y) : _y(y) {}
void X::update_x(int val)
{
x = val;
_y.some_x_changed(val);
}
Note, that X shouldn't use Y::max_xs_at_least_10 directly, because it violates Encapsulation OOP principle: Y should manage its state itself, X should only use Y public interface. That ensures, that changing internal Y logic won't cause changes in X.
In more sophisticated cases, for example, when it's possible that any other objects should be also notified about changing in X, it may be a good idea to use Observer design pattern.
Simple implementation may look like:
class XObserver
{
public:
virtual void x_updated(int new_x) = 0;
};
class X {
private:
int x;
std::vector<XObserver*> observers;
public:
void add_observer(XObserver* observer) {
observers.push_back(observer);
}
void update_x(int val) {
x = val;
for (auto observer : observers) {
observer->x_updated(val);
}
}
bool operator<(const X& o) const {
// Objects has to be comparable to be used in std::set
return x < o.x;
}
};
class Y : XObserver {
private:
std::set<X> xs;
bool max_xs_at_least_10 = false;
public:
void expand_xs()
{
X x;
x.add_observer(this);
xs.insert(x);
}
void x_updated(int new_x) override
{
if (new_x >= 10) {
max_xs_at_least_10 = true;
}
}
void change_an_element_in_xs()
{
//call X::update_x on some element in xs
}
};
The idea is simple: if any other object should be notified, it's class should be derived from Observer class and implement void x_updated(int) method.
After that you can register a new observer using X::register_observer(Observer*) method.
After changing state of X every registered observer will be notified.
Note, that you should be careful with Observers lifetime: if X will be updated after one of observers is destroyed, you will get a crash.
This code just shows an idea: you may want to add X::deregister_observer() method, or use smart pointers -- it's up to you, your needs and creativity.
Good luck!
// UPD: Also note, that I addressed a generic idea of notifiying other objects about change; If your code really looks like that -- X is changed only by calling Y::change_an_element_in_xs() it's a way simplier just to put your logic in this method.
I'm trying to save an Object in an 2D Vector. The vector needs to be sized at runtime. Therefore i use the resize function as mentioned in many other issues.
Her an broke down code example of my problem. So the code might not make sense but I get the same error.
Animation.h
class myPoint{
public:
int x, y;
myPoint(){}
myPoint(int x, int y) : x(x), y(y) {}
};
class AnimationFrame {
private:
std::vector<std::vector<myPoint>> sprites; //the important part
public:
void addSpritePoint(myPoint gridPos, myPoint tilePos);
...
};
class Animation {
private:
std::vector<AnimationFrame*> animationFrames;
public:
...
};
Animation.cpp
Animation::Animation() {}
int Animation::addAnimationFrame() {
AnimationFrame *newAnimationFrame = new AnimationFrame();
this->animationFrames.emplace_back(newAnimationFrame);
}
//AnimationFrame class
AnimationFrame::AnimationFrame(){
int w = 3; //just for the test
int h = 3;
this->sprites.resize(w, std::vector<myPoint>(h, myPoint(0,0)));
}
void AnimationFrame::addSpritePoint(myPoint gridPos, myPoint tilePos) {
this->sprites[gridPos.x][gridPos.y] = tilePos;
//printf(""); //breakpoint here
}
main.cpp
int main() {
Animation *a = new Animation();
a->addAnimationFrame();
a->getAnimationFrame(0).addSpritePoint(myPoint(0,0), myPoint(1,1));
a->getAnimationFrame(0).addSpritePoint(myPoint(0,1), myPoint(2,2));
a->getAnimationFrame(0).addSpritePoint(myPoint(0,2), myPoint(3,3));
}
I expect that the sprites 2D vector from my AnimationFrame class holds the values. When the first breakpoint kicks in the the Point(1,1) is in sprites(0,0) but when i now skip to the next breakpoint the values in sprites(0,0) is (0,0) again. So it resets the value. And i have no clue why.
The problem comes from the fact that Animation::getAnimationFrame() returns a copy of its internal data:
AnimationFrame Animation::getAnimationFrame(int frame) const;
So this modifies a temporary object and has no effect once the full expression has been evaluated:
a->getAnimationFrame(0).addSpritePoint(myPoint(0,0), myPoint(1,1));
The fix is simple: return by reference:
const AnimationFrame& Animation::getAnimationFrame(int frame) const
{
return *animationFrames[frame];
}
AnimationFrame& Animation::getAnimationFrame(int frame)
{
return *animationFrames[frame];
}
(yes, you need a const and a non-const version)
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm working on a simple arcade style space shooter and I'm having some problems with my player class.
This is the code:
#include<iostream>
class player {
public:
int xPos, yPos;
void setPlayerPos(int x, int y);
int getX();
int getY();
};
void player::setPlayerPos(int x, int y) {
xPos = x;
yPos = y;
return;
}
int player::getX() {
return xPos;
}
int player::getY() {
return yPos;
}
void onGameStart() {
player Player;
Player.setPlayerPos(3,10);
}
void main() {
onGameStart();
while (gameIsRunning) {
onGameDraw();
}
}
Of course, everything starts in main() on the bottom of the code. It runs a simple onGameStart() function which is supposed to set the player's beginning coordinates.
Here is the thing. When I set the values of xPos and yPos when initializing those variables, Player.getX() and Player.getY() will always return the correct value. However, when set them using Player.setPlayerPos(x,y), then Player.getX() and Player.getY() returns junk. (Or original initialized values, if set).
I would like to know what I'm doing wrong and why Player.setPlayerPos(x,y) does not update xPos and yPos.
Try using a variable in main like this:
class player {
public:
int xPos, yPos;
void setPlayerPos(int x, int y);
int getX();
int getY();
};
void player::setPlayerPos(int x, int y) {
xPos = x;
yPos = y;
return;
}
int player::getX() {
return xPos;
}
int player::getY() {
return yPos;
}
void onGameStart(player & Player) {
Player.setPlayerPos(3,10);
}
int main() {
player Player;
onGameStart(Player);
while (gameIsRunning) {
onGameDraw(Player); // Need to know more about the implementation but it should be similiar to onGameStart.
}
}
your code seems not to be complete ...
this code seems to be not usable:
void onGameStart() {
player Player;
Player.setPlayerPos(3,10);
}
because you are changing the local variable - those player is destroyed outside of function scope. The player you are using in your code is probably some other instance - so it's x and y are not those set in your function, but some junk x and y value - because you are not initializing them in the constructor.
If you declare those player Player globaly (which is not a good practice) then your code should work (but global variables are always bad idea). Maybe try passing those player via pointer or reference to the function onGameStart
In the function onGameStart you are creating a local variable player and you set its position but then after the function ends you can no longer access it, so it is useless. Maybe you want to have a global variable player and set its position on game start? I suspect you are confusing the local variable and another one which you aren't modifying from this function and you aren't getting the results you want.
The following object: player Player; is local to your freestanding void onGameStart() function. Once that function goes out of scope the object gets destroyed. Your other object's data members remain uninitialized hence the garbage values. Your local object has nothing to do with other (main?) objects you have in a program:
int main() {
player p;
onGameStart(); // only modifies its internal object, not the p
std::cout << p.getX(); // prints garbage because xPos is uninitialized
std::cout << p.getY(); // prints garbage because yPos is uninitialized
}
And if you want the onGameStart() function to be able to modify the object one way is to pass the object by reference:
void onGameStart(player& p) {
p.setPlayerPos(3, 10);
}
Now this code prints 3 and 10:
int main() {
player p;
onGameStart(p); // now modifies the p
std::cout << p.getX(); // prints 3
std::cout << p.getY(); // prints 10
}
Maybe that's the confusion. Initialize your data members in a constructor:
class player {
public:
int xPos, yPos;
player() : xPos(0), yPos(0) {}
};
Lately I was working on a simple game and the game structure required me to declare many types of objects... and to make working with functions easier, I made a parent class for all of the other classes. this is a part of the entire code(simplified):
int q=500;
struct ship
{
int x,y;
bool dec=0;
};
struct enemysol : public ship
{
int life=100,y=0,x;
bool dec=0;
void declare()
{
dec=1;
x=10+rand()%(getmaxx()-20);
life=100;
y=0;
}
};
int next(ship main[]) //finding next undeclared sol
{
int i=1;
while(main[i].dec)
{
i++;
if(i==q)
return -1;
}
return i;
}
The problem is that the next function will return i even if enemysol.dec=1
this code worked when I hadn't declared ship, but the project would have been very confusing and large if I didn't declared it..
You use the wrong way to initialize the member variables of your enemysol class.
When you write:
int life=100,y=0,x;
bool dec=0;
you declare new member variables, which have the same name than the x, y and dec that you already have in ship. So everytime you use x, y or dec in your enemysol class, you don't refer to the ship variables as these are hidden.
The right way of doing it would be something like:
struct enemysol : public ship
{
int life; // define only additional member variables not already in ship
enemysol() // constructor
: y(0), dec(false), life(100) // init members
{
}
void declare()
{
dec=1;
x=10+rand()%(getmaxx()-20);
life=100;
y=0;
}
};
I'm making a card game and I have a few classes.
I have a Hand class, a Player Class, a "Column" class (where the cards are placed on the screen after the hand) and I need each class to have access to the other classes' variables.
class Hand
{
private:
int **Hx,Hy;** //Hand X, Hand Y
int HAmount;//Amount of cards in Hand
int HOwner; //Player 1/2
int Limit; //Limit of cards in Hand
int HContents[8]; //Card Position in 54 card deck NOT card value.
bool Removed;
public:
Hand();
void Lim();
void Get_Card();
void Show();
void Set_Values(int y, int Own);
};
Then in another class I need to have access to some of the variables above.
void Card::show()
{
if((apply == true)
{
if((Track == true)&&(SelNum == TNum)&&(TOwner == COwner))
{
ScnPos = TAmount;
x = Tx;
y = Ty + ScnPos*10;
}
if((Hand == true)&&(**HOwner** == COwner))
{
x = **Hx** + ScnPos*45;
y = **Hy;**
}
apply_surface(x,y,Cards,Screen,&Clip[Pos]);
}
}
I've tried using class friendship and other methods but I can't make it work.
(obviously I have more variables which need this same treatment)
(ignore any errors in my code)
The errors in your code are the real problem here. there is no reason that a Card will access a Hand's private member. this is design error, and your other problems are just trying to tell you that.
Well, you should make getters and setters for your variables. E.g.:
class Test {
private: int a;
public: int GetA() {
return this->a;
}
void SetA(int a) {
this->a = a;
}
}