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 - Disch

Pages: 1 2 3 [4] 5 6 ... 15
46
Graphics / Making a player change direction??
« on: September 12, 2011, 06:12:05 am »
Of course if you want to move the player to the clicked coords, you already have both beginning and endpoints, so you don't need angles.

The movement vector is newpoint - oldpoint.  So in this case, newpoint would be the place the user clicked, and oldpoint would be the player's current position.

You then want to translate that into a "unit vector", which is a just a vector with a length of 1.  You do this by dividing x and y by the length of the movement vector.

The length can be found with good old pythagorean's theroum:

Code: [Select]

c*c = a*a + b*b
// or in this case:
c = sqrt( a*a + b*b );


So... in review, all of the above can be accomplished simply:

Code: [Select]

Vector2f newpoint;  // the clicked position
Vector2f oldpoint;  // the player's current position

Vector2f motion = newpoint - oldpoint;  // the movement vector

float len = sqrt(motion.x * motion.x + motion.y * motion.y); // length of the movement vector

Vector2f unit = motion / len;

// that's it!  Now to move the player in that direction, you just apply the speed:

playerposition += unit * speed;

47
Quote
Point was, you can merge functions into one where applicable.


It's a maintenance thing.

My point was, there are things you can do with separate get/set functions that you can't do with an all-in-one get function.  The opposite is not true.

Hence, it limits your implementation.

If your particular implementation should happen to work into an all-in-one interface, then yeah you can combine it.

However, should the implementation need to change in the future (due to additional needs, or a change in overall design, or whatever), it might be difficult/impossible to keep the all-in-one function.  Which means you have an API break, which means you have to rewrite not only the class, but all code that uses it.

So yeah -- it's something to avoid.

Quote
you'll like the assignment operators.


As long as they make sense conceptually and aren't simply a way to avoid typing out a function name, then I'm fine with it  =P

Quote
Exceeding it's capacity (or changing it's size) is a resize.


But see, exceeding it's capacity or changing it's size are two different things, which I'm not sure you're grasping.

A vector may only have 10 elements in it, but will have space allocated for 20.  (ie:  a size of 10, a capacity of 20).

You can add and remove any number of elements to the end of that vector without needing any reallocation, until you exceed 20 elements, at which point, the capacity needs to be increased and the memory reallocated.

See std::vector::reserve and std::vector::capacity.  They're different from std::vector::resize and std::vector::size.

Quote
Aside from a hat-tip to realloc,


realloc causes complex types to explode, hence why it can't be used in such a class unless you limit that class to contain POD types only.

Quote
my point is it needs to copy less frequently rather than not at all. Latter statement is true, but classes shouldn't have the capacity to be used wrongly.


vector actually makes an effort to "guess" as to how much capacity you need in anticipation of future growth.  Yeah, it will get it wrong a lot, but it's pretty much impossible to get it right all the time (or even a high percentage of the time).

As for being able to use a class wrongly -- that's where the performance-vs-safety issue comes in.  Although in this case we're not really talking about using vector "wrong", just "inefficiently".

Quote
Optimisation usually requires you re-write the foundation code in the first place


I don't know about "usually".  Sometimes, yeah.

But we're not talking about ripping apart and reoptimizing an entire program, here.  We're talking about replacing one linked list with another.  They're both going to work more or less the same way, so really there's no reason why they couldn't/shouldn't be interchangable.

Quote
I find it better to optimise first. More specifically, write short example code to test assumptions, if assumptions wrong, update, if assumptions correct, expand, clarify, incorporate.


I find that optimizing is a very small part of the actual work I do on a project.

I keep it in mind when designing to avoid doing things that are obviously slow or wasteful, but other than that I just run with it.  Running into performance issues that actually needed to be seriously addressed afterward is actually quite rare.  C++ is fast.

Quote
Bear in mind I type like a zoned out monkey when it comes to code.


I guess I just assumed everyone is as occupied with real life as I am sometimes.  =P


Quote
Actually, combining both gives you the best of both worlds, fast insertion, with random access [snip]

it's more intended you add a load of items, access them at random, do some work, access it at random, then add more items, repeat.


I guess I'm just having a hard time seeing how this would be useful.  Your example at the end of your post didn't make a lot of sense to me.  Why would you need to access images randomly?

