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