From c51fdd74835f906be7ae2e260db70a24a50f1ca8 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 17 Sep 2015 16:36:22 +0200 Subject: [PATCH] New vector class. --- CMakeLists.txt | 3 ++ src/gameobjjumping.d | 12 +++++ src/vector.d | 114 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 src/vector.d diff --git a/CMakeLists.txt b/CMakeLists.txt index 375ba69..6701083 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/src/gameobjjumping.d b/src/gameobjjumping.d index 1ce34be..d87c7e5 100644 --- a/src/gameobjjumping.d +++ b/src/gameobjjumping.d @@ -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()); } diff --git a/src/vector.d b/src/vector.d new file mode 100644 index 0000000..967c229 --- /dev/null +++ b/src/vector.d @@ -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 . + */ + +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); +}