variable resetting "randomly" - c++

I am building a text based adventure game and I'm currently stuck on an issue.
I have a two variables that hold the values for the map(rooms) called x and y, I am changing them from a class and as soon as it exits the class code back to main it resets the values for x and y.
int x = 0, y = 0;
...
void IncreaseY(){
y++;
}
void MoveDirection(Direction direction)
{
switch (direction)
{
case North:
DecreaseY();
break;
case South:
IncreaseY();
break;
case East:
IncreaseX();
break;
case West:
DecreaseX();
break;
case None:
break;
default:
break;
}
}
...
class player{
void DoStuff()
{
MoveDirection(South);
}
}
...
void main()
{
Player player = Player.NewOrLoadCharacter();
player.doStuff();
}
This is most of the relevant code summarized.
I have stepped through the program using breakpoints and stepping several times and I am completely sure that as soon as I leave the Player class the variables x and y reset back to 0.
Question:
What could be causing the resetting of the variables x and y?
Note: This is an issue that just popped up since it has worked previously just fine.
edit: Source code: http://pastebin.com/uKS55LEZ
P.S.: I know the code is poorly written, I started with C++ moving from C# a week ago.

The code changed considerably since this answer was first posted, yet the problem is still actually a kind of mirage.
Here's what's happening at the current version of the code (the OP question does not represent this situation at the time of this writing):
In main, there is a Player declared thus:
Player player;
In a standard game loop, this code exists:
while( true )
{
ClearConsole();
Print(map.CreateMap(player));
map.doRoom(player);
}
This is greatly improved over earlier versions (much cleaner). There is one small problem causing the behavior described. It's the signature of the function doRoom (and this may apply to CreateMap, though I doubt it).
void doRoom(Player player)
This is a member of Room (in the loop above, that's map). The problem is that player is passed by value. This means a copy of player is made to provide the input parameter for doRoom. This copy is changed by doRoom (moving x and y, for example). When doRoom returns, the copy which it acts upon evaporates (falls from scope) - and the edited data goes with it.
Change the signature to
void doRoom(Player & player)
Now, the function takes a reference to player. There is no copy being made. As such, changes made to player are retained from one iteration of the loop to the next.
I said earlier this MIGHT apply to map.CreateMap, but that's true only if CreateMap modifies contents of player. If not, it wouldn't matter, but it would be technically slower to create a copy of player just to make the output CreateMap produces. It can take a reference, as I've suggested doRoom must take.
There is one other minor problem. The main loop above has no means of escape. There is no way to end the game. map.doRoom( player ) should probably return a bool, and perhaps if a false is returned, break the loop.

Related

Box2D Collision Issues

Very new at Box2D, would appreciate help.
I've got a simple function that takes in a b2World and b2Body*, where the body is supposed to fall until it collides with a ground box (already created in main())
The code is essentially as follows:
void snake::update(b2World world, b2Body* snake)
{
bool running = true;
Clock deltaClock;
Time deltaTime;
while (running)
{
deltaTime = deltaClock.getElapsedTime();
deltaClock.restart();
world.Step(deltaTime.asSeconds(), 6, 2);
position = snake->GetPosition();
char ch;
if (_kbhit())
{
ch = _getch();
if (ch == 'x')
{
running = false;
}
}
}
}
This code was originally implemented in main(), and it worked fine. However, when I tried to move it to its own function in a separate class, the collision no longer works... I've got no idea as to why, as it was literally copy/pasted, just changing around variable names to fit the parameters...
I've got no idea what's going wrong, and if you need any additional information, I'd be more than happy to provide.
Thanks in advance.
Basically the way you had your parameter set before you were passing the b2World object by value in your original function head.
void snake::update(b2World world, b2Body* snake)
This means you are creating a copy and if this copy is being modified, the original object that was passed to the function remains the same. With the & behind the type you are now passing the object by reference.
void snake::update(b2World& world, b2Body* snake)
This means there is no copy being created but instead the function works with the original object and thus, changes do affect it aswell.
So when you were using this loop before it was probably nested inside of your main function or whatever and could modify the original variable world which was declared in that scope. Now that you have moved it to a seperate function you have to tell the compiler you want to work with the original object.
Read more about passing by value and passing by reference here and here for example

why doesn't work the else-branch with the set()-method?

Link to my sketch:
http://www.openprocessing.org/sketch/377417
void check(ship s){
float d = dist(s.getX(),s.getY(),this.posx,this.posy);
if (d <= this.radius){
s.setSpeed(0.5);
}
if (d > this.radius){
s.setSpeed(2);
}
}
When i delete the second if-statement, the ship reduces its speed but don't accelerate when the distance is greater than the obstacle's radius.
Something's wrong with the set-method?
In the future, please provide an MCVE directly in your post instead of making us go to external websites. Also, please use standard naming conventions: classes should start with an upper-case letter. While you're at it, standard formatting (indent your code) would help too.
That being said, your problem is caused by this: think about how you're calling your check() function. You call it for every obstacle. Then you set the speed of the ship based on the distance from that obstacle.
The problem is, say you only have two obstacles. The first obstacle is colliding with the ship, so you set its speed to 0.5. Then you check the second obstacle, which isn't colliding with the ship, so you set its speed back up to 2. In other words, you're only ever changing the ship's speed based on the last obstacle in the loop.
If you take out the call to setSpeed(2), then of course your ship will never change speed back to 2.
You need to refactor your code so that you set the speed to 0.5 if the ship is colliding with any obstacle. It might look something like this:
boolean collides = false;
for(Obstacle o : obstacles){
if(o.collidesWith(ship)){
collides = true;
break;
}
}
if(collides){
ship.setSpeed(.5);
}
else{
ship.setSpeed(2);
}

Public variables of class not being preserved when altered in function c++

I've found a question sorta similar to this one, though put in a more complex way than I think I require (received a -2 for question score). Hopefully this will be easier to follow.
The general gist of things is the two classes involved are GUI and Player (I've had the same problem elsewhere with other classes, but if I can understand why this one isn't working, it should apply to the rest).
GUI includes "Player.h". The class Player has a public boolean variable 'hasBall'; When a 'Player' is passed into a function Pass() and the boolean value changed, it seems that it is only a temp object thus isn't updating the object being passed itself. See code below:
This works fine, boolean values for Plyr1A and Plyr2A (defined in Gui.h) are changed and preserved
Plyr1A.hasBall = false;
Plyr2A.hasBall = true;
However boolean values for Plyr1A and Plyr2A remain the same with this.
Pass(Plyr1A,Plyr2A); //Boolean values for Plyr1A and Plyr2A remain the same with this.
void GUI::Pass(Player passer, Player receiver) {
passer.hasBall = false;
receiver.hasBall = true;
}
If anyone could explain to me why this occurs I'd be rather thankful! If there is any extra information needed please let me know.
Cheers :)
Your function makes a copy of the arguments (they are passed by value), then changes the copy, not the "original" objects(in the body of the function).
You should change it to take pointers or references, for example:
//-------------------v---------------v <---these are references
void GUI::Pass(Player& passer, Player& receiver) {
Of course, you should change the declaration, too.
Use references to pass your objects.
Consider this function:
void someFunction (int j)
{
j = 8;
}
And say we call it like this:
someFunction (3);
Are you thinking the assignment in someFunction somehow makes that 3 become an 8? Your expectation makes no sense. Without some kind of special arrangement, it cannot be that an assignment inside a function changes values in the caller.

C++ segfault at the end of a for loop

This code is segfaulting and I can't really figure out why. When I use gdb it segfaults at the end of the function (the curly brace). So that doesn't really give me a lot of information as to what's going on. Here's the code, I'll provide extra info if needed.
typedef std::list<Ground> l_Ground;
void Player::y_collisions(l_Ground grounds) {
for (l_Ground::const_iterator ent = grounds.begin(); ent != grounds.end(); ent++) {
if (getGlobalBounds().intersects(ent->getGlobalBounds())) {
in_air = false;
velocity -= gravity;
}
}
}
EDIT: Upon closer inspection, it's probably segfaulting at the end of that for loop. Which still doesn't really make sense because of the way the for loop is written. It shouldn't go beyond the end of the list.
EDIT2: This will work because of the answer below.
typedef std::list<Ground> l_Ground;
void Player::y_collisions(const l_Ground& grounds) {
for (l_Ground::const_iterator ent = grounds.begin(); ent != grounds.end(); ent++) {
if (getGlobalBounds().intersects(ent->getGlobalBounds())) {
in_air = false;
velocity -= gravity;
}
}
}
You were passing the grounds parameter by value. That means a copy of the list was made. Apparently your Ground class have a broken copy constructor, which makes the getGlobalBounds() method referring to some invalid pointer, which caused the crash.
You should almost never pass a big object by value unless you want to immediately copy it. Always train yourself to type const & all the time :).

