C++ Can't increment a variable - c++

I'm working on an Animation class for a small game engine, and for some reason the frame counter does not want to increment, it keeps stuck at 0 or 1.
This is the Animation::Step code (here's where the incrementation is supposed to happen):
void Animation::Step()
{
...
time += (float)glfwGetTime();
if (time >= Speed)
{
time = 0;
if (f++ >= count - 1)
{
...
}
}
// Here I do some math to get a clip rectangle...
...
}
Now this is the part where Animation::Step is called:
inline void DrawAnimation(Animation ani, Vec2 pos, BlendMode mode, DrawTextureAttributes attr)
{
ani.Step();
...
// draw texture
}
And in the game mainloop:
void on_render(Renderer r)
{
DrawTextureAttributes attr;
attr.Scale = Vec2(1.5);
r.DrawAnimation(ani, Vec2(320, 240), BlendMode::Normal, attr);
}
EDIT:
The class definition:
class Animation
{
public:
Animation() {}
Animation(Texture2D tex, int rows, int cols, int *frames, float speed, bool loop=false);
Animation(Texture2D tex, int rows, int cols, float speed, bool loop=false);
Texture2D Texture;
std::vector<int> Frames;
float Speed;
bool Loop;
float getCellWidth();
float getCellHeight();
void Step();
UVQuad RETUV;
private:
int f, r, c; // here's F
float w, h;
float time;
};
Well, thanks in advance! (and sorry for my kinda bad english)

inline void DrawAnimation(Animation ani...
Each time you pass object by value to this function. So, any increment would be applied to this copy rather than your original value. You can pass by reference to get the desired behavior.
inline void DrawAnimation(Animation& ani...

Related

C++ functions of pointers to classes don't work?

I'm trying to generate a terrain using perlin noise, to improve the quality of the terrain, I want to use multiple noises at once. So I have written a class that should to that for me. Here are the hpp and cpp files:
#include "perlinNoise.hpp"
class MultiPerlinNoise: public PerlinNoise {
public:
MultiPerlinNoise();
std::vector<PerlinNoise*> perlinNoises;
float octaveNoise(float x, float y);
};
cpp:
#include "multiPerlinNoise.hpp"
MultiPerlinNoise::MultiPerlinNoise():
PerlinNoise(0) {
}
float MultiPerlinNoise::octaveNoise(float x, float y) {
float sum = 0.0f;
for(int i = 0; i < perlinNoises.size(); i++)
sum += perlinNoises[i]->octaveNoise(x, y);
return sum;
}
The PerlinNoise class is a wrapper around the code for a octave peril noise I found on the internet. It looks like this:
#include "sivPerlinNoise.hpp"
class PerlinNoise {
public:
PerlinNoise(unsigned int seed);
float octaveNoise(float x, float y);
float frequency;
float multiplier;
int octaves;
unsigned int seed;
float offset;
private:
siv::PerlinNoise perlinNoise;
};
cpp:
#include "perlinNoise.hpp"
PerlinNoise::PerlinNoise(unsigned int seed):
perlinNoise(seed), frequency(2.0f), multiplier(1.0f), octaves(1), seed(seed), offset(0.0f) {
}
float PerlinNoise::octaveNoise(float x, float y) {
return perlinNoise.octaveNoise(x / frequency, y / frequency, octaves) * multiplier + offset;
}
Now the problem is, that when I pass a pointer to my noise into my map class, the function always return 0.0f. This is how the constructor of my map class looks like:
Map::Map(PerlinNoise *noise, Shader *shader, const RenderData *data):
noise(noise), shader(shader), data(data), texture("resources/textures/stones.png") {
printf("%f\n", noise->octaveNoise(-(CHUNK_SIZE / 2.0f) + 0.0f, -(CHUNK_SIZE / 2.0f) + 0.0f));
update(glm::vec3(0.0f));
}
When I don't use a pointer to my noise everything is working as it should. How can this be fixed?
You need to declare octaveNoise as virtual, so the method can be overridden by inheriting classes:
class MultiPerlinNoise: public PerlinNoise {
public:
MultiPerlinNoise();
std::vector<PerlinNoise*> perlinNoises;
virtual float octaveNoise(float x, float y);
};

How do I pass a random value from one function to another function using classes in C++?

I have a sample of code for some framework that I am using. For ease of reading I have separated blocks of code from different files.
Tile.h
class Tile
{
public:
Tile(int row, int column);
~Tile();
void Draw();
void Update(double delta);
void SetValue(int value);
int GetValue();
private:
//Member variables
Label* m_ValueLabel;
int m_Value = 0;
int m_Row;
int m_Column;
float duration = 0.0f;
float xScale = 0;
float yScale = 0;
};
Tile.cpp
void Tile::SetValue(int value)
{
//Set the Tile's value
m_Value = value;
//if (m_Value != EMPTY_TILE)
{
//Update the Tile's Label
m_ValueLabel->SetText(to_string(m_Value));
}
/*else
{
m_ValueLabel->SetText("");
}*/
}
Game.h
class Game
{
public:
Game(); //Constructor
~Game(); //Destructor
void Update(double delta);
void Draw();
void HandleLeftMouseClick(float mouseX, float mouseY);
void HandleRightMouseClick(float mouseX, float mouseY);
void HandleKeyPress(Keyboard::Key key);
bool isBoardFull();
int GetEmptyTileIndex();
void SpawnTile();
void RandomizeSeed();
int RandomRange(int min, int max);
private:
//Member variables should go here
Tile* m_Tiles[NUM_TILES];
bool isTileFull[16] = {};
int TileValueArray[5] = { 2,2,2,4,4 };
};
Game.cpp
void Game::SpawnTile()
{
RandomizeSeed();
int meaningfulVariableName = GetEmptyTileIndex();
if (meaningfulVariableName != -1)
{
int RandomNumber = RandomRange(0,4);
int TileValue = TileValueArray[RandomNumber];
}
else if (meaningfulVariableName == -1)
{
//Does nothing
}
}
What I need to do with this is make it so that the TileValue created in Game.cpp can be passed to the SetValue function in Tile.cpp because the value created is required for m_Value in SetValue.
The majority of code present can probably be ignored, and anything commented out should not effect how I need the code to function at the moment. There is nothing wrong with the framework outside of these files, as I have used it several times before.
I know there are easier ways to do this, but this is how I am required to do it. I would really appreciate if someone could help me with this because anything that I have found online has not helped. If you think that you may need more code for clarification on something, please do not hesitate to ask. Also, in case it helps I am using this to create a 2048 clone.
You have a function Game::GetEmptyTileIndex which will return an index. You can use that index to set Game::m_Tiles by changing the Game::SpawnTile function like so:
// Game.cpp
void Game::SpawnTile()
{
RandomizeSeed();
// Returns a tile index.
int meaningfulVariableName = GetEmptyTileIndex();
if (meaningfulVariableName != -1)
{
int RandomNumber = RandomRange(0,4);
int TileValue = TileValueArray[RandomNumber];
// Set the value for the tile at the required index.
m_Tiles[meaningfulVariableName]->SetValue(TileValue);
}
else if (meaningfulVariableName == -1)
{
//Does nothing
}
}

Odd behavior of std::vector back()

The following code asserts in the indicated place with "iterator+offset is out of range."
void Network::PushInput(int c, int h, int w) {
Input* input = new Input(batch, c, h, w, data);
layers.push_back(input); // this happens to be the first push_back()
// layers.push_back(input); // doing another doesn't change the assert!
Layer *foo = layers.back(); // asserts here
Layer *baz = layers[layers.size()-1]; // does not assert
}
Input is a public subclass of Layer. layers is declared as
std::vector<Layer *>layers;
If I attempt to duplicate the above with more vanilla template types, e.g., int*, back() works as expected with no asserts. Somehow, the template type matters here. (Note: _ITERATOR_DEBUG_LEVEL is 2, which triggers that assert check in the vector class.)
I'd rather not bluntly change all of the back()'s in the code to size()-1, but would rather understand what is going on here.
Any ideas? (I'll continue to perturb the code until I can find the apparent cause of this, but hopefully this will be obvious to someone else.)
(I'm using Visual Studio 2013 Community Edition, if that matters.)
.....
Here's a stand-alone file that compiles that shows the problem:
#include <vector>
using namespace std;
namespace layer {
class Layer {
public:
Layer(float alpha = 0, float momentum = 0.9f, float weight_decay = 0);
virtual ~Layer();
// three virtual method that all layers should have
virtual void forward(bool train = true) = 0;
virtual void backward() = 0;
virtual void update() = 0;
void adjust_learning(float scale); // change the learning rate
Layer* prev; // previous layer
Layer* next; // next layer
float* data; // X': output (cuDNN y)
int batch; // n: batch size
float alpha; // learning rate
float momentum; // beta: momentum of gradient
float weight_decay; // gamma: weight decay rate
};
} /* namespace layer */
namespace layer {
Layer::Layer(float alpha_, float momentum_, float weight_decay_)
{
std::memset(this, 0, sizeof(*this));
alpha = alpha_;
momentum = momentum_;
weight_decay = weight_decay_;
}
Layer::~Layer() {}
void Layer::adjust_learning(float scale) {
alpha *= scale;
}
}
namespace layer {
class Input : public Layer {
public:
Input(int n, int c, int h, int w, float* _data);
virtual ~Input();
void forward(bool train = true);
void backward();
void update();
};
}
namespace layer {
Input::Input(int n, int c, int h, int w, float* _data) : Layer() {
prev = NULL;
batch = n;
data = _data;
}
Input::~Input() {
data = NULL;
}
void Input::forward(bool train) {
// nothing
}
void Input::backward() {
// nothing
}
void Input::update() {
// nothing
}
}
using namespace layer;
namespace model {
class Network {
private:
std::vector<Layer*> layers; // list of layers
bool has_input, has_output; // sanity check
float* data; // input on device
int batch; // whole size of data, batch size
public:
Network(int batch_size);
virtual ~Network();
void PushInput(int c, int h, int w);
};
}
namespace model {
void Network::PushInput(int c, int h, int w) {
Input* input = new Input(batch, c, h, w, data);
layers.push_back(input);
Layer *foo = layers.back(); // **WHY DOES THIS ASSERT??**
}
Network::Network(int _batch) {
std::memset(this, 0, sizeof(*this));
batch = _batch;
}
Network::~Network() {
for (Layer* l : layers)
delete l;
}
}
void main()
{
model::Network foo(10);
foo.PushInput(2, 3, 4);
}
You have undefined behavior in your code.
In the Layer constructor you do
std::memset(this, 0, sizeof(*this));
The problem with this is that the above call will clear the virtual function table (which is a part of the object) as well. Any virtual function called after that will not work as expected, if at all. That includes the destruction of the objects as the destructors are virtual.

Point, square, and cube program help on C++

I've been writing a program for CS class that's supposed to get the X and Y coordinates from the user, as well as the length of a square and the height of the cube, and it should then calculate the area of the square and the surface area and volume of the cube (plus some coordinates stuff but that's not a pressing issue right now)
I've written the test file and it compiled successfully, but I've been getting very long answers for the square and cube properties that are obviously wrong. Can anyone point out whatever logical errors I might have or if I have the access specification and relationship between the classes wrong?
Point.h
class Point
{
protected:
double Xint, Yint;
public:
Point();
void setX(double);
void setY(double);
double getX() const;
double getY() const;
};
Point.ccp
Point::Point()
{
Xint = 0;
Yint = 0;
}
void Point::setX(double x)
{ Xint = x; }
void Point::setY(double y)
{ Yint = y; }
double Point::getX() const
{ return Xint; }
double Point::getY() const
{ return Yint; }
Square.h
#include "Point.h"
class Square : public Point
{
protected:
Point lowerLeft;
double sideLength;
public:
Square(double sideLength, double x, double y) : Point()
{
sideLength = 0.0;
x = 0.0;
y = 0.0;
}
void setLowerLeft(double, double);
void setSideLength(double);
double getSideLength() const;
double getSquareArea() const;
};
Square.ccp
#include "Square.h"
void Square::setLowerLeft(double x, double y)
{
lowerLeft.setX(x);
lowerLeft.setY(y);
}
void Square::setSideLength(double SL)
{ sideLength = SL; }
double Square::getSideLength() const
{ return sideLength; }
// Calculate the area of square
double Square::getSquareArea() const
{ return sideLength * sideLength; }
Cube.h
#include "Square.h"
class Cube : public Square
{
protected:
double height;
double volume;
public:
Cube(double height, double volume) : Square(sideLength, Xint, Yint)
{
height = 0.0;
volume = 0.0;
}
double getSurfaceArea() const;
double getVolume() const;
};
Cube.ccp
#include "Cube.h"
// Redefine GetSquareArea to calculate the cube's surface area
double Cube::getSurfaceArea() const
{ return Square::getSquareArea() * 6; }
// Calculate the volume
double Cube::getVolume() const
{ return getSquareArea() * height; }
"Can anyone point out whatever logical errors I might have or if I have the access specification and relationship between the classes wrong?"
Well, from our well known 3-dimensional geometry a cube is made up from exactly 6 squares.
So how do you think inheriting a Cube class from a Square actually should work well?
You can easily define a Cube class by means of a fixed Point (e.g. the upper, left, front corner) and a fixed size of the edge length.
If you really want and need to, you can add a convenience function for your Cube class, that returns all of the 6 Squares it consist of in 3 dimensional space:
class Cube {
public:
Cube(const Point& upperLeftFrontCorner, double edgeLength);
std::array<Square,6> getSides() const;
};

How to use a vector within a class

I used the Fireworks init function to store a particle into the particles vector class.
And when I try to retrieve the count of the particles vector in the update() function, the particles vector is empty. Why?
Fireworks.cpp class:
void Fireworks::init(){
float x = randf();
float y = - 1 * randf(); //Going UP
float z = randf();
Particle part(position,Vector3f(x,y,z), color, randInt(1,50));
particles.push_back(part);
}
bool Fireworks::update(){
Particle particle;
int count = particles.size(); //Total num of particles in system
cout << particles.size() << " ";
}
class Fireworks: public ParticleSystem {
private:
void init();
public:
Fireworks(Vector3f pos, Vector3f col) {
position = pos;
color = col;
init();
}
virtual bool update();
};
particlesystem.h
class ParticleSystem {
protected:
vector<Particle> particles;
public:
//virtual Particle generateParticle();
virtual bool update(){return false;};
};
main.cpp
ParticleSystem *PS;
int main( int argc, char *argv[] ) {
PS = &Fireworks(Vector3f(0,0,0), Vector3f(200,0,255));
glutIdleFunc(move);
}
void move()
{
PS->update();
}
PS = &Fireworks(Vector3f(0,0,0), Vector3f(200,0,255));
This introduces undefined behavior. The right hand side creates a temporary, which will be deleted as soon as that full expression is over (i.e. right after the ;). PS will point to a deleted object after that line - doing anything with it is undefined behavior.
Use new.
PS = new Fireworks(Vector3f(0,0,0), Vector3f(200,0,255));
Also, you must return from all functions that are declared as returning something (non-void). It doesn't matter if they're virtual or not.