Prechádzať zdrojové kódy

Import cmake project

DricomDragon 4 rokov pred
rodič
commit
5325afd5a9

+ 32 - 0
CMakeLists.txt

@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.7)
+project(SpaceExpansion)
+
+set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CmakeFinders")
+
+find_package(SDL2)
+find_package(SDL2_image)
+find_package(SDL2_ttf)
+
+include_directories(${SDL2_INCLUDE_DIR} ${SDL2_IMAGE_INCLUDE_DIR} ${SDL2_TTF_INCLUDE_DIRS})
+
+set(CMAKE_CXX_STANDARD 11)
+
+set(SOURCE_FILES
+        main.cpp
+        GameCore.cpp
+        Control/Input.cpp
+        Graphics/Renderer.cpp
+        Graphics/Visual.cpp
+        Contents/Universe.cpp
+        Contents/Planet.cpp
+        Contents/StarShip.cpp
+        Contents/Stock.cpp
+        Maths/b2Angle.cpp
+        Control/Camera.cpp
+        Rules/PlanetStep.cpp
+        Rules/PeopleExpGrowth.cpp
+        Rules/PeopleMinimalGrowth.cpp)
+
+add_executable(SpaceExpansion ${SOURCE_FILES})
+
+target_link_libraries(SpaceExpansion ${SDL2_LIBRARY} ${SDL2_IMAGE_LIBRARY} ${SDL2_TTF_LIBRARIES})

+ 173 - 0
CmakeFinders/FindSDL2.cmake

@@ -0,0 +1,173 @@
+
+# This module defines
+# SDL2_LIBRARY, the name of the library to link against
+# SDL2_FOUND, if false, do not try to link to SDL2
+# SDL2_INCLUDE_DIR, where to find SDL.h
+#
+# This module responds to the the flag:
+# SDL2_BUILDING_LIBRARY
+# If this is defined, then no SDL2main will be linked in because
+# only applications need main().
+# Otherwise, it is assumed you are building an application and this
+# module will attempt to locate and set the the proper link flags
+# as part of the returned SDL2_LIBRARY variable.
+#
+# Don't forget to include SDLmain.h and SDLmain.m your project for the
+# OS X framework based version. (Other versions link to -lSDL2main which
+# this module will try to find on your behalf.) Also for OS X, this
+# module will automatically add the -framework Cocoa on your behalf.
+#
+#
+# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration
+# and no SDL2_LIBRARY, it means CMake did not find your SDL2 library
+# (SDL2.dll, libsdl2.so, SDL2.framework, etc).
+# Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again.
+# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value
+# as appropriate. These values are used to generate the final SDL2_LIBRARY
+# variable, but when these values are unset, SDL2_LIBRARY does not get created.
+#
+#
+# $SDL2DIR is an environment variable that would
+# correspond to the ./configure --prefix=$SDL2DIR
+# used in building SDL2.
+# l.e.galup  9-20-02
+#
+# Modified by Eric Wing.
+# Added code to assist with automated building by using environmental variables
+# and providing a more controlled/consistent search behavior.
+# Added new modifications to recognize OS X frameworks and
+# additional Unix paths (FreeBSD, etc).
+# Also corrected the header search path to follow "proper" SDL guidelines.
+# Added a search for SDL2main which is needed by some platforms.
+# Added a search for threads which is needed by some platforms.
+# Added needed compile switches for MinGW.
+#
+# On OSX, this will prefer the Framework version (if found) over others.
+# People will have to manually change the cache values of
+# SDL2_LIBRARY to override this selection or set the CMake environment
+# CMAKE_INCLUDE_PATH to modify the search paths.
+#
+# Note that the header path has changed from SDL2/SDL.h to just SDL.h
+# This needed to change because "proper" SDL convention
+# is #include "SDL.h", not <SDL2/SDL.h>. This is done for portability
+# reasons because not all systems place things in SDL2/ (see FreeBSD).
+
+#=============================================================================
+# Copyright 2003-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+# message("<FindSDL2.cmake>")
+
+SET(SDL2_SEARCH_PATHS
+	~/Library/Frameworks
+	/Library/Frameworks
+	/usr/local
+	/usr
+	/sw # Fink
+	/opt/local # DarwinPorts
+	/opt/csw # Blastwave
+	/opt
+	${SDL2_PATH}
+)
+
+FIND_PATH(SDL2_INCLUDE_DIR SDL.h
+	HINTS
+	$ENV{SDL2DIR}
+	PATH_SUFFIXES include/SDL2 include
+	PATHS ${SDL2_SEARCH_PATHS}
+)
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8) 
+	set(PATH_SUFFIXES lib64 lib/x64 lib)
+else() 
+	set(PATH_SUFFIXES lib/x86 lib)
+endif() 
+
+FIND_LIBRARY(SDL2_LIBRARY_TEMP
+	NAMES SDL2
+	HINTS
+	$ENV{SDL2DIR}
+	PATH_SUFFIXES ${PATH_SUFFIXES}
+	PATHS ${SDL2_SEARCH_PATHS}
+)
+
+IF(NOT SDL2_BUILDING_LIBRARY)
+	IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
+		# Non-OS X framework versions expect you to also dynamically link to
+		# SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms
+		# seem to provide SDL2main for compatibility even though they don't
+		# necessarily need it.
+		FIND_LIBRARY(SDL2MAIN_LIBRARY
+			NAMES SDL2main
+			HINTS
+			$ENV{SDL2DIR}
+			PATH_SUFFIXES ${PATH_SUFFIXES}
+			PATHS ${SDL2_SEARCH_PATHS}
+		)
+	ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
+ENDIF(NOT SDL2_BUILDING_LIBRARY)
+
+# SDL2 may require threads on your system.
+# The Apple build may not need an explicit flag because one of the
+# frameworks may already provide it.
+# But for non-OSX systems, I will use the CMake Threads package.
+IF(NOT APPLE)
+	FIND_PACKAGE(Threads)
+ENDIF(NOT APPLE)
+
+# MinGW needs an additional link flag, -mwindows
+# It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -mwindows
+IF(MINGW)
+	SET(MINGW32_LIBRARY mingw32 "-mwindows" CACHE STRING "mwindows for MinGW")
+ENDIF(MINGW)
+
+IF(SDL2_LIBRARY_TEMP)
+	# For SDL2main
+	IF(NOT SDL2_BUILDING_LIBRARY)
+		IF(SDL2MAIN_LIBRARY)
+			SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP})
+		ENDIF(SDL2MAIN_LIBRARY)
+	ENDIF(NOT SDL2_BUILDING_LIBRARY)
+
+	# For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa.
+	# CMake doesn't display the -framework Cocoa string in the UI even
+	# though it actually is there if I modify a pre-used variable.
+	# I think it has something to do with the CACHE STRING.
+	# So I use a temporary variable until the end so I can set the
+	# "real" variable in one-shot.
+	IF(APPLE)
+		SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa")
+	ENDIF(APPLE)
+
+	# For threads, as mentioned Apple doesn't need this.
+	# In fact, there seems to be a problem if I used the Threads package
+	# and try using this line, so I'm just skipping it entirely for OS X.
+	IF(NOT APPLE)
+		SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT})
+	ENDIF(NOT APPLE)
+
+	# For MinGW library
+	IF(MINGW)
+		SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP})
+	ENDIF(MINGW)
+
+	# Set the final string here so the GUI reflects the final state.
+	SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found")
+	# Set the temp variable to INTERNAL so it is not seen in the CMake GUI
+	SET(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "")
+ENDIF(SDL2_LIBRARY_TEMP)
+
+# message("</FindSDL2.cmake>")
+
+INCLUDE(FindPackageHandleStandardArgs)
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR)

+ 100 - 0
CmakeFinders/FindSDL2_image.cmake

