I have a class Rect such that it holds the width, height, x and y values of a shape. The class can draw using the values in the parameter and move the drawn rect.
Rect::Rect(w, h, x, y, const std::string &image_path) : _w(w), _h(h),
_x(x), _y(y)
{
SDL_Surface *surface = IMG_Load(image_path.c_str());
if (!surface) {
std::cerr << "Failed to create surface.";
}
//create texture
texture = SDL_CreateTextureFromSurface(Window::renderer, surface);
if (!texture) {
std::cerr << "Failed to create worker texture.";
}
SDL_FreeSurface(surface);
}
Rect::~Rect()
{
SDL_DestroyTexture(texture);
}
Rect::draw()
{
//where the constructor parameters are parsed
SDL_Rect rect= {_x, _y, _w, _h} ;
//extra code about some SDL texture stuff and RenderCopy
}
Rect::moveX(int x){
_x +=x;
}
In my Unit class, I include the class Rect and I create my units, draw them in the same function. There is another function in unit that moves rect by checking another value from another class that changes.
Unit::Unit()
Unit::~Unit()
void Unit::createUnit(int type, int x, int y){
if (type == 0)
{
Rect unit1(unitImageWidth, unitImageSizeHeight, x, y, "res/unit1.png");
}
if (type == 1)
{
Rect unit2(unitImageWidth, unitImageSizeHeight, x, y, "res/unit2.png");
}
}
void Unit::moveUnit(int x){
if(selection == 0)
{
unit1.movex(x);
}
if (selection == 1)
{
unit2.movex(x);
}
}
My question is:
When in Unit::moveUnit(), how can I reference the object Rect "unit1" and Rect "unit2" that are initialized in Unit::createUnit()?
When I try to compile, it say that unit1 and unit2 are undefined.
You can't do what you want to do. Non-static local variables are bound to their scope. They are only visible inside and are destroyed when the program exits the area bounded by the {} braces.
The simplest solution is to go in a completely different direction. Add to Unit a private variable to contain the Rect for example,
Rect sprite;
Then replace
void createUnit(int type, int x, int y);
with a Unit constructor
Unit(int type, int x, int y);
And implement the constructor something like
Unit::Unit(int type, int x, int y): sprite(unitImageWidth,
unitImageSizeHeight,
x,
y,
type == 0? "res/unit1.png": "res/unit2.png")
{
}
The colon : starts a Member Initializer List and that crazy ?: Is a one line if statement called the Ternary or Conditional Operator
Note: I don't know what unitImageWidth and unitImageSizeHeight are or where they come from. Make sure you do and make sure they are accessible.
moveUnit becomes
void Unit::moveUnit(int x)
{
sprite.movex(x);
}
because sprite knows what it is and what image has been loaded and can move the Rect to x (or whatever movex does).
To use you
Unit myUnit(0, 1024, 42); // creates a unit of type 0 at coordinates 1024,42
myUnit.movex(88); // moves myUnit to 88,42 (I think)
Just add two Rect members in your class Unit, then you can use it in different member functions.
Better using pointer, as below:
class Unit
{
public:
Unit::Unit()
: uint1(NULL), uint2(NULL){};
Unit::~Unit()
{
if (uint1 != NULL) {
delete unit1;
uint1 = NULL;
}
if (uint2 != NULL) {
delete unit2;
uint2 = NULL;
}
};
void Unit::createUnit(int type, int x, int y)
{
if (type == 0) {
unit1 = new Rect(unitImageWidth, unitImageSizeHeight, x, y, "res/unit1.png");
}
if (type == 1) {
unit2 = new Rect(unitImageWidth, unitImageSizeHeight, x, y, "res/unit2.png");
}
}
void Unit::moveUnit(int x)
{
if (selection == 0) {
unit1->movex(x);
}
if (selection == 1) {
unit2->movex(x);
}
}
private:
Rect *unit1;
Rect *unit2;
};
Related
I am using an SDL Template and I am trying to implement gravity into my code so I am trying to set a Y as the strength of my gravity in update but when I try to use a pointer to setY I always get an error "a pointer to a bound function may only be used to call the function using a setter" the code below is from my GameScene.cpp
#include "GameScene.h"
GameScene::GameScene()
{
// Register and add game objects on constructor
player = new Player();
this->addGameObject(player);
floor = new Floor();
this->addGameObject(floor);
}
GameScene::~GameScene()
{
delete player;
}
void GameScene::start()
{
Scene::start();
// Initialize any scene logic here
}
void GameScene::draw()
{
Scene::draw();
}
void GameScene::update()
{
Scene::update();
if (player->getOnFloor() == false) {
player->setY -= 1;
}
else {
player->setY = 0;
}
}
This code is from my Player.h where the setters and getters are located
#pragma once
#include "GameObject.h"
#include "common.h"
#include "draw.h"
class Player :
public GameObject
{
public:
void start();
void update();
void draw();
//X Setter
void setX(int x) {
x = x;
}
//X Getter
int getX() {
return x;
}
//Y Setter
void setY(int y) {
y = y;
}
//Y Getter
int getY() {
return y;
}
//Height Setter
void setHeight(int height) {
height = height;
}
//Height Getter
int getHeight() {
return height;
}
//Width Setter
void setWidth(int width) {
width = width;
}
//Width Getter
int getWidth() {
return width;
}
//OnFloor Setter
void setOnFloor(int onFloor) {
onFloor = onFloor;
}
//OnFloor Getter
int getOnFloor() {
return onFloor;
}
private:
SDL_Texture* texture;
int x;
int y;
int height;
int width;
int speed;
bool onFloor;
};
I have tried putting () beside the setY like this
if (player->getOnFloor() == false) {
player->setY() -= 1;
}
else {
player->setY)( = 0;
}
But it still did not work, I was expecting it to make my player fall down but VS studio kept showing me the error
this may be a noobie question but I am still a noobie programmer so please bear with me
EDITED:
The player is now falling upwards, I tried doing -= 1 to make him fall downwards
void GameScene::update()
{
Scene::update();
if (player->getOnFloor() == false) {
player->setY(player->getY() -= 1);
}
else {
player->setY(0);
}
}
but I get an error on player in "player->getY()" saying that expression must be a modifiable lvalue
The error you are getting is because you are trying to use the setY setter function as a variable. In order to use the setter function to set the y property of the player object, you need to call the setY function and pass in the new value for y as an argument. Here is how you would use the setY setter function in your GameScene::update function:
void GameScene::update()
{
Scene::update();
if (player->getOnFloor() == false) {
player->setY(player->getY() + 1);
}
else {
player->setY(0);
}
}
Note that in this example, we are calling the getY getter function to get the current value of y, and then subtracting 1 from it before passing the result to the setY setter function. This will update the y property of the player object and make it fall down by 1 unit each time the update function is called.
Hi im doing little project tomy school and keep getting weird for me error.
While calling one of methods in my object this pointer is set to 0xcdcdcdcd. i googled it and found some info about erasing memory or destroing objects before calling, but i make sure no destructors are called before.
World.h
class Organism;
class Human;
class World
{
private:
vector <Organism*> organisms;
vector <Organism*> organismsToAdd;
vector <string> logs;
int turn_;
void initializeWorld();
void drawInterface();
void drawInfo();
void drawOrganisms();
void nextTurn();
bool isPositionTaken(int x, int y);
Organism* getOrganism(int x, int y);
void queueOrganismToAdd(Organism* newOrganism);
void addQueuedOrganisms();
void generateStartOrganisms();
bool isPlayerAlive();
public:
void executeMove(Organism* moving, int toX, int toY); //here's the problem
bool isPositionValid(int x, int y);
World(int x, int y);
struct
{
int x_, y_;
} worldSize;
void startGame();
~World();
};
executeMove
void World::executeMove(Organism* moving, int toX, int toY)
{
cout << moving->getSign();
getch();
if (!isPositionTaken(toX, toY)) // <- here it brake
{
moving->setPosition(toX, toY);
}
else if (moving->getSign() == getOrganism(toX, toY)->getSign())
{
//multiply
//make log
}
else {
if (!moving->specialCollision((getOrganism(toX, toY)))) return;
if (!getOrganism(toX, toY)->specialCollision(moving)) return;
if (moving->getPower() >= getOrganism(toX, toY)->getPower())
{
//log
//delete losser
}
else
{
//log
//delete losser
}
moving->setPosition(toX, toY);
}
}
isPositioinTaken
bool World::isPositionTaken(int x, int y)
{
for (int i = 0; i < this->organisms.size(); ++i) // here this is set to 0xcdcdcdcd
{
if (organisms[i]->getPositionX() == x && organisms[i]->getPositionY() == y) return true;
}
return false;
}
Method isPositionTaken is worlking well in other parts of project so im totally lost if finding whats wrong, i aprreciate any help
Since the organisms member has a default constructor, the only way to see this behavior at the line you indicated is if the call to executeMove() was using a pointer which was uninitialized.
Something like:
World *ptr; // not initialized on stack
...
ptr->executeMove();
Or this method was called from another method with the same problem.
C++ (Arduino wrapper) question: I'm writing a shoot em up game on an Arduino which has a LCD connected -
I have a base class (Sprite), and from this other classes are derived - Alien, Missile and Player. The constructor of the Alien class also has private member pMissile (a pointer to a Missile class) - 'an object within an object' would be a way to describe this I think.
[when an Alien fires a missile, it passes its own (x,y) coordinates to the missile, and the missile has its own method of moving starting from the Alien's coordinates]
My question is: How can I access the coordinates of the missile through the Alien object?
Streamlined code is below and I have also drawn a representation of the classes:
// Bass class - has a form/shape, x and y position
class Sprite
{
public:
Sprite(unsigned char * const spacePtrIn, unsigned int xInit, unsigned int yInit);
virtual void Move() = 0;
void Render() { display.drawBitmap(x,y, spacePtr, 5, 6, BLACK); }
unsigned int getX() const { return x; }
unsigned int getY() const { return y; }
protected:
unsigned char *spacePtr;
unsigned int x, y;
};
// Derived class "Missile", also a sprite and has a specific form/shape, and specific (x,y) derived from input sprite
class Missile : public Sprite
{
public:
Missile(): Sprite(&spaceMissile[0], 0, 0) {}
virtual void Move(); // its own method of moving
};
// Derived class "Alien" - has a specific form/shape, and specific (x,y) position
class Alien : public Sprite
{
public:
Alien();
virtual void Move(); // its own method of moving
private:
Missile *pMissile;
};
Alien::Alien(): Sprite(&spaceAlien[0], random(5, 75), random(4, 10))
{
Missile MissileArray[MaxAmmoSize];
pMissile = &MissileArray[0];
}
void Alien::Move()
{
if( random(10) % 2 == 0 )
x += 1;
if( random(10) % 3 == 0 )
y += 1;
if( (pMissile != NULL) && (random(10) == 1) )
{
pMissile->setCoord(x, y);
pMissile->Move(); // move the missile
pMissile++; // move onto the next missile in the array
}
Render();
}
/*****************************************************************************************/
Alien MONSTER;
Player HERO;
Alien *pMONSTER = &MONSTER;
void loop()
{
display.clearDisplay();
MONSTER.Move();
HERO.Move();
pMONSTER->getX(); // this is x location of MONSTER
**// how does pMONSTER access pMissile(x,y) within MONSTER.**
delay(100);
display.display();
}
Embedded C++ Class interaction
The common way is to add a getter function to Alien:
class Alien {
public:
Missile* getMissile() { return pMissile; }
}
To use it:
Alien* a = getAlienFromSomewhere();
auto pMissile = a.GetMissile();
if (pMissile != NULL) {
x = pMissile->getX();
y = pMissile->getY();
}
I imagine that you want to access your missile position through the alien to test the collision with your hero entity, but if you need to keep the track of your missiles you should not "walk" with your pointer to the next missile as shown in the Alien::Move(). Doing this you will lose the reference of the beginning of the array.
IMHO, I would do something like this in your alien class:
// Bass class - has a form/shape, x and y position
class Sprite
{
public:
Sprite(unsigned char * const spacePtrIn, unsigned int xInit, unsigned int yInit);
virtual void Move() = 0;
void Render() { display.drawBitmap(x,y, spacePtr, 5, 6, BLACK); }
unsigned int& getX() const { return x; }
unsigned int& getY() const { return y; }
protected:
unsigned char *spacePtr;
unsigned int x, y;
};
// Derived class "Missile", also a sprite and has a specific form/shape, and specific (x,y) derived from input sprite
class Missile : public Sprite
{
public:
Missile(): Sprite(&spaceMissile[0], 0, 0) {}
virtual void Move(); // its own method of moving
};
// Derived class "Alien" - has a specific form/shape, and specific (x,y) position
class Alien : public Sprite
{
public:
Alien();
~Alien(); // a destructor to cleanup your missiles - arduino have almost no memory to handle leaks ;-)
virtual void Move(); // its own method of moving
inline Missile& getMissile(unsigned char n) { return pMissile[n]; }
inline Missile& operator[](unsigned char n) { return getMissile(n); }
inline unsigned int& getX(unsigned char n) { return getMissile(n).getX(); }
inline unsigned int& getY(unsigned char n) { return getMissile(n).getY(); }
private:
Missile *pMissile;
// adding the code to handle the count
unsigned char missileCount;
};
Alien::Alien():
Sprite(&spaceAlien[0], random(5, 75), random(4, 10)),
missileCount(0)
{
// this way of allocation creates a local object that is destroyed by the end of this scope
//Missile MissileArray[MaxAmmoSize];
//pMissile = &MissileArray[0];
// so you should do somethin like this
pMissile = new Missile[MaxAmmoSize];
}
Alien()::~Alien()
{
delete[] pMissile;
}
void Alien::Move()
{
if( random(10) % 2 == 0 )
x += 1;
if( random(10) % 3 == 0 )
y += 1;
if( (pMissile != NULL) && (random(10) == 1) )
{
// my proposal to fire it up
Missile& missile = pMissile[missileCount];
missile->setCoord(x, y);
missile->Move(); // move the missile
missileCount++; // move onto the next missile in the array
}
Render();
}
Using the code like this you could access the locations of your missiles by using:
MONSTER.getX(0) += 1;
MONSTER[0].getY() +=1;
MONSTER.getMissile(1).getX() = 10;
To have some clarity I recommend also the refactoring of the getX() and getY() methods to x() and y(), since they are returning references to the class contents (and doing this, you should also rename your x and y members to something else, or you can get crazy with name conflicts).
So, i decided to create a collision detection function in my game and i put it into the class of enemies. Then i put it to "enemy.cpp" and i used "this" pointer.
The code:
if(((this->sprite.getPosition().y + this->sprite.getTextureRect().height) >= blocklist[i].sprite.getPosition().y) &&
(this->sprite.getPosition().y <= blocklist[i].sprite.getPosition().y))
This gives me SIGSEGV segmentation error. I can't find what could be the problem in this line, here is the enemyclass for reference.
class enemyclass
{
public:
sf::Sprite sprite;
sf::Sprite bubble;
//PROPERTIES
float xspeed, yspeed;
int x, y;
float health;
bool colR, colL, colU, colD;
int skin;
void detectCollisions(int blocksize);
};
and the blockclass that i made a vector of to use as a list of enemies:
class blockclass
{
public:
sf::Sprite sprite;
int x, y;
};
I would be very thankfull for an answer since i can't find out what's wrong.
As others have said, if some complicated instruction causes an error, split it into smaller parts and see, in which part the error arises:
if( this->x == 0) // changes nothing
x = 0; // but validates 'this'
int thisy = sprite.getPosition().y;
int thish = sprite.getTextureRect().height;
sf::Sprite &that = blocklist[i].sprite;
if( that.x == 0) // validate 'that'
that.x = 0;
int thaty = that.getPosition().y;
if(thisy + thish >= thaty && thisy <= thaty) {
// ......
}
I'm a bit confused with classes was hoping some one could explain.
I have a class I'm making to create buttons for a game menu. There are four variables:
int m_x
int m_y
int m_width
int m_height
I then want to use a render function in the class but Im not understanding how i use the 4 int variables in the class and pass it to the function in the class?
My class is like this:
class Button
{
private:
int m_x, m_y; // coordinates of upper left corner of control
int m_width, m_height; // size of control
public:
Button(int x, int y, int width, int height)
{
m_x = x;
m_y = y;
m_width = width;
m_height = height;
}
void Render(SDL_Surface *source,SDL_Surface *destination,int x, int y)
{
SDL_Rect offset;
offset.x = x;
offset.y = y;
SDL_BlitSurface( source, NULL, destination, &offset );
}
} //end class
Where i am confused is how the values created in public:Button is passed to void render I'm not fully sure I've got this right, if i have its pure luck so far because I'm still a little bit confused.
Maybe an example will help:
#include <iostream>
class Button
{
private:
int m_x, m_y; // coordinates of upper left corner of control
int m_width, m_height; // size of control
public:
Button(int x, int y, int width, int height) :
//This is initialization list syntax. The other way works,
//but is almost always inferior.
m_x(x), m_y(y), m_width(width), m_height(height)
{
}
void MemberFunction()
{
std::cout << m_x << '\n';
std::cout << m_y << '\n';
//etc... use all the members.
}
};
int main() {
//Construct a Button called `button`,
//passing 10,30,100,500 to the constructor
Button button(10,30,100,500);
//Call MemberFunction() on `button`.
//MemberFunction() implicitly has access
//to the m_x, m_y, m_width and m_height
//members of `button`.
button.MemberFunction();
}
You might want to spend some time learning C++ before getting too deep into a complex programming project.
To answer your question, The variables initialized in the constructor (Button) are part of the class instance. So they're available within any class method, including Render.