Welcome, Guest. Please login or register. Did you miss your activation email?

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Lee R

Pages: 1 2 [3] 4 5 6
31
Quote from: Nexus
The postcondition of the function is that it yields a unit vector, thus the caller expects the result to have length 1. When a zero vector is passed, this is impossible to achieve. Since the expectation cannot be met in any circumstances, the argument passed to unitVector() must be wrong.

So yes, crashing the application is the best way to immediately find the bug. Ignoring it will only let the error propagate and show up later, where it is much more difficult to find. I'm aware that there may be situations where one would really want a zero vector back; but in my opinion these cases are rare and should be handled explicitly by the user. The nice side effect of assert is that no performance is wasted to deal with situations that do not occur in correct code.

Actually, we're both I'm talking nonsense. These are floating point values, so assuming an IEEE 754 complaint environment, your implementation will simply return infinite in the zero vector case. Sorry to break the bad news. :P

Quote from: Nexus
And I don't think there is any ambiguity concerning where to place the assert. [...]

Well yes, clearly. I didn't mean debug assertions though. Anyway, this hardly seems like the appropriate thread to continue this discussion.

EDIT: It seems that I may have misunderstood your position. Obviously debug assertions should immediately halt the program.

32
You could of course use an assert in the implementation I provided, should you feel it necessary. The choice between the two implementations then comes down to where you think the error check should happen, and in the case of an error, should it be considered fatal (i.e. do we really want to crash the entire application rather than returning a zero vector?).

I agree that the name 'normalize' does seem to imply a mutation.

33
Quote from: magneonx
Ah I see, it seems that if I set to false, I can put my sprite everywhere and I can make my sprite move and that it is guided by the tile path? For short, I can make my sprite move not tile to tile but only relative to it?

Exactly.

Quote from: magneonx
I also have question, how do you imperatively define length()? Is that subtracting the current position to target position to get the remaining distance?

Length is defined as the magnitude of a vector (as Nexus has already taught us :P). It can be used to calculate the distance between two vectors in exactly the way you describe (i.e. 'distance = length(b - a);' where 'a' and 'b' are vectors) The C++ incantation goes thusly:

template<typename T>
inline T length(const sf::Vector2<T>& v)
{
        return std::sqrt(v.x * v.x + v.y * v.y);
}
 

The normalize function is then as follows:
template<typename T>
inline sf::Vector2<T> normalize(const sf::Vector2<T>& v)
{
    const T len = length(v);
    T invLen = T(1);

    if (len != T(0))
    {
        invLen /= len;
    }

        return sf::Vector2<T>(v.x * invLen, v.y * invLen);
}
 

34
Yes, that is how it decides in which direction the sprite should move. It also restricts the sprite's movement to up, down, left and right. If moving up, the direction vector will be [0.0f, -1.0f], or [0.0f, 1.0f] if down, [-1.0f, 0.0f] if left or [1.0f, 0.0f] if right. Therefore, only one axis of the direction vector will affect movement. Consider:

Speed = 10
Direction = [1.0f, 0.0f] = right
Movement = Direction * Speed = [1.0 * 10, 0.0 * 10] = [10.0f, 0.0f] = move right 10 units.

EDIT: Just to be clear, the code I provided will calculate the direction of movement on it's own. The 'lockAxis' parameter simply specifies whether to allow arbitrary movement in any direction (when lockAxis = false), or to restrict movement such that it will only choose to move up, down, left or right (when lockAxis = true).

35
Unfortunately, I think it is still quite hard to decipher what you are actually asking for. 'what I want is to move the sprite tile by tile' is not very descriptive.

You said earlier that the code provided Ixrec is "what I wanted". I note that his code contains several bugs; for instance, when checking the major axis, the absolute value of each axis should be taken. Also, his approach is not exempt from normalization, which in 1D amounts to taking the sign of the major axis.