@@ -0,0 +1,100 @@
+# Locate SDL_image library
+#
+# This module defines:
+#
+# ::
+#
+#   SDL2_IMAGE_LIBRARIES, the name of the library to link against
+#   SDL2_IMAGE_INCLUDE_DIRS, where to find the headers
+#   SDL2_IMAGE_FOUND, if false, do not try to link against
+#   SDL2_IMAGE_VERSION_STRING - human-readable string containing the version of SDL_image
+#
+#
+#
+# For backward compatibility the following variables are also set:
+#
+# ::
+#
+#   SDLIMAGE_LIBRARY (same value as SDL2_IMAGE_LIBRARIES)
+#   SDLIMAGE_INCLUDE_DIR (same value as SDL2_IMAGE_INCLUDE_DIRS)
+#   SDLIMAGE_FOUND (same value as SDL2_IMAGE_FOUND)
+#
+#
+#
+# $SDLDIR is an environment variable that would correspond to the
+# ./configure --prefix=$SDLDIR used in building SDL.
+#
+# Created by Eric Wing.  This was influenced by the FindSDL.cmake
+# module, but with modifications to recognize OS X frameworks and
+# additional Unix paths (FreeBSD, etc).
+
+#=============================================================================
+# Copyright 2005-2009 Kitware, Inc.
+# Copyright 2012 Benjamin Eikel
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+find_path(SDL2_IMAGE_INCLUDE_DIR SDL_image.h
+        HINTS
+        ENV SDL2IMAGEDIR
+        ENV SDL2DIR
+        PATH_SUFFIXES SDL2
+        # path suffixes to search inside ENV{SDLDIR}
+        include/SDL2 include
+        PATHS ${SDL2_IMAGE_PATH}
+        )
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+    set(VC_LIB_PATH_SUFFIX lib/x64)
+else()
+    set(VC_LIB_PATH_SUFFIX lib/x86)
+endif()
+
+find_library(SDL2_IMAGE_LIBRARY
+        NAMES SDL2_image
+        HINTS
+        ENV SDL2IMAGEDIR
+        ENV SDL2DIR
+        PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX}
+        PATHS ${SDL2_IMAGE_PATH}
+        )
+
+if(SDL2_IMAGE_INCLUDE_DIR AND EXISTS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h")
+    file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h" SDL2_IMAGE_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_IMAGE_MAJOR_VERSION[ \t]+[0-9]+$")
+    file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h" SDL2_IMAGE_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_IMAGE_MINOR_VERSION[ \t]+[0-9]+$")
+    file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h" SDL2_IMAGE_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_IMAGE_PATCHLEVEL[ \t]+[0-9]+$")
+    string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_MAJOR "${SDL2_IMAGE_VERSION_MAJOR_LINE}")
+    string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_MINOR "${SDL2_IMAGE_VERSION_MINOR_LINE}")
+    string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_PATCH "${SDL2_IMAGE_VERSION_PATCH_LINE}")
+    set(SDL2_IMAGE_VERSION_STRING ${SDL2_IMAGE_VERSION_MAJOR}.${SDL2_IMAGE_VERSION_MINOR}.${SDL2_IMAGE_VERSION_PATCH})
+    unset(SDL2_IMAGE_VERSION_MAJOR_LINE)
+    unset(SDL2_IMAGE_VERSION_MINOR_LINE)
+    unset(SDL2_IMAGE_VERSION_PATCH_LINE)
+    unset(SDL2_IMAGE_VERSION_MAJOR)
+    unset(SDL2_IMAGE_VERSION_MINOR)
+    unset(SDL2_IMAGE_VERSION_PATCH)
+endif()
+
+set(SDL2_IMAGE_LIBRARIES ${SDL2_IMAGE_LIBRARY})
+set(SDL2_IMAGE_INCLUDE_DIRS ${SDL2_IMAGE_INCLUDE_DIR})
+
+include(FindPackageHandleStandardArgs)
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_image
+        REQUIRED_VARS SDL2_IMAGE_LIBRARIES SDL2_IMAGE_INCLUDE_DIRS
+        VERSION_VAR SDL2_IMAGE_VERSION_STRING)
+
+# for backward compatibility
+set(SDLIMAGE_LIBRARY ${SDL2_IMAGE_LIBRARIES})
+set(SDLIMAGE_INCLUDE_DIR ${SDL2_IMAGE_INCLUDE_DIRS})
+set(SDLIMAGE_FOUND ${SDL2_IMAGE_FOUND})
+
+mark_as_advanced(SDL2_IMAGE_LIBRARY SDL2_IMAGE_INCLUDE_DIR)

+ 98 - 0
CmakeFinders/FindSDL2_ttf.cmake

