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);
}
Related
Im trying to follow along and break down a the source code for a pacman clone. There is an if statement that im confused about.
void PacMan::queueDirection(Direction dir)
{
if (!directions.empty())
{
if (dir == -directions.front()) //this statement
{
std::queue<Direction> clear;
std::swap(directions, clear);
}
}
if(directions.size() < 2)
directions.push(dir);
}
My question is what does the - infront of -directions.front() do? directions is a queue. Does it multiply the reference returned by front() by -1?
Thanks for the help - ill post a link below to the github where the whole project is.
https://github.com/HexagonNico/Pac-Man/blob/master/PacMan.cpp if that tickles your fancy.
The code you have pasted seems to have the following intent:
In case the Direction instance at the head of the queue, directions, is a negative of the value supplied as the argument of this function, the queue is cleared and the supplied argument is enqueued.
The type Direction in this case is an enum as defined in the header Directions.h
enum Direction
{
Up = 1,
Down = -1,
Left = 2,
Right = -2,
Unset = 0
};
Negating a Direction instance, in this case, just gives us its diametric opposite.
As an example, consider that the value Direction::Up is at the head of the queue at the time the function is invoked and the argument to the function is Direction::Down. In this case the queue directions will be cleared. I have added an example to make this point clearer.
I asked a question about this project previously (this isn't the same problem), but I'm working on a imitation of Space Invaders for an assignment. I have almost everything working, but I'm having problems with the bullet-alien interaction. I'm new to lists, so I apologize if it's an obvious problem. :)
I have a function for making the aliens disappear when they intersect with the bullets, but when the bullet kills two of them, or if the bullet flies past them and disappears, the program gets stuck in an infinite loop (outer loop).
This is the function involved :
(if you need to see anything from the other classes, I can add those too)
void alienGroupMgr::disappear(shotMgr m)
{
// shotMgr is just a class that manages the bullet data (vector of ptrs to bullets)
// getSprite returns data about individual sprites
for (list<alien*>::iterator iter = theGang.begin();iter != theGang.end();) // each alien
{
alien* ptrShot = *iter;
FloatRect alienBound = ptrShot->getSprite().getGlobalBounds();
// theGang is a list of ptrs to aliens from the alien group mgr class
// alien is a class for each alien
for (int i = 0; i < m.getAmountFilled(); i++) // each bullet
{ // getlist returns an index from the vector of bullet ptrs
FloatRect bulletBound = m.getList(i)->getSprite().getGlobalBounds();
if (alienBound.intersects(bulletBound))
{
iter = theGang.erase(iter);
}
else
{
iter++;
}
}
}
}
I tested a version of the function where I limited the outer loop to 9 times through using a counter. It works half of the time and the other half, it gives an error that says 'Expression : cannot increment end list iterator'.
I would really appreciate some advice! Thanks.
It seems strange that you have that iter++ line inside the inner loop.
For example, think about the case when no bullet intersects with any alien. Then I guess you want the code to go through all the combinations, but that will not happen because you have the iter++ line happening each time there was no intersection.
I would suggest that instead of removing from theGang inside the inner loop, use a bool variable that is false before the inner loop and that you set to true if you find an intersection with any bullet. Then, after the inner loop, you check the bool variable to see if you should remove the alien. Then it becomes easier to see what the code is doing: first check if the alien is hit by any bullet, then remove the alien if it was hit.
I have looked into this, but it's not what I wanted: Convert string to variable name or variable type
I have code that reads an ini file, stores data in a QHash table, and checks the values of the hash key, (see below) if a value is "1" it's added to World.
Code Examples:
World theWorld;
AgentMove AgentMovement(&theWorld);
if(rules.value("AgentMovement") == "1")
theWorld.addRule(&AgentMovement);
INI file:
AgentMovement=1
What I want to do is, dynamically read from the INI file and set a reference to a hard coded variable.
for(int j = 0; j < ck.size(); j++)
if(rules.value(ck[j]) == "1")
theWorld.addRule("&" + ck[j]);
^
= &AgentMovement
How would you make a string into a reference as noted above?
This is a common theme in programming: A value which can only be one of a set (could be an enum, one of a finite set of ints, or a set of possible string values, or even a number of buttons in a GUI) is used as a criteria to perform some kind of action. The simplistic approach is to use a switch (for atomic types) or an if/else chain for complex types. That is what you are currently doing, and there is nothing wrong with it as such:
if(rules.value(ck[j]) == "1") theWorld.addRule(&AgentMovement);
else if(rules.value(ck[j]) == "2") theWorld.addRule(&AgentEat);
else if(rules.value(ck[j]) == "3") theWorld.addRule(&AgentSleep);
// etc.
else error("internal error: weird rules value %s\n", rules.value(ck[j]));
The main advantages of this pattern are in my experience that it is crystal clear: anybody, including you in a year, understands immediately what's going on and can see immediately which criteria leads to which action. It is also trivial to debug which can be a surprising advantage: You can break at a specific action, and only at that action.
The main disadvantage is maintainability. If the same criteria (enum or whatever) is used to switch between different things in various places, all these places have to be maintained, for example when a new enum value is added. An action may come with a sound, an icon, a state change, a log message, and so on. If these do not happen at the same time (in the same switch), you'll end up switching multiple times over the action enum (or if/then/else over the string values). In that case it's better to bundle all information connected to an action in a data structure and put the structures in a map/hash table with the actions as keys. All the switches collapse to single calls. The compile-time initialization of such a map could look like this:
struct ActionDataT { Rule rule; Icon icon; Sound sound; };
map<string, AcionDataT> actionMap
= {
{"1", {AgentMovement, moveIcon, moveSound} }
{"2", {AgentEat, eatIcon, eatSound } } ,
//
};
The usage would be like
for(int j = 0; j < ck.size(); j++)
theWorld.addRule(actionMap[rules.value(ck[j])].rule);
And elsewhere, for example:
if(actionFinished(action)) removeIcon(actionMap[action].icon);
This is fairly elegant. It demonstrates two principles of software design: 1. "All problems in computer science can be solved by another level of indirection" (David Wheeler), and 2. There is often a choice between more data or more code. The simplistic approach is code-oriented, the map approach is data oriented.
The data-centrist approach is indispensable if switches occur in more than one situation, because coding them out each time would be a maintenance nightmare.
Note that with the data-centrist approach none of the places where an action is used has to be touched when a new action is added. This is essential. The mechanism resembles (in principle and implementation, actually) the call of a virtual member function. The calling code doesn't know and isn't really interested in what is actually done. Responsibility is transferred to the object. The calling code may perform actions later in the life cycle of a program which didn't exist when it was written. By contrast, compare it to a program with many explicit switches where every single use must be examined when an action is added.
The indirection involved in the data-centrist approach is its disadvantage though, and the only problem which cannot be solved by another level of indirection, as Wheeler remarked. The code becomes more abstract and hence less obvious and harder to debug.
You have to provide the mapping from the names to the object by yourself. I would wrap it into a class, something like this:
template <typename T>
struct ObjectMap {
void addObject(std::string name,T* obj){
m[name] = obj;
}
T& getRef(std::string name) const {
auto x = m.find(name);
if (x != m.end() ) { return *(x->second);}
else { return dummy; }
}
private:
std::map<std::string,T*> m;
T dummy;
}
The problem with this approach is that you have to decide what to do if an object is requested that is actually not in the map. A reference always has to reference something (in contrast to a pointer that can be 0). I decided to return the reference to a dummy object. However, you might want to consider to use pointers instead of references. Another option might be to throw an error in case the object is not in the map.
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.
I'm building a simple generic engine for my true start in the making of games, and I am trying to be somehow organized and decent in the making of my engine, meaning I don't want it to be something I throw to the side once I make what I'm planning to.
I add objects to be displayed, drawObjects, and these can either move, not move, and have an animation, or not have one.
In case they DO have an animation, I want to initialize a single animationSet, and this animationSet will have xxx animationComp inside of it. As I'm trying to be neat and have worked abit on "optimizations" towards memory and cpu usage (such as sharing already-loaded image pointers, and whatever came across my mind), I wanted to not ask for possibly unused memory in arrays.
So I had animationSetS* animationSet = NULL; initially, planning to do a animationSet = animationSetS[spacesINEED]; after, only on the objects that needed animation that I added, being those that aren't animations a NULL and therefore not using memory (correct?).
And then this question popped up! (title)
struct animationComp {
SDL_Rect* clip;
int clipsize;
};
struct animationSetS {
animationComp* animation;
int currentFrame;
int currentAnimation;
int animationNumber;
};
struct drawObject { // Um objecto.
char* name;
SDL_Surface* surface;
bool draw = true;
float xPos;
float yPos;
bool willMove = false; // 0 - Won't move, 10 - Moves alot, TO IMPLEMENT
bool isSprite = false;
animationSetS* animationSet;
};
I dabble alot in my questions, sorry for that. For any clarifications reply here, I'll reply within 10 minutes for the next... 1 hour perhaps? Or more.
Thanks!
Setting the pointer to NULL means that you'll be able to add ASSERT(ptr != NULL); and KNOW that your pointer does not accidentally contain some rubbish value from whatever happens to be in the memory it was using.
So, if for some reason, you end up using the object before it's been properly set up, you can detect it.
It also helps if you sometimes don't use a field, you can still call delete stuff; [assuming it's allocated in the first place].
Note that leaving a variable uninitialized means that it can have ANY value within it's valid range [and for some types, outside the valid range - e.g. pointers and floating point values can be "values that are not allowed by the processor"]. This means that it's impossible to "tell" within the code if it has been initialized or not - but things will go horribly wrong if you don't initialize things!
If this should be really implemented in C++ (as you write), why don't you use the C++ Standard Library? Like
struct animationSetS {
std::vector< std::shared_ptr<animationComp> > animation;
// ...
}