New vector class.

This commit is contained in:
King_DuckZ 2015-09-17 16:36:22 +02:00
parent b3e122eeef
commit c51fdd7483
3 changed files with 129 additions and 0 deletions

View file

@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(hello_d C D)
set(CMAKE_D_FLAGS_DEBUG "${CMAKE_D_FLAGS_DEBUG} -funittest -O0")
include_directories(
src/
)
@ -15,6 +17,7 @@ add_executable(${PROJECT_NAME}
src/bpg.d
src/texture.d
src/gameobjjumping.d
src/vector.d
lib/DerelictSDL2/source/derelict/sdl2/functions.d
lib/DerelictSDL2/source/derelict/sdl2/image.d

View file

@ -20,6 +20,9 @@ public import gameobj;
import derelict.sdl2.sdl;
import texture;
import std.stdio;
import vector : Vector;
alias vec2 = Vector!(float, 2);
//This is one possible game scene. It will draw a texture on the screen
//and it will report user wants to quit if you press the close button in the
@ -46,6 +49,15 @@ class GameObjJumping : GameObj {
override void prepare() {
string texture_name = "bcruiser_normal.bpg";
writeln("Loading texture %s", texture_name);
//Note how this is doing a swap and not a copy. You can verify that
//in the output. The first "Destroying texture (null)" message is the
//temporary created here, which took m_texture's content (null) and gets
//destroyed as it goes out of scope.
//The following code for example won't compile as it would trigger a
//copy construction, but this(this) is marked as @disable in Texture:
// auto tmp = Texture(texture_name, renderer());
// m_texture = tmp;
m_texture = Texture(texture_name, renderer());
}

114
src/vector.d Normal file
View file

@ -0,0 +1,114 @@
/* Copyright 2015, Michele Santullo
* This file is part of "Jumping in D".
*
* "Jumping in D" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "Jumping in D" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "Jumping in D". If not, see <http://www.gnu.org/licenses/>.
*/
module vector;
import std.algorithm : fill;
struct Vector(T, int N) {
//With the if(condition) before the function body we can tell the compiler
//this particular template should only be considered when condition is true.
this(P...)(P parInit) if (N == parInit.length) {
int index = 0;
foreach(p;parInit) {
m_data[index++] = p;
}
}
this(P...)(P parInit) if (N > 1 && 1 == parInit.length) {
//m_data is a static array, by slicing it we get a dynamic array and
//fill that one. You will get a build error if you dont add the [].
fill(m_data[], parInit[0]);
}
//Define x, y, z, w accessors. Vectors larger than 4 elements won't have any
//of those.
static if (N <= 4) {
//Getter
@property T x() const { return m_data[0]; }
//Setter
@property T x(in T parVal) { return m_data[0] = parVal; }
static if (N >= 2) {
@property T y() const { return m_data[1]; }
@property T y(in T parVal) { return m_data[1] = parVal; }
}
static if (N >= 3) {
@property T z() const { return m_data[2]; }
@property T z(in T parVal) { return m_data[2] = parVal; }
}
static if (N >= 4) {
@property T w() const { return m_data[3]; }
@property T w(in T parVal) { return m_data[3] = parVal; }
}
}
//Other accessors that can make using vectors more convenient - same static
//if as above, but written here to separate code for the sake of clarity.
static if (N <= 4) {
@property Vector!(T, 2) x0() const { return Vector!(T, 2)(x, T(0)); }
@property Vector!(T, 2) x1() const { return Vector!(T, 2)(x, T(1)); }
@property Vector!(T, 2) _0x() const { return Vector!(T, 2)(T(0), x); }
@property Vector!(T, 2) _1x() const { return Vector!(T, 2)(T(1), x); }
static if (N > 1) {
@property Vector!(T, 2) xy() const { return Vector!(T, 2)(x, y); }
@property Vector!(T, 2) y0() const { return Vector!(T, 2)(y, T(0)); }
@property Vector!(T, 2) y1() const { return Vector!(T, 2)(y, T(1)); }
@property Vector!(T, 2) _0y() const { return Vector!(T, 2)(T(0), y); }
@property Vector!(T, 2) _1y() const { return Vector!(T, 2)(T(1), y); }
}
static if (N > 2) {
@property Vector!(T, 3) xyz() const { return Vector!(T, 3)(x, y, z); }
@property Vector!(T, 3) zxy() const { return Vector!(T, 3)(z, x, y); }
@property Vector!(T, 3) yzx() const { return Vector!(T, 3)(y, z, x); }
@property Vector!(T, 3) xzy() const { return Vector!(T, 3)(x, z, y); }
@property Vector!(T, 3) zyx() const { return Vector!(T, 3)(z, y, x); }
@property Vector!(T, 3) yxz() const { return Vector!(T, 3)(y, x, z); }
//add more if you need
}
}
//Overload operator[] to allow accessing the vector with array syntax
//inout tells the compiler to generate both a const and a non-const
//version of this method.
ref inout(T) opIndex (size_t parIndex) inout {
assert(parIndex < N);
return m_data[parIndex];
}
private:
T m_data[N];
}
//You can write unit tests inside unittest {} blocks. These will only be
//compiled if you specify the -funittest switch (gdc). Unit tests are run as
//your program starts, but needs to be grammatically correct even if you don't
//use the -funittest switch.
unittest {
auto v1 = Vector!(int, 3)(2);
assert(2 == v1.x);
assert(2 == v1.y);
assert(2 == v1.z);
auto v2 = Vector!(int, 4)(3, 4, 5, 6);
assert(3 == v2.x);
assert(4 == v2.y);
assert(5 == v2.z);
assert(6 == v2.w);
assert(Vector!(int, 2)(3, 0) == v2.x0);
assert(Vector!(int, 2)(4, 0) == v2.y0);
assert(Vector!(int, 3)(5, 4, 3) == v2.zyx);
}