![]() |
|
Vector |
Nakhash
Member #8,267
January 2007
![]() |
Does anyone here have a sample of code they used for data in thier game which uses Vectors? Yes, me and my Eglish teacher did not see eye to eye.
Nakhash If you like Dragon Warrior, then try out my trilogy at http://dragonwarriorreborn.com |
Mark Oates
Member #1,146
March 2001
![]() |
There's some really nice Vector code in Openlayer. You can download it here . Vec2D.hpp
1#ifndef OL_VEC2D_HPP
2#define OL_VEC2D_HPP
3
4#include <cmath>
5#include <string>
6#include <sstream>
7#include "General.hpp"
8#include "Declspec.hpp"
9
10
11namespace ol {
12
13
14
15class OL_LIB_DECLSPEC Vec2D {
16public:
17 float x, y;
18
19
20 // CONSTRUCTORS //
21
22 Vec2D( float x = 0.0, float y = 0.0 )
23 : x( x ), y( y ) {}
24
25
26 static inline Vec2D PolarCoords( float angle, float magnitude ) {
27 return Vec2D( magnitude * std::cos( angle ), magnitude * std::sin( angle ));
28 }
29
30
31 // METHODS //
32
33 inline float GetAngle() const {
34 return std::atan2( y, x );
35 }
36
37
38 inline float GetMagnitude() const {
39 return std::sqrt( GetMagnitudeSquared() );
40 }
41
42
43 inline float GetMagnitudeSquared() const {
44 return x * x + y * y;
45 }
46
47
48 inline Vec2D Normalized() const {
49 float magnitude = GetMagnitude();
50
51 return Vec2D( x / magnitude, y / magnitude );
52 }
53
54
55 // OPERATORS //
56
57
58 inline void operator += ( const Vec2D &other ) {
59 x += other.x; y += other.y;
60 }
61
62 inline void operator -= ( const Vec2D &other ) {
63 x -= other.x; y -= other.y;
64 }
65
66
67 inline void operator *= ( float factor ) {
68 x *= factor; y *= factor;
69 }
70
71
72 inline void operator /= ( float divisor ) {
73 x /= divisor; y /= divisor;
74 }
75
76 inline bool operator == ( const Vec2D &other ) const {
77 return fabs(x - other.x) < 0.01 && fabs(y - other.y) < 0.01;
78 }
79
80 inline bool operator != ( const Vec2D &other ) const {
81 return !(*this == other);
82 }
83
84 inline std::string ToString() const {
85 std::ostringstream str;
86 str << "( " << x << ", " << y << " )";
87 return str.str();
88 }
89
90 inline std::string GetString() const {
91 return ToString();
92 }
93};
94
95
96// ADDITION AND SUBTRACTION //
97
98inline Vec2D operator + ( Vec2D first, Vec2D second ) {
99 return Vec2D( first.x + second.x, first.y + second.y );
100}
101
102
103inline Vec2D operator - ( Vec2D first, Vec2D second ) {
104 return Vec2D( first.x - second.x, first.y - second.y );
105}
106
107
108// MULTIPLICATION AND DIVISION
109
110inline Vec2D operator * ( Vec2D vec, float factor ) {
111 return Vec2D( factor * vec.x, factor * vec.y );
112}
113
114
115inline Vec2D operator * ( float factor, Vec2D vec ) {
116 return Vec2D( factor * vec.x, factor * vec.y );
117}
118
119
120inline Vec2D operator / ( Vec2D vec, float divisor ) {
121 return Vec2D( vec.x / divisor, vec.y / divisor );
122}
123
124
125// DOT PRODUCT //
126
127inline float operator * ( Vec2D first, Vec2D second ) {
128 return first.x * second.x + first.y * second.y;
129}
130
131
132// SIGN //
133
134inline Vec2D operator - ( Vec2D vec ) {
135 return Vec2D( -vec.x, -vec.y );
136}
137
138
139// NORMALIZATION
140
141inline Vec2D operator ~ ( Vec2D vec ) {
142 return vec.Normalized();
143}
144
145
146// TESTS
147
148
149// Checks if the points are in counter clockwise order //
150
151inline OL_LIB_DECLSPEC bool IsCounterClockwise( const Vec2D first, const Vec2D second, const Vec2D third ) {
152 float dx1, dx2, dy1, dy2;
153
154 dx1 = second.x - first.x;
155 dy1 = second.y - first.y;
156 dx2 = third.x - second.x;
157 dy2 = third.y - second.y;
158
159 return dy1*dx2 < dy2*dx1;
160}
161
162
163}
164
165
166
167
168
169
170
171
172
173
174
175#endif
-- |
OnlineCop
Member #7,919
October 2006
![]() |
Nakhash
Member #8,267
January 2007
![]() |
I mean like, I use Structs to contain all of my Race data for each Castle in my game. Is it possiable to use Vector to store several ints? Nakhash If you like Dragon Warrior, then try out my trilogy at http://dragonwarriorreborn.com |
bamccaig
Member #7,536
July 2006
![]() |
1#include <iostream>
2#include <vector>
3
4int main(int argc, char * argv[])
5{
6 std::vector<int> v;
7
8 // One way to load it with data. Check a library reference for more details.
9 v.push_back(1);
10 v.push_back(12;
11 v.push_back(23);
12 v.push_back(34);
13 v.push_back(45);
14 v.push_back(56);
15
16 std::cout << '[';
17
18 // Iterate with indexes.
19 for(int i=0, l=v.size(); i<l; i++)
20 {
21 if(i > 0)
22 std::cout << ',';
23
24 std::cout << v[i];
25 }
26
27 std::cout << ']' << std::endl << '[';
28
29 // Iterate with iterators.
30 for(std::vector<int>::iterator it = v.begin(); it != v.end(); it++)
31 {
32 int x = (int)*it;
33
34 if(it != v.begin())
35 std::cout << ','; // Edit: added missing semi-colon.
36
37 std::cout << x;
38 }
39
40 std::cout << ']' << std::endl;
41
42 return 0;
43}
I'm really tired (waiting for a backup process to complete) so I'm not going to test it, but if I made no mistakes it should output: [1,12,23,34,45,56] [1,12,23,34,45,56]
-- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
Nakhash
Member #8,267
January 2007
![]() |
Your code is readable and I appreciate it. I guess what I'm asking for is, would it be possiable to use a vector like a struct.. like... struct Character { int Hitpoints; int Magicpoints; int Strength; }GoodGuys[10]; GoodGuys[0].Hitpoints=50; GoodGuys[0].Magicpoints=10;
and so on... I have ways to code around it, but is there an easier way with STL? Nakhash If you like Dragon Warrior, then try out my trilogy at http://dragonwarriorreborn.com |
OnlineCop
Member #7,919
October 2006
![]() |
The real difference is that when you're adding items to a vector, you use push_back(), like bamccaig showed. (Note to bamccaig: Line 35 Once you've pushed all of the numbers onto the array that you want, you can index them with the normal "[]" brackets like you do with a normal array: std::vector<int> array; array.push_back(10); array.push_back(-13); // ... array.push_back(6); int current_value = array[0]; // 0th element, value of "10" int next_value = array[1]; // 1st element, value of "-13" // ... EDIT: Nakhash said: I guess what I'm asking for is, would it be possiable to use a vector like a struct.. Yes, absolutely you can do something like this. That's what the std::vector was made for. You define the "type" of vector using the "<" and ">" brackets: 1struct Character
2{
3
4 int Hitpoints;
5 int Magicpoints;
6 int Strength;
7
8};
9
10// ...
11
12int main()
13{
14 // Put "Character" into the "<" and ">" brackets:
15 std::vector<Character> GoodGuys; 16 Character man1;
17 man1.Hitpoints=50;
18 man1.Magicpoints=10;
19
20 GoodGuys.push_back(man1);
21
22 Character man2;
23 man2.Hitpoints=75;
24 man2.Magicpoints=5;
25
26 GoodGuys.push_back(man2);
27
28 // ...
29
30 size_t num_GoodGuys = GoodGuys.size();
31 for (size_t i = 0; i < num_GoodGuys; ++i)
32 {
33 // ...
34 }
|
Nakhash
Member #8,267
January 2007
![]() |
So then with my GoodGuys code, I'd have to make a seperate Vector for every Struct element? Like std::vector<int> GoodGuyHitpoints; std::vector<int> GoodGuyMagicpoints; GoodGuyHitpoints.push_back(10); GoodGuyHitpoints.push_back(8); GoodGuyMagicpoints.push_back(5); And so on... Is there a way to group certain Vectors together like a struct, and give it a common name like I did for my struct Char? [EDIT] Oh my Gosh, you just changed my world... I never knew you could vector an entire struct... I'm absolutely shocked! Nakhash If you like Dragon Warrior, then try out my trilogy at http://dragonwarriorreborn.com |
LennyLen
Member #5,313
December 2004
![]() |
Nakhash said: and so on... I have ways to code around it, but is there an easier way with STL?
1struct Character
2{
3
4 int Hitpoints;
5 int Magicpoints;
6 int Strength;
7
8}
9
10vector<Character> GoodGuys;
11
12...
13
14Character temp;
15
16// do the following for each character type you want in your Vector of Characters
17temp.Hitpoints = 50;
18temp.Magicpoints = 5;
19temp.Strength = 30;
20
21GoodGuys.push_back(temp);
22// the first one will be GoodGuys[0], then GoodGuys[1], etc, just like an array
23
24...
25
26GoodGuys.erase(GoodGuys.begin() + 4); // erases GoodGuys[5]
|
OnlineCop
Member #7,919
October 2006
![]() |
No, no, no. Unless a single GoodGuy has multiple Hitpoints, which I don't think you want. You want to have multiple Characters. Each Character will have its own "Hitpoints", "Magicpoints", etc. as defined in the struct that you provided earlier. If you have "GoodGuys" defined as the vector, it's the same as having: Character GoodGuys[3]; GoodGuys[0].Name="Bob"; GoodGuys[0].Hitpoints=50; GoodGuys[0].Magicpoints=10; GoodGuys[1].Name="Fredrick"; GoodGuys[1].Hitpoints=75; GoodGuys[1].MagicPoints=5; ... and so on. "Bob" will only have a single set of Hitpoints, value 50. "Fredrick" will have 75 Hitpoints. "Jimmy" will have his own. What you were asking is the equivalent of "Bob" having 10 Hitpoints, as well as 8 Hitpoints, etc.
|
Nakhash
Member #8,267
January 2007
![]() |
Yeah I saw the error of my ways after the last two responses were given... In regards to LennyLen post, if I delete GoodGuys[5], would GoodGuys[6]'s data take it's place an so on until the entire Vector was one shorter in length? GoodGuys.erase(GoodGuys.begin() + 4); // erases GoodGuys[5] [EDIT] Vector reminds me of the push pop in Assembly Language. Nakhash If you like Dragon Warrior, then try out my trilogy at http://dragonwarriorreborn.com |
OnlineCop
Member #7,919
October 2006
![]() |
Nakhash said: In regards to LennyLen post, if I delete GoodGuys[5], would GoodGuys[6]'s data take it's place an so on until the entire Vector was one shorter in length? GoodGuys.erase(GoodGuys.begin() + 4); // erases GoodGuys[5] Yes. Therefore, if you think that you'll be deleting a lot of stuff in the middle, you may want to look into linked lists: std::list It follows the same format as std::vector: std::list<Character> The difference is that if you're iterating through linked lists, it takes a lot longer (because it has to start at "node 0" and iterate through each one before coming to "node 17"). With vectors, you can point right to it by simply saying "GoodGuys[17]". However, if you delete from the middle of a linked list, it unhooks the previous Node and the next Node, attaches them together, and gets rid of the one that you specified to remove. You can get around this by a simple trick (if order doesn't matter): take the LAST element in the vector, stick it where the current element is, and then delete from the end of the vector. Then you don't have to shift all 1,000 other "Character" elements "up one". But if order does matter, you'll just have to settle for the "shift up one" when you remove that element. ::shrug:: EDIT: Explained more. Long-winded. Yup, yup.
|
Nakhash
Member #8,267
January 2007
![]() |
Your pretty smart for a Cop...Wolf... I'm looking at erasing a vector each time a troop dies. So it would be about 1 every 2 mins or so. And my vector Struct will contain 8 kingdoms worth of 20-50 troops. Vector sounds like the way to go...but I'll read about the List you are talking about. Nakhash If you like Dragon Warrior, then try out my trilogy at http://dragonwarriorreborn.com |
Goalie Ca
Member #2,579
July 2002
![]() |
protip: 1//use case: -(vec1 + vec2)
2//modifies and returns the unnamed vector
3//created from (vec1 + vec2)
4//requires c++0x
5Vec2D&& operator-( Vec2D&& vec )
6{
7 vec.x = -vec.x;
8 vec.y = -vec.y;
9 return std::move(vec);
10}
11
12//use case: -vec1
13//passes a reference rather than
14//creating and passing a copy
15Vec2D operator-( const Vec2D& vec )
16{
17 return Vec2D( -vec.x, -vec.y );
18}
------------- |
OnlineCop
Member #7,919
October 2006
![]() |
Goalie: Nakhash: Since you're not going to be removing them every second, std::vector sounds about right for you. The only two things you'll want to consider when doing this is: I don't know how much you've worked with pointers, but I've actually found it worthwhile for me to store a vector of points to the structs/classes that I've created. Then, if you do something like "array[current_index] = array[another_index];", it won't COPY the object using the object's assignment operator ( Troop& operator= (const Troop& rhs); ). It will just copy the pointer address and you're done. The only real overhead you have with this is that you must call new() and delete() yourself. Passing by reference, instead of passing by pointer, does all of this for you (even calling the destroyed object's destructor when appropriate), though you incur the "deep" or "shallow" copy I just mentioned.
|
Nakhash
Member #8,267
January 2007
![]() |
OnlineCop: Nakhash Reply: I shouldn't have a lot of elements. It should be about 5 Vector structs total with the biggest one being 100 or so... I use a lot of Structs referencing other structs which references another struct. It's like a long line of code that equals 5 or something. It enables me to not reference or make duplicates of data. An example would be for my current game. 1
2struct ClassDef//Base Stats per Class if Unit was Level 1
3{
4 int Strength;
5 int Defence;
6}Class[20];
7
8struct UnitsDef //Use this for the Units Current Stats
9{
10 int ClassID;
11 int Strength;
12 int Defence;
13 int Level;
14}Units[8][50];
15
16struct TroopsDef
17{
18 int UnitsID;
19 int X;
20 int Y;
21 int Faceing;
22}PlayerTroops[25];//Only Allow 25 of the total 50 Units to be in 1 battle at 1 time.
23
24
25
26Class[Units[KingdomID][PlayerTroops[TroopSelect].UnitID].ClassID].Strength
[EDIT] Nakhash If you like Dragon Warrior, then try out my trilogy at http://dragonwarriorreborn.com |
OnlineCop
Member #7,919
October 2006
![]() |
Nakhash said:
OnlineCop: Nakhash Reply: You can use <quote>...</quote> tags if it helps. Okay... Since your 2struct ClassDef
3{
4 int Strength;
5 int Defense;
6};
and your 8struct UnitsDef
9{
10 int ClassID;
11 int Strength; 12 int Defense; 13 int Level;
14};
contain two of the same variables, why not use inheritance? struct ClassDef { int Strength; int Defense; };
Nakhash said: I shouldn't have a lot of elements.
Quote:
1struct ClassDef
2{
3 // ...
4}Class[20];
5
6struct UnitsDef
7{
8 // ...
9}Units[8][50];
10
11struct TroopsDef
12{
13 // ...
14}PlayerTroops[25]
15
16Class[ Units[KingdomID][PlayerTroops[TroopSelect].UnitID].ClassID ].Strength
Now, if I've broken this down correctly, you have:
That's (20 * 8) * (400 * 16) * (25 * 16) bytes, or 409,600,000 Yes, I'd definitely go with the vector approach, and only allocate them as needed.
|
Per Larsson
Member #276
April 2000
![]() |
Shouldn't that be ________________________ |
Nakhash
Member #8,267
January 2007
![]() |
I don't think inheritance will work for me since I haven't fully repersented my variables in each struct. I've been going off memory to show how I'm using the data. So in other words ClassDef has variables that UnitDef doesn't have and the Class Strength should also be a different number then the Units Strength. I've been using ClassDef as an intro set of stats for my troops, and it also contains graphical X,Y cordance data for my sprite bitmaps that correspond to the correct Class(Job..Ex..Archer..Wizard)/Race I do appreciate all of your guys help. Nakhash If you like Dragon Warrior, then try out my trilogy at http://dragonwarriorreborn.com |
bamccaig
Member #7,536
July 2006
![]() |
OnlineCop said: Note to bamccaig: Line 35
Nakhash said: Yes I've used pointers before, but I think I'll stick to the Vecter approach that was given to me. Currently I only use pointers for char that I want used in another function without declaring a global char. You'd still use a std::vector, but instead of storing objects in the std::vector by value, you'd store them by pointer. It makes certain operations much faster (though complicates matters slightly by forcing you to manage memory yourself). 1#include <iostream>
2#include <sstream>
3#include <string>
4#include <vector>
5
6class IStringifyable
7{
8public:
9 virtual ~IStringifyable(void) = 0;
10
11 virtual std::string toString(void) const = 0;
12};
13
14IStringifyable::~IStringifyable(void) {}
15
16class Character:
17 public IStringifyable
18{
19 int hp_;
20 int mp_;
21 int str_;
22public:
23 Character(const int, const int, const int);
24 ~Character(void);
25
26 int getHP(void) const;
27 int getMP(void) const;
28 int getSTR(void) const;
29
30 int setHP(const int);
31 int setMP(const int);
32 int setSTR(const int);
33
34 std::string toString(void) const;
35};
36
37Character::Character(const int hp, const int mp, const int str):
38 hp_(hp),
39 mp_(mp),
40 str_(str)
41{
42}
43
44Character::~Character(void) {}
45
46int Character::getHP(void) const
47{
48 return this->hp_;
49}
50
51int Character::getMP(void) const
52{
53 return this->mp_;
54}
55
56int Character::getSTR(void) const
57{
58 return this->str_;
59}
60
61int Character::setHP(const int hp)
62{
63 return this->hp_ = hp;
64}
65
66int Character::setMP(const int mp)
67{
68 return this->mp_ = mp;
69}
70
71int Character::setSTR(const int str)
72{
73 return this->str_ = str;
74}
75
76std::string Character::toString(void) const
77{
78 std::stringstream ss;
79
80 ss << "{\n"
81 << " HP : " << this->hp_ << ",\n"
82 << " MP : " << this->mp_ << ",\n"
83 << " STR : " << this->str_ << "\n"
84 << "}";
85
86 return ss.str();
87}
88
89std::ostream & operator<<(std::ostream & out, const IStringifyable & strable)
90{
91 return out << strable.toString();
92}
93
94typedef std::vector<Character *> CharacterPtrVector;
95
96int main(int argc, char * argv[])
97{
98 CharacterPtrVector v;
99
100 v.push_back(new Character(100, 100, 23));
101 v.push_back(new Character(87, 121, 15));
102 v.push_back(new Character(53, 534, 22));
103 v.push_back(new Character(234, 32, 51));
104
105 for(int i=0, l=v.size(); i<l; i++)
106 {
107 const Character * const chr_ptr = v[i];
108
109 // Output our characters, one by one.
110 std::cout << *chr_ptr << std::endl << std::endl;
111
112 // We might as well use the same loop for cleanup.
113 delete chr_ptr;
114 }
115
116 /*
117 * We've already deleted all of the objects so we should clear the vector to
118 * release the pointers.
119 */
120 v.clear();
121
122 return 0;
123}
$ g++ -c main.cpp $ g++ -o chrvct main.o $ ./chrvct { HP : 100, MP : 100, STR : 23 } { HP : 87, MP : 121, STR : 15 } { HP : 53, MP : 534, STR : 22 } { HP : 234, MP : 32, STR : 51 } $ The advantage to using pointers is that container operations won't cause copies of entire objects. Only their memory addresses need to be copied. Even better, if you don't mind installing Boost, would be using boost::shared_ptr<Character> (or if you've got a C++0x compatible compiler, std::shared_ptr<Character>) because it acts just like a pointer and is efficient like a pointer, but cleanup is automatic[1]. References
-- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
Goalie Ca
Member #2,579
July 2002
![]() |
OnlineCop said: Goalie: Okay I will.. someone please bookmark/remind me to make a wiki if this ends up being referred to in other posts. //use case: -(vec1 + vec2) //modifies and returns the unnamed vector //created from (vec1 + vec2) //requires c++0x Vec2D&& operator-( Vec2D&& vec ) { vec.x = -vec.x; vec.y = -vec.y; return std::move(vec); } So, in C++ there are r-values and l-values. An r-value is a value without an explicit name.. these are temporary objects that can only be accessed in one way. Vec2D a(1,2); Vec2D b(-1,2); Vec2D c = (a + b) - b; In this example a,b,c are named variables. That means that any line of code in that scope can use the label (ie: name) to access that object. (a+b) is a function of named variables a and b and returns a variable. What is this variable called? It is unnamed therefore nowhere else in the code can touch that result. This means that we can make an optimization here! Let us re-use the result from (a+b) by storing the result of (a+b)-b into the temporary created by (a+b). Vec2D&& operator-(Vec2D&& ab, const Vec2D& b) { ab.x -= b.x; ab.y -= b.y; return std::move(ab); } So && is the C++0x notation for r-value. Once we give an r-value a name it becomes an l-value. So ab is an l-value. But we want to return an r-value here so we use std::move which simply casts an l-value to an r-value. Notice how we re-use the temporary ab rather than making a new-copy! ------------- |
anonymous
Member #8025
November 2006
|
Except why would that be any optimization here if there's nothing to be gained from moving? With the following the version with rvalue references appears to be slower. 1#include <iostream>
2#include <ctime>
3
4#define USE_RVALUE_MINUS 1
5struct Vec2D
6{
7 int x, y;
8};
9
10Vec2D operator+(const Vec2D& a, const Vec2D& b)
11{
12 return { a.x + b.x, a.y + b.y };
13}
14
15#if USE_RVALUE_MINUS
16Vec2D&& operator-( Vec2D&& vec )
17{
18 vec.x = -vec.x;
19 vec.y = -vec.y;
20 return std::move(vec);
21}
22#else
23
24Vec2D operator-(const Vec2D& vec)
25{
26 return {-vec.x, -vec.y };
27}
28#endif
29
30int main()
31{
32 clock_t start = clock();
33 Vec2D a{1, 2}, b{1, -1};
34 for (int i = 0; i != 10000000; ++i) {
35 a = -(a + b);
36 }
37 std::cout << clock() - start << ' ' << a.x << ' ' << a.y;
38}
|
Goalie Ca
Member #2,579
July 2002
![]() |
anonymous said: Except why would that be any optimization here if there's nothing to be gained from moving? std::move does nothing but cast from Var& to Var&&. Where is the code that runs the actual test? Say for example you had a string.. string&& operator+( string&& a, const string& b ) { //some magic } //write out other permutations of arguments... string& operator+( const string& a, const string& b) { //some different magic } Then you would see a great performance increase from something like this string c = a + b + "hello world " + d + e + f + g + "something else "; In many programming languages they say avoid doing this because it constructs a new string for every addition and then throws it away. A lot of language tell you to use a.join etc. With r-values you can mimic that join behavior with a naive syntax. ------------- |
anonymous
Member #8025
November 2006
|
String's a different thing indeed. But with something as simple as a Vec2D, everything goes on on the stack, and the compiler, I assume, can optimize away the temporaries via return value optimizations and inlining. I have feeling there isn't much point to bother exploding the number of overloads you need for simple things like that. |
|