@@ -0,0 +1,98 @@
+# Locate SDL_ttf library
+#
+# This module defines:
+#
+# ::
+#
+#   SDL2_TTF_LIBRARIES, the name of the library to link against
+#   SDL2_TTF_INCLUDE_DIRS, where to find the headers
+#   SDL2_TTF_FOUND, if false, do not try to link against
+#   SDL2_TTF_VERSION_STRING - human-readable string containing the version of SDL_ttf
+#
+#
+#
+# For backward compatibility the following variables are also set:
+#
+# ::
+#
+#   SDLTTF_LIBRARY (same value as SDL2_TTF_LIBRARIES)
+#   SDLTTF_INCLUDE_DIR (same value as SDL2_TTF_INCLUDE_DIRS)
+#   SDLTTF_FOUND (same value as SDL2_TTF_FOUND)
+#
+#
+#
+# $SDLDIR is an environment variable that would correspond to the
+# ./configure --prefix=$SDLDIR used in building SDL.
+#
+# Created by Eric Wing.  This was influenced by the FindSDL.cmake
+# module, but with modifications to recognize OS X frameworks and
+# additional Unix paths (FreeBSD, etc).
+
+#=============================================================================
+# Copyright 2005-2009 Kitware, Inc.
+# Copyright 2012 Benjamin Eikel
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+find_path(SDL2_TTF_INCLUDE_DIR SDL_ttf.h
+        HINTS
+        ENV SDL2TTFDIR
+        ENV SDL2DIR
+        PATH_SUFFIXES SDL2
+        # path suffixes to search inside ENV{SDLDIR}
+        include/SDL2 include
+        PATHS ${SDL2_TTF_PATH}
+        )
+
+if (CMAKE_SIZEOF_VOID_P EQUAL 8)
+    set(VC_LIB_PATH_SUFFIX lib/x64)
+else ()
+    set(VC_LIB_PATH_SUFFIX lib/x86)
+endif ()
+
+find_library(SDL2_TTF_LIBRARY
+        NAMES SDL2_ttf
+        HINTS
+        ENV SDL2TTFDIR
+        ENV SDL2DIR
+        PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX}
+        PATHS ${SDL2_TTF_PATH}
+        )
+
+if (SDL2_TTF_INCLUDE_DIR AND EXISTS "${SDL2_TTF_INCLUDE_DIR}/SDL_ttf.h")
+    file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL_ttf.h" SDL2_TTF_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_TTF_MAJOR_VERSION[ \t]+[0-9]+$")
+    file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL_ttf.h" SDL2_TTF_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_TTF_MINOR_VERSION[ \t]+[0-9]+$")
+    file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL_ttf.h" SDL2_TTF_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_TTF_PATCHLEVEL[ \t]+[0-9]+$")
+    string(REGEX REPLACE "^#define[ \t]+SDL_TTF_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_MAJOR "${SDL2_TTF_VERSION_MAJOR_LINE}")
+    string(REGEX REPLACE "^#define[ \t]+SDL_TTF_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_MINOR "${SDL2_TTF_VERSION_MINOR_LINE}")
+    string(REGEX REPLACE "^#define[ \t]+SDL_TTF_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_PATCH "${SDL2_TTF_VERSION_PATCH_LINE}")
+    set(SDL2_TTF_VERSION_STRING ${SDL2_TTF_VERSION_MAJOR}.${SDL2_TTF_VERSION_MINOR}.${SDL2_TTF_VERSION_PATCH})
+    unset(SDL2_TTF_VERSION_MAJOR_LINE)
+    unset(SDL2_TTF_VERSION_MINOR_LINE)
+    unset(SDL2_TTF_VERSION_PATCH_LINE)
+    unset(SDL2_TTF_VERSION_MAJOR)
+    unset(SDL2_TTF_VERSION_MINOR)
+    unset(SDL2_TTF_VERSION_PATCH)
+endif ()
+
+set(SDL2_TTF_LIBRARIES ${SDL2_TTF_LIBRARY})
+set(SDL2_TTF_INCLUDE_DIRS ${SDL2_TTF_INCLUDE_DIR})
+
+include(FindPackageHandleStandardArgs)
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_ttf
+        REQUIRED_VARS SDL2_TTF_LIBRARIES SDL2_TTF_INCLUDE_DIRS
+        VERSION_VAR SDL2_TTF_VERSION_STRING)
+
+# for backward compatibility
+set(SDLTTF_LIBRARY ${SDL2_TTF_LIBRARIES})
+set(SDLTTF_INCLUDE_DIR ${SDL2_TTF_INCLUDE_DIRS})
+set(SDLTTF_FOUND ${SDL2_TTF_FOUND})

+ 102 - 0
Contents/Planet.cpp

@@ -0,0 +1,102 @@
+//
+// Created by jovian on 17/08/17.
+//
+
+#include "Planet.h"
+#include "../Maths/b2Angle.h"
+
+int Planet::m_incr = 0;
+
+Planet::Planet(const PlanetDef &def)
+        : m_def(def), m_imgId(1 + (unsigned int) m_incr % 5),
+          m_angle(b2Angle(def.pos, b2Vec2(1.0f, 1.0f))) {
+
+    // A better name
+    if (m_def.name == "---")
+        m_def.name = Planet::randomName();
+
+    // Identification
+    m_idPlanet = Planet::m_incr;
+    Planet::m_incr++;
+}
+
+Planet::~Planet() {
+    // Clear vector (do not destroy pointers !)
+    m_landedShips.clear();
+}
+
+Visual *Planet::makeVisual() {
+    return new Visual(m_imgId, m_def.pos, m_angle, m_def.size);
+}
+
+void Planet::applyRule(PlanetStep *rule) {
+    rule->callApply(m_def);
+}
+
+const PlanetDef &Planet::getDef() const {
+    return m_def;
+}
+
+int Planet::getId() const {
+    return m_idPlanet;
+}
+
+void Planet::landShip(StarShip *ship) {
+    // Find a empty place in the hangar
+    m_landedShips.push_back(ship);
+
+    // Unload this ship
+    m_def.stock += ship->unload();
+}
+
+bool Planet::readyShip() {
+    return !m_landedShips.empty();
+}
+
+std::string Planet::randomName() {
+    int size(5 + rand() % 9);
+
+    std::string voyel("aeiou");
+    std::string conson("bcdfghjklmnpqrstvwxyz");
+
+    std::string newName;
+
+    for (int k(0); k < size; k++) {
+        if (k % 2) { // Voyelle
+            newName.append(1, voyel[rand() % voyel.length()]);
+        } else { // Consonne
+            newName.append(1, conson[rand() % conson.length()]);
+        }
+    }
+
+    newName[0] = toupper(newName[0]);
+
+    return newName;
+}
+
+StarShip *Planet::launchShip(const Stock &avg) {
+    // Security : empty space port
+    if (m_landedShips.empty())
+        return nullptr;
+
+    // Design a good stock
+    Stock pack;
+    pack = m_def.stock - avg;
+    pack.setPositive();
+
+    // Launch ship
+    StarShip* ship(m_landedShips.back());
+    m_def.stock -= pack;
+    ship->load(pack);
+
+    m_landedShips.pop_back();
+    return ship;
+}
+
+bool Planet::need(Resource res, Stock average) {
+    // Is above average
+    Stock pack;
+    pack = m_def.stock - average;
+
+    return pack.get(res) < 0;
+}

+ 49 - 0
Contents/Planet.h

@@ -0,0 +1,49 @@
+//
+// Created by jovian on 17/08/17.
+//
+
+#ifndef SPACEEXPANSION_PLANET_H
+#define SPACEEXPANSION_PLANET_H
+
+#include <string>
+#include "../Graphics/Visual.h"
+#include "../Rules/PlanetStep.h"
+#include "StarShip.h"
+
+class Planet {
+    // Methods
+public:
+    Planet(const PlanetDef &def);
+    virtual ~Planet();
+
+    Visual *makeVisual();
+
+    void applyRule(PlanetStep *rule);
+
+    const PlanetDef &getDef() const;
+    int getId() const;
+
+    void landShip(StarShip *ship); // If a ship is arrived it can land on the planet
+    bool readyShip(); // Return true if at least one ship is ready to go
+    StarShip* launchShip(const Stock &avg); // Load and launch a ship into space
+
+    bool need(Resource res, Stock average); // Return true if this lanet need res
+
+    static std::string randomName();
+
+    // Attributes
+private:
+    PlanetDef m_def;
+    int m_idPlanet;
+    unsigned int m_imgId;
+    float m_angle;
+
+    std::vector<StarShip *> m_landedShips;
+
+    // Static
+private:
+    static int m_incr; // Useful for indexing
+};
+
+
+#endif //SPACEEXPANSION_PLANET_H

+ 30 - 0
Contents/PlanetDef.h

@@ -0,0 +1,30 @@
+//
+// Created by jovian on 18/08/17.
+//
+
+#ifndef SPACEEXPANSION_PLANETDEF_H
+#define SPACEEXPANSION_PLANETDEF_H
+
+#include <string>
+#include <Box2D/Common/b2Math.h>
+#include "Stock.h"
+
+enum PlanetState {
+    EMPTY, INHABITED, MINOR, RESEARCH, FARMER, INDUSTRIAL
+};
+
+struct PlanetDef {
+    PlanetDef() : stock(), level(0), nuclearPlants(0),
+                  militaryPower(0), state(EMPTY), pos(), name("---"), size(1.0f) {};
+
+    Stock stock;
+    int level;
+    int nuclearPlants;
+    int militaryPower;
+    PlanetState state;
+    b2Vec2 pos;
+    std::string name;
+    float size;
+};
+
+#endif //SPACEEXPANSION_PLANETDEF_H

+ 72 - 0
Contents/StarShip.cpp

@@ -0,0 +1,72 @@
+//
+// Created by jovian on 17/08/17.
+//
+
+#include "StarShip.h"
+#include "../Maths/b2Angle.h"
+
+StarShip::StarShip(const StarShipDef &def) : m_def(def), m_angle(0.0f),
+                                             m_targetPlanet(NO_TARGET_PLANET), m_arrived(true) {}
+
+StarShip::~StarShip() {}
+
+Visual *StarShip::makeVisual() {
+    return new Visual((unsigned int) 6 + m_def.motor, m_def.pos, m_angle, 0.0142f * m_def.cargo);
+}
+
+void StarShip::update() {
+    if (!m_arrived) {
+        //todo Speed from motor
+        float speed(0.005f);
+
+        // Distance between this ship and targeted planet
+        b2Vec2 dir(m_targetPos - m_def.pos);
+        float dist(dir.Length());
+        if (dist < speed) {
+            // Arriving
+            m_arrived = true;
+        } else {
+            // Moving
+            dir *= speed / dist;
+            m_def.pos += dir;
+        }
+    }
+}
+
+Stock StarShip::unload() {
+    // Send into a probe
+    Stock probe(m_def.stock);
+
+    // Clear local stock
+    m_def.stock.setZero();
+
+    // Return probe to the planet
+    return probe;
+}
+
+void StarShip::load(Stock stock) {
+    // todo Check capacity
+    m_def.stock = stock;
+}
+
+void StarShip::travelTo(int targetPlanet, b2Vec2 targetPos) {
+    // Plot a course
+    m_targetPlanet = targetPlanet;
+    m_targetPos = targetPos;
+
+    // Let's go
+    m_arrived = false;
+    m_angle = b2Angle(m_targetPos - m_def.pos, b2Vec2(0.0f, -1.0f));
+}
+
+bool StarShip::isArrived() const {
+    return m_arrived;
+}
+
+int StarShip::getTargetPlanet() const {
+    return m_targetPlanet;
+}
+
+const StarShipDef &StarShip::getDef() const {
+    return m_def;
+}

+ 59 - 0
Contents/StarShip.h

@@ -0,0 +1,59 @@
+//
+// Created by jovian on 17/08/17.
+//
+
+#ifndef SPACEEXPANSION_STARSHIP_H
+#define SPACEEXPANSION_STARSHIP_H
+
+#include <Box2D/Common/b2Math.h>
+#include "../Graphics/Visual.h"
+#include "Stock.h"
+
+#define NO_TARGET_PLANET -1
+
+enum ShipMotor {
+    GAZ = 0, ION = 1, LASER = 2, ANTIMATER = 3, GRAVITY = 4, ALCUBIERRE = 5, HYPERDRIVE = 6
+};
+
+struct StarShipDef {
+    StarShipDef() : motor(GAZ), cargo(10), militaryPower(0), stock(),
+                    pos(0.0f, 0.0f) {};
+
+    ShipMotor motor;
+    int cargo;
+    int militaryPower;
+    Stock stock;
+    b2Vec2 pos;
+};
+
+class StarShip {
+    // Methods
+public:
+    StarShip(const StarShipDef &def);
+    virtual ~StarShip();
+
+    Visual *makeVisual();
+
+    void update();
+
+    Stock unload();
+    void load(Stock stock);
+
+    void travelTo(int targetPlanet, b2Vec2 targetPos);
+
+    bool isArrived() const;
+    int getTargetPlanet() const;
+    const StarShipDef &getDef() const;
+
+    // Attributes
+private:
+    StarShipDef m_def;
+
+    float m_angle;
+    int m_targetPlanet;
+    b2Vec2 m_targetPos;
+    bool m_arrived;
+};
+
+
+#endif //SPACEEXPANSION_STARSHIP_H

+ 107 - 0
Contents/Stock.cpp

@@ -0,0 +1,107 @@
+//
+// Created by jovian on 20/08/17.
+//
+
+#include "Stock.h"
+
+Stock::Stock() {
+    setZero();
+}
+
+int Stock::set(Resource res, int val) {
+    int prev(m_tab[res]);
+    m_tab[res] = val;
+    return prev;
+}
+
+int Stock::add(Resource res, int val) {
+    m_tab[res] += val;
+    return m_tab[res];
+}
+
+int Stock::get(Resource res) const {
+    return m_tab[res];
+}
+
+void Stock::setZero() {
+    for (int& res : m_tab) {
+        res = 0;
+    }
+}
+
+void Stock::setPositive() {
+    for (int& res : m_tab) {
+        if (res < 0)
+            res = 0;
+    }
+}
+
+Stock &Stock::operator+=(Stock const &stock) {
+    for (int id(0); id < RESOURCE_NUMBER; ++id) {
+        m_tab[id] += stock.m_tab[id];
+    }
+
+    return *this;
+}
+
+Stock &Stock::operator-=(Stock const &stock) {
+    for (int id(0); id < RESOURCE_NUMBER; ++id) {
+        m_tab[id] -= stock.m_tab[id];
+    }
+
+    return *this;
+}
+
+Stock &Stock::operator*=(int const& multi) {
+    for (int id(0); id < RESOURCE_NUMBER; ++id) {
+        m_tab[id] *= multi;
+    }
+
+    return *this;
+}
+
+Stock &Stock::operator/=(int const& multi) {
+    for (int id(0); id < RESOURCE_NUMBER; ++id) {
+        m_tab[id] /= multi;
+    }
+
+    return *this;
+}
+
+Resource Stock::mostResource() const {
+    int highest(0);
+    Resource most(ENERGY);
+
+    for (int res(0); res < RESOURCE_NUMBER; ++res) {
+        if (m_tab[res] > highest) {
+            highest = m_tab[res];
+            most = (Resource)res;
+        }
+    }
+
+    return most;
+}
+
+Stock operator+(Stock const &a, Stock const &b) {
+    Stock copy(a);
+    copy += b;
+    return copy;
+}
+
+Stock operator-(Stock const &a, Stock const &b) {
+    Stock copy(a);
+    copy -= b;
+    return copy;
+}
+
+Stock operator*(Stock const &a, int const &b) {
+    Stock copy(a);
+    copy *= b;
+    return copy;
+}
+
+Stock operator/(Stock const &a, int const &b) {
+    Stock copy(a);
+    copy /= b;
+    return copy;
+}

+ 63 - 0
Contents/Stock.h

@@ -0,0 +1,63 @@
+//
+// Created by jovian on 20/08/17.
+//
+
+#ifndef SPACEEXPANSION_STOCK_H
+#define SPACEEXPANSION_STOCK_H
+
+#include <array>
+
+#define RESOURCE_NUMBER 8
+enum Resource {
+    PEOPLE,
+    ORE,
+    METAL,
+    ENERGY,
+    NUCLEAR_ORE,
+    SOLAR_PANELS,
+    RADIOACTIVITY,
+    METAL_INDUSTRY,
+    SOLAR_INDUSTRY,
+    NUCLEAR_INDUSTRY,
+    SHIP_INDUSTRY,
+    SHIP_PROGRESS
+};
+
+class Stock {
+    // Methods
+public:
+    Stock();
+    // todo Copy constructor
+
+    int set(Resource res, int val); // Replace value and return the previous one
+    int add(Resource res, int val); // Add value and return total
+    int get(Resource res) const; // Read a value
+
+    void setZero(); // Set every value to zero
+    void setPositive(); // Set negative values to zero
+
+    Resource mostResource() const; // Return the most present resource
+
+    Stock &operator+=(Stock const &stock);
+
+    Stock &operator-=(Stock const &stock);
+
+    Stock &operator*=(int const &multi);
+
+    Stock &operator/=(int const &multi);
+
+    // Attributes
+private:
+    std::array<int, RESOURCE_NUMBER> m_tab;
+};
+
+Stock operator+(Stock const &a, Stock const &b);
+
+Stock operator-(Stock const &a, Stock const &b);
+
+Stock operator*(Stock const &a, int const &b);
+
+Stock operator/(Stock const &a, int const &b);
+
+
+#endif //SPACEEXPANSION_STOCK_H

+ 188 - 0
Contents/Universe.cpp

@@ -0,0 +1,188 @@
+//
+// Created by jovian on 17/08/17.
+//
+
+#include <iostream>
+#include "Universe.h"
+
+Universe::Universe() {}
+
+Universe::~Universe() {
+    // Planets
+    while (!m_planets.empty()) {
+        if (m_planets.back() != nullptr)
+            delete m_planets.back();
+
+        m_planets.pop_back();
+    }
+
+    // Ships
+    m_travellingShips.clear();
+
+    while (!m_ships.empty()) {
+        if (m_ships.back() != nullptr)
+            delete m_ships.back();
+
+        m_ships.pop_back();
+    }
+
+    // Rules
+    while (!m_rules.empty()) {
+        if (m_rules.back() != nullptr)
+            delete m_rules.back();
+
+        m_rules.pop_back();
+    }
+}
+
+void Universe::collectVisuals(std::vector<Visual *> &scope) {
+    // Sun
+    scope.push_back(new Visual(13, b2Vec2(0.0f, 0.0f), 0.0f));
+
+    // Planets
+    for (auto it(m_planets.begin()); it != m_planets.end(); it++)
+        scope.push_back((*it)->makeVisual());
+
+    // Ships
+    for (auto it(m_travellingShips.begin()); it != m_travellingShips.end(); it++)
+        scope.push_back((*it)->makeVisual());
+}
+
+void Universe::update() {
+    // Apply rules on planets
+    for (auto it_r(m_rules.begin()); it_r != m_rules.end(); it_r++) {
+        for (auto it_p(m_planets.begin()); it_p != m_planets.end(); it_p++) {
+            (*it_p)->applyRule(*it_r);
+        }
+    }
+
+    // Move ships
+    for (auto it(m_travellingShips.begin()); it != m_travellingShips.end(); it++)
+        (*it)->update();
+}
+
+void Universe::routeShips() {
+    // Check ready ships
+    bool ready(false);
+    auto it1(m_planets.begin());
+    while (it1 != m_planets.end() && !ready) {
+        ready = (*it1)->readyShip();
+        it1++;
+    }
+
+    // Compute needs
+    if (ready) {
+        // Compute average
+        Stock avrg;
+        for (auto it(m_planets.begin()); it != m_planets.end(); it++)
+            avrg += (*it)->getDef().stock;
+
+        avrg /= m_planets.size();
+
+        // Send ships
+        StarShip *ship(nullptr);
+        Resource majRes;
+
+        for (auto it(m_planets.begin()); it != m_planets.end(); it++) {
+            if ((*it)->readyShip()) {
+                // Get ship and most resource
+                ship = (*it)->launchShip(avrg);
+                b2Vec2 from(ship->getDef().pos);
+                majRes = ship->getDef().stock.mostResource();
+
+                // Seek a ideal planet
+                auto spottedPlanet(m_planets.begin());
+                bool notFound(true);
+
+                if (ship->getDef().stock.get(majRes) == 0) {
+                    // Seek a master planet
+                    for (auto itp(m_planets.begin()++); itp != m_planets.end(); itp++) {
+                        if (!(*itp)->need(PEOPLE, avrg) && (*itp)->getId() != (*it)->getId() &&
+                            (notFound || b2Distance((*spottedPlanet)->getDef().pos, from) >
+                                         b2Distance((*itp)->getDef().pos, from))) {
+                            spottedPlanet = itp;
+                            notFound = false;
+                        }
+                    }
+                } else {
+                    // Seek a needed planet
+                    for (auto itp(m_planets.begin()++); itp != m_planets.end(); itp++) {
+                        if ((*itp)->need(majRes, avrg) && (*itp)->getId() != (*it)->getId() &&
+                            (notFound || b2Distance((*spottedPlanet)->getDef().pos, from) >
+                                         b2Distance((*itp)->getDef().pos, from))) {
+                            spottedPlanet = itp;
+                            notFound = false;
+                        }
+                    }
+                }
+
+                // Go toward this planet
+                ship->travelTo((*spottedPlanet)->getId(), (*spottedPlanet)->getDef().pos);
+                m_travellingShips.insert(ship);
+            }
+        }
+    }
+
+    // Check arrived ships
+    auto it2(m_travellingShips.begin());
+    while (it2 != m_travellingShips.end()) {
+        if ((*it2)->isArrived()) {
+            m_planets[(*it2)->getTargetPlanet()]->landShip(*it2);
+            it2 = m_travellingShips.erase(it2);
+        } else {
+            it2++;
+        }
+    }
+
+}
+
+void Universe::createRandomUniverse() {
+    // todo better Universe::createRandomUniverse()
+    // Hand crafted universe
+    PlanetDef def;
+
+    for (int k(0); k < 12; k++) {
+        def.pos.Set((float)rand() / RAND_MAX * 8.0f - 4.0f, (float)rand() / RAND_MAX * 8.0f - 4.0f);
+        def.size = 0.2f + (float)rand() / RAND_MAX * 2.0f;
+        m_planets.push_back(new Planet(def));
+    }
+
+    def.pos.Set(1.0f, 1.0f);
+    def.stock.set(PEOPLE, 2);
+    def.name = "Earth";
+    def.size = 1.2f;
+    m_planets.push_back(new Planet(def));
+
+    // Debug ship
+    StarShipDef s_def;
+    s_def.stock.set(PEOPLE, 10);
+    s_def.pos = b2Vec2(5.0f, 1.3f); // m_planets[2]->getDef().pos
+    StarShip *myShip(new StarShip(s_def));
+
+    myShip->travelTo(m_planets[2]->getId(), m_planets[2]->getDef().pos);
+
+    m_ships.push_back(myShip);
+    m_travellingShips.insert(myShip);
+}
+
+void Universe::addRule(PlanetStep *rule) {
+    m_rules.push_back(rule);
+}
+
+const PlanetDef Universe::getNearestPlanetInfo(b2Vec2 from) {
+    // Void system
+    if (m_planets.empty())
+        return PlanetDef();
+
+    // Search minimum
+    auto spottedPlanet(m_planets.begin());
+
+    for (auto it(m_planets.begin()++); it != m_planets.end(); it++) {
+        if (b2Distance((*spottedPlanet)->getDef().pos, from) > b2Distance((*it)->getDef().pos, from))
+            spottedPlanet = it;
+    }
+
+    // Return def
+    return (*spottedPlanet)->getDef();
+}
+

+ 44 - 0
Contents/Universe.h

@@ -0,0 +1,44 @@
+//
+// Created by jovian on 17/08/17.
+//
+
+#ifndef SPACEEXPANSION_UNIVERSE_H
+#define SPACEEXPANSION_UNIVERSE_H
+
+#include <set>
+#include <vector>
+#include "Planet.h"
+#include "StarShip.h"
+#include "../Rules/PlanetStep.h"
+
+class Universe {
+    // Methods
+public:
+    Universe();
+
+    ~Universe();
+
+    void collectVisuals(std::vector<Visual *> &scope);
+
+    void update(); // Call update for each ship and each planet
+
+    void routeShips(); // Move ships between space and planets
+
+    void createRandomUniverse();
+
+    void addRule(PlanetStep *rule);
+
+    const PlanetDef getNearestPlanetInfo(b2Vec2 from);
+
+    // Attributes
+private:
+    std::vector<Planet *> m_planets;
+    std::vector<StarShip *> m_ships;
+
+    std::set<StarShip *> m_travellingShips;
+
+    std::vector<PlanetStep *> m_rules;
+};
+
+
+#endif //SPACEEXPANSION_UNIVERSE_H

+ 58 - 0
Control/Camera.cpp

@@ -0,0 +1,58 @@
+//
+// Created by jovian on 18/08/17.
+//
+
+#include "Camera.h"
+
+Camera::Camera() : m_pos(0.0f, 0.0f), m_cursorPos(0.0f, 0.0f), m_zoom(100.0f), m_press(false), m_infoWanted(false) {}
+
+Camera::~Camera() {}
+
+void Camera::refresh(Input *input) {
+    // Change position
+    if (input->isMouseMoving() && input->getMouseKey(MOUSE_RIGHT)) {
+        b2Vec2 move;
+        move.x = (float) input->getXRel() / m_zoom;
+        move.y = (float) input->getYRel() / m_zoom;
+
+        m_pos -= move;
+    }
+
+    // Zoom
+    if (input->getMouseKey(MOUSE_ANNEX_A))
+        m_zoom += 1.0f;
+
+    if (input->getMouseKey(MOUSE_ANNEX_B))
+        m_zoom -= 1.0f;
+
+    if (input->getMouseKey(MOUSE_MIDDLE))
+        m_zoom = 100.0f;
+
+    // Compute cursor position
+    m_cursorPos.x = m_pos.x + (float) input->getXFromCenter() / m_zoom;
+    m_cursorPos.y = m_pos.y + (float) input->getYFromCenter() / m_zoom;
+
+    // Info wanted
+    if (m_press != input->getMouseKey(MOUSE_LEFT)) {
+        if (!m_press)
+            m_infoWanted = !m_infoWanted;
+
+        m_press = input->getMouseKey(MOUSE_LEFT);
+    }
+}
+
+bool Camera::getInfoWanted() const {
+    return m_infoWanted;
+}
+
+const b2Vec2 &Camera::getPos() const {
+    return m_pos;
+}
+
+float Camera::getZoom() const {
+    return m_zoom;
+}
+
+const b2Vec2 &Camera::getCursorPos() const {
+    return m_cursorPos;
+}

+ 39 - 0
Control/Camera.h

@@ -0,0 +1,39 @@
+//
+// Created by jovian on 18/08/17.
+//
+
+#ifndef SPACEEXPANSION_CAMERA_H
+#define SPACEEXPANSION_CAMERA_H
+
+#include "Input.h"
+#include <Box2D/Common/b2Math.h>
+
+class Camera {
+    // Methods
+public:
+    Camera();
+
+    virtual ~Camera();
+
+    void refresh(Input *input);
+
+    bool getInfoWanted() const;
+
+    const b2Vec2 &getPos() const;
+
+    const b2Vec2 &getCursorPos() const;
+
+    float getZoom() const;
+
+    // Attributes
+private:
+    b2Vec2 m_pos;
+    b2Vec2 m_cursorPos;
+    float m_zoom;
+
+    bool m_press;
+    bool m_infoWanted;
+};
+
+
+#endif //SPACEEXPANSION_CAMERA_H

+ 166 - 0
Control/Input.cpp

@@ -0,0 +1,166 @@
+#include "Input.h"
+
+
+// Constructor
+Input::Input()
+        : m_x(0), m_y(0), m_xRel(0), m_yRel(0),
+          m_finished(false), m_relativeMouse(false), m_window(0), m_windowHalfHeight(0), m_windowHalfWidth(0) {
+    // Initialisation du tableau m_keys[]
+    for (int i(0); i < SDL_NUM_SCANCODES; i++)
+        m_keys[i] = false;
+
+    // Initialisation du tableau m_mouseKeys[]
+    for (int i(0); i < 8; i++)
+        m_mouseKeys[i] = false;
+}
+
+// Destructor
+Input::~Input() {}
+
+
+// Methods
+void Input::updateEvents() {
+    // Reset relative coordinates
+    m_xRel = 0;
+    m_yRel = 0;
+
+    // Clear instant keys
+    m_instantKeys.clear();
+
+    // Event loop
+    while (SDL_PollEvent(&m_event)) {
+        if (catchKeyBoardEvents(m_event))
+            continue;
+        else if (catchMouseEvents(m_event))
+            continue;
+        else
+            catchWindowEvents(m_event);
+    }
+
+    // Keeping mouse in window
+    if (m_relativeMouse)
+        SDL_WarpMouseInWindow(m_window, m_windowHalfWidth, m_windowHalfHeight);
+}
+
+bool Input::catchKeyBoardEvents(const SDL_Event &event) {
+    switch (event.type) {
+        case SDL_KEYDOWN:
+            m_keys[event.key.keysym.scancode] = true;
+            m_instantKeys.insert(event.key.keysym.scancode);
+            return true;
+        case SDL_KEYUP:
+            m_keys[event.key.keysym.scancode] = false;
+            return true;
+        default:
+            return false;
+    }
+}
+
+bool Input::catchMouseEvents(const SDL_Event &event) {
+    switch (event.type) {
+        case SDL_MOUSEBUTTONDOWN:
+            m_mouseKeys[event.button.button] = true;
+            return true;
+        case SDL_MOUSEBUTTONUP:
+            m_mouseKeys[event.button.button] = false;
+            return true;
+        case SDL_MOUSEMOTION:
+            if (m_relativeMouse) {
+                m_xRel = event.motion.x - m_windowHalfWidth;
+                m_yRel = event.motion.y - m_windowHalfHeight;
+            } else {
+                m_x = event.motion.x;
+                m_y = event.motion.y;
+                m_xRel = event.motion.xrel;
+                m_yRel = event.motion.yrel;
+            }
+            return true;
+        default:
+            return false;
+    }
+}
+
+bool Input::catchWindowEvents(const SDL_Event &event) {
+    switch (event.type) {
+        case SDL_WINDOWEVENT:
+            if (event.window.event == SDL_WINDOWEVENT_CLOSE)
+                m_finished = true;
+            return true;
+        default:
+            return false;
+    }
+}
+
+bool Input::isFinished() const {
+    return m_finished;
+}
+
+
+void Input::showCursor(bool flag) const {
+    if (flag)
+        SDL_ShowCursor(SDL_ENABLE);
+    else
+        SDL_ShowCursor(SDL_DISABLE);
+}
+
+
+void Input::capPtr(bool flag) {
+    m_relativeMouse = flag;
+}
+
+
+// Getters
+bool Input::getKey(const SDL_Scancode key) const {
+    return m_keys[key];
+}
+
+bool Input::getInstantKey(const SDL_Scancode key) const {
+    return m_instantKeys.find(key) != m_instantKeys.end();
+}
+
+bool Input::getMouseKey(const Uint8 key) const {
+    return m_mouseKeys[key];
+}
+
+
+bool Input::isMouseMoving() const {
+    return !(m_xRel == 0 && m_yRel == 0);
+}
+
+
+// Getters upon cursor position
+int Input::getX() const {
+    return m_x;
+}
+
+int Input::getY() const {
+    return m_y;
+}
+
+int Input::getXFromCenter() {
+    return m_x - m_windowHalfWidth;
+}
+
+int Input::getYFromCenter() {
+    return m_y - m_windowHalfHeight;
+}
+
+int Input::getXRel() const {
+    return m_xRel;
+}
+
+int Input::getYRel() const {
+    return m_yRel;
+}
+
+void Input::setWindow(SDL_Window *activWindow) {
+    // Direct relation
+    m_window = activWindow;
+
+    // Middle computation
+    SDL_GetWindowSize(activWindow, &m_windowHalfWidth, &m_windowHalfHeight);
+    m_windowHalfWidth /= 2;
+    m_windowHalfHeight /= 2;
+}
+
+

+ 85 - 0
Control/Input.h

@@ -0,0 +1,85 @@
+#ifndef DEF_INPUT
+#define DEF_INPUT
+
+///Jovian
+///Centralisation du traitement d'évènement
+
+// Include
+#include <set>
+#include <SDL.h>
+
+#define MOUSE_LEFT 1
+#define MOUSE_MIDDLE 2
+#define MOUSE_RIGHT 3
+#define MOUSE_ANNEX_A 4
+#define MOUSE_ANNEX_B 5
+
+class Input {
+    /// Methods
+public:
+
+    Input();
+
+    virtual ~Input();
+
+    virtual void updateEvents();
+
+protected: // Deal with an event, return true if caught
+    bool catchKeyBoardEvents(const SDL_Event &event);
+
+    bool catchMouseEvents(const SDL_Event &event);
+
+    bool catchWindowEvents(const SDL_Event &event);
+
+public:
+    bool isFinished() const;
+
+    void showCursor(bool flag) const;
+
+    void capPtr(bool flag);
+
+    bool getKey(const SDL_Scancode key) const;
+
+    bool getInstantKey(const SDL_Scancode key) const;
+
+    bool getMouseKey(const Uint8 key) const;
+
+    bool isMouseMoving() const;
+
+    int getX() const;
+
+    int getY() const;
+
+    int getXFromCenter();
+
+    int getYFromCenter();
+
+    int getXRel() const;
+
+    int getYRel() const;
+
+    void setWindow(SDL_Window *activWindow);
+
+    /// Variables
+protected:
+
+    SDL_Event m_event;
+    bool m_keys[SDL_NUM_SCANCODES];
+    std::set<SDL_Scancode> m_instantKeys;
+    bool m_mouseKeys[8];
+
+    int m_x;
+    int m_y;
+    int m_xRel;
+    int m_yRel;
+
+    bool m_finished;
+    bool m_relativeMouse;
+
+    SDL_Window *m_window;
+    int m_windowHalfHeight;
+    int m_windowHalfWidth;
+};
+
+#endif
+

+ 123 - 0
GameCore.cpp

@@ -0,0 +1,123 @@
+//
+// Created by jovian on 18/07/17.
+//
+
+// Basics
+#include <iostream>
+#include "GameCore.h"
+
+//Rules
+#include "Rules/PeopleExpGrowth.h"
+#include "Rules/PeopleMinimalGrowth.h"
+
+GameCore::GameCore()
+        : m_input(nullptr), m_rend(nullptr), m_universe(nullptr), m_camera(nullptr) {}
+
+GameCore::~GameCore() {
+    // Input
+    if (m_input != nullptr) {
+        delete m_input;
+        m_input = nullptr;
+    }
+
+    // Destroy SDL renderer
+    if (m_rend != nullptr) {
+        delete m_rend;
+        m_rend = nullptr;
+    }
+
+    // Destroy universe :-(
+    if (m_universe != nullptr) {
+        delete m_universe;
+        m_universe = nullptr;
+    }
+
+    // Destroy camera
+    if (m_camera != nullptr) {
+        delete m_camera;
+        m_camera = nullptr;
+    }
+}
+
+bool GameCore::initialize() {
+    // Already initialized
+    if (m_input != nullptr)
+        return false;
+
+    // Error check
+    bool okay(true);
+
+    // Create display
+    m_rend = new Renderer;
+    okay = okay && m_rend->initialize();
+
+    // Create hardware interface
+    m_input = new Input;
+    m_input->setWindow(m_rend->getWindow());
+
+    // Create an empty universe
+    m_universe = new Universe;
+    m_universe->createRandomUniverse();
+
+    // Create a basic camera
+    m_camera = new Camera;
+
+    // End
+    return okay;
+}
+
+void GameCore::startQuickGame() {
+    // Time
+    Uint32 frameRate(60); // Frame per second
+    Uint32 prevTime(0); // Previous chrono
+    Uint32 waitTime(1000 / frameRate); // Time to wait between each frame
+    Uint32 osBuffer(4); // To prevent SDL_Delay mistake : high > less mistake, more CPU usage
+
+    // Textures
+    std::vector<Visual *> myScope;
+
+    // Set up scenario
+    m_universe->addRule(new PeopleMinimalGrowth(4));
+
+    // Main loop
+    while (!m_input->isFinished() && !m_input->getKey(SDL_SCANCODE_ESCAPE)) {
+        // Update events
+        m_input->updateEvents();
+
+        // Update universe
+        m_universe->update();
+        m_universe->routeShips();
+
+        // Move camera
+        m_camera->refresh(m_input);
+
+        // Clear visuals
+        clearVisuals(myScope);
+
+        // Gather visuals
+        m_universe->collectVisuals(myScope);
+
+        // Rendering
+        m_rend->clearWindow();
+
+        m_rend->renderScene(myScope, m_camera->getPos(), m_camera->getZoom());
+
+        if (m_camera->getInfoWanted())
+            m_rend->renderPlanetHUD(m_universe->getNearestPlanetInfo(m_camera->getCursorPos()));
+
+        m_rend->presentWindow();
+
+        // todo Remove debug
+        /*Uint32 debug_conso(SDL_GetTicks() - prevTime);
+        std::cout << "Time use : " << debug_conso << std::endl;*/
+
+        // Pause
+        if (SDL_GetTicks() + osBuffer < prevTime + waitTime)
+            SDL_Delay(waitTime + prevTime - SDL_GetTicks() - osBuffer);
+
+        while (SDL_GetTicks() < prevTime + waitTime) {}
+
+        prevTime = SDL_GetTicks();
+    }
+}
+

+ 34 - 0
GameCore.h

@@ -0,0 +1,34 @@
+//
+// Created by jovian on 18/07/17.
+//
+
+#ifndef TINYSHOOTER_GAMECORE_H
+#define TINYSHOOTER_GAMECORE_H
+
+// Read hardware commands
+#include "Control/Input.h"
+#include "Control/Camera.h"
+
+// For game display
+#include "Graphics/Renderer.h"
+
+// Host stars and planets
+#include "Contents/Universe.h"
+
+class GameCore {
+public :
+    GameCore();
+    virtual ~GameCore();
+
+    bool initialize(); // Create attributes, return false if failure occurred
+    void startQuickGame(); // Start a default game
+
+protected:
+    Input *m_input;
+    Renderer *m_rend;
+    Universe *m_universe;
+    Camera *m_camera;
+};
+
+
+#endif //TINYSHOOTER_GAMECORE_H

+ 409 - 0
Graphics/Renderer.cpp

@@ -0,0 +1,409 @@
+//
+// Created by jovian on 18/07/17.
+//
+
+#include <iostream>
+#include <SDL_image.h>
+#include "Renderer.h"
+
+#define RAD_TO_DEG 57.2957795130f
+
+Renderer::Renderer()
+        : m_screenWidth(0), m_screenHeight(0), m_window(nullptr), m_renderer(nullptr), m_font(nullptr) {}
+
+Renderer::~Renderer() {
+    // Destroy textures
+    while (!m_pictureTab.empty()) {
+        if (m_pictureTab.back() != nullptr)
+            SDL_DestroyTexture(m_pictureTab.back());
+        m_pictureTab.pop_back();
+    }
+
+    // Destroy string textures
+    for (auto it(m_stringTab.begin()); it != m_stringTab.end(); it++) {
+        if (it->second != nullptr)
+            SDL_DestroyTexture(it->second);
+
+        it->second = nullptr;
+    }
+    m_stringTab.clear();
+
+    // Destroy SDL renderer
+    if (m_renderer != nullptr) {
+        SDL_DestroyRenderer(m_renderer);
+        m_renderer = nullptr;
+    }
+
+    // Destroy the beautiful window
+    if (m_window != nullptr) {
+        SDL_DestroyWindow(m_window);
+        m_window = nullptr;
+    }
+
+    // Quit modules
+    TTF_Quit();
+    IMG_Quit();
+    SDL_Quit();
+}
+
+bool Renderer::initialize() {
+    // Announce
+    std::cout << "Renderer::initialize() > ";
+
+    // Already initialized
+    if (m_window != nullptr) {
+        std::cout << "Window already created." << std::endl << std::endl;
+        return false;
+    }
+
+    // Default screen size
+    m_screenWidth = 1200;
+    m_screenHeight = 700;
+
+    // Init video
+    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
+        std::cout << "SDL video failed : " << SDL_GetError() << std::endl << std::endl;
+        return false;
+    }
+
+    // Init font
+    if (TTF_Init() == -1) {
+        std::cout << "TTF failed : " << TTF_GetError() << std::endl << std::endl;
+        return false;
+    }
+
+    m_font = TTF_OpenFont("droid.ttf", 28);
+    if (m_font == NULL) {
+        std::cout << "Open droid.ttf failed : " << TTF_GetError() << std::endl << std::endl;
+        return false;
+    }
+
+    // Opening window
+    m_window = SDL_CreateWindow("SpaceExpansion",
+                                SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+                                m_screenWidth, m_screenHeight,
+                                SDL_WINDOW_SHOWN /*| SDL_WINDOW_FULLSCREEN_DESKTOP*/);
+    if (m_window == nullptr) {
+        std::cout << "Window creation failed : " << SDL_GetError() << std::endl << std::endl;
+        SDL_Quit();
+        return false;
+    }
+
+    // Hardware physical screen size
+    SDL_GetWindowSize(m_window, &m_screenWidth, &m_screenHeight);
+
+    // Create renderer
+    m_renderer = SDL_CreateRenderer(m_window, -1,
+                                    SDL_RENDERER_ACCELERATED |
+                                    SDL_RENDERER_PRESENTVSYNC);
+    if (m_renderer == nullptr) {
+        SDL_DestroyWindow(m_window);
+        std::cout << "SDL Renderer creation failed : " << SDL_GetError() << std::endl << std::endl;
+        SDL_Quit();
+        return false;
+    }
+
+    // End
+    std::cout << "Done, no error detected." << std::endl;
+
+    // Okay
+    return loadEveryPicture();
+}
+
+void Renderer::clearWindow() {
+    // Clean up buffer
+    SDL_SetRenderDrawColor(m_renderer, 0x00, 0x00, 0x00, 0x00);
+    SDL_RenderClear(m_renderer);
+}
+
+void Renderer::renderScene(std::vector<Visual *> &scope, const b2Vec2 &center, float zoom) {
+    // Texture existence
+    if (m_pictureTab.empty())
+        return;
+
+    // Rect
+    SDL_Rect dst;
+    SDL_Texture *tex;
+    b2Vec2 rel;
+    float localZoom;
+
+    // For each
+    for (auto it(scope.begin()); it != scope.end(); it++) {
+        // Skip if no invalid texture
+        if ((*it)->getImgId() > m_pictureTab.size() || m_pictureTab[(*it)->getImgId()] == nullptr)
+            tex = m_pictureTab[0];
+        else
+            tex = m_pictureTab[(*it)->getImgId()];
+
+        // Adjusting local zoom
+        localZoom = zoom * (*it)->getScale();
+
+        // Rect set up
+        rel = (*it)->getPos() - center;
+        dst.x = (int) (rel.x * zoom) + m_screenWidth / 2;
+        dst.y = (int) (rel.y * zoom) + m_screenHeight / 2;
+        SDL_QueryTexture(tex, NULL, NULL, &dst.w, &dst.h);
+
+        // Zoom correction
+        dst.w = (int) (localZoom * dst.w / DEFAULT_ZOOM);
+        dst.h = (int) (localZoom * dst.h / DEFAULT_ZOOM);
+
+        // Center texture
+        dst.x -= dst.w / 2;
+        dst.y -= dst.h / 2;
+
+        // SDL rendering
+        SDL_RenderCopyEx(m_renderer, tex, NULL, &dst, (*it)->getAngle() * RAD_TO_DEG, NULL, SDL_FLIP_NONE);
+    }
+
+}
+
+void Renderer::renderPlanetHUD(PlanetDef def) {
+    // Variable
+    SDL_Rect dst;
+
+    // Line under color
+    const Uint8 uncl(0xaf);
+
+    // Render rect
+    dst.x = 10;
+    dst.y = 10;
+    int w = m_screenWidth / 2 - 2*dst.x + 24;
+    int h = m_screenHeight * 2 / 3 - 2*dst.y;
+    dst.w = w;
+    dst.h = h;
+
+    SDL_SetRenderDrawColor(m_renderer, 0x66, 0x66, 0x66, 0xff);
+    SDL_RenderFillRect(m_renderer, &dst);
+
+    SDL_SetRenderDrawColor(m_renderer, 0xff, 0xff, 0xff, 0xff);
+    SDL_RenderDrawRect(m_renderer, &dst);
+    SDL_RenderDrawLine(m_renderer, dst.x, dst.y + 37, dst.x + dst.w - 1, dst.y + 37);
+
+    // Render planet name
+    dst.x = 11;
+    dst.y = 11;
+    renderName(dst, def.name);
+
+    // Column
+    dst.x = 20;
+
+    // Jumps
+#define H_NEXT_BAR 32
+#define H_OFFSET_BAR 10
+
+    // People
+    dst.y = 60;
+    SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
+    SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
+    renderName(dst, "People");
+    renderBar(dst.y + H_OFFSET_BAR, def.stock.get(PEOPLE));
+
+    // Ore
+    dst.y += H_NEXT_BAR;
+    SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
+    SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
+    renderName(dst, "Ore");
+    renderBar(dst.y + H_OFFSET_BAR, def.stock.get(ORE));
+
+    // Metal
+    dst.y += H_NEXT_BAR;
+    SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
+    SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
+    renderName(dst, "Metal");
+    renderBar(dst.y + H_OFFSET_BAR, def.stock.get(METAL));
+
+    // Energy
+    dst.y += H_NEXT_BAR;
+    SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
+    SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
+    renderName(dst, "Energy");
+    renderBar(dst.y + H_OFFSET_BAR, def.stock.get(ENERGY));
+
+    // Nuclear ore
+    dst.y += H_NEXT_BAR;
+    SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
+    SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
+    renderName(dst, "Nuclear ore");
+    renderBar(dst.y + H_OFFSET_BAR, def.stock.get(NUCLEAR_ORE));
+
+    // Solar panels
+    dst.y += H_NEXT_BAR;
+    SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
+    SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
+    renderName(dst, "Solar panels");
+    renderBar(dst.y + H_OFFSET_BAR, def.stock.get(SOLAR_PANELS));
+
+    // Radioactivity
+    dst.y += H_NEXT_BAR;
+    SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
+    SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
+    renderName(dst, "Radioactivity");
+    renderBar(dst.y + H_OFFSET_BAR, def.stock.get(RADIOACTIVITY));
+
+    // Metal industry
+    dst.y += H_NEXT_BAR;
+    SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
+    SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
+    renderName(dst, "Metal industry");
+    renderBar(dst.y + H_OFFSET_BAR, def.stock.get(METAL_INDUSTRY));
+
+    // Solar industry
+    dst.y += H_NEXT_BAR;
+    SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
+    SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
+    renderName(dst, "Solar industry");
+    renderBar(dst.y + H_OFFSET_BAR, def.stock.get(SOLAR_INDUSTRY));
+
+    // Nuclear industry
+    dst.y += H_NEXT_BAR;
+    SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
+    SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
+    renderName(dst, "Nuke industry");
+    renderBar(dst.y + H_OFFSET_BAR, def.stock.get(NUCLEAR_INDUSTRY));
+
+    // Ship industry
+    dst.y += H_NEXT_BAR;
+    SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
+    SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
+    renderName(dst, "Ship industry");
+    renderBar(dst.y + H_OFFSET_BAR, def.stock.get(SHIP_INDUSTRY));
+
+    // Ship progress
+    dst.y += H_NEXT_BAR;
+    SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
+    SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
+    renderName(dst, "Ship progress");
+    renderBar(dst.y + H_OFFSET_BAR, def.stock.get(SHIP_PROGRESS));
+}
+
+void Renderer::renderName(SDL_Rect &dst, std::string name) {
+    // Seek an existing name texture
+    auto it(m_stringTab.find(name));
+
+    if (it == m_stringTab.end()) {
+        // Not loaded yet, let's fix this !
+        if (!loadStringTexture(name))
+            return;
+
+        SDL_QueryTexture(m_stringTab[name], NULL, NULL, &dst.w, &dst.h);
+        SDL_RenderCopy(m_renderer, m_stringTab[name], NULL, &dst);
+    }
+    else {
+        // Faster plot
+        SDL_QueryTexture(it->second, NULL, NULL, &dst.w, &dst.h);
+        SDL_RenderCopy(m_renderer, it->second, NULL, &dst);
+    }
+}
+
+void Renderer::renderBar(int y, const int &value) {
+    // Set position
+    SDL_Rect dst;
+    dst.x = 208;
+    dst.y = y;
+    dst.h = 16;
+
+    // Set color and scale
+    if (value == 0) {
+        SDL_SetRenderDrawColor(m_renderer, 0x00, 0x00, 0x00, 0xff);
+        dst.w = dst.h;
+    }
+    else if (value < 400) {
+        SDL_SetRenderDrawColor(m_renderer, 0x00, 0xff, 0x00, 0xff);
+        dst.w = value;
+    }
+    else if (value < 4000) {
+        SDL_SetRenderDrawColor(m_renderer, 0xff, 0xff, 0x00, 0xff);
+        dst.w = value / 10;
+    }
+    else if (value < 400000) {
+        SDL_SetRenderDrawColor(m_renderer, 0xff, 0xaa, 0x00, 0xff);
+        dst.w = value / 1000;
+    }
+    else if (value < 40000000) {
+        SDL_SetRenderDrawColor(m_renderer, 0xff, 0x55, 0x00, 0xff);
+        dst.w = value / 100000;
+    }
+    else {
+        SDL_SetRenderDrawColor(m_renderer, 0xff, 0x00, 0x00, 0xff);
+        dst.w = value / 10000000;
+    }
+
+    // Draw
+    SDL_RenderFillRect(m_renderer, &dst);
+    SDL_SetRenderDrawColor(m_renderer, 0xaf, 0xaf, 0xaf, 0xff);
+    if (value == 0) {
+        SDL_RenderDrawLine(m_renderer, dst.x, dst.y, dst.x + dst.w - 1, dst.y + dst.h - 1);
+        SDL_RenderDrawLine(m_renderer, dst.x, dst.y + dst.h - 1, dst.x + dst.w - 1, dst.y);
+    } else {
+        dst.w = 400;
+    }
+    SDL_RenderDrawRect(m_renderer, &dst);
+}
+
+void Renderer::presentWindow() {
+    // Activate display
+    SDL_RenderPresent(m_renderer);
+}
+
+bool Renderer::loadPicture(std::string name) {
+    SDL_Texture *texture = IMG_LoadTexture(m_renderer, name.c_str());
+
+    if (texture == nullptr) {
+        std::cout << "Renderer::loadPicture() > " << SDL_GetError() << std::endl << std::endl;
+        return false;
+    }
+
+    m_pictureTab.push_back(texture);
+    return true;
+}
+
+bool Renderer::loadStringTexture(std::string name) {
+    // Render text surface
+    //SDL_Surface* textSurface = TTF_RenderText_Solid(m_font, name.c_str(), {0, 255, 0, 255});
+    SDL_Surface* textSurface = TTF_RenderText_Shaded(m_font, name.c_str(), {0x00, 0xff, 0x00, 0xff}, {0x66, 0x66, 0x66, 0xff});
+
+    if (textSurface == NULL) {
+        std::cout << "Renderer::loadStringTexture() [1] > " << TTF_GetError() << std::endl << std::endl;
+        return false;
+    }
+
+    // Create texture from surface pixels
+    SDL_Texture* texture(SDL_CreateTextureFromSurface(m_renderer, textSurface));
+    SDL_FreeSurface(textSurface);
+
+    if (texture == NULL) {
+        std::cout << "Renderer::loadStringTexture() [2] > " << SDL_GetError() << std::endl << std::endl;
+        return false;
+    }
+
+    m_stringTab[name] = texture;
+
+    // All right
+    return true;
+}
+
+bool Renderer::loadEveryPicture() {
+    bool okay(true);
+    okay = okay && loadPicture("Pictures/NoPict.png");          // 0
+    okay = okay && loadPicture("Pictures/Planet1.png");         // 1
+    okay = okay && loadPicture("Pictures/Planet2.png");         // 2
+    okay = okay && loadPicture("Pictures/Planet3.png");         // 3
+    okay = okay && loadPicture("Pictures/Planet4.png");         // 4
+    okay = okay && loadPicture("Pictures/Planet5.png");         // 5
+    okay = okay && loadPicture("Pictures/Ship1Gaz.png");        // 6
+    okay = okay && loadPicture("Pictures/Ship2Ion.png");        // 7
+    okay = okay && loadPicture("Pictures/Ship3Laser.png");      // 8
+    okay = okay && loadPicture("Pictures/Ship4AntiMater.png");  // 9
+    okay = okay && loadPicture("Pictures/Ship5Gravity.png");    // 10
+    okay = okay && loadPicture("Pictures/Ship6Alcubierre.png"); // 11
+    okay = okay && loadPicture("Pictures/Ship7Hyperdrive.png"); // 12
+    okay = okay && loadPicture("Pictures/Sun.png"); // 13
+
+    return okay;
+}
+
+SDL_Window *Renderer::getWindow() const {
+    return m_window;
+}
+

+ 49 - 0
Graphics/Renderer.h

@@ -0,0 +1,49 @@
+//
+// Created by jovian on 18/07/17.
+//
+
+#ifndef TINYSHOOTER_RENDERER_H
+#define TINYSHOOTER_RENDERER_H
+
+#include <SDL.h>
+#include <vector>
+#include <map>
+#include <SDL_ttf.h>
+#include "Visual.h"
+#include "../Contents/PlanetDef.h"
+
+class Renderer {
+public :
+    Renderer();
+
+    virtual ~Renderer();
+
+    bool initialize(); // Initialize SDL and load features (return false if error)
+
+    void clearWindow(); // Clear all content
+    void renderScene(std::vector<Visual *> &scope, const b2Vec2 &center, float zoom); // Displays a view
+    void renderPlanetHUD(PlanetDef def);
+    void renderName(SDL_Rect &dst, std::string name);
+    void renderBar(int y, const int &value);
+    void presentWindow(); // Refresh window
+
+    SDL_Window *getWindow() const;
+
+private:
+    bool loadPicture(std::string name); // Load a single picture
+    bool loadStringTexture(std::string name); // Load a texture from a string
+    bool loadEveryPicture(); // Load all contents needed in the game
+
+protected:
+    int m_screenWidth;
+    int m_screenHeight;
+
+    SDL_Window *m_window; // SDL main window
+    SDL_Renderer *m_renderer; // SDL main renderer
+    TTF_Font *m_font; // TTF main font
+    std::vector<SDL_Texture *> m_pictureTab; // Every game texture
+    std::map<std::string, SDL_Texture *> m_stringTab; // Every game name texture
+};
+
+
+#endif //TINYSHOOTER_RENDERER_H

+ 35 - 0
Graphics/Visual.cpp

@@ -0,0 +1,35 @@
+//
+// Created by jovian on 18/07/17.
+//
+
+#include "Visual.h"
+
+Visual::Visual(unsigned int imgId, const b2Vec2 &relPos, float angle, float scale)
+        : m_imgId(imgId), m_relPos(relPos), m_angle(angle), m_scale(scale) {}
+
+unsigned int Visual::getImgId() const {
+    return m_imgId;
+}
+
+const b2Vec2 &Visual::getPos() const {
+    return m_relPos;
+}
+
+float Visual::getAngle() const {
+    return m_angle;
+}
+
+float Visual::getScale() const {
+    return m_scale;
+}
+
+void clearVisuals(std::vector<Visual *> &scope) {
+    while (!scope.empty()) {
+        if (scope.back() != nullptr) {
+            delete scope.back();
+            scope.back() = nullptr;
+        }
+
+        scope.pop_back();
+    }
+}

+ 36 - 0
Graphics/Visual.h

@@ -0,0 +1,36 @@
+//
+// Created by jovian on 18/07/17.
+//
+
+#ifndef TINYSHOOTER_VISUAL_H
+#define TINYSHOOTER_VISUAL_H
+
+#include <vector>
+#include <Box2D/Common/b2Math.h>
+
+/* class Visual :
+ * Describe something to show.
+ */
+
+#define DEFAULT_ZOOM 100.0f // Default Universe/pixel scale
+
+class Visual {
+public :
+    Visual(unsigned int imgId, const b2Vec2 &relPos, float angle, float scale = 1.0f);
+
+    unsigned int getImgId() const;
+    const b2Vec2 &getPos() const;
+    float getAngle() const;
+    float getScale() const;
+
+protected:
+    const unsigned int m_imgId; // Id of SDL texture
+    const b2Vec2 m_relPos; // From left top corner
+    const float m_angle; // Angle of object
+    const float m_scale; // Zoom multiplier
+};
+
+void clearVisuals(std::vector<Visual*> &scope);
+
+
+#endif //TINYSHOOTER_VISUAL_H

+ 20 - 0
Maths/b2Angle.cpp

@@ -0,0 +1,20 @@
+//
+// Created by jovian on 31/07/17.
+//
+
+#include "b2Angle.h"
+
+
+float b2Angle(b2Vec2 u, b2Vec2 v) {
+    u.Normalize();
+    v.Normalize();
+    float rep(std::acos(b2Dot(u, v)));
+    if ( b2Cross(u, v) > 0.0f )
+        rep *= -1.0f;
+
+    return rep;
+}
+
+float b2Angle(b2Vec2 u) {
+    return b2Angle(u, b2Vec2(1.0f, 0.0f));
+}

+ 25 - 0
Maths/b2Angle.h

@@ -0,0 +1,25 @@
+//
+// Created by jovian on 31/07/17.
+//
+
+#ifndef TINYSHOOTER_B2ANGLE_H
+#define TINYSHOOTER_B2ANGLE_H
+
+#include <Box2D/Box2D.h>
+
+/**
+ * Give angle between u and v
+ * @param u : First vector
+ * @param v : Second vector
+ * @return Float angle in radians
+ */
+float b2Angle(b2Vec2 u, b2Vec2 v);
+
+/**
+ * Give angle between u and horizon
+ * @param u : Vector
+ * @return Float angle in radians
+ */
+float b2Angle(b2Vec2 u);
+
+#endif //TINYSHOOTER_B2ANGLE_H

+ 16 - 0
Rules/PeopleExpGrowth.cpp

@@ -0,0 +1,16 @@
+//
+// Created by jovian on 18/08/17.
+//
+
+#include "PeopleExpGrowth.h"
+
+PeopleExpGrowth::PeopleExpGrowth(int delay, int divisor) : PlanetStep(delay), m_divisor(divisor) {
+
+}
+
+void PeopleExpGrowth::apply(PlanetDef &def) {
+    if (def.stock.get(PEOPLE) > 0) {
+        def.stock.add(PEOPLE, def.stock.get(PEOPLE) / m_divisor);
+        def.stock.add(PEOPLE, 1);
+    }
+}

+ 23 - 0
Rules/PeopleExpGrowth.h

@@ -0,0 +1,23 @@
+//
+// Created by jovian on 18/08/17.
+//
+
+#ifndef SPACEEXPANSION_PEOPLEGROWTH_H
+#define SPACEEXPANSION_PEOPLEGROWTH_H
+
+#include "PlanetStep.h"
+
+class PeopleExpGrowth : public PlanetStep {
+    // Method
+public:
+    PeopleExpGrowth(int delay = 100, int divisor = 1000);
+
+    void apply(PlanetDef &def) override;
+
+    // Attributes
+private:
+    const int m_divisor;
+};
+
+
+#endif //SPACEEXPANSION_PEOPLEGROWTH_H

+ 14 - 0
Rules/PeopleMinimalGrowth.cpp

@@ -0,0 +1,14 @@
+//
+// Created by jovian on 19/08/17.
+//
+
+#include "PeopleMinimalGrowth.h"
+
+PeopleMinimalGrowth::PeopleMinimalGrowth(int delay) : PlanetStep(delay) {}
+
+void PeopleMinimalGrowth::apply(PlanetDef &def) {
+    if (def.stock.get(PEOPLE) > 0) {
+        def.stock.add(PEOPLE, 1);
+    }
+}
+

+ 19 - 0
Rules/PeopleMinimalGrowth.h

@@ -0,0 +1,19 @@
+//
+// Created by jovian on 19/08/17.
+//
+
+#ifndef SPACEEXPANSION_PEOPLEMINIMALGROWTH_H
+#define SPACEEXPANSION_PEOPLEMINIMALGROWTH_H
+
+#include "PlanetStep.h"
+
+class PeopleMinimalGrowth : public PlanetStep {
+    // Methods
+public:
+    PeopleMinimalGrowth(int delay = 30);
+
+    void apply(PlanetDef &def) override;
+};
+
+
+#endif //SPACEEXPANSION_PEOPLEMINIMALGROWTH_H

+ 18 - 0
Rules/PlanetStep.cpp

@@ -0,0 +1,18 @@
+//
+// Created by jovian on 18/08/17.
+//
+
+#include "PlanetStep.h"
+
+PlanetStep::PlanetStep(int delay) : m_delay(delay), m_elapsed(0) {}
+
+void PlanetStep::callApply(PlanetDef &def) {
+    // Time is running out
+    m_elapsed++;
+
+    // Check if it is necessary
+    if (m_elapsed > m_delay) {
+        apply(def);
+        m_elapsed = 0;
+    }
+}

+ 27 - 0
Rules/PlanetStep.h

@@ -0,0 +1,27 @@
+//
+// Created by jovian on 18/08/17.
+//
+
+#ifndef SPACEEXPANSION_PLANETSTEP_H
+#define SPACEEXPANSION_PLANETSTEP_H
+
+#include "../Contents/PlanetDef.h"
+
+class PlanetStep {
+    // Methods
+public :
+    PlanetStep(int delay);
+
+    void callApply(PlanetDef &def); // Call apply if time is elapsed
+
+private:
+    virtual void apply(PlanetDef &def) = 0; // Apply rule
+
+    // Attributes
+protected:
+    const int m_delay; // Number of frames between each application
+    int m_elapsed;
+};
+
+
+#endif //SPACEEXPANSION_PLANETSTEP_H

+ 28 - 0
main.cpp

@@ -0,0 +1,28 @@
+// Includes
+#include <iostream>
+#include "GameCore.h"
+
+using namespace std;
+
+int main() {
+    // Start
+    cout << "SpaceExpansion starts." << endl;
+
+    // Random start
+    srand((unsigned int) time(0));
+
+    // Initialisation
+    GameCore spaceManager;
+
+    if (!spaceManager.initialize()){
+        cout << "SpaceExpansion has encountered a problem." << endl;
+        cout << "Ask Jovian to debug his program ..." << endl;
+        return 1;
+    }
+
+    // QuickGame
+    spaceManager.startQuickGame();
+
+    // End
+    return 0;
+}