SDL2 crash whit InputHandler mouse motion - c++

No warnings, no errors. Compile fine, but in the bottom of update function, the following lines make crash the program:
(*m_mousePosition).setX(event.motion.x);
(*m_mousePosition).setY(event.motion.y);
This is the complete code:
#include <SDL2/SDL.h>
#include <vector>
#include "Vector2D.h"
using namespace std;
#ifndef INPUTHANDLER_H
#define INPUTHANDLER_H
enum mouse_buttons{
LEFT = 0,
MIDDLE = 1,
RIGHT = 2
};
class InputHandler{
public:
static InputHandler* Instance(){
if(s_pInstance==0){
s_pInstance= new InputHandler();
}
return s_pInstance;
}
void update(){
if(event.type == SDL_MOUSEBUTTONDOWN){
if(event.button.button == SDL_BUTTON_LEFT){
m_mouseButtonStates[LEFT]=true;
}
if(event.button.button == SDL_BUTTON_MIDDLE){
m_mouseButtonStates[MIDDLE]=true;
}
if(event.button.button == SDL_BUTTON_RIGHT){
m_mouseButtonStates[RIGHT]=true;
}
}
if(event.type == SDL_MOUSEBUTTONUP){
if(event.button.button == SDL_BUTTON_LEFT){
m_mouseButtonStates[LEFT]=false;
}
if(event.button.button == SDL_BUTTON_MIDDLE){
m_mouseButtonStates[MIDDLE]=false;
}
if(event.button.button == SDL_BUTTON_RIGHT){
m_mouseButtonStates[RIGHT]=false;
}
}
if(event.type == SDL_MOUSEMOTION){
(*m_mousePosition).setX(event.motion.x);
(*m_mousePosition).setY(event.motion.y);
}
}
SDL_Event* getEvent(){
return &event;
}
void clear();
bool getMouseButtonStates(int buttonNumber){
return m_mouseButtonStates[buttonNumber];
}
Vector2D* getMousePosition(){
return m_mousePosition;
}
private:
SDL_Event event;
vector<bool> m_mouseButtonStates;
Vector2D* m_mousePosition;
InputHandler(){
for(int i=0; i<3; i++){
m_mouseButtonStates.push_back(false);
}
}
~InputHandler(){}
static InputHandler* s_pInstance;
};
typedef InputHandler TheInputHandler;
#endif /* INPUTHANDLER_H */
Maybe its a problem whit pointers, but I don't know, I can't solve
==============================NEW EDIT======================================
Now I don't use pointers, but I must initialize the Vector2D whit two parametres. I put it in the InputHandler constructor:
InputHandler::InputHandler():m_position(0,0){
for(int i=0; i<3; i++){
m_mouseButtonStates.push_back(false);
}
}
And give me the following error:
InputHandler.cpp:12:30: error: member initializer 'm_position' does not name a non-static data member or base class
InputHandler::InputHandler():m_position(0,0){
^~~~~~~~~~~~~~~
The definition of Vector2D class:
#include<math.h>
using namespace std;
#ifndef VECTOR2D_H
#define VECTOR2D_H
class Vector2D {
public:
Vector2D(float x, float y):m_x(x), m_y(y){}
float getX(){return m_x;}
float getY(){return m_y;}
void setX(float x){m_x=x;}
void setY(float y){m_y=y;}
float length(){return sqrt(m_x*m_x + m_y*m_y);}
private:
float m_x;
float m_y;
};
#endif /* VECTOR2D_H */

yes, the problem is "pointers" as you put it.
m_mousePosition is declared but you never assign anything to it so it is NULL/garbage.
you probably dont need to use pointers here.

Related

How to get the value from the sensors in to the vector<ISensor>?

I have to make a program using this UML diagram
to implement the monitoring system of a house.
The value of the generate Temperature, Humidity and Pressure are random. CreateRoom will create a text file where the value of the sensors goes, updateRoom will add the values to the file, readRoom will show on the screen the content of the file and deleteRoom will delete the file. I am stuck at updateRoom because I don't know how to get the value from the sensors in to the vector<IRoom> sensor and then to put it in the file.
This is what I have done so far:
//ISensor.h
#ifndef ISensor_H
#define ISensor_H
class ISensor {
public:
virtual double readSensor() const = 0;
};
#endif
//Temperature.h
#ifndef Temperature_H
#define Temperatur_H
#include<iostream>
#include "ISensor.h"
class Temperature : public ISensor
{
public:
double readSensor() const {
return generateTemperature();
}
private:
double generateTemperature()const {
int temperature;
srand((int)time(NULL));
temperature = -40 + (rand() % 120);
return temperature;
}
};
#endif
//Humidity.h
#ifndef Humidity_H
#define Humidity_H
#include <iostream>
#include "ISensor.h"
class Humidity :public ISensor
{
public:
double readSensor()const {
return generateHumidity();
}
private:
double generateHumidity()const {
int humidity;
srand((int)time(NULL));
humidity = 1 + (rand() % 100);
return humidity;
}
};
#endif
//Presure.h
#ifndef Presure_H
#define Presure_H
#include <iostream>
#include "ISensor.h"
class Presure :public ISensor
{
public:
double readSensor()const {
return generatePresure();
}
private:
double generatePresure()const {
int presure;
srand((int)time(0));
presure = 300+ (rand() % 800);
return presure;
}
};
#endif
//IRoom.h
#ifndef IROOM_H
#define IROOM_H
class IRoom {
public:
virtual void readRoom() const = 0;
virtual void createRoom() const = 0;
virtual void updateRoom() const = 0;
virtual void deleteRoom() const = 0;
};
#endif // !IROOM_H
//Living.h
#ifndef LIVING_H
#define LIVING_G
#include"IRoom.h"
#include"ISensor.h"
#include<iostream>
#include<fstream>
#include<vector>
using namespace std;
class Living :public IRoom {
public:
void createRoom() const{
ofstream Myfile("Living.txt");
}
void updateRoom()const {
ofstream out;
out.open("Livinf.txt", ios::app);
}
void deleteRoom() const{
remove("Living.txt");
}
void readRoom() const{
}
private:
vector<ISensor> sensors;
};
#endif

How can I fix the architecture of the program so that I can use the variables of the Base class in other classes?

I took the design of a game from one person and now I have a problem.
Below there is an implementation of the class Base, in which all the initial parameters of the window are defined, and all its fields are brought into the global scope.
Base.h :
#pragma once
#include "Define.h"
#include "Audio.h"
#include "Font.h"
#include "Texture.h"
#include "GameObject.h"
class Base {
public:
static sf::RenderWindow wnd;
static Texture texture;
static Font font;
static Audio audio;
static sf::Event event;
static int scr_w;
static int scr_h;
static v2f cur_p;
static v2f cur_p_wnd;
static vector<unique_ptr<GameObject>> objects;
static float time;
static void SystemUpdate() {
time = float(clock.getElapsedTime().asMicroseconds()) / 1000.f, clock.restart();
cur_p = wnd.mapPixelToCoords(sf::Mouse::getPosition(wnd));
cur_p_wnd = v2f(sf::Mouse::getPosition(wnd));
}
static void CloseEvent() {
if (event.type == sf::Event::Closed || (event.type == sf::Event::KeyPressed && event.key.code == Keyboard::Escape)) wnd.close();
}
static bool IsKeyPressed(const sf::Keyboard::Key& code) {
if (event.type == sf::Event::KeyPressed)
if (event.key.code == code) return true;
return false;
}
static bool IsKeyReleased(const sf::Keyboard::Key& code) {
if (event.type == sf::Event::KeyReleased)
if (event.key.code == code) return true;
return false;
}
template <class T>
static void new_object(T* obj) {
B::objects.push_back(unique_ptr<GameObject>(obj));
}
template <class T>
static void delete_object(T* obj) {
for (auto itr = B::objects.begin(); itr != B::objects.end(); ++itr) {
if ((*itr)->ID == obj->ID) {
B::objects.erase(itr);
return;
}
}
}
static bool IsMouseInRect(Shape& s) {
return s.getGlobalBounds().contains(B::wnd.mapPixelToCoords(sf::Mouse::getPosition(B::wnd)));
}
Base(string init) {
if (init == "init") {
scr_w = sf::VideoMode::getDesktopMode().width;
scr_h = sf::VideoMode::getDesktopMode().height;
font = Font();
texture = Texture();
audio = Audio();
wnd.create(sf::VideoMode(scr_w, scr_h), "Sea Battle", sf::Style::Close, sf::ContextSettings(0, 0, 8));
cur_p = v2f(0, 0);
cur_p_wnd = v2f(0, 0);
wnd.setMouseCursorVisible(true);
wnd.setFramerateLimit(30);
srand(::time(0));
}
}
Base(void) {}
private:
static sf::Clock clock;
};
sf::RenderWindow B::wnd;
Texture B::texture;
Font B::font;
Audio B::audio;
sf::Event B::event;
int B::scr_w;
int B::scr_h;
v2f B::cur_p;
v2f B::cur_p_wnd;
float B::time;
sf::Clock B::clock;
vector<unique_ptr<GameObject>> B::objects;
It is included to the class Game, in which its constructor is called.
Game.cpp :
#include "Game.h"
Game::Game() {
B("init");
game_state = GameState::Planning;
GameObject* background = new GameObject(v2f(5000, 5000));
background->getRect().setFillColor(Color(255, 255, 255));
new_object(background);
new_object(new Field());
}
void Game::Update() {
switch (game_state) {
case GameState::MainMenu:
break;
case GameState::Planning:
for (auto itr = B::objects.begin(); itr != B::objects.end(); ++itr) {
(*itr)->Update();
}
break;
case GameState::Settings:
//
break;
case GameState::Game:
//
break;
default: break;
}
UpdateUI();
}
void Game::Action() {
switch (game_state) {
case GameState::MainMenu:
break;
case GameState::Planning:
for (auto itr = B::objects.begin(); itr != B::objects.end(); ++itr) {
(*itr)->Action();
}
break;
case GameState::Settings:
//
break;
case GameState::Game:
//
break;
default: break;
}
ActionUI();
}
void Game::Draw() {
wnd.clear();
switch (game_state) {
case GameState::MainMenu:
break;
case GameState::Planning:
for (auto itr = B::objects.begin(); itr != B::objects.end(); ++itr) {
(*itr)->Draw(wnd);
}
break;
case GameState::Settings:
//
break;
case GameState::Game:
//
break;
default: break;
}
DrawUI();
wnd.display();
}
void Game::UpdateUI() {}
void Game::ActionUI() {}
void Game::DrawUI() {}
void Game::Play() {
while (wnd.isOpen()) {
SystemUpdate();
Update();
while (wnd.pollEvent(event)) {
CloseEvent();
Action();
}
Draw();
}
}
Game::~Game(){}
int main() {
Game game;
game.Play();
return 0;
}
The main game loop is in the class Game, and this class must call the Draw, Action, Update methods for each object contained in the object vector.(objects vector is in the Base.h)
But if I create any new object class and try to implement its Draw, Action, Update methods in it, then I will not be able to use in them all the variables in Base.h, brought to the global scope, and without them I cannot properly implement my objects, how can I change the architecture so that everything works?
///
For example, if I want the position of my object to change to the current position of the cursor, then I need a variable from Base.h, which I will refer to as B::cur_p, but the compiler simply gives an error: "unknown authenticator".
The answer to globals is NO globals (just like optimization, only use them if you know its worth the cost). It is bad for maintainability and bad for testing! (and in large projects bad for component dependency and bad for build times) If you want to learn about architecture, now is a good time te read up on dependency injection. e.g. https://en.wikipedia.org/wiki/Dependency_injection
Here is an example in code for your game :
#include <vector>
//-----------------------------------------------------------------------------
// just some structs to be able to use names from your Game to recognize.
struct RenderWindow {};
struct Texture {};
struct Font {};
struct Audio {};
struct GameObject
{
void update() {};
};
// etc
//-----------------------------------------------------------------------------
// global_data_itf.h
// model of a screen, those values belong together
struct screen_size_t
{
unsigned int width{ 3440 };
unsigned int height{ 1440 };
};
// Now define an interface for accessing your data.
// This also allows you
// to create mocks (e.g. with different screen sizes) for testing
// not something you can do with static or real global variables
//
// Note you should really make functions const and return const&
// if data is readonly!
//
class global_data_itf
{
public:
virtual RenderWindow& render_window() = 0;
virtual Texture& texture() = 0;
virtual Font& font() = 0;
virtual Audio& audio() = 0;
virtual const screen_size_t& screen_size() = 0;
// unique_ptr probably not needed. Give GameObject a move constructor
// and emplace gameobjects
virtual std::vector<GameObject>& objects() = 0;
virtual float& time() = 0;
virtual ~global_data_itf() = default;
protected:
global_data_itf() = default;
};
//-----------------------------------------------------------------------------
// global_data.h
// #include "global_data_itf.h"
// For the game you need a default implementation of the global_data_itf
// this is it.
class global_data final :
public global_data_itf
{
// todo constructor with proper initialization
virtual RenderWindow& render_window() override
{
return m_render_window;
}
virtual Texture& texture() override
{
return m_texture;
}
virtual Font& font() override
{
return m_font;
}
virtual Audio& audio() override
{
return m_audio;
}
virtual const screen_size_t& screen_size() override
{
return m_screen_size;
}
virtual std::vector<GameObject>& objects() override
{
return m_objects;
}
virtual float& time() override
{
return m_time;
}
private:
RenderWindow m_render_window;
Texture m_texture;
Font m_font;
Audio m_audio;
screen_size_t m_screen_size;
std::vector<GameObject> m_objects;
float m_time;
};
//-----------------------------------------------------------------------------
// Game.h
// #include "global_data_itf.h"
class Game
{
public:
explicit Game(global_data_itf& data);
void Update();
private:
global_data_itf& m_data;
};
//-----------------------------------------------------------------------------
// Game.cpp
// include "game.h"
Game::Game(global_data_itf& data) :
m_data{ data }
{
}
void Game::Update()
{
for (auto& object : m_data.objects())
{
object.update();
}
}
//-----------------------------------------------------------------------------
// main.cpp
// #include "global_data.h"
// #include "game.h"
int main()
{
global_data data;
Game game(data); // inject the dependency on data into game.
// if you have other classes needing access to global data
// you can inject global_data into those classes as well.
return 0;
}
Well at first, if you want to access your variables from wherever, you can make them real global variables, put them in a header, etc. If I got you right, this fixes the whole problem as variables and methods go separately.

cocos2d this->getBoundingBox

In a pawn class that inherits from the cocos2d Sprite class, I used this->getBoundingBox() in it's update function. This caused an "Access violation at reading location" error. Then, I swapped "this" with "GAME::PLAYER", a variable in a namespace that references the player and it worked. Why does this->getBoundingBox() cause an error when GAME::PLAYER->getBoundingBox() works perfectly fine? Aren't they supposed to be the same thing? Just to note, "this->" works with any other function but getBoundingBox. Is it something I'm doing wrong? I'm not THAT good with C++
Here's pawn.h
#include <cocos2d.h>
#ifndef PLAYER_CONTROLLER
#define PLAYER_CONTROLLER GAME::PLAYER
class pawn : public cocos2d::Sprite {
public:
pawn();
~pawn();
static pawn* create();
static pawn* create(bool default_moving);
bool moving;
bool right;
int speed;
cocos2d::Rect getBounds();
void step();
void initOptions();
void update(float dt) override;
void move(cocos2d::Vec2 vec);
void moveX(int x);
void moveY(int y);
virtual bool touchBegan(cocos2d::Touch*, cocos2d::Event*);
virtual void touchEnded(cocos2d::Touch*, cocos2d::Event*);
};
namespace GAME {
static pawn* PLAYER;
};
#endif
Here's pawn.cpp
#include "player.h"
#include <cocos2d.h>
pawn::pawn() {
}
pawn::~pawn() {
}
bool pawn::touchBegan(cocos2d::Touch* touch, cocos2d::Event* event) {
this->move(cocos2d::Vec2(5, 0));
this->moving = false;
return true;
}
void pawn::touchEnded(cocos2d::Touch* touch, cocos2d::Event* event) {
this->moving = true;
}
void pawn::step() {
if (this->moving) {
if (this->right) {
this->move(cocos2d::Vec2(this->speed, 0));
}
else {
this->move(cocos2d::Vec2(-this->speed, 0));
}
if (this->getPositionX() < 0) {
this->right = true;
CCLOG("Going right V4");
}
else {
if (this->getPositionX() + this->getContentSize().width > cocos2d::Director::getInstance()->getWinSizeInPixels().width + cocos2d::Director::getInstance()->getVisibleOrigin().x){
this->right = false;
CCLOG("Going left V4");
}
}
}
}
void pawn::move(cocos2d::Vec2 vec) {
PLAYER_CONTROLLER->setPosition(cocos2d::Vec2(PLAYER_CONTROLLER->getPositionX() + vec.x, PLAYER_CONTROLLER->getPositionY() + vec.y));
}
void pawn::moveX(int x) {
}
void pawn::moveY(int y) {
}
void pawn::update(float dt) {
//cocos2d::Rect act = this->getBoundingBox();
this->getPosition();
this->step();
}
cocos2d::Rect pawn::getBounds() {
if (!PLAYER_CONTROLLER) {
CCLOG("Is this the problem?");
}
return PLAYER_CONTROLLER->getBoundingBox();
}
pawn* pawn::create() {
auto character = new pawn();
character->moving = true;
character->right = false;
character->speed = 5;
character->setPositionY(50);
if (PLAYER_CONTROLLER == NULL) {
CCLOG("There is no player, yet.");
CCLOG("Adding player");
PLAYER_CONTROLLER = character;
}
else {
CCLOG("There's already a player");
return NULL;
}
//character->setPositionX(40);
if (character->initWithFile("Base.jpg")){
return character;
}
CC_SAFE_DELETE(character);
return NULL;
}
pawn* pawn::create(bool default_moving) {
pawn* character = new pawn();
character->moving = default_moving;
character->setPositionX(40);
if (character->initWithFile("Base.jpg")){
return character;
}
CC_SAFE_DELETE(character);
return NULL;
}
Is it maybe because I call a pawn method from another class? I use a Collider class to call functions in pawn
Collider.cpp
#include "Collider.h"
#include "player.h"
Collider::Collider() : CollideMode(OVERLAP) {
}
Collider::~Collider() {
}
Collider* Collider::create() {
Collider* col = new Collider;
if (col->initWithFile("Base.jpg")){
col->setAnchorPoint(cocos2d::Vec2(0, 0));
col->setContentSize(cocos2d::Size(100, 100));
return col;
}
CC_SAFE_DELETE(col);
return NULL;
}
void Collider::collision(cocos2d::Vec2 intersect) {
CCLOG("IT IS COLLIDING");
if (intersect.x < intersect.y) {
PLAYER_CONTROLLER->move(cocos2d::Vec2(-intersect.x, 0));
CCLOG("X");
}
else if (intersect.x > intersect.y) {
PLAYER_CONTROLLER->move(cocos2d::Vec2(0, -intersect.y));
CCLOG("Y");
}
}
void Collider::update(float dt) {
//cocos2d::Rect col = this->getBoundingBox();
auto act = PLAYER_CONTROLLER->getBounds();
if (PLAYER_CONTROLLER) {
if (!PLAYER_CONTROLLER) {
CCLOG("There is no player?");
}
}
else {
CCLOG("Not colliding");
}
}
I don't seems any problem with this->getBoundingBox() inside update(float dt) function.
I've created small test :
declaration inside .h file
class MySprite: public Sprite {
public:
bool init() override;
void update(float) override;
CREATE_FUNC(MySprite);
};
Now method definition inside .cpp file
bool MySprite::init(){
if(!Sprite::init())
return false;
scheduleUpdate();
return true;
}
void MySprite::update(float dt){
auto rect=this->getBoundingBox();
CCLOG("Inside Update method of MySprite Bounding rect Width %f & Height %f",rect.size.width,rect.size.height);
}
Then I created an autoreleased object of MySprite and add to parent.
auto mysprite=MySprite::create();
mysprite->setContentSize(Size(10,10));
addChild(mysprite);
Run, Expected result on output console.
I see my mistake. It was the fact that I redefined the namespace "GAME" and it's variable, "GAME::PLAYER" every time I included pawn.h, the other source files that I called the pawn functions from didn't know what GAME::PLAYER or PLAYER_CONTROLLER ( just a macro for GAME::PLAYER ) was, as I had only defined PLAYER_CONTROLLER in pawn.cpp. That's why when you called PLAYER_CONTROLLER->method() in another file, it passed in NULL as "this", and also why PLAYER_CONTROLLER was referring to a different PLAYER_CONTROLLER than the one passed in as "this".
I solved it by using the extern keyword that makes the variables global between all files, which was my original intention.
pawn.h
#include <cocos2d.h>
#ifndef PLAYER_CONTROLLER
#define PLAYER_CONTROLLER GAME::PLAYER
#define INITIALIZE_PLAYER pawn* GAME::PLAYER = NULL
class pawn : public cocos2d::Sprite {
public:
pawn();
~pawn();
static pawn* create();
static pawn* getController();
static pawn* create(bool default_moving);
bool moving;
bool right;
int speed;
cocos2d::Rect getBounds();
void step();
void initOptions();
void update(float dt) override;
void move(cocos2d::Vec2 vec);
void moveX(int x);
void moveY(int y);
virtual bool touchBegan(cocos2d::Touch*, cocos2d::Event*);
virtual void touchEnded(cocos2d::Touch*, cocos2d::Event*);
};
namespace GAME {
extern pawn* PLAYER;
};
#endif
This is why I said I wasn't that good at C++.

0xcdcdcdcd while using this->

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.

Unable to push_back elements in a list

I'm facing a really peculiar problem with my code,
I am unable to push elements into a list.
I'm trying to implement a scan fill algorithm.
I want the list of points that I have plotted on the screen so that I can check if a scan line intersects with them.
In my Screen::plot_pixel function I push the Point into the plotted_points list.
But when I iterate through the list, it's empty.(I'm iterating in shape.cpp using a friend function)
I tried using a set too but to no avail. I have attached the console output I get too.
plot_pixel gets called multiple times, I verified this by adding a print statement there but the points refuse to get pushed in.
Here's all my code, point.h
#ifndef POINT_H
#define POINT_H
class Point
{
float x_coordinate,y_coordinate;
public:
Point(){}
Point(float x, float y):x_coordinate(x),y_coordinate(y){}
float get_x() const{return x_coordinate;}
float get_y() const {return y_coordinate;}
bool operator==(const Point rhs)const
{
if( ((int)x_coordinate == (int)rhs.get_x()) && ((int)y_coordinate == (int)rhs.get_y()) )
return true;
else return false;
}
bool operator<(const Point rhs)const
{
if((int)x_coordinate < (int)rhs.get_x())
return true;
else return false;
}
};
#endif
screen.h
#ifndef SCREEN_H
#define SCREEN_H
#include<graphics.h>
#include "point.h"
#include<list>
class Shape;
class Screen
{
private:
int max_x,max_y,grid_size;
int delta_x,delta_y;
int origin_x,origin_y;
public:
std::list<Point> plotted_points;
// Default Constructor to Initialize the screen with the grid
Screen(int, int, int);
//Method prototypes
void plot_pixel(int,int,int);
void dda_line(Point p1, Point p2);
int get_max_x(){return max_x;}
int get_max_y(){ return max_y;}
friend void draw_shape(Screen,Shape);
friend void fill_shape(Screen,Shape);
};
#endif
screen.cpp
#include "screen.h"
void Screen::plot_pixel(int xcoord,int ycoord,int col=WHITE)
{
int l,t,r,b;
l = origin_x + xcoord * delta_x;
r = l + delta_x;
b = origin_y - ycoord * delta_y;
t = b - delta_y;
setcolor(col);
bar(l,t,r,b);
setcolor(WHITE);
Point *tmp = new Point(xcoord,ycoord);
//the culprit code
plotted_points.push_back(*tmp);
delete tmp;
}
void Screen::dda_line(Point p1, Point p2)
{
.....
plot_pixel(x,y,0);
}
shape.h
#ifndef SHAPE_H
#define SHAPE_H
#include<list>
#include<iostream>
#include "point.h;
class Screen;
class Shape
{
list<Point> figure;
public:
Shape(list<Point> s);
friend void draw_shape(Screen,Shape);
friend void fill_shape(Screen,Shape);
};
#endif
shape.cpp
#include "shape.h"
#include "screen.h"
Shape::Shape(list<Point> s):figure(s){}
void fill_shape(Screen scr, Shape sh)
{
list<Point>::iterator pit,vit;
//HERE's Where I try iterating over the list and get nothing
//to check if the plotted points and vertices are listed correctly
cout<<"Plotted Points :\n";
for( pit = scr.plotted_points.begin();pit != scr.plotted_points.end();pit++)
{
cout<<pit->get_x()<<" "<<pit->get_y()<<endl;
}
cout<<"Vertices :\n";
for( vit = sh.figure.begin();vit != sh.figure.end();vit++)
{
cout<<vit->get_x()<<" "<<vit->get_y()<<endl;
}
}
and finally my driver
#include "screen.h"
#include "shape.h"
using namespace std;
int main()
{
Screen s(641,641,32);
Point p1(-10,-10),p2(-10,10),p3(10,10),p4(10,-10);
list<Point> rectangle_points;
//to construct the rectangle
rectangle_points.push_back(p1);
rectangle_points.push_back(p2);
rectangle_points.push_back(p3);
rectangle_points.push_back(p4);
Shape rectangle(rectangle_points);
draw_shape(s,rectangle);
fill_shape(s,rectangle);
getch();
return 0;
}
Here's the output
Plotted Points :
Vertices :
-10 -10
-10 10
10 10
10 -10
You are passing the Screen object s into your functions, but they take the Screen object by value. They therefore take a copy of the object which they then modify. Your original Screen "s" is unchanged after the call to draw_shape().
You should probably modify them so they take a reference to a Screen object, such as:
void draw_shape(Screen& scr, Shape shp)