48
General discussions / The new graphics API in SFML 2
« on: September 12, 2011, 12:20:47 am »
I'm just thinking out loud here.  Take all of this with a grain of salt:


The SetTransform and SetView thing seems a little awkward to me.  Views and Transforms seem to be very similar things.  Functionally, there isn't much that separates them, other than that a View does everything in the opposing direction.

sf::View could just be a specialized sf::Transform (inherited) which simply inverts all operations.

Then, you can remove SetView completely, and instead of an interface where you have only one view and only one transform active at any time, you allow a way to "stack" any number of transformations.

Older OpenGL did this with glPushMatrix and glPopMatrix.  I'm envisioning something similar.

The only way I can think of to do this though would make the interface awkward, though.  I don't think the user should be responsible for pushing/popping transformations and keeping track of how many are pushed.

It also makes moving the view more difficult because you have to pop all transformations, change the view, then push them all back.  You can't just set a new view as you could before.



---

Maybe that could all be avoided if you keep SetView and SetTransform, but allow ways for transformations to be stacked internally.  This would offer more or less the same functionality, but would keep the interface simpler.

You said sf::Transform was basically just a wrapper around a 3x3 matrix, right?  So then it could be as simple as overloading the * operator:

Code: [Select]

sf::Transform bos = target.GetTransform();
sf::Transform tos = bos * some_other_transformation;
target.SetTransform(tos);
target.Draw(whatever); // both 'bos' and 'some_other_transformation' applied
target.SetTransform(bos);  // effectively "popping" the stack

// from here, only 'bos' applied




again just thinking out loud....

49
I'm actually starting to wonder why you'd even need to call size() frequently enough for it to be a performance issue.  The only times I can see needing it are for serialization or output to the user -- neither of which would be timing critical.

50
Quote from: "Joshua Flynn"
I don't see how that restricts the implementation,


It forces you to have an int that's always accessable via a reference, which may not be possible if the int is part of another object.

It also prevents you from monitoring writes to that int -- to check for boundary checks, illegal writes, or make other internal state changes depending on the data written.

Quote
O(n) is worst-case and O(1) is best case, compared to my own class which is O(1) worst-case and O(1) best case.


Fine fine.  I'll concede on this point since you're clearly dedicated to it.  Whether or not it's a good idea is still questionable in my mind.

Really the major reason for my interjection in this thread was your ill-advised operator abuse.

Quote
Point is, if vector (as a std) does scary inefficient stuff like that


I assume you're talking about copying on resize.

vector guarantees contiguous memory allocation.  That's the whole point.  It's fast random access.  There's no way to keep it all contiguous in memory if you don't move everything when you run out of space.

It's not inefficient if you use it right.

Quote
iterator can hop out of bounds


Iterators are thin layers over pointers.  Just as you can have a bad pointer (or a bad index), you can have a bad iterator.  std doesn't double-check every access because that would make it too slow for practical use.  They opt for speed over safety.

Quote
and list has an inconsistent O() for size, they don't leave a good impression.


Don't take this the wrong way, but I think you're just in a funk where you want to build a better mouse trap.  I've been there before.  It's easy to find fault in existing implementations and think you can do better.  But when you consider how rubust and flexible the standard container classes are, the performance and elegance they offer is surprisingly high.  They're very reusable.

Does that make them perfect for every task?  No.  Do you have to go with your own implementation sometimes?  Yes, although it's quite rare.  Is this particular instance one of those times where you'd have to go with your own implementation?  I doubt it, but it's your call.

One of the advantages to using existing libs is that you can build your program on the backs of other people's foundations.  This makes it easier to write "programs" rather than writing "code".

That's besides the point that you're trying to optimize before you have anything written.  Optimizing one area of the program won't matter if the bottleneck is elsewhere.  Get it working first, optimize later.  Like I say, if it turns out std::list is no good, you can drop in your own class at any time in the future.  All you'd have to do is change a typedef.  And if it turns out that std::list works fine, you just saved yourself a good month of wasted time and effort.

Quote
Class with vector (of pointers), list. Items add to list, set vector size to match list size, populate vector with addresses of list items on operator[] call if the vector is not same as list size.


What's the point of having the list if you have a vector?  They're contradictory storage containers.

vector has slow insertion and fast random access
list has fast insertion and no random access.

combining both gives you the worst of both worlds.  You can't access the list randomly and you can't insert/remove items in the vector quickly.

