From 96ab5904b059e00e78b26a6527790c8dc951e324 Mon Sep 17 00:00:00 2001
From: Daniel Karbach <daniel.karbach@localhorst.tv>
Date: Mon, 16 Dec 2013 07:42:43 +0100
Subject: [PATCH 1/1] grid view

---
 .gitignore                 |   5 ++
 build/config.mk            |  32 +++++++++
 build/debug/Makefile       |   7 ++
 build/release/Makefile     |   8 +++
 build/space.mk             |  77 ++++++++++++++++++++++
 build/targets.mk           |  10 +++
 src/app/Application.cpp    | 126 +++++++++++++++++++++++++++++++++++
 src/app/Application.h      |  52 +++++++++++++++
 src/entity/Ship.h          |  15 +++++
 src/graphics/Camera.cpp    |  17 +++++
 src/graphics/Camera.h      |  29 ++++++++
 src/graphics/Color.h       |  32 +++++++++
 src/graphics/Moveable.h    |  43 ++++++++++++
 src/graphics/primitive.cpp | 131 +++++++++++++++++++++++++++++++++++++
 src/graphics/primitive.h   |  40 +++++++++++
 src/math/Vector.h          |  94 ++++++++++++++++++++++++++
 src/sdl/InitSDL.cpp        |  20 ++++++
 src/sdl/InitSDL.h          |  22 +++++++
 src/sdl/InitScreen.cpp     |  40 +++++++++++
 src/sdl/InitScreen.h       |  33 ++++++++++
 src/space.cpp              |  19 ++++++
 src/world/Resource.cpp     |  18 +++++
 src/world/Resource.h       |  24 +++++++
 src/world/Sector.cpp       |  22 +++++++
 src/world/Sector.h         |  27 ++++++++
 src/world/Universe.cpp     |  27 ++++++++
 src/world/Universe.h       |  29 ++++++++
 27 files changed, 999 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 build/config.mk
 create mode 100644 build/debug/Makefile
 create mode 100644 build/release/Makefile
 create mode 100644 build/space.mk
 create mode 100644 build/targets.mk
 create mode 100644 src/app/Application.cpp
 create mode 100644 src/app/Application.h
 create mode 100644 src/entity/Ship.h
 create mode 100644 src/graphics/Camera.cpp
 create mode 100644 src/graphics/Camera.h
 create mode 100644 src/graphics/Color.h
 create mode 100644 src/graphics/Moveable.h
 create mode 100644 src/graphics/primitive.cpp
 create mode 100644 src/graphics/primitive.h
 create mode 100644 src/math/Vector.h
 create mode 100644 src/sdl/InitSDL.cpp
 create mode 100644 src/sdl/InitSDL.h
 create mode 100644 src/sdl/InitScreen.cpp
 create mode 100644 src/sdl/InitScreen.h
 create mode 100644 src/space.cpp
 create mode 100644 src/world/Resource.cpp
 create mode 100644 src/world/Resource.h
 create mode 100644 src/world/Sector.cpp
 create mode 100644 src/world/Sector.h
 create mode 100644 src/world/Universe.cpp
 create mode 100644 src/world/Universe.h

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..643d422
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+/build/*/space
+/build/*/src
+
+*.swp
+*.swo
diff --git a/build/config.mk b/build/config.mk
new file mode 100644
index 0000000..efbf376
--- /dev/null
+++ b/build/config.mk
@@ -0,0 +1,32 @@
+# commands
+CXX = g++ -std=c++11
+RM ?= rm -Rf
+MKDIR ?= mkdir -p
+RMDIR ?= rmdir -p --ignore-fail-on-non-empty
+
+# names and pathes
+BUILD := $(dir $(lastword $(MAKEFILE_LIST)))
+TOP := $(BUILD)..
+srcdir = $(TOP)/src
+
+# flags
+CPPFLAGS ?=
+CXXFLAGS ?=
+LDFLAGS ?=
+
+CXXFLAGS += -Wall -Werror
+
+# libraries
+SDL_FLAGS = $(shell pkg-config --cflags sdl)
+SDL_LIBS = $(shell pkg-config --libs sdl)
+
+SDL_IMG_FLAGS = $(shell pkg-config --cflags SDL_image)
+SDL_IMG_LIBS = $(shell pkg-config --libs SDL_image)
+
+CPPUNIT_FLAGS = $(shell pkg-config --cflags cppunit)
+CPPUNIT_LIBS = $(shell pkg-config --libs cppunit)
+
+# set to empty to show tool invocations
+VERBOSE = @
+
+-include $(BUILD)local-config.mk
diff --git a/build/debug/Makefile b/build/debug/Makefile
new file mode 100644
index 0000000..157c238
--- /dev/null
+++ b/build/debug/Makefile
@@ -0,0 +1,7 @@
+include ../targets.mk
+include ../config.mk
+include ../space.mk
+
+CXXFLAGS += -O0 -g3
+
+-include local.mk
diff --git a/build/release/Makefile b/build/release/Makefile
new file mode 100644
index 0000000..32bdbc4
--- /dev/null
+++ b/build/release/Makefile
@@ -0,0 +1,8 @@
+include ../targets.mk
+include ../config.mk
+include ../space.mk
+
+CPPFLAGS += -DNDEBUG
+CXXFLAGS += -O2
+
+-include local.mk
diff --git a/build/space.mk b/build/space.mk
new file mode 100644
index 0000000..8a6f147
--- /dev/null
+++ b/build/space.mk
@@ -0,0 +1,77 @@
+SPACE_DIRS := $(shell cd $(TOP) && find src -type d)
+SPACE_SRCS := $(shell cd $(TOP) && find src -type f -name '*.cpp')
+SPACE_DEPS = $(SPACE_SRCS:%.cpp=%.d)
+SPACE_OBJS = $(SPACE_SRCS:%.cpp=%.o)
+SPACE_EXES = space
+
+SPACE_TEST_DIRS := $(shell cd $(TOP) && find tests -type d)
+SPACE_TEST_SRCS := $(shell cd $(TOP) && find tests -type f -name '*.cpp')
+SPACE_TEST_DEPS := $(SPACE_TEST_SRCS:%.cpp=%.d)
+SPACE_TEST_OBJS := $(SPACE_TEST_SRCS:%.cpp=%.o)
+SPACE_TEST_EXES := test-all
+
+SPACE_FLAGS = $(sort $(strip \
+		$(SDL_FLAGS) \
+		$(SDL_IMG_FLAGS) \
+		))
+SPACE_LIBS = $(sort $(strip \
+		$(SDL_LIBS) \
+		$(SDL_IMG_LIBS) \
+		))
+
+SPACE_TEST_FLAGS = $(SPACE_FLAGS) $(CPPUNIT_FLAGS)
+SPACE_TEST_LIBS = $(SPACE_LIBS) $(CPPUNIT_LIBS)
+
+-include $(SPACE_DEPS)
+-include $(SPACE_TEST_DEPS)
+
+$(SPACE_OBJS): %.o: $(TOP)/%.cpp
+	-@$(MKDIR) "$(@D)"
+	@echo "compile: $@"
+	$(VERBOSE) $(CXX) -c -o "$@" -MMD -MP -MF"$*.d" -MT"$@" "$<" \
+			$(SPACE_FLAGS) $(CPPFLAGS) $(CXXFLAGS)
+
+$(SPACE_EXES): $(SPACE_OBJS)
+	-@$(MKDIR) "$(@D)"
+	@echo "link: $@"
+	$(VERBOSE) $(CXX) -o "$@" $^ \
+			$(SPACE_FLAGS) $(SPACE_LIBS) $(LDFLAGS)
+
+$(SPACE_TEST_OBJS): %.o: $(TOP)/%.cpp
+	-@$(MKDIR) "$(@D)"
+	@echo "compile: $@"
+	$(VERBOSE) $(CXX) -c -o "$@" -MMD -MP -MF"$*.d" -MT"$@" "$<" \
+			$(SPACE_TEST_FLAGS) $(CPPFLAGS) $(CXXFLAGS)
+
+$(SPACE_TEST_EXES): $(SPACE_TEST_OBJS) $(filter-out src/main.o, $(SPACE_OBJS))
+	-@$(MKDIR) "$(@D)"
+	@echo "link: $@"
+	$(VERBOSE) $(CXX) -o "$@" $^ \
+			$(SPACE_TEST_FLAGS) $(SPACE_TEST_LIBS) $(LDFLAGS)
+
+space-all: $(SPACE_EXES)
+
+space-clean:
+	$(VERBOSE) -$(RM) $(SPACE_DEPS)
+	$(VERBOSE) -$(RM) $(SPACE_OBJS)
+	$(VERBOSE) -$(RM) $(SPACE_EXES)
+	$(VERBOSE) -$(RM) $(SPACE_TEST_DEPS)
+	$(VERBOSE) -$(RM) $(SPACE_TEST_OBJS)
+	$(VERBOSE) -$(RM) $(SPACE_TEST_EXES)
+	$(VERBOSE) -$(RMDIR) $(SPACE_DIRS)
+	$(VERBOSE) -$(RMDIR) $(SPACE_TEST_DIRS)
+
+space-tests: $(SPACE_TEST_EXES)
+
+space-test-all: test-all
+	@echo "test: test-all"
+	$(VERBOSE) ./test-all
+
+all: space-all
+clean: space-clean
+tests: space-tests
+test: space-test-all
+
+.PHONY: space-all space-clean space-tests space-test-all
+
+-include $(BUILD)space-local.mk
diff --git a/build/targets.mk b/build/targets.mk
new file mode 100644
index 0000000..5793443
--- /dev/null
+++ b/build/targets.mk
@@ -0,0 +1,10 @@
+all:
+
+clean:
+	@echo "clean"
+
+tests:
+
+test:
+
+.PHONY: all clean tests test
diff --git a/src/app/Application.cpp b/src/app/Application.cpp
new file mode 100644
index 0000000..247819c
--- /dev/null
+++ b/src/app/Application.cpp
@@ -0,0 +1,126 @@
+#include "Application.h"
+
+#include "../graphics/Color.h"
+#include "../graphics/primitive.h"
+#include "../sdl/InitScreen.h"
+
+
+namespace space {
+
+Application::Application(InitScreen &s)
+: screen(s)
+, univ(10, 10, 10, 10, 10)
+, focus(Vector<float>(500, 500), 500)
+, cam(800, 800, focus.Pos())
+, last(SDL_GetTicks())
+, running(false) {
+
+}
+
+
+void Application::Run() {
+	running = true;
+	while (running) {
+		Uint32 now = SDL_GetTicks();
+		int delta = now - last;
+		Loop(delta);
+		last = now;
+	}
+}
+
+
+void Application::Loop(int delta) {
+	HandleEvents();
+	Update(delta);
+	Render();
+	screen.Flip();
+}
+
+
+void Application::HandleEvents() {
+	SDL_Event event;
+	while (SDL_PollEvent(&event)) {
+		switch (event.type) {
+			case SDL_QUIT:
+				running = false;
+				break;
+			case SDL_VIDEORESIZE:
+				screen.Resize(event.resize.w, event.resize.h);
+				cam.Resize(event.resize.w, event.resize.h);
+				break;
+			case SDL_KEYDOWN:
+				OnKeyDown(event.key);
+				break;
+			case SDL_KEYUP:
+				OnKeyUp(event.key);
+				break;
+			default:
+				// skip event
+				break;
+		}
+	}
+}
+
+void Application::OnKeyDown(const SDL_KeyboardEvent &e) {
+	switch (e.keysym.sym) {
+		case SDLK_UP:
+			focus.MoveUp();
+			break;
+		case SDLK_DOWN:
+			focus.MoveDown();
+			break;
+		case SDLK_LEFT:
+			focus.MoveLeft();
+			break;
+		case SDLK_RIGHT:
+			focus.MoveRight();
+			break;
+		default:
+			break;
+	}
+}
+
+void Application::OnKeyUp(const SDL_KeyboardEvent &e) {
+	switch (e.keysym.sym) {
+		case SDLK_UP:
+			focus.StopUp();
+			break;
+		case SDLK_DOWN:
+			focus.StopDown();
+			break;
+		case SDLK_LEFT:
+			focus.StopLeft();
+			break;
+		case SDLK_RIGHT:
+			focus.StopRight();
+			break;
+		default:
+			break;
+	}
+}
+
+
+void Application::Update(int dt) {
+	focus.Update(dt / 1e3);
+}
+
+
+void Application::Render() {
+	constexpr Color background(0x00, 0x00, 0x00);
+	constexpr Color univGrid(0xFF, 0xFF, 0xFF);
+	constexpr Color sectGrid(0xAA, 0xAA, 0xAA);
+
+	constexpr Vector<int> areaSize(10, 10);
+	constexpr Vector<int> sectSize(areaSize * 10);
+	constexpr Vector<int> univSize(sectSize * 10);
+
+	SDL_Surface *dst = screen.Screen();
+	Vector<int> offset = cam.Offset();
+
+	Fill(dst, background);
+	Grid(dst, offset, offset + univSize + Vector<int>(1, 1), areaSize, sectGrid);
+	Grid(dst, offset, offset + univSize + Vector<int>(1, 1), sectSize, univGrid);
+	Cross(dst, offset + Vector<int>(focus.Pos()), 15, Color(0xFF, 0xFF, 0x00));
+}
+
+}
diff --git a/src/app/Application.h b/src/app/Application.h
new file mode 100644
index 0000000..a852696
--- /dev/null
+++ b/src/app/Application.h
@@ -0,0 +1,52 @@
+#ifndef SPACE_APPLICATION_H_
+#define SPACE_APPLICATION_H_
+
+#include "../graphics/Camera.h"
+#include "../graphics/Moveable.h"
+#include "../math/Vector.h"
+#include "../world/Universe.h"
+
+#include <SDL/SDL.h>
+
+
+namespace space {
+
+class InitScreen;
+
+class Application {
+
+public:
+	explicit Application(InitScreen &);
+
+public:
+	void Run();
+
+private:
+	void Loop(int delta_ms);
+
+	void HandleEvents();
+	void OnKeyDown(const SDL_KeyboardEvent &);
+	void OnKeyUp(const SDL_KeyboardEvent &);
+
+	void Update(int delta_ms);
+
+	Vector<float> FocusVel() const;
+
+	void Render();
+
+private:
+	InitScreen &screen;
+
+	Universe univ;
+
+	Moveable<float> focus;
+	Camera cam;
+
+	Uint32 last;
+	bool running;
+
+};
+
+}
+
+#endif
diff --git a/src/entity/Ship.h b/src/entity/Ship.h
new file mode 100644
index 0000000..8bcc4bc
--- /dev/null
+++ b/src/entity/Ship.h
@@ -0,0 +1,15 @@
+#ifndef SPACE_SHIP_H_
+#define SPACE_SHIP_H_
+
+
+namespace space {
+
+class Ship {
+
+private:
+
+};
+
+}
+
+#endif
diff --git a/src/graphics/Camera.cpp b/src/graphics/Camera.cpp
new file mode 100644
index 0000000..0994a5a
--- /dev/null
+++ b/src/graphics/Camera.cpp
@@ -0,0 +1,17 @@
+#include "Camera.h"
+
+
+namespace space {
+
+Camera::Camera(int w, int h, const Vector<float> &t)
+: target(&t)
+, offset(w/2, h/2) {
+
+}
+
+
+void Camera::Resize(int w, int h) {
+	offset = Vector<float>(w/2, h/2);
+}
+
+}
diff --git a/src/graphics/Camera.h b/src/graphics/Camera.h
new file mode 100644
index 0000000..10699f0
--- /dev/null
+++ b/src/graphics/Camera.h
@@ -0,0 +1,29 @@
+#ifndef SPACE_CAMERA_H_
+#define SPACE_CAMERA_H_
+
+#include "../math/Vector.h"
+
+
+namespace space {
+
+class Camera {
+
+public:
+	Camera(int w, int h, const Vector<float> &);
+
+public:
+	void Resize(int w, int h);
+
+	Vector<float> Offset() {
+		return -(*target - offset);
+	}
+
+private:
+	const Vector<float> *target;
+	Vector<float> offset;
+
+};
+
+}
+
+#endif
diff --git a/src/graphics/Color.h b/src/graphics/Color.h
new file mode 100644
index 0000000..d561fc8
--- /dev/null
+++ b/src/graphics/Color.h
@@ -0,0 +1,32 @@
+#ifndef SPACE_COLOR_H_
+#define SPACE_COLOR_H_
+
+#include <SDL/SDL.h>
+
+
+namespace space {
+
+struct Color {
+
+	constexpr Color()
+	: Color(0, 0, 0) { }
+	constexpr Color(Uint8 r, Uint8 g, Uint8 b, Uint8 a = 0xFF)
+	: r(r), g(g), b(b), a(a) { }
+
+	Uint32 MapRGB(SDL_Surface *s) const
+		{ return MapRGB(s->format); }
+	Uint32 MapRGB(SDL_PixelFormat *f) const
+		{ return SDL_MapRGB(f, r, g, b); }
+
+	Uint32 MapRGBA(SDL_Surface *s) const
+		{ return MapRGBA(s->format); }
+	Uint32 MapRGBA(SDL_PixelFormat *f) const
+		{ return SDL_MapRGBA(f, r, g, b, a); }
+
+	Uint8 r, g, b, a;
+
+};
+
+}
+
+#endif
diff --git a/src/graphics/Moveable.h b/src/graphics/Moveable.h
new file mode 100644
index 0000000..b5fbfe5
--- /dev/null
+++ b/src/graphics/Moveable.h
@@ -0,0 +1,43 @@
+#ifndef SPACE_MOVEABLE_H_
+#define SPACE_MOVEABLE_H_
+
+#include "../math/Vector.h"
+
+
+namespace space {
+
+template<class Scalar>
+class Moveable {
+
+public:
+	Moveable(Vector<Scalar> pos, Scalar speed)
+	: dir(0, 0), pos(pos), speed(speed) { }
+
+public:
+	const Vector<Scalar> &Pos() const { return pos; }
+	Vector<Scalar> Vel() const { return Vector<Scalar>(dir) * speed; }
+
+	void Update(Scalar delta) {
+		pos += Vel() * delta;
+	}
+
+public:
+	void MoveUp() { dir.y -= 1; }
+	void StopUp() { dir.y += 1; }
+	void MoveDown() { dir.y += 1; }
+	void StopDown() { dir.y -= 1; }
+	void MoveLeft() { dir.x -= 1; }
+	void StopLeft() { dir.x += 1; }
+	void MoveRight() { dir.x += 1; }
+	void StopRight() { dir.x -= 1; }
+
+private:
+	Vector<int> dir;
+	Vector<Scalar> pos;
+	Scalar speed;
+
+};
+
+}
+
+#endif
diff --git a/src/graphics/primitive.cpp b/src/graphics/primitive.cpp
new file mode 100644
index 0000000..c97345a
--- /dev/null
+++ b/src/graphics/primitive.cpp
@@ -0,0 +1,131 @@
+#include "primitive.h"
+
+#include <algorithm>
+
+using namespace std;
+
+
+namespace space {
+
+void Fill(SDL_Surface *dst, Color c) {
+	Fill(dst, c.MapRGBA(dst));
+}
+
+void Fill(SDL_Surface *dst, Uint32 color) {
+	SDL_FillRect(dst, nullptr, color);
+}
+
+
+void HLine(SDL_Surface *dst, Vector<int> pos, int len, Color c) {
+	HLine(dst, pos, len, c.MapRGBA(dst));
+}
+
+void HLine(SDL_Surface *dst, Vector<int> pos, int len, Uint32 c) {
+	FillRect(dst, pos, Vector<int>(len, 1), c);
+}
+
+void VLine(SDL_Surface *dst, Vector<int> pos, int len, Color c) {
+	VLine(dst, pos, len, c.MapRGBA(dst));
+}
+
+void VLine(SDL_Surface *dst, Vector<int> pos, int len, Uint32 c) {
+	FillRect(dst, pos, Vector<int>(1, len), c);
+}
+
+
+void FillRect(SDL_Surface *dst, Vector<int> pos, Vector<int> size, Color c) {
+	FillRect(dst, pos, size, c.MapRGBA(dst));
+}
+
+void FillRect(SDL_Surface *dst, Vector<int> pos, Vector<int> size, Uint32 c) {
+	SDL_Rect destRect;
+	destRect.x = pos.x;
+	destRect.y = pos.y;
+	destRect.w = size.x;
+	destRect.h = size.y;
+	SDL_FillRect(dst, &destRect, c);
+}
+
+void OutlineRect(SDL_Surface *dst, Vector<int> pos, Vector<int> size, Color c) {
+	OutlineRect(dst, pos, size, c.MapRGBA(dst));
+}
+
+void OutlineRect(SDL_Surface *dst, Vector<int> pos, Vector<int> size, Uint32 c) {
+	SDL_Rect destRect;
+
+	destRect.x = pos.x;
+	destRect.y = pos.y;
+	destRect.w = size.x;
+	destRect.h = 1;
+	SDL_FillRect(dst, &destRect, c);
+
+	destRect.x = pos.x;
+	destRect.y = pos.y + size.y - 1;
+	destRect.w = size.x;
+	destRect.h = 1;
+	SDL_FillRect(dst, &destRect, c);
+
+	destRect.x = pos.x;
+	destRect.y = pos.y;
+	destRect.w = 1;
+	destRect.h = size.y;
+	SDL_FillRect(dst, &destRect, c);
+
+	destRect.x = pos.x + size.x - 1;
+	destRect.y = pos.y;
+	destRect.w = 1;
+	destRect.h = size.y;
+	SDL_FillRect(dst, &destRect, c);
+}
+
+
+void Cross(
+		SDL_Surface *dst,
+		Vector<int> pos,
+		int extent,
+		Color color) {
+	Uint32 c = color.MapRGBA(dst);
+	int len = 2 * extent + 1;
+
+	HLine(dst, Vector<int>(pos.x - extent, pos.y), len, c);
+	VLine(dst, Vector<int>(pos.x, pos.y - extent), len, c);
+}
+
+
+void Grid(
+		SDL_Surface *dst,
+		Vector<int> first,
+		Vector<int> second,
+		Vector<int> size,
+		Color color) {
+	Uint32 c = color.MapRGBA(dst);
+
+	Vector<int> from = min(first, second);
+	Vector<int> to = max(first, second);
+
+	if (size.x <= 1 || size.y <= 1) {
+		FillRect(dst, from, to - from, c);
+		return;
+	}
+
+	if (from.x > dst->w || from.y > dst->h || to.x < 0 || to.y < 0) {
+		return;
+	}
+
+	while (from.x < -size.x) from.x += size.x;
+	while (from.y < -size.y) from.y += size.y;
+	while (to.x > dst->w + size.x) to.x -= size.x;
+	while (to.y > dst->h + size.y) to.y -= size.y;
+
+	int width = to.x - from.x;
+	int height = to.y - from.y;
+
+	for (Vector<int> pos(from); pos.x <= to.x; pos.x += size.x) {
+		VLine(dst, pos, height, c);
+	}
+	for (Vector<int> pos(from); pos.y <= to.y; pos.y += size.y) {
+		HLine(dst, pos, width, c);
+	}
+}
+
+}
diff --git a/src/graphics/primitive.h b/src/graphics/primitive.h
new file mode 100644
index 0000000..133e1f9
--- /dev/null
+++ b/src/graphics/primitive.h
@@ -0,0 +1,40 @@
+#ifndef SPACE_PRIMITIVE_H_
+#define SPACE_PRIMITIVE_H_
+
+#include "Color.h"
+#include "../math/Vector.h"
+
+#include <SDL/SDL.h>
+
+
+namespace space {
+
+void Fill(SDL_Surface *, Color);
+void Fill(SDL_Surface *, Uint32 color);
+
+void HLine(SDL_Surface *, Vector<int> pos, int len, Color);
+void HLine(SDL_Surface *, Vector<int> pos, int len, Uint32 color);
+void VLine(SDL_Surface *, Vector<int> pos, int len, Color);
+void VLine(SDL_Surface *, Vector<int> pos, int len, Uint32 color);
+
+void FillRect(SDL_Surface *, Vector<int> pos, Vector<int> size, Color);
+void FillRect(SDL_Surface *, Vector<int> pos, Vector<int> size, Uint32 color);
+void OutlineRect(SDL_Surface *, Vector<int> pos, Vector<int> size, Color);
+void OutlineRect(SDL_Surface *, Vector<int> pos, Vector<int> size, Uint32 color);
+
+void Cross(
+	SDL_Surface *,
+	Vector<int> pos,
+	int extent,
+	Color);
+
+void Grid(
+	SDL_Surface *,
+	Vector<int> from,
+	Vector<int> to,
+	Vector<int> size,
+	Color);
+
+}
+
+#endif
diff --git a/src/math/Vector.h b/src/math/Vector.h
new file mode 100644
index 0000000..5fa2eb3
--- /dev/null
+++ b/src/math/Vector.h
@@ -0,0 +1,94 @@
+#ifndef SPACE_VECTOR_H_
+#define SPACE_VECTOR_H_
+
+#include <algorithm>
+
+
+namespace space {
+
+template<class Scalar>
+class Vector {
+
+public:
+	constexpr Vector() : x(0), y(0) { }
+	constexpr Vector(Scalar x, Scalar y) : x(x), y(y) { }
+
+	template<class Other>
+	constexpr Vector(Vector<Other> other) : x(other.x), y(other.y) { }
+
+public:
+	Vector<Scalar> &operator +=(Vector<Scalar> other) {
+		x += other.x;
+		y += other.y;
+		return *this;
+	}
+	Vector<Scalar> &operator -=(Vector<Scalar> other) {
+		x -= other.x;
+		y -= other.y;
+		return *this;
+	}
+
+public:
+	Scalar x;
+	Scalar y;
+
+};
+
+
+template<class Scalar>
+constexpr Vector<Scalar> operator -(Vector<Scalar> v) {
+	return Vector<Scalar>(-v.x, -v.y);
+}
+
+
+template<class Scalar>
+constexpr Vector<Scalar> operator +(Vector<Scalar> lhs, Vector<Scalar> rhs) {
+	return Vector<Scalar>(lhs.x + rhs.x, lhs.y + rhs.y);
+}
+
+template<class Scalar>
+constexpr Vector<Scalar> operator -(Vector<Scalar> lhs, Vector<Scalar> rhs) {
+	return Vector<Scalar>(lhs.x - rhs.x, lhs.y - rhs.y);
+}
+
+
+template<class Scalar>
+constexpr Vector<Scalar> operator *(Vector<Scalar> lhs, Scalar rhs) {
+	return Vector<Scalar>(lhs.x * rhs, lhs.y * rhs);
+}
+
+template<class Scalar>
+constexpr Vector<Scalar> operator *(Scalar lhs, Vector<Scalar> rhs) {
+	return rhs * lhs;
+}
+
+}
+
+
+namespace std {
+
+template<class Scalar>
+constexpr space::Vector<Scalar> min(
+		space::Vector<Scalar> lhs,
+		space::Vector<Scalar> rhs
+) {
+	return space::Vector<Scalar>(
+		min(lhs.x, rhs.x),
+		min(lhs.y, rhs.y)
+	);
+}
+
+template<class Scalar>
+constexpr space::Vector<Scalar> max(
+		space::Vector<Scalar> lhs,
+		space::Vector<Scalar> rhs
+) {
+	return space::Vector<Scalar>(
+		max(lhs.x, rhs.x),
+		max(lhs.y, rhs.y)
+	);
+}
+
+}
+
+#endif
diff --git a/src/sdl/InitSDL.cpp b/src/sdl/InitSDL.cpp
new file mode 100644
index 0000000..0676dfb
--- /dev/null
+++ b/src/sdl/InitSDL.cpp
@@ -0,0 +1,20 @@
+#include "InitSDL.h"
+
+#include <stdexcept>
+
+using std::runtime_error;
+
+
+namespace space {
+
+InitSDL::InitSDL(Uint32 flags) {
+	if (SDL_Init(flags) != 0) {
+		throw runtime_error("failed to initialize SDL");
+	}
+}
+
+InitSDL::~InitSDL() {
+	SDL_Quit();
+}
+
+}
diff --git a/src/sdl/InitSDL.h b/src/sdl/InitSDL.h
new file mode 100644
index 0000000..dd3cf72
--- /dev/null
+++ b/src/sdl/InitSDL.h
@@ -0,0 +1,22 @@
+#ifndef SPACE_INITSDL_H_
+#define SPACE_INITSDL_H_
+
+#include <SDL/SDL.h>
+
+
+namespace space {
+
+class InitSDL {
+
+public:
+	explicit InitSDL(Uint32 flags = SDL_INIT_EVERYTHING);
+	~InitSDL();
+
+	InitSDL(const InitSDL &) = delete;
+	InitSDL &operator =(const InitSDL &) = delete;
+
+};
+
+}
+
+#endif
diff --git a/src/sdl/InitScreen.cpp b/src/sdl/InitScreen.cpp
new file mode 100644
index 0000000..2ed13dd
--- /dev/null
+++ b/src/sdl/InitScreen.cpp
@@ -0,0 +1,40 @@
+#include "InitScreen.h"
+
+#include <stdexcept>
+
+using std::runtime_error;
+
+
+namespace space {
+
+InitScreen::InitScreen(int width, int height, int bpp, Sint32 flags)
+: screen(SDL_SetVideoMode(width, height, bpp, flags))
+, bpp(bpp)
+, flags(flags) {
+	if (!screen) {
+		throw runtime_error("failed to open screen");
+	}
+}
+
+InitScreen::~InitScreen() {
+
+}
+
+
+SDL_Surface *InitScreen::Resize(int width, int height) {
+	SDL_Surface *newScreen(SDL_SetVideoMode(width, height, bpp, flags));
+	if (!newScreen) {
+		throw runtime_error("failed to resize screen");
+	}
+	return screen = newScreen;
+}
+
+void InitScreen::Flip() {
+	SDL_Flip(screen);
+	if (!(screen->flags & SDL_HWSURFACE)) {
+		// probably got no vsync, so suspend execution for a while
+		SDL_Delay(1);
+	}
+}
+
+}
diff --git a/src/sdl/InitScreen.h b/src/sdl/InitScreen.h
new file mode 100644
index 0000000..38ac9da
--- /dev/null
+++ b/src/sdl/InitScreen.h
@@ -0,0 +1,33 @@
+#ifndef SPACE_INITSCREEN_H_
+#define SPACE_INITSCREEN_H_
+
+#include <SDL/SDL.h>
+
+namespace space {
+
+class InitScreen {
+
+public:
+	InitScreen(int width, int height, int bpp = 32, Sint32 flags = SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_RESIZABLE);
+	~InitScreen();
+
+	InitScreen(const InitScreen &) = delete;
+	InitScreen &operator =(const InitScreen &) = delete;
+
+public:
+	SDL_Surface *Screen() { return screen; };
+	const SDL_Surface *Screen() const { return screen; };
+
+	void Flip();
+	SDL_Surface *Resize(int width, int height);
+
+private:
+	SDL_Surface *screen;
+	int bpp;
+	Sint32 flags;
+
+};
+
+}
+
+#endif
diff --git a/src/space.cpp b/src/space.cpp
new file mode 100644
index 0000000..606cc61
--- /dev/null
+++ b/src/space.cpp
@@ -0,0 +1,19 @@
+#include "app/Application.h"
+#include "sdl/InitSDL.h"
+#include "sdl/InitScreen.h"
+#include "world/Resource.h"
+#include "world/Sector.h"
+#include "world/Universe.h"
+
+using namespace space;
+
+
+int main(int argc, const char *argv[]) {
+	InitSDL sdl;
+	InitScreen screen(800, 600);
+
+	Application app(screen);
+	app.Run();
+
+	return 0;
+}
diff --git a/src/world/Resource.cpp b/src/world/Resource.cpp
new file mode 100644
index 0000000..ca2440c
--- /dev/null
+++ b/src/world/Resource.cpp
@@ -0,0 +1,18 @@
+#include "Resource.h"
+
+
+namespace space {
+
+Resource::Resource()
+: id(-1)
+, name(nullptr) {
+
+}
+
+Resource::Resource(int id, const char *name)
+: id(id)
+, name(name) {
+
+}
+
+}
diff --git a/src/world/Resource.h b/src/world/Resource.h
new file mode 100644
index 0000000..45de344
--- /dev/null
+++ b/src/world/Resource.h
@@ -0,0 +1,24 @@
+#ifndef SPACE_RESOURCE_H_
+#define SPACE_RESOURCE_H_
+
+namespace space {
+
+class Resource {
+
+public:
+	Resource();
+	Resource(int id, const char *name);
+
+public:
+	int ID() const { return id; }
+	const char *Name() const { return name; }
+
+private:
+	int id;
+	const char *name;
+
+};
+
+}
+
+#endif
diff --git a/src/world/Sector.cpp b/src/world/Sector.cpp
new file mode 100644
index 0000000..bbe0bf4
--- /dev/null
+++ b/src/world/Sector.cpp
@@ -0,0 +1,22 @@
+#include "Sector.h"
+
+#include <cstring>
+
+
+namespace space {
+
+Sector::Sector(int w, int h, int numres)
+: w(w)
+, h(h)
+, numres(numres)
+, total(w * h * numres)
+, res_begin(new int[total])
+, res_end(res_begin + total) {
+	std::memset(res_begin, 0, total * sizeof(int));
+}
+
+Sector::~Sector() {
+	delete[] res_begin;
+}
+
+}
diff --git a/src/world/Sector.h b/src/world/Sector.h
new file mode 100644
index 0000000..fa27b7f
--- /dev/null
+++ b/src/world/Sector.h
@@ -0,0 +1,27 @@
+#ifndef SPACE_SECTOR_H_
+#define SPACE_SECTOR_H_
+
+namespace space {
+
+class Sector {
+
+public:
+	Sector(int w, int h, int numres);
+	~Sector();
+
+	Sector(const Sector &) = delete;
+	Sector &operator =(const Sector &) = delete;
+
+private:
+	int w;
+	int h;
+	int numres;
+	int total;
+	int *res_begin;
+	int *res_end;
+
+};
+
+}
+
+#endif
diff --git a/src/world/Universe.cpp b/src/world/Universe.cpp
new file mode 100644
index 0000000..ec307a5
--- /dev/null
+++ b/src/world/Universe.cpp
@@ -0,0 +1,27 @@
+#include "Universe.h"
+
+#include "Sector.h"
+
+#include <cstring>
+#include <memory>
+
+
+namespace space {
+
+Universe::Universe(int w, int h, int sec_w, int sec_h, int numres)
+: w(w)
+, h(h)
+, numres(numres)
+, total(w * h)
+, sec_begin(reinterpret_cast<Sector *>(new char[total * sizeof(Sector)]))
+, sec_end(sec_begin + total) {
+	for (Sector *i = sec_begin; i < sec_end; ++i) {
+		new (i) Sector(sec_w, sec_h, numres);
+	}
+}
+
+Universe::~Universe() {
+	delete[] reinterpret_cast<char *>(sec_begin);
+}
+
+}
diff --git a/src/world/Universe.h b/src/world/Universe.h
new file mode 100644
index 0000000..29e4ecb
--- /dev/null
+++ b/src/world/Universe.h
@@ -0,0 +1,29 @@
+#ifndef SPACE_UNIVERSE_H_
+#define SPACE_UNIVERSE_H_
+
+namespace space {
+
+class Sector;
+
+class Universe {
+
+public:
+	Universe(int w, int h, int sec_w, int sec_h, int numres);
+	~Universe();
+private:
+	Universe(const Universe &);
+	Universe &operator =(const Universe &);
+
+private:
+	int w;
+	int h;
+	int numres;
+	int total;
+	Sector *sec_begin;
+	Sector *sec_end;
+
+};
+
+}
+
+#endif
-- 
2.39.5