Visual Studio Compiler is highlighting Static variables differently?

I'm programming in C++ and have a method which uses a static variable. The method isn't working as I think it should; upon investigation, I found that my static variable is being highlighted in red in two places and blue in other places. Below is the code:
int GameModeState::changeJob(int number)
{
static int job = 1; //red
if (number == 1)
{
job = (job+1); //First one is red, second one is blue
return job; //blue
} else {
return job; //blue
}
}
I'm calling this method with other methods, one shown for example:
int GameModeState::getJob()
{
int currentJob = (changeJob(2));
return currentJob;
}
I want a method like getJob() to simply return the current value of job, while another method, when calling changeJob(number) is changeJob(1), to increment job's value by one. (Hence the if/else statement in changeJob(number)).
Since the job variables are highlighted differently, I'm thinking the compiler is saying that it views the two separately somehow? I'm getting stuck with job being some even value.
EDIT I also have Awesomium... I believe that is the only addition to the compiler, but I'm not completely sure.
MOAR EDIT In another class, I have a method which should determine the current job's number and do something based on if the number is even or odd (since right now there are only two jobs)
void ZoneMovementState::_changeZone(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output)
{
//Awesomium::JSValue::Object object = input.getObject();
//String zoneFilename = Convert::toString(object[L"zoneFilename"].toString());
// If the number from getJob is even, the player is currently a geologist
if (GameModeState::getJob()%2 == 0)
{
ZoneParser::getSingleton().load("../media/zones/geology_zone.xml", false);
} else {
ZoneParser::getSingleton().load("../media/zones/farm_zone.xml", false);
}
transitionHandler->go();
}
Ignore the two commented out lines; they deal with JS, which I'm not working on for now.
In the program, I can access the farm_zone until I increment job's value using the below method in GameModeState:
void GameModeState::_openNotebook(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output)
{
mNotebookTransition->go();
static int currentJob = changeJob(1);
}
.... So I figured out my problem. While going through the code to show you guys, I realized that the static for currentJob was probably unneeded... once I removed it, my code works as it should now.
Thanks for the help guys!
Part of the problem here is you're using a static local for what very likely should just be a member variable. A static local maintains it's value across all calls to a function in all threads in a process. It's much more likely that you want it to persist for all calls to changeJob in a particular GameModeState instance (else why make it a member functon to begin with?).
To do this you'll need to define a member variable on GameModeState initialize it in the constructor and then access it in the method. For example
class GameModeState {
int job;
GameModeState() : job(1) {}
int changeJob(int number);
};
int GameModeState::changeJob(int number) {
if (number == 1) {
job = (job+1);
return job;
} else {
return job;
}
}
Note: I'm not entirely sure why you're seeing the color's your are seeing. Visual Studio by default won't color member variables a particular color in C++ so it's very likely another add-in you are using.
Nah, highlighting doesn't mean anything. That is, the editor doesn't call the compiler before deciding how/what/when to highlight. So that is not your problem. Sorry 'bout that :-)
You can prove this to yourself by going to Tools->Options->TextEditor and noticing that you can change the highlighting by choosing a different text-editing model.