Maybe I'm missing the point here.

Quote
[vector] Recopying on every resize.


It doesn't.  It recopies when you exceed its capacity.  The capacity can be preset with a call to reserve.

51
Quote
Which is bad, consider:

int &Int(){return *Ptr;} //Does both of the above functions whilst not permitting the user to alter the pointer itself


Well that restricts your implementation, which is why it's not typically done that way.  With the 'return a reference' approach you have to have a int that can be get/set without supervision in your implementation, which might not always be optimal.

Quote
Non O(1) size returns. Which is pretty bad for something 'extensively' tested. Why does a novice coder like myself need to supply that?


Again... have you profiled this?  Or are you just making assumptions?

All the documentation I've seen says it's implementation dependent, and I would be quite surprised if such a commonly used function wasn't well optimized.

Your issue might be moot.  I'd really recommend you at least test it before you do all this work to solve a problem that might not even exist in the first place.

Quote
And, I don't know how it works on the lowest level.


You don't need to, that's kind of the point.  ;P

Quote
It could do something scary like std::vector (which is to recopy everything everytime it runs out of space... which defeats the point of being dynamic).


It's a linked list.  So it doesn't do that (no linked list implementation would).  You're right, that would defeat the entire point.

Again -- instead of just assuming list will give you a performance bottleneck, you should use it and see if it really does.  If it does, you can swap in your own class later without having to rewrite anything in your code (except a single typedef).

Quote
Std::vector could easily be combined with a list to make it so it doesn't recopy anything until the array itself is called (then it keeps a hard copy until the list is modified).


That wouldn't be easy.  That would drastically change the overall structure of the class and turn it into a mess.  vector is already complicated enough without being a weird hybrid mash.

Quote
And you can actually do something even more clever. AN array of pointers that point to the individual list items so modification to the array == modification to the list.


If this is what you are after, then writing your own class would be a reasonable thing to do, since it is not offered in any of the standard classes.  I was under the impression you just wanted a linked list.

But of course there are performance tradeoffs with this as well.  Inserting elements in a list is no longer O(1), there's a higher memory footprint, etc, etc.

Quote
The std library is that many years out of date (see vector complaints above)


I didn't see any vector complaints?  (EDIT:  other than the "combine it with a list" thing, but I think that's crazy  /EDIT)

Quote
It's fairly easy to be stable when you don't do much to rock the boat.


You just discovered the golden rule of programming.  KISS:  Keep it simple, stupid.

Overcomplication is a bane of many programmers and programs.  You'll find that out in time.  ;P

Quote
How exactly can an iterator be 'less consistent'?


When you insert an elements in a std::list, existing iterators remain valid.

When you insert an element in a std::deque or std::vector, they don't (since memory may have needed to be shifted around)

That's all it means.  Don't freak out  =P

Quote
Given that doubly linked nodes can be allocated anywhere, chances are Iterator + 3 might run outside of scope and find itself a nice segfault.
To demonstrate.


All of those posts on google are people misusing the class.  Of course if you don't know what you're doing you will run into problems.

You can make the effort to write a fool-proof container class that guards against every possible invalid access, but its performance will suck.  std figures performance is more important for practical applications.

Quote
I gain bonus points by building my own lists because I can optimise them on all ends of the scope and learn as I go along.


Well in the end if you do decide to reinvent the wheel, I hope you at least run some tests to compare its performance with std container classes.  You might be surprised at the result -- std performs quite well.

Quote
Consider <<. Bitwise shift or piping data?


I agree that the << and >> overloads of iostream were a big mistake.  Ambiguity aside, they also cause thread safety issues.

But just because std made that mistake doesn't mean it's OK to repeat it.

Remember that operator overloads are not there to reduce typing, they're there to make the code more clear.  If what you want them to do isn't intuitive, it shouldn't be there (and judging by the multiple responses you got in this thread, I would say it's not intuitive).

52
That's interesting.  I hadn't even thought about splice.

I would think the best way to handle that would be to invalidate the size after a splice, and only recalculate it if needed.  That way you can get O(1) for both, except the first time you call size() after a splice operation, which is the only time it would take O(n):

Code: [Select]

