Here is the following main function or my program
void scene_render(const struct Scene *s);
int main(void) { //leave main as is
struct Scene myScene;
scene_init(&myScene);
int keep_going = 1;
while (keep_going == 1) {
cons_clear_screen(); //clear off-screen display buffer
scene_render(&myScene); //render the scene to display buffer
cons_update(); //copy the display buffer to the display
cons_sleep_ms(ANIMATION_DELAY); //pause
scene_update(&myScene); //update the scene
int key = cons_get_keypress(); //see if the user has pressed a key
if (key != -1) {
keep_going = 0;
}
}
return 0;
}
void scene_render(Scene *s)
{
cons_clear_screen();
for(int i=0; i<NUM_PARTICLES; i++)
{
particle_render(&s->parts[i]);
}
}
When I run the makefile command on Cygwin, it passes the errors and starts compiling, but hits an error when it hits scene_render(&myScene);. It says that a reference to it is undefined. It refers to a variable in a function that is a const struct, while all other instances where &myScene is called are merely structs. Any idea what the issue may be? This lab is mostly about using pointers, if that helps.
The program (with assistance from external functions) should generate and throw randomly colored pixels around the command window, bouncing them back to keep them in the screen. Deleting the issue causes the program to compile successfully, but then loads a blank window that seems to do nothing.
Problem
With
void scene_render(const struct Scene *s);
you promise scene_render takes a const struct Scene as a parameter. By the way, you can discard the use of struct here. C++ knows Scene is a struct.
But the function that is defined is
void scene_render(Scene *s)
which takes a plain old, non-const Scene, so when the linker goes looking for a function that matches the promise it does not find one.
Solution
Change
void scene_render(Scene *s)
to
void scene_render(const Scene *s)
to keep the promise. But make certain that const-correctness is maintained throughout.
Related
I have a project where my textures are not displayed inside window properly. Instead of textures it will always show blank white sprites. I cant find out what I'am doing wrong. Here is my code:
class header with vector holding textures
class textures
{
public:
sf::Texture dirt_Texture;
sf::Texture grass_Texture;
std::vector<sf::Texture> texturesVector;
/*
dirt = 0
grass = 1
*/
public:
textures();
sf::Texture getTextureByID(int id);
};
and .cpp file for it:
//constructor populate vector with textures
textures::textures()
{
if (!dirt_Texture.loadFromFile("dirt.PNG"))
{
std::cout << "Error while loading texture.\n";
}
dirt_Texture.isSmooth();
texturesVector.push_back(dirt_Texture);
if (!grass_Texture.loadFromFile("grass.PNG"))
{
std::cout << "Error while loading texture.\n";
}
texturesVector.push_back(grass_Texture);
std::cout << "Texture constructor has been called.\n";
}
sf::Texture textures::getTextureByID(int id)
{
return texturesVector[id];
}
with child class sprite:
class sprites : public textures
{
private:
//textures* textureClass;
sf::Sprite sprite;
std::vector<int> textureIDsVector;
public:
sprites();
~sprites();
int getVectorValueAtLine(int &line);
void setVectorValueAtLineTo(int &line, int value);
void updateTextureAtLine(int& line);
sf::Sprite* getSprite();
};
where primary functions looks this in .cpp
sprites::sprites()
{
std::vector<int> cubeIDsVector(100, 0);
textureIDsVector = cubeIDsVector;
//textureClass = new textures();
std::cout << "Sprite constructor has been called.\n";
}
void sprites::updateTextureAtLine(int& line)
{
switch (textureIDsVector[line])
{
case 0:
//switcher = 0;
sprite.setTexture(getTextureByID(0));
sprite.setColor(sf::Color(55, 150, 150, 150));
std::cout << "case 0\n";
break;
case 1:
//switcher = 1;
sprite.setTexture(getTextureByID(1));
sprite.setColor(sf::Color(155, 50, 150, 150));
std::cout << "case 1\n";
break;
default:
break;
}
}
at main loop I create sprite object on the heap after sf::RenderWindow and after window.clean(...) call updateTextureAtLine() function from the for loop.
No error returned and at debug it seems fine too, I am new into it but it was looking like texture is always at memory, I cant find out where is the problem.
Solved as described below.
getTextureByID() returns a copy of a texture and not a reference. This copy is destroyed when it goes out of scope - so as soon as the call to sprite.setTexture() finishes.
This results in the Sprite having a pointer to a texture that no longer exists.
The solution is to instead return a pointer or a reference from getTextureByID(). Whilst we are changing that function we could should also make the function and returned value const as we are not planning on modifying it, although this is optional - it is a good habit I might as well point out.
Here is an example of a const function that returns a const reference:
// header
const sf::Texture& getTextureByID(int id) const;
// source
const sf::Texture& textures::getTextureByID(int id) const {
return texturesVector[id];
}
This should hopefully solve your problem.
Unrelated notes:
Your textures class is storing four textures total, two dirt textures, and two grass textures.
This might be what you intended, or this might not be.
One solution is to not have the member variables dirt_Texture and grass_Texture or just not to have texturesVector.
The other solution is to make texturesVector store pointers to textures, these could also be const and this would look like this:
// header
std::vector<const sf::Texture*> texturesVector;
// source
// constructor
texturesVector.push_back(&dirt_Texture);
...
texturesVector.push_back(&grass_Texture);
// getTextureByID()
return *texturesVector[id]; // (or alternatively return a pointer)
Finally, if you ARE storing texture objects inside of texturesVector (if you switch to pointers this won't be a problem), then note that adding any more textures might force the internal array of the vector to change memory location and thus invalidate your textures.
If you are not planning on adding more textures midway through running the program, then that is ok. I do add textures midway through running programs a lot because I like lazy initialization. If you are planning on adding more textures, then either use another container that does not move it's objects, or dynamically allocate a place for your textures. I am a fan of the latter, using a map of strings to unique pointers of textures (std::unordered_map<std::string, std::unique_ptr<sf::Texture>>)
EDIT:
The solution:
I tried to create a pointer on a memberfunction and thought the pointer would contain the required informations about the class. It turned out that it didn't.
So Intellisense was absolutely right about the pointer not pointing to an object with the memberfunction but only the memberfunction (or at least that is how I understood it).
In my case I was able to simply use a static member function instead eventhough this function cannot change any memberfunctions without a reference the outer object
Hi and thanks for taking the time to help me.
I'm currently working on some kind of Event-system. I have a class InputManager which checks if the member-function check is called for events the console-window has reveived and then calls the proper event-handlers which are stored in member-function-pointer-vectors (I will later make it a template).
class InputManager
{
private:
HANDLE cursor;
DWORD numEventsCaught, consoleMode, i;
INPUT_RECORD eventBuffer[128];
std::vector<void (InputForm::*)(KEY_EVENT_RECORD)> keyEventHandlers;
std::vector<void (InputForm::*)(MOUSE_EVENT_RECORD)> mouseEventHandlers;
public:
InputManager()
void addKeyEventHandler(void (InputForm::*e)(KEY_EVENT_RECORD));
void addMouseEventHandler(void (InputForm::*e)(MOUSE_EVENT_RECORD));
void check();
};
As you can see, the current type of my vector is a pointer to a member-function of the InputForm-class with a specific parameter. This is also the type that Visual Studio shows me in the little popup-info.
But as soon as I use that vector inside a member-function, the popup-info shows something different and the it tells me that I need to use a pointer-to type.
It tells me that the vector has got the type void (KEY_EVENT_RECORD) instead of void (InputForm::*)(KEY_EVENT_RECORD).
I have no idea how that can happen - i mean how can the type of a vector change just by the scope it's used in?
Here is the function where the problem happens (but it also happens in every other function as well):
void InputManager::check()
{
int size;
if (!ReadConsoleInput(cursor, eventBuffer, 128, &numEventsCaught))
POST_DEBUG_MESSAGE(-1, "Failed to Read Console Input");
for (i = 0; i < numEventsCaught; i++)
{
switch (eventBuffer[i].EventType)
{
case KEY_EVENT:
size = keyEventHandlers.size();
for (int x = 0; x < size; x++)
{
keyEventHandlers[x](eventBuffer[i].Event.KeyEvent); //ERROR ONE
}
break;
case MOUSE_EVENT:
size = mouseEventHandlers.size();
for (int x = 0; x < size; x++)
{
mouseEventHandlers[x](eventBuffer[i].Event.MenuEvent); //ERROR TWO
}
}
}
}
Just in case you want to view all the code, here it is (otherwise just ignore it)
InputManager::InputManager()
{
cursor = GetStdHandle(STD_INPUT_HANDLE);
if (cursor == INVALID_HANDLE_VALUE)
POST_DEBUG_MESSAGE(-1, "Invalid Handle Value, GetStdHandle failed.");
// Deactivate Quickedit
consoleMode = ENABLE_EXTENDED_FLAGS;
if (!SetConsoleMode(cursor, consoleMode))
POST_DEBUG_MESSAGE(-1, "Failed to set Console Mode (Couldn't deactivate Quickedit)");
// Activate mouse and window input
consoleMode = ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT;
if (!SetConsoleMode(cursor, consoleMode))
POST_DEBUG_MESSAGE(-1, "Failed to activate mouse or window inputs");
}
void InputManager::addKeyEventHandler(void (InputForm::*e)(KEY_EVENT_RECORD))
{
keyEventHandlers.push_back(e); // Works properly
}
void InputManager::addMouseEventHandler(void (InputForm::*e)(MOUSE_EVENT_RECORD))
{
mouseEventHandlers.push_back(e);
}
What might be interesting as well is that even if keyEventHandlers.push_back(e) works correctly, it also tells me that e is not member-function-pointer but a usual function pointer -> but the void (InputForm::*e)(KEY_EVENT_RECORD) tells me something else...
I really have no clue what's going on here. Do you have an Idea?
Thank you very much in advance.
I really need help on this one cause I am extremely stuck and have no idea what to do.
Edit:
A lot of you guys are saying that I need to use the debugger but let me be clear I have not used C++ for an extremely long time and I've used visual studio for a grand total of 2 weeks so I do not know all the cool stuff it can do with the debugger.
I am a student at university at the beginning of my second year who is trying to work out how to do something mostly by failing.
I AM NOT a professional coder and I don't have all the knowledge that you people have when it comes to these issues and that is why I am asking this question. I am trying my best to show my issue so yes my code contains a lot of errors as I only have a very basic understanding of a lot of C++ principles so can you please keep that in mind when commenting
I'm only posting this here because I can don't know who else to ask right now.
I have a function called world that is suppose to call my render class to draw all the objects inside of its vector to the screen.
#include "C_World.h"
C_World::C_World()
{
// creates an instance of the renderer class to render any drawable objects
C_Renderer *render = new C_Renderer;
}
C_World::~C_World()
{
delete[] render;
}
// adds an object to the world vector
void C_World::addToWorld(C_renderable* a)
{
world_list.push_back(a);
}
void C_World::World_Update()
{
render->ClearScreen();
World_Render();
}
void C_World::World_Render() {
for (int i = 0; i < 1; i++)
{
//render->DrawSprite(world_list[i]->getTexture(), world_list[i]->get_X, world_list[i]->get_Y());
render->DrawSprite(1, 1, 1);
}
}
While testing I commented out the Sprites get functions in order to check if they were causing the issue.
the renderer sprites are added to the vector list in the constructor through the create sprite function
C_Renderer::C_Renderer()
{
// test sprite: Id = 1
CreateSprite("WhiteBlock.png", 250, 250, 1);
}
I thought this might of been the issue so I had it in other functions but this didn't solve anything
Here are the Draw and create Sprite functions
// Creates a sprite that is stored in the SpriteList
// Sprites in the spriteList can be used in the drawSprite function
void C_Renderer::CreateSprite(std::string texture_name,
unsigned int Texture_Width, unsigned int Texture_height, int spriteId)
{
C_Sprite *a = new C_Sprite(texture_name,Texture_Width,
Texture_height,spriteId);
SpriteList.push_back(a);
size_t b = SpriteList.size();
HAPI.DebugText(std::to_string(b));
}
// Draws a sprite to the X and Y co-ordinates
void C_Renderer::DrawSprite(int id,int x,int y)
{
Blit(screen, _screenWidth, SpriteList[id]->get_Texture(),
SpriteList[id]->getTexture_W(), SpriteList[id]->getTexture_H(), x, y);
}
I even added some test code into the create sprite function to check to see if the sprite was being added too the vector list. It returns 1 so I assume it is.
Exception thrown: read access violation.
std::_Vector_alloc<std::_Vec_base_types<C_Sprite *,
std::allocator<C_Sprite *> > >::_Mylast(...) returned 0x8.
that is the full error that I get from the compiler
I'm really really stuck if there is anymore information you need just say and ill post it straight away
Edit 2:
#pragma once
#include <HAPI_lib.h>
#include <vector>
#include <iostream>
#include "C_renderable.h"
#include "C_Renderer.h"
class C_World
{
public:
C_World();
~C_World();
C_Renderer *render = nullptr;
void World_Update();
void addToWorld(C_renderable* a);
private:
std::vector<C_renderable*> world_list;
void C_World::World_Render();
};
#pragma once
#include <HAPI_lib.h>
#include "C_renderable.h"
#include "C_Sprite.h"
#include <vector>
class C_Renderer
{
public:
C_Renderer();
~C_Renderer();
// gets a pointer to the top left of screen
BYTE *screen = HAPI.GetScreenPointer();
void Blit(BYTE *destination, unsigned int destWidth,
BYTE *source, unsigned int sourceWidth, unsigned int sourceHeight,
int posX, int posY);
void C_Renderer::BlitBackground(BYTE *destination,
unsigned int destWidth, unsigned int destHeight, BYTE *source,
unsigned int sourceWidth, unsigned int sourceHeight);
void SetPixel(unsigned int x,
unsigned int y, HAPI_TColour col,BYTE *screen, unsigned int width);
unsigned int _screenWidth = 1750;
void CreateSprite(std::string texture_name,
unsigned int Texture_Width,unsigned int Texture_height, int spriteId);
void DrawSprite(int id, int x, int y);
void ClearScreen();
private:
std::vector<C_Sprite*> SpriteList;
};
I don't say this lightly, but the code you've shown is absolutely terrible. You need to stop and go back several levels in your understanding of C++.
In all likeliness, your crash is the result of a simple "shadowing" issue in one or more of your functions:
C_World::C_World()
{
// creates an instance of the renderer class to render any drawable objects
C_Renderer *render = new C_Renderer;
}
C_World::~C_World()
{
delete[] render;
}
There are multiple things wrong here, and you don't show the definition of C_World but if this code compiles we can deduce that it has a member render, and you have fallen into a common trap.
C_Renderer *render = new C_Renderer;
Because this line starts with a type this is a definition of a new, local variable, render. Your compiler should be warning you that this shadows the class-scope variable of the same name.
What these lines of code
C_World::C_World()
{
// creates an instance of the renderer class to render any drawable objects
C_Renderer *render = new C_Renderer;
}
do is:
. assign an undefined value to `this->render`,
. create a *local* variable `render`,
. construct a dynamic `C_Renderer` presumably on the heap,
. assign that to the *local* variable `render`,
. exit the function discarding the value of `render`.
So at this point the memory is no-longer being tracked, it has been leaked, and this->render is pointing to an undefined value.
You repeat this problem in several of your functions, assigning new results to local variables and doing nothing with them. It may not be this specific instance of the issue that's causing the problem.
Your next problem is a mismatch of new/delete vs new[]/delete[]:
C_World::~C_World()
{
delete[] render;
}
this would result in undefined behavior: this->render is undefined, and delete[] on a non-new[] allocation is undefined.
Most programmers use a naming convention that distinguishes a member variable from a local variable. Two common practices are an m_ prefix or an _ suffix for members, e.g.
class C_World
{
public:
C_Foo* m_foo; // option a
C_Renderer* render_; // option b
// ...
}
Perhaps you should consider using modern C++'s concept of smart pointers:
#include <memory>
class C_World {
// ...
std::unique_ptr<C_Renderer> render_;
// ...
};
C_World::C_World()
: render_(new C_Renderer) // initializer list
{}
But it's unclear why you are using a dynamic allocation here in the first place. It seems like an instance member would be better:
class C_World {
C_Renderer render_;
};
C_World::C_World() : render_() {}
I have a university assignment and I am completely confused on how to pass the array correctly to prevent the array from being passed as a single array and not a 2D array.
We are to create a random maze generator that will allow us to play that maze too. We are using a specialized windows code to display the maze, but that's not were the problem is so Ill leave that out
My lecturer gave us the skeleton code to work from. What must I change to get it to work?
We have not learnt dynamic memory location or vectors. We have to use an array. Please Help!!?
Here is his code:
I have used the same and just added all the function parameters. I have not changed anything with 'maze' though
class MazeSquare
{
public:
bool leftWall, rightWall, bottomWall, topWall;
bool visited;
int steps;
MazeSquare() // constructor
{
Initialise();
}
void Initialise(void) // reinitialise a square for a new maze
{
leftWall = true; // create the maze square with all the walls
rightWall = true;
bottomWall = true;
topWall = true;
visited = false; // the robot has not visited the square yet
steps = 256; // greater than maximum possible number of steps
}
};
// constants
const int MAZE_SIZE = 16;
// function prototypes
void CreateMaze(MazeSquare maze[MAZE_SIZE][MAZE_SIZE]);
void SolveMaze(MazeSquare maze[MAZE_SIZE][MAZE_SIZE]);
void RestartMaze(MazeSquare maze[MAZE_SIZE][MAZE_SIZE]);
void MoveRobot(MazeSquare maze[MAZE_SIZE][MAZE_SIZE], int &x, int &y, Point click);
void DrawWindow(MazeSquare maze[MAZE_SIZE][MAZE_SIZE], int x, int y);
int ccc_win_main() // main function for a graphics program
{
MazeSquare maze[MAZE_SIZE][MAZE_SIZE]; // maze design
int x = 0, y = 0; // robot position
bool exit = false; // flag to control end of program
// initialise the random number generator
srand((unsigned int)(time(NULL)));
/* initialise the window coordinates here */
CreateMaze(maze); // create a new maze
DrawWindow(maze); // draw the image in the GUI window
do
{
// get a mouse click
Point click = cwin.get_mouse("Click a button or move the robot");
// handle the different types of mouse clicks
if (/* new button is clicked */)
{
CreateMaze(maze);
x = 0;
y = 0;
}
if (/* solve button is clicked */)
{
SolveMaze(maze);
}
if (/* restart button is clicked */)
{
RestartMaze(maze);
x = 0;
y = 0;
}
if (/* exit button is clicked */)
{
exit = true;
}
// handle robot moves
if (/* maze is clicked */)
{
MoveRobot(maze, x, y);
}
DrawWindow(maze);
} while (!exit);
return 0;
}
Confusion number one - You cannot pass arrays to functions in C++.
Confusion number two - You cannot declare arrays as function parameters in C++
Confusion number three - 2D arrays are single arrays, a 2D array is an arrays of arrays, therefore it's a 'single array` also. I guess I'm saying the term single array doesn't have much meaning.
Arrays are a confusing topic in C++. You cannot do everything you might expect to be able to do with them. Instead everything is done with pointers. The relationship beween arrays and pointers in C++ is another confusing topic. You really need to read a book. Any specific questions, ask again.
But on the bright side I don't see anything particularly wrong with your code. You're certainly are not passing single arrays to your functions, as you are worried about.
EDIT:
Perhaps I should make this a little clearer. On point two, this code
void CreateMaze(MazeSquare maze[MAZE_SIZE][MAZE_SIZE]);
certainly looks like you are declaring a function with an array parameter. But it doesn't. Instead the compiler takes the code and converts it into the equivalent code that uses pointers.
On point one, this code
CreateMaze(maze); // create a new maze
certainly looks like you are passing an array to a function, but again you are not. Given that code the compiler passes a pointer to the first element of your maze array, it doesn't pass the array itself.
So I'm trying my hand at some C++ after finishing up an introductory book, and I've become stuck. I've made a vector of objects that each have an SFML circle object as a member, and I want main() to go and draw these circles. The vector is called theBoard, but when I try to access it, I get the following error messages:
error: request for member 'theBoard' in 'GameBoard', which is of non-class type 'Board*'
error: 'theBoard' was not declared in this scope
I'm new to this (came from two years of Python), so I'm sure I made a mistake somewhere. Here is the relevant code for the board creation:
class Board
{
public:
//These are the member functions.
Board();
~Board();
vector<Space*> CreateBoard();
//This will be the game board.
vector<Space*> theBoard;
//These clusters represent the waiting areas for pieces not yet in the game.
vector<Space*> Cluster1;
vector<Space*> Cluster2;
vector<Space*> Cluster3;
private:
//These integers represent the number of spaces on each row, starting at the top (which is row [0])
vector<int> RowNums;
};
Board::Board()
{
//Fill in RowNums with the right values.
RowNums.push_back(1);
RowNums.push_back(17);
RowNums.push_back(2);
RowNums.push_back(17);
RowNums.push_back(1);
RowNums.push_back(1);
RowNums.push_back(5);
RowNums.push_back(2);
RowNums.push_back(7);
RowNums.push_back(2);
RowNums.push_back(11);
RowNums.push_back(3);
RowNums.push_back(17);
RowNums.push_back(4);
RowNums.push_back(17);
//Then, create the board.
theBoard = CreateBoard();
}
CreateBoard() is a very, very long function that returns a vector of pointers to Space objects. I doubt there's a problem here, as the only error message I get crops up when I try to access the circle members of Space objects in main(). It seems to me as though I have declared theBoard in the relevant scope, that is, as a data member of the Board class.
My main() function, in case it's important:
int main()
{
//This sets up the display window.
sf::RenderWindow App(sf::VideoMode(1200, 900, 32), "Malefiz");
//This creates the board on the heap, and a pointer to it.
Board* GameBoard = new Board();
cout << "Board made.";
//This is the game loop.
while(App.IsOpened())
{
//This is used to poll events.
sf::Event Event;
while(App.GetEvent(Event))
{
//This closes the window.
if(Event.Type == sf::Event::Closed)
{
App.Close();
}
}
//This gets the time since the last frame.
//float ElapsedTime = App.GetFrameTime();
//This fills the window with black.
App.Clear(sf::Color(200, 200, 125));
//This draws the places into the window.
for(int i = 0; i < GameBoard.theBoard.size(); ++i)
{
App.Draw(GameBoard.*theBoard[i].m_Circle);
}
//This displays the window.
App.Display();
}
return EXIT_SUCCESS;
}
In your main() function, GameBoard is a Board *, not a Board. So to access members, you need to use -> instead of .. e.g.:
GameBoard->theBoard.size()
[Some people (I am one of them) like to name their pointer variables with a leading p or ptr prefix, in order to make this kind of irritation explicitly clear.]
GameBoard is a pointer to a Board object, and thus you need to use the "->" operator instead of the "." operator to access any of its member variables or methods.
The error is quite explicit if you read it carefully:
error: request for member 'theBoard' in 'GameBoard', which is of non-class type 'Board*'
error: 'theBoard' was not declared in this scope
The first line is telling you that you have a pointer to a Board object and you are trying to access a member directly. That is:
Board *p = ...
p.theBoard; // Error, should be p->theBoard, as p is a pointer
Also note that GameBoard.*theBoard[i].m_Circle might not be what you want, you probably want (I am guessing as there are important bits missing) something like GameBoard->theBoard[i]->m_Circle.
GameBoard is a pointer, so the syntax should be this:
for(int i = 0; i < GameBoard->theBoard.size(); ++i)
{
App.Draw((GameBoard->theBoard[i])->m_Circle);
}
Since elements of theBoard also are pointer, so I used the pointer notation when accessing m_Circle.