Here is an attempt to resolve said bugs (although it may well contain several new bugs, because we have no way of testing against your codebase. Also because I couldn't resist flattening your control flow :P). I have introduced a new parameter, 'axisLocked', which when true will lock movement to the current major axis as in Ixrec's code, otherwise it will allow arbitrary movement, as in your original code.

void PathFinder::moveToDestination( float dt, bool axisLocked = false )
{
    if ( !_isPathFound ) {
        return;
    }

    if ( (c + 1) < path.size() ) {
        spriteNextTile = path[c + 1];
    }

    const float tilesize = static_cast<float>( tileset->getTilesize() );

    targetPosition.x = spriteNextTile->getTileGridPositionX() * tilesize;
    targetPosition.y = spriteNextTile->getTileGridPositionY() * tilesize;

    spritePosition.x = movableObjects->getSpritePositionX();
    spritePosition.y = movableObjects->getSpritePositionY();

    delta = targetPosition - spritePosition;

    // distance considered 'close enough' to target position.
    const float tolerance = 1.0f;

    // actual distance to target position.
    const float distance = length( delta );

    // amount of movement this time step.
    const float displacement = movableObjects->getVelocity() * dt;

    // direction of movement.
    sf::Vector2f direction( 0.0f, 0.0f );

    if ( axisLocked )
    {
        // movment restricted to major axis.
        if( std::abs(delta.x) > std::abs(delta.y) )
        {
            // horizontal movement.
            direction.x = (delta.x < 0.0f) ? -1.0f : 1.0f;
        }
        else
        {
            // vertical movement.
            direction.y = (delta.y < 0.0f) ? -1.0f : 1.0f;
        }
    }
    else
    {
        // movement in arbitrary direction.
        direction = normalize( delta );
    }

    if ( distance <= tolerance || distance <= displacement )
    {
        // target position reached.
        spritePosition = targetPosition;
        if ( ++c >= path.size() - 1 )
        {
            // end of path reached.
            _isPathFound = false;
            c = 0;
            reset();
        }
    }
    else
    {
        // advance towards target position.
        spritePosition += direction * displacement;
    }

    movableObjects->setSpritePosition( spritePosition.x, spritePosition.y );
}
 

Really though, this is no better than looking into a crystal ball. I could well be that you have competing forces which need resolving, or any other number of possibilities. AI code is notoriously fiddly, often leading straight to tweakers hell.

36
Graphics / Re: function that returns a 2d array of sprites
« on: August 12, 2013, 08:58:18 am »
I can assure you that I have no such misunderstanding. You seem to have completely ignored my carefully chosen wording. There is a difference between the address of an array in memory, and an array type (i.e. T[N]). An array T[N] /cannot/ appear as the return type of a function, thus the post I responded to was not /sufficient/ to answer the OP's question.

37
Graphics / Re: function that returns a 2d array of sprites
« on: August 11, 2013, 01:08:04 am »
Like any array.

It's hard to imagine why you thought that to be a sufficient answer to the OP's questions, given that an array cannot appear as the return type of a function in C++.

38
Graphics / Re: How to fix white square problem when used vectors?
« on: August 11, 2013, 12:30:55 am »
You need to define both a copy constructor and copy assignment operator for the 'Player' class which sets the sprite's texture to that instance's internal copy (e.g. 'sprPlayer.setTexture(texturePlayer);').

39
System / Re: creating a spin-down timer
« on: May 02, 2013, 12:00:29 am »
In the most general sense, what you're trying to describe is called "interpolation". The 'quadratic ease out' equation fits with the "slowing down" behaviour you're after.

http://gizma.com/easing/#quad2

Unfortunately, frame based animations tend to look like poop when you slow them down, because they cannot generate frames-between-frames. This is the raison d'ĂȘtre for inbetweening, aka tweening.

40
SFML projects / Re: Thor 2.0
« on: May 01, 2013, 04:50:55 pm »
Check this snippet, taken from 'ParticleSystem::computeVertices':

// Fill vertex array
AURORA_FOREACH(const Particle& p, mParticles)
{
    for (unsigned int i = 0; i < 4; ++i)
    {
        sf::Transform transform;
        transform.translate(p.position);
        transform.rotate(p.rotation);
        transform.scale(p.scale);

        mVertices.append( sf::Vertex(transform.transformPoint(positionOffsets[i]), p.color, texCoords[i]) );
    }
}

There is no need to re-construct the transform for each iteration of the inner loop. I'm guessing this is a refactoring artifact?

41
Ah yes I see what you mean now.

However, one of my goals was to avoid writing a rigorous treatise on proper measurement techniques. There are a number of articles already on the web dealing with the subject in much more detail than I could ever manage. But, you are free to edit the article with that kind of information if you think it would benefit people :P

EDIT:
Having thought about it some more, I think it would be nice to provide some kind of ScopedSample class. Again though, I really don't want to be in the business of explaining object lifetime and scoping rules in C++.

42
Quote from: eXpl0it3r
Well then, I've fixed it for you. [...]
I've updated the link in my OP. Thanks :)

Quote from: eXpl0it3r
You might warn people though, that the part that happens outside of the begin/end block is not recorded. ;)

Sorry but I'm having a hard time seeing the ambiguity. Are the words 'begin' and 'end' really not explicit enough? Also, I explicitly define a unit of measure in the article:
Quote from: FrameClock
The time elapsed during the last sampled frame (i.e. between a beginFrame/endFrame pair) can be obtained with the member function getLastFrameTime.

The only way I can imagine this coming to someone's mind, is if they had not read the article and instead went straight to the source code, had a quick look at the implementation of 'FrameClock::endFrame', and being confused by the absence of code to reset the internal timer. But then it's just a case of Read the Fine Manual :P

43
I'll have a look into the link thing at some point.

As for your second point, I actually considered adding a 'design rationale' section in the article to explain exactly that. The short answer is that splitting the update into two separate 'begin/end' functions allows the class to be more general, i.e. can more easily be used outside of loop contexts, or to measure just a fraction of some code inside a loop.

44
Hi,

I've made my first contribution to the SFML wiki by adding the source code of a class designed to track various frame time statistics, such as:

    * total number of frames;
    * total frame time;
    * current frame time;
    * shortest measured frame time;
    * longest measured frame time;
    * average frame time over a user specified number of frames (called sample depth);
    * frames per second;
    * lowest measured frames per second;
    * highest measured frames per second, and;
    * average frames per second over a user specified number of frames (called sample depth).

Full details at the link below:
https://github.com/SFML/SFML/wiki/Source:-FrameClock

Thanks,
Lee.

45
General discussions / Do you use C++11?
« on: March 18, 2012, 08:24:05 am »
Quote from: "eXpl0it3r"
[...] If it's something else like lambdas which is only supported by MSVC++ 2011 [...].

http://msdn.microsoft.com/en-us/library/dd293608.aspx

Ahem...

Pages: 1 2 [3] 4 5 6
anything