class list
{
//...
private:
  mutable size_t listsize;
  mutable bool sizevalid;

//...
void splice(...)
{
  //...
  sizevalid = false;
}

//...
size_t size() const
{
  if(!sizevalid)
  {
    recalcsize();
    sizevalid = true;
  }
  return listsize;
}
//...
};


I wonder if any implementations do it like that.

53
Even if that's the case, you can just store the size of the list separately.  To redo the entire class from scratch for such a minor detail is excessive.

54
Quote from: "Joshua Flynn"
Std::list requires log(n) time to get the size of the list,


How do you figure that?  All it has to do is store the size of the list internally (which I'm reasonably sure it does) and it gets O(1).

I don't even see how it could get O(log(n))

Quote
Custom-lists also gain the advantage of improving over iteration(IE design and improvement)


I don't follow.  How can you improve upon linked list iteration?

Quote
fewer functions


So you basically want to make a list that does less.

Call me crazy, but that's a shortcoming, not an advantage.

Quote
more capability


What is std::list incapable of?

Quote
stability.


So you plan to write a linked list that's more stable than the one that's been around for several years and has been extensively used and tested by virtually every C++ programmer in the world.



I don't mean to sound negative.  It's just that this seems like a fool's errand to me.  Unless it's purely for academic/educational reasons, there's really no good reason to reinvent the wheel like this.  It just seems like a massive waste of time, and will confuse/annoy any people who use your code in the future.


EDIT:

Quote
These are generally the ideas I had for the list. Iteration across the list was the other alternative


Again, the mere fact that there are multiple possibilities of what the operators could be doing is a pretty clear indication to me that they should not be overloaded.

55
None of those operators make any sense.

How can you increment a list?  How can you assign an entire list to one item?

The closest thing I can imagine would be that !TemplateList would check to see if the list is empty, but even that is "blech".

EDIT:
Don't get cute with operator overloading.  The reason it exists is to make code more natural, not to avoid typing function names.  If you have to ask the question "what should this operator do or return", then you shouldn't be making that operator.  It defeats the point and makes your code more confusing.
/EDIT

Any reason why you don't want to just use std::list?


EDIT 2:

Quote
if you make it a += its a perfectly acceptable "Append"


I disagree that that's perfectly acceptable  =P

56
General discussions / A new logo for SFML
« on: September 03, 2011, 07:29:17 am »
I haven't really been keeping up with the thread...

but I agree, that gear splash is really hot.  A still of it would work well for a static logo on the site/forums (you wouldn't want an animating logo).

Seems like it would work well on any backdrop color, too.

Very nice indeed.  It has my vote for the new logo (if that counts for anything)

57
Graphics / Kerning, Convert 'char' to 'sf::Uint32' etc.
« on: September 03, 2011, 07:15:09 am »
Quote
Am i doing the types around string and sf::Uint32 wrong?


Depends on how your string is encoded.

It looks like all you're doing is promoting it, which will work for ASCII but will fail for pretty much anything else.

58
General / Direction Working out
« on: August 30, 2011, 07:04:20 am »
Can you be more descriptive?

The center of the thing not being the center of the other thing?  I can't follow you.  What are the things, and what are they doing that you want to change?

59
Graphics / Removing a Sprite Completely
« on: August 23, 2011, 08:43:40 pm »
Quote
I have a variable keeping track if the sprite has been collected. I draw the sprite on screen only if the sprite is not collected. I check collision with the sprite and if it collided then I set the variable flag as true and the sprite is not drawn on screen


From what you describe, this should work.  If the variable indicates the object no longer exists, then it wont' exist.  The only way it can come back is if you change that variable to bring it back.

I'd need to see some code in order to spot the actual problem.

60
General discussions / [IDEA] Move sf::Rect into System Module?
« on: August 23, 2011, 05:26:00 am »
I understand Laurent's hesitation.  It isn't as cut and dry as it may seem.

Sure Rect might seem strange in the Graphics module.  But really, when you think about it, is it any less strange than the System module?  What does Rect have to do with the system?  At least in the Graphics module it has applications.

To me, the real question is, how are these modules defined?  I get the impression that people here have the idea that the System module is sort of like a catch-all for the classes that don't fit anywhere else.  But is that really the intent?

Perhaps a solution here is to introduce another module for one-off classes that don't fit anywhere else, like the Vectors, Rect, etc.  But that's probably more trouble than it's worth.

Pages: 1 2 3 [4] 5 6 ... 15
anything