1 /* 2 * DSFML - The Simple and Fast Multimedia Library for D 3 * 4 * Copyright (c) 2013 - 2018 Jeremy DeHaan (dehaan.jeremiah@gmail.com) 5 * 6 * This software is provided 'as-is', without any express or implied warranty. 7 * In no event will the authors be held liable for any damages arising from the 8 * use of this software. 9 * 10 * Permission is granted to anyone to use this software for any purpose, 11 * including commercial applications, and to alter it and redistribute it 12 * freely, subject to the following restrictions: 13 * 14 * 1. The origin of this software must not be misrepresented; you must not claim 15 * that you wrote the original software. If you use this software in a product, 16 * an acknowledgment in the product documentation would be appreciated but is 17 * not required. 18 * 19 * 2. Altered source versions must be plainly marked as such, and must not be 20 * misrepresented as being the original software. 21 * 22 * 3. This notice may not be removed or altered from any source distribution 23 * 24 * 25 * DSFML is based on SFML (Copyright Laurent Gomila) 26 */ 27 28 /** 29 * $(U Vector2) is a simple structure that defines a mathematical vector with 30 * two coordinates (x and y). It can be used to represent anything that has two 31 * dimensions: a size, a point, a velocity, etc. 32 * 33 * The template parameter T is the type of the coordinates. It can be any type 34 * that supports arithmetic operations (+, -, /, *) and comparisons (==, !=), 35 * for example int or float. 36 * 37 * You generally don't have to care about the templated form (Vector2!(T)), 38 * the most common specializations have special aliases: 39 * $(UL 40 * $(LI Vector2!(float) is Vector2f) 41 * $(LI Vector2!(int) is Vector2i) 42 * $(LI Vector2!(uint) is Vector2u)) 43 * 44 * $(PARA 45 * The $(U Vector2) struct has a small and simple interface, its x and y members 46 * can be accessed directly (there are no accessors like `setX()`, `getX()`) and 47 * it contains no mathematical function like dot product, cross product, length, 48 * etc.) 49 * 50 * Example: 51 * --- 52 * auto v1 = Vector2f(16.5f, 24.f); 53 * v1.x = 18.2f; 54 * float y = v1.y; 55 * 56 * auto v2 = v1 * 5.f; 57 * Vector2f v3; 58 * v3 = v1 + v2; 59 * 60 * bool different = (v2 != v3); 61 * --- 62 * 63 * See_Also: 64 * $(VECTOR3_LINK) 65 */ 66 module dsfml.system.vector2; 67 68 import std.traits; 69 70 /** 71 * Utility template struct for manipulating 2-dimensional vectors. 72 */ 73 struct Vector2(T) 74 if(isNumeric!(T) || is(T == bool)) 75 { 76 /// X coordinate of the vector. 77 T x; 78 79 /// Y coordinate of the vector. 80 T y; 81 82 /** 83 * Construct the vector from its coordinates. 84 * 85 * Params: 86 * X = X coordinate 87 * Y = Y coordinate 88 */ 89 this(T X,T Y) 90 { 91 x = X; 92 y = Y; 93 } 94 95 /** 96 * Construct the vector from another type of vector. 97 * 98 * Params: 99 * otherVector = Vector to convert 100 */ 101 this(E)(Vector2!(E) otherVector) 102 { 103 x = cast(T)(otherVector.x); 104 y = cast(T)(otherVector.y); 105 } 106 107 /// Invert the members of the vector. 108 Vector2!(T) opUnary(string s)() const 109 if (s == "-") 110 { 111 return Vector2!(T)(-x, -y); 112 } 113 114 /// Add/Subtract between two vector2's. 115 Vector2!(T) opBinary(string op, E)(Vector2!(E) otherVector) const 116 if(isNumeric!(E) && ((op == "+") || (op == "-"))) 117 { 118 static if (op == "+") 119 { 120 return Vector2!(T)(cast(T)(x+otherVector.x),cast(T)(y+otherVector.y)); 121 } 122 static if(op == "-") 123 { 124 return Vector2!(T)(cast(T)(x-otherVector.x),cast(T)(y-otherVector.y)); 125 } 126 } 127 128 /// Multiply/Divide a vector with a numaric value. 129 Vector2!(T) opBinary (string op, E)(E num) const 130 if(isNumeric!(E) && ((op == "*") || (op == "/"))) 131 { 132 static if (op == "*") 133 { 134 return Vector2!(T)(cast(T)(x*num),cast(T)(y*num)); 135 } 136 static if(op == "/") 137 { 138 return Vector2!(T)(cast(T)(x/num),cast(T)(y/num)); 139 } 140 } 141 142 /// Assign Add/Subtract with another vector2. 143 ref Vector2!(T) opOpAssign(string op, E)(Vector2!(E) otherVector) 144 if(isNumeric!(E) && ((op == "+") || (op == "-"))) 145 { 146 static if(op == "+") 147 { 148 x = cast(T)(x + otherVector.x); 149 y = cast(T)(y + otherVector.y); 150 return this; 151 } 152 static if(op == "-") 153 { 154 x = cast(T)(x - otherVector.x); 155 y = cast(T)(y - otherVector.y); 156 return this; 157 } 158 } 159 160 /// Assign Multiply/Divide with a numaric value. 161 ref Vector2!(T) opOpAssign(string op,E)(E num) 162 if(isNumeric!(E) && ((op == "*") || (op == "/"))) 163 { 164 static if(op == "*") 165 { 166 x *= num; 167 y *= num; 168 return this; 169 } 170 static if(op == "/") 171 { 172 x /= num; 173 y /= num; 174 return this; 175 } 176 } 177 178 /// Assign the value of another vector whose type can be converted to T. 179 ref Vector2!(T) opAssign(E)(Vector2!(E) otherVector) 180 { 181 x = cast(T)(otherVector.x); 182 y = cast(T)(otherVector.y); 183 return this; 184 } 185 186 /// Compare two vectors for equality. 187 bool opEquals(E)(const Vector2!(E) otherVector) const 188 if(isNumeric!(E)) 189 { 190 return ((x == otherVector.x) && (y == otherVector.y)); 191 } 192 193 /// Output the string representation of the Vector2. 194 string toString() const 195 { 196 import std.conv; 197 return "X: " ~ text(x) ~ " Y: " ~ text(y); 198 } 199 } 200 201 /// Definition of a Vector2 of integers. 202 alias Vector2!(int) Vector2i; 203 204 /// Definition of a Vector2 of floats. 205 alias Vector2!(float) Vector2f; 206 207 /// Definition of a Vector2 of unsigned integers. 208 alias Vector2!(uint) Vector2u; 209 210 unittest 211 { 212 version(DSFML_Unittest_System) 213 { 214 import std.stdio; 215 216 writeln("Unit test for Vector2"); 217 218 auto floatVector2 = Vector2f(100,100); 219 220 assert((floatVector2/2) == Vector2f(50,50)); 221 222 assert((floatVector2*2) == Vector2f(200,200)); 223 224 assert((floatVector2 + Vector2f(50, 0)) == Vector2f(150, 100)); 225 226 assert((floatVector2 - Vector2f(50,0)) == Vector2f(50,100)); 227 228 floatVector2/=2; 229 230 assert(floatVector2 == Vector2f(50,50)); 231 232 floatVector2*=2; 233 234 assert(floatVector2 == Vector2f(100,100)); 235 236 floatVector2+= Vector2f(50,0); 237 238 assert(floatVector2 == Vector2f(150,100)); 239 240 floatVector2-=Vector2f(50,100); 241 242 assert(floatVector2 == Vector2f(100,0)); 243 244 writeln("Vector2 tests passed"); 245 writeln(); 246 247 } 248 }