1
Fork 0

first commit

This commit is contained in:
Joshua Moerman 2013-03-13 13:49:30 +01:00
commit c3be4d5d12
16 changed files with 1307 additions and 0 deletions

21
.gitignore vendored Normal file
View file

@ -0,0 +1,21 @@
.DS_Store
*.blend1
*.blend2
*.bullet
*.sublime-workspace
build-*
CMakeCache.txt
CMakeFiles
build/
mingw-build-codeblocks/
mingw-build/
onegame.kdev4
linux-packages
#Kdev temp file ignore
*~
.kdev4
windows\-installer/*.bmp

46
CMakeLists.txt Normal file
View file

@ -0,0 +1,46 @@
cmake_minimum_required(VERSION 2.8)
add_subdirectory("motor")
include(motor/cmake/set_system_include_flag.cmake)
include(motor/cmake/address_sanitizer.cmake)
include(motor/cmake/detect_compiler.cmake)
check_compiling_with_clang(COMPILING_WITH_CLANG)
check_compiling_with_gcc(COMPILING_WITH_GCC)
if(${COMPILING_WITH_CLANG})
if(APPLE)
include_directories(SYSTEM "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/c++/v1/")
endif()
endif()
if(MINGW)
include(motor/cmake/enable_gnu11.cmake)
else()
include(motor/cmake/enable_cpp11.cmake)
endif()
if(UNIX)
#Always compile with debugging symbols
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3")
else()
if(MSVC)
message(FATAL_ERROR "Were not supporting MSVC at this time")
elseif(MINGW)
#assume were runnig cross compilation
add_definitions("-DGLEW_STATIC" "-DAL_LIBTYPE_STATIC" "-DALURE_STATIC_LIBRARY" "-DBOOST_THREAD_USE_LIB")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3")
else()
message(FATAL_ERROR "Unsupported platform detected")
endif()
endif()
include(motor/cmake/warning_settings.cmake)
get_sane_warning_flags(warnings)
include(motor/cmake/join.cmake)
join("${warnings}" " " warnings)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${warnings}")
add_subdirectory("src")

37
run Executable file
View file

@ -0,0 +1,37 @@
#!/bin/bash
set -o nounset #Error when unset vars are used
set -o errexit #Exit on errors
set -o pipefail #Causes failure when input-pipe-program fails
set -x
build_configuration="Debug"
if [ ! -z ${1:-} ]
then
build_configuration=$1
fi
run_target="modelviewer"
if [ ! -z ${2:-} ]
then
run_target=$2
fi
run_command="./build-$build_configuration/src/$run_target ${3:-}"
if [ $build_configuration = "mingw" ]; then
if [ ! -d "build-$build_configuration" ]; then
if [ $# -ne 2 ]; then
set +x
echo "Trying to run \"./run mingw\" for the first time without toolchain file."
echo "Please specify a cross_compile toolchain file as second argument."
set -x
else
./vanillabuild $build_configuration $2 && $run_command.exe
fi
else
./vanillabuild $build_configuration && $run_command.exe
fi
else
./vanillabuild $build_configuration && $run_command
fi

63
sdlgame.sublime-project Normal file
View file

@ -0,0 +1,63 @@
{
"folders":
[
{
"path": "."
}
],
"settings":
{
"sublimeclang_options":
[
"-std=c++0x",
"-Weverything",
"-Wno-c++98-compat-pedantic",
"-Wno-cast-align",
"-Wno-conditional-uninitialized",
"-Wno-conversion",
"-Wno-covered-switch-default",
"-Wno-deprecated-declarations",
"-Wno-disabled-macro-expansion",
"-Wno-exit-time-destructors",
"-Wno-float-equal",
"-Wno-format-nonliteral",
"-Wno-global-constructors",
"-Wno-lambda-extensions",
"-Wno-missing-noreturn",
"-Wno-missing-prototypes",
"-Wno-newline-eof",
"-Wno-padded",
"-Wno-sign-conversion",
"-Wno-shadow",
"-Wno-switch-enum",
"-Wno-undef",
"-Wno-unreachable-code",
"-Wno-variadic-macros",
"-Wno-vla",
"-Wno-weak-vtables",
"-Wno-unused-parameter",
"-I${folder:${project_path:sdlgame.sublime-project}}",
"-I${folder:${project_path:sdlgame.sublime-project}}/motor",
"-isystem${folder:${project_path:sdlgame.sublime-project}}/motor/contrib/assimp-3.0.1270/include",
"-isystem${folder:${project_path:sdlgame.sublime-project}}/motor/contrib/soil",
"-isystem${folder:${project_path:sdlgame.sublime-project}}/motor/contrib/bullet/src",
"-isystem${folder:${project_path:sdlgame.sublime-project}}/motor/contrib/freetype-gl",
"-isystem${folder:${project_path:sdlgame.sublime-project}}/motor/moggle/include",
"-isystem${folder:${project_path:sdlgame.sublime-project}}/motor/contrib/",
"-isystem${folder:${project_path:sdlgame.sublime-project}}/sc-includes/",
"-ferror-limit=0",
"-std=c++11",
"-stdlib=libc++",
"-DDEBUG=1",
"-nostdinc",
"-isystem/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk",
"-isystem/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/c++/v1",
"-isystem/System/Library/Frameworks/OpenGL.framework/Versions/Current/Header",
"-isystem/usr/local/include",
"-isystem/sw/include",
"-isystem/opt/local/include",
"-isystem/usr/include"
// Add your personal inclusions below here
]
}
}

85
src/Base.cpp Normal file
View file

@ -0,0 +1,85 @@
#include "Base.hpp"
namespace games {
using namespace motor;
Base::Base(int window_width_, int window_height_)
: window_width(window_width_), window_height(window_height_)
{}
Base::~Base(){}
bool Base::has_ended(){
return false;
}
void Base::update(float const dt, std::map<SDLKey, bool> __attribute__((unused)) keys_went_down, std::map<SDLKey, bool> __attribute__((unused)) is_pressed, std::map<SDLKey, bool> __attribute__((unused)) keyw_went_up){
time += dt;
update_bullet(dt);
check_collisions();
}
void Base::update_bullet(float const dt){
dynamics_world->stepSimulation(dt, 20);
for (int j=dynamics_world->getNumCollisionObjects()-1; j>=0 ;j--)
{
btCollisionObject* obj = dynamics_world->getCollisionObjectArray()[j];
btRigidBody* body = btRigidBody::upcast(obj);
if (body && body->getMotionState())
{
if(body->getUserPointer() != nullptr){
btTransform trans = body->getWorldTransform();
Body* b = static_cast<Body*>(body->getUserPointer());
b->sync_from_bullet(trans);
}
}
}
}
void Base::check_collisions(){
std::vector<std::pair<btCollisionObject const*, btCollisionObject const*>> bullet_objects_colliding;
int const manifolds = dynamics_world->getDispatcher()->getNumManifolds();
for(int manifold_index = 0; manifold_index < manifolds; ++manifold_index){
auto const manifold = dynamics_world->getDispatcher()->getManifoldByIndexInternal(manifold_index);
btCollisionObject const* first_object = manifold->getBody0();
btCollisionObject const* second_object = manifold->getBody1();
bullet_objects_colliding.emplace_back(first_object, second_object);
}
for(auto const& c : bullet_objects_colliding){
if(!astrant::contains(bullet_objects_in_collision_previous_frame, c)){
bullet_objects_entered_collision(c.first, c.second);
}
}
for(auto const& c : bullet_objects_in_collision_previous_frame){
if(!astrant::contains(bullet_objects_colliding, c)){
bullet_objects_exited_collision(c.first, c.second);
}
}
bullet_objects_in_collision_previous_frame = bullet_objects_colliding;
}
void Base::draw(){
//First, clear the screen
fbo.unbind();
moggle::gl::set_viewport(0, 0, window_width, window_height);
moggle::gl::set_clear_color(0.1f, 0.1f, 0.1f, 1.0f);
moggle::gl::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
moggle::gl::enable(GL_DEPTH_TEST);
moggle::gl::enable(GL_BLEND);
moggle::gl::blend_equation(GL_FUNC_ADD);
moggle::gl::blend_function(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
scene->draw();
}
ResourceCache Base::resource_cache;
}

171
src/Base.hpp Normal file
View file

@ -0,0 +1,171 @@
#pragma once
#include <iostream>
#include <memory>
#include <SDL/SDL.h>
#include <moggle/xxx/mesh.hpp>
#include <motor/basic/body.hpp>
#include <motor/basic/scene.hpp>
#include <motor/core/fbo.hpp>
#include <astrant-extensions/algorithm.hpp>
#include "globals.hpp"
//! Returns (f(ax, bx) && f(ay, by)) || (f(ax, by) && f(ay, bx))
//! Useful for instance when you want to compare two pairs if they contain the same elements, but don't care about the order
//! (and we provide an overload for that of course)
template <typename First, typename Second, typename Third, typename Fourth, typename CompareFunction>
bool order_agnostic_compare(First const& ax, Second const& ay, Third const& bx, Fourth const& by, CompareFunction const& f){
return
(f(ax, bx) && f(ay, by))
||
(f(ax, by) && f(ay, bx));
}
//TODO: Figure out what the syntax of this was, then express equal, less{,or equal}, greater{, or equal}.
//using order_agnostic_equalness<First, Second, Third, Fourth> = order_agnostic_compare<First, Second, Third, Fourth, std::eq>;
template <typename First, typename Second, typename Third, typename Fourth>
bool order_agnostic_equal(First const& ax, Second const& ay, Third const& bx, Fourth const& by){
return ((ax == bx && ay == by) || (ax == by && ay == bx));
}
template <typename First, typename Second, typename Third, typename Fourth>
bool order_agnostic_equal(std::pair<First, Second> const& a, std::pair<Third, Fourth> const& b){
return order_agnostic_equalness(a.first, a.second, b.first, b.second);
}
namespace games {
using namespace motor;
struct Base {
static ResourceCache resource_cache;
std::shared_ptr<Scene> scene = std::make_shared<Scene>();
int window_width;
int window_height;
Fbo fbo{window_width, window_height};
float time = 0.0;
// So all this is needed to set up Bullet!
// You pay for modularity with a lot of code, but perhaps we can wrap this in our own motor::world or something.
std::unique_ptr<btDefaultCollisionConfiguration> collison_configuration{new btDefaultCollisionConfiguration()};
std::unique_ptr<btCollisionDispatcher> collision_dispatcher{new btCollisionDispatcher(collison_configuration.get())};
btVector3 const world_minimum = btVector3(-1000,-1000,-1000);
btVector3 const world_maximum = btVector3(1000,1000,1000);
std::unique_ptr<btBroadphaseInterface> overlapping_pair_cache{new btAxisSweep3(world_minimum, world_maximum)};
std::unique_ptr<btConstraintSolver> constraint_solver{new btSequentialImpulseConstraintSolver()};
std::unique_ptr<btDynamicsWorld> dynamics_world{new btDiscreteDynamicsWorld(collision_dispatcher.get(), overlapping_pair_cache.get(), constraint_solver.get(), collison_configuration.get())};
Base(int window_width, int window_height);
virtual ~Base();
virtual bool has_ended();
private:
// Contains objects that were colliding in the previous update
std::vector<std::pair<btCollisionObject const*, btCollisionObject const*>> bullet_objects_in_collision_previous_frame{};
public:
virtual void update(float const dt, std::map<SDLKey, bool> keys_went_down, std::map<SDLKey, bool> is_pressed, std::map<SDLKey, bool> keys_went_up);
void update_bullet(float const dt);
void check_collisions();
//! A callback for when a collision between two objects occurs.
//! TODO: Expand to N-objects?
//! The pointers aren't const here so we can call f with the two arguments
struct dual_collision_callback {
//! The constructor.
//! CallbackFunctor must be a valid ctor-parameter for @member f
template <typename CallbackFunctor>
dual_collision_callback(std::shared_ptr<Body> first_, std::shared_ptr<Body> second_, CallbackFunctor&& c)
: first(first_)
, second(second_)
, f(c)
{}
std::shared_ptr<Body> first;
std::shared_ptr<Body> second;
std::function<void(decltype(first), decltype(second))> f;
void operator()() {
f(first, second);
}
};
struct single_collision_callback {
template <typename CallbackFunctor>
single_collision_callback(std::shared_ptr<Body> b_, CallbackFunctor&& c)
: b(b_)
, f(c)
{}
std::shared_ptr<Body> b;
std::function<void(decltype(b))> f;
void operator()() {
f(b);
}
};
void register_on_enter_collision_callback(dual_collision_callback&& c){
on_enter_dual_collision_callback.emplace_back(std::move(c));
}
void register_on_exit_collision_callback(dual_collision_callback&& c){
on_exit_dual_collision_callback.emplace_back(std::move(c));
}
void register_on_enter_collision_callback(single_collision_callback&& c){
on_enter_single_collision_callback.emplace_back(std::move(c));
}
void register_on_exit_collision_callback(single_collision_callback&& c){
on_exit_single_collision_callback.emplace_back(std::move(c));
}
private:
std::vector<dual_collision_callback> on_enter_dual_collision_callback{};
std::vector<dual_collision_callback> on_exit_dual_collision_callback{};
std::vector<single_collision_callback> on_enter_single_collision_callback{};
std::vector<single_collision_callback> on_exit_single_collision_callback{};
void bullet_objects_entered_collision(btCollisionObject const* x, btCollisionObject const* y){
for(auto& c : on_enter_dual_collision_callback){
if(order_agnostic_equal(c.first->get_physical_body(), c.second->get_physical_body(), x, y)){
c();
}
}
for(auto& c : on_enter_single_collision_callback){
if(c.b->get_physical_body() == x || c.b->get_physical_body() == y){
c();
}
}
}
void bullet_objects_exited_collision(btCollisionObject const* x, btCollisionObject const* y){
for(auto& c : on_exit_dual_collision_callback){
if(order_agnostic_equal(c.first->get_physical_body(), c.second->get_physical_body(), x, y)){
c();
}
}
for(auto& c : on_exit_single_collision_callback){
if(c.b->get_physical_body() == x || c.b->get_physical_body() == y){
c();
}
}
}
public:
virtual void draw();
};
} // namespace games

63
src/CMakeLists.txt Normal file
View file

@ -0,0 +1,63 @@
cmake_minimum_required(VERSION 2.8)
project(onegame)
find_package(Boost 1.48 REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR})
find_package(SDL REQUIRED)
include_directories(${SDL_INCLUDE_DIR})
set(boost ${Boost_LIBRARIES})
set(opengl ${OPENGL_LIBRARIES})
set(sdl ${SDL_LIBRARY})
set(moggle moggle_xxx)
if(UNIX)
set(motor motor)
set(zlib z)
set(alure alure)
set(assimp assimp)
if(APPLE)
include_directories("/sw/include/")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/sw/lib")
set(os_libs "-framework Cocoa" "-framework IOKit")
set(openal "-framework OpenAL")
else()
set(openal openal)
endif()
else()
if(MSVC)
set(motor motor)
set(assimp assimp)
set(zlib zlib)
set(opengl opengl32.lib)
set(openal openAL32.lib)
set(alure alure32.lib)
set(graphics_libs glew32.lib)
else()
#Assume were crosscompiling
set(motor motor)
set(assimp assimp)
set(zlib zlib)
set(os_libs "${os_libs}" "-lwinmm")
endif()
endif()
include_directories("${PROJECT_SOURCE_DIR}")
include_directories("${PROJECT_SOURCE_DIR}/..")
include_directories(SYSTEM "${PROJECT_SOURCE_DIR}/../motor/..")
include_directories(SYSTEM "${PROJECT_SOURCE_DIR}/../motor/contrib/assimp-3.0.1270/include")
include_directories(SYSTEM "${PROJECT_SOURCE_DIR}/../motor/contrib/bullet/src")
include_directories(SYSTEM "${PROJECT_SOURCE_DIR}/../motor/contrib/freetype-gl")
include_directories(SYSTEM "${PROJECT_SOURCE_DIR}/../motor/contrib/")
include_directories(SYSTEM "${PROJECT_SOURCE_DIR}/../motor/moggle/include")
add_library(onegame_common Base.cpp)
set(all_friggin_libraries onegame_common ${boost} ${motor} ${moggle} ${assimp} ${zlib} ${opengl} ${sdl} ${openal} ${alure} ${graphics_libs} ${os_libs} ${glew})
file(GLOB beamer_sources "beamer/*.cpp")
add_executable(beamer beamer_main.cpp ${beamer_sources})
target_link_libraries(beamer ${all_friggin_libraries})

303
src/beamer/beamer.cpp Normal file
View file

@ -0,0 +1,303 @@
#include "beamer.hpp"
#include "simplex.h"
#include "coordinates.h"
#include "procedural_textures.h"
namespace games {
using namespace motor;
using namespace std;
Beamer::House::House(){
model = std::make_shared<Body>(resource_cache.get_mesh(::bundle.get_model_path() + "house.obj"));
model->set_scale({0.2, 0.2, 0.2});
}
Beamer::Planet::Planet(float const waterlevel, float const displacement, Color const watercolor){
srand(::time(0));
{
auto watermesh = std::make_shared<Mesh>(::bundle.get_model_path() + "planet.obj");
auto const & positions = watermesh->geometry->vertices()->attribute("position").buffer<moggle::hvector4<float>>();
auto const & colors = watermesh->geometry->vertices()->attribute("color").buffer<moggle::hvector4<float>>();
for(unsigned int i = 0; i < positions->size(); ++i){
auto& p = positions->at(i);
auto& c = colors->at(i);
float r = watercolor[0] * (0.5 + 0.5*simplex_noise(1, p[0], p[1], p[2]));
float g = watercolor[1] * (0.5 + 0.5*simplex_noise(1, p[0], p[1], p[2]));
float b = watercolor[2];
c = {r, g, b, 1.0};
}
colors->mark_dirty();
water = std::make_shared<Body>(watermesh);
water->set_scale({radius*waterlevel, radius*waterlevel, radius*waterlevel});
}
{
auto planetmesh = std::make_shared<Mesh>(::bundle.get_model_path() + "planet.obj");
auto vertices = planetmesh->geometry->vertices();
auto const & positions = vertices->attribute("position").buffer<moggle::hvector4<float>>();
auto const & normals = vertices->attribute("normal").buffer<moggle::vector3<float>>();
auto const & colors = vertices->attribute("color").buffer<moggle::hvector4<float>>();
moggle::buffer<moggle::vector3<float>> texcoordsbuf(positions->size());
vertices->attribute("texture_coordinate", std::move(texcoordsbuf));
auto const & texcoords = planetmesh->geometry->vertices()->attribute("texture_coordinate").buffer<moggle::vector3<float>>();
for(unsigned int i = 0; i < positions->size(); ++i){
auto& p = positions->at(i);
auto& n = normals->at(i);
auto& c = colors->at(i);
c = {0,0,0,0};
auto& tc= texcoords->at(i);
auto sp = to_spherical(moggle::vector3<float>{p[0], p[1], p[2]});
tc = {0.5 * sp[1] * M_1_PI, sp[2] * M_1_PI + 0.5};
if(tc[0] < 0) tc[0] += 1.0;
float const speed = 0.9;
float r = simplex_noise(1, p[0]*speed, p[1]*speed, p[2]*speed);
p += displacement * r * n;
}
auto texture = std::make_shared<moggle::texture>(create_noise_for_sphere(4, 4, [](moggle::vector3<float> position) -> moggle::hvector4<float>{
float r = simplex_noise(1, position[0], position[1], position[2]);
r += 1.0;
r *= 0.5;
if(r > 1) r = 1;
if(r < 0) r = 0;
if(r > 0.75)
return {r, r, r};
else
return {0.2, 0.6, 0.5*r};
}));
planetmesh->material->diffuse_map = texture;
positions->mark_dirty();
normals->mark_dirty();
model = std::make_shared<Body>(planetmesh);
model->set_scale({radius, radius, radius});
}
int number_of_houses = astrant::random_value(5, 10);
for(int i = 0; i < number_of_houses; ++i){
House house;
float phi = astrant::random_value(0.0, 2 * M_PI);
float psi = astrant::random_value(-M_PI_2, M_PI_2);
Position house_pos = from_spherical(moggle::vector3<float>{radius, phi, psi});
// COUT << "house at: " << house_pos << std::endl;
house.model->set_position(house_pos);
houses.push_back(house);
}
}
std::vector<std::shared_ptr<Body>> Beamer::Planet::get_all_bodies() const {
std::vector<std::shared_ptr<Body>> ret{model, water};
for(auto& h : houses){
ret.push_back(h.model);
}
return ret;
}
struct Beamer::Player{
// 3D speed, or 2D?
typedef moggle::vector3<float> Speed;
Position position{0.0, 0.0, 5.0};
Speed speed{0.0, 1.0, 0.0};
float time{0};
float flight_height{5.0};
void update(float dt){
time += dt;
// move
position += dt*speed;
// clamp to sphere (we will later set it to its radius)
normalize(position);
// accelerator with noise
float noisespeed = 0.03;
float x = simplex_noise(3, noisespeed*time, 0, 0);
float y = simplex_noise(3, 0, noisespeed*time, 0);
float z = simplex_noise(3, 0, 0, noisespeed*time);
moggle::vector3<float> change{x, y, z};
speed += 100.0 * dt * change;
// make speed follow the sphere
float p = dot(speed, position);
speed -= p * moggle::vector3<float>(position);
normalize(speed);
// put the ufo in the air :)
position *= flight_height;
}
};
bool Beamer::has_ended(){
return false;
}
void Beamer::reset_camera(){
scene->camera.set_perspective(80.0f, 4.0f/3.0f, 1.0f, 1000.0f);
scene->camera.set_position({0, 0, 5});
}
void Beamer::reset_players(){
player.reset(new Player());
}
void Beamer::reset(){
reset_camera();
reset_players();
}
Beamer::Beamer(int window_width_, int window_height_)
: Base(window_width_, window_height_)
, player(new Player())
{
{
PointLight p{Position{0.f, 0.0f, 8.0f, 1.0f}, 200.0f, Color{1, 0, 0, 1}};
scene->add(std::make_shared<PointLight>(p));
}
{
PointLight p{Position{-4.f, -4.0f, -6.0f, 1.0f}, 200.0f, Color{0, 0, 1, 1}};
scene->add(std::make_shared<PointLight>(p));
}
{
PointLight p{Position{4.f, -4.0f, -6.0f, 1.0f}, 200.0f, Color{0, 1, 0, 1}};
scene->add(std::make_shared<PointLight>(p));
}
{
PointLight p{Position{0.f, 6.0f, -6.0f, 1.0f}, 200.0f, Color{1, 1, 1, 1}};
scene->add(std::make_shared<PointLight>(p));
}
reset();
for(auto& body : planet.get_all_bodies()){
scene->add(body);
}
}
Beamer::~Beamer() = default;
void Beamer::reset_effects(){
game_speed = 1.0;
}
void Beamer::handle_players(float const dt, map<SDLKey, bool> is_pressed){
constexpr float paddle_rotation_speed = M_PI*2.0f;
float const paddle_rotation = paddle_rotation_speed * dt;
if(is_pressed[SDLK_UP]){
for(auto& model : planet.get_all_bodies()){
model->add_pitch(paddle_rotation);
}
}
if(is_pressed[SDLK_DOWN]){
for(auto& model : planet.get_all_bodies()){
model->add_pitch(-paddle_rotation);
}
}
if(is_pressed[SDLK_LEFT]){
for(auto& model : planet.get_all_bodies()){
model->add_roll(-paddle_rotation);
}
}
if(is_pressed[SDLK_RIGHT]){
for(auto& model : planet.get_all_bodies()){
model->add_roll(paddle_rotation);
}
}
if(is_pressed[SDLK_k]){
scene->update_shader_pipeline();
}
bool planet_dirty = false;
if(is_pressed[SDLK_z] && !is_pressed[SDLK_LSHIFT]){
waterlevel += 3.0*dt;
planet_dirty = true;
}
if(is_pressed[SDLK_z] && is_pressed[SDLK_LSHIFT]){
waterlevel -= 3.0*dt;
planet_dirty = true;
}
if(is_pressed[SDLK_x] && !is_pressed[SDLK_LSHIFT]){
displacement += 3.0*dt;
planet_dirty = true;
}
if(is_pressed[SDLK_x] && is_pressed[SDLK_LSHIFT]){
displacement -= 3.0*dt;
planet_dirty = true;
}
if(is_pressed[SDLK_r] && !is_pressed[SDLK_LSHIFT]){
watercolor[0] += 0.2;
planet_dirty = true;
}
if(is_pressed[SDLK_r] && is_pressed[SDLK_LSHIFT]){
watercolor[0] -= 0.2;
planet_dirty = true;
}
if(is_pressed[SDLK_g] && !is_pressed[SDLK_LSHIFT]){
watercolor[1] += 0.2;
planet_dirty = true;
}
if(is_pressed[SDLK_g] && is_pressed[SDLK_LSHIFT]){
watercolor[1] -= 0.2;
planet_dirty = true;
}
if(is_pressed[SDLK_b] && !is_pressed[SDLK_LSHIFT]){
watercolor[2] += 0.2;
planet_dirty = true;
}
if(is_pressed[SDLK_b] && is_pressed[SDLK_LSHIFT]){
watercolor[2] -= 0.2;
planet_dirty = true;
}
if(planet_dirty){
for(auto const& body : planet.get_all_bodies()){
scene->remove(body);
}
planet = Planet(waterlevel, displacement, watercolor);
for(auto const& body : planet.get_all_bodies()){
scene->add(body);
}
}
}
void Beamer::update(float const dt, map<SDLKey, bool> keys_went_down, map<SDLKey, bool> is_pressed, map<SDLKey, bool> keys_went_up){
Base::update(game_speed*dt, keys_went_down, is_pressed, keys_went_up);
handle_players(game_speed*dt, is_pressed);
player->update(game_speed*dt);
scene->camera.set_position(player->position);
scene->camera.look_at({0, 0, 0}, player->speed);
}
}

64
src/beamer/beamer.hpp Normal file
View file

@ -0,0 +1,64 @@
#pragma once
#include <motor/sound/sound.hpp>
#include <motor/basic/texture_label.hpp>
#include "../Base.hpp"
namespace games {
using namespace motor;
using namespace std;
template <typename T>
struct check_type {
template <typename U>
bool operator()(shared_ptr<U> const& p){
return (dynamic_pointer_cast<T>(p) != nullptr);
}
};
struct Beamer : public Base {
static constexpr char bundle_name[] = "beamer";
struct House{
std::shared_ptr<Body> model;
House();
};
struct Planet {
float radius{2.5};
std::shared_ptr<Body> model;
std::shared_ptr<Body> water;
std::vector<House> houses;
std::vector<std::shared_ptr<Body>> get_all_bodies() const;
Planet(float const waterlevel, float const displacement, Color const watercolor);
};
float waterlevel = 0.7;
float displacement = 0.2;
Color watercolor = {0.0, 1.0, 1.0, 1.0};
Planet planet{waterlevel, displacement, watercolor};
struct Player;
std::unique_ptr<Player> player;
float game_speed{1.0};
Beamer(int window_width, int window_height);
~Beamer();
virtual bool has_ended();
virtual void update(float const dt, map<SDLKey, bool> keys_went_down, map<SDLKey, bool> is_pressed, map<SDLKey, bool> keys_went_up);
void reset_camera();
void reset_players();
void reset_effects();
void reset();
void handle_players(float const dt, map<SDLKey, bool> is_pressed);
};
} // namespace games

45
src/beamer/coordinates.h Normal file
View file

@ -0,0 +1,45 @@
#pragma once
#include <cmath>
#include <moggle/math/matrix.hpp>
#include <astrant-extensions/stream.hpp>
/*
Spherical coordinates: (r, phi1, phi2)
where r is the radius, phi1 rotation through y-axis, phi2 rotation determining height
This way we can see the sphere as something 2-dimensional (r=1).
*/
template <typename T>
moggle::vector3<T> from_spherical(moggle::vector3<T> const & p){
return {
p[0] * cos(p[2]) * cos(p[1]),
p[0] * sin(p[2]),
p[0] * cos(p[2]) * sin(p[1])
};
}
template <typename T>
moggle::vector3<T> to_spherical(moggle::vector3<T> const & p){
float r = sqrt(p[0]*p[0] + p[1]*p[1] + p[2]*p[2]);
if(r == 0) return {0.0, 0.0, 0.0};
return {
r,
atan2(p[2], p[0]),
asin(p[1] / r)
};
}
inline void test(){
for(unsigned int i = 0; i < 20; ++i){
auto f = [](moggle::vector3<float> p){return from_spherical(to_spherical(p));};
auto g = [](moggle::vector3<float> p){return to_spherical(from_spherical(p));};
moggle::vector3<float> p{
rand() / float(RAND_MAX) - 0.5,
rand() / float(RAND_MAX) - 0.5,
rand() / float(RAND_MAX) - 0.5
};
COUT << p << "\n" << f(p) << "\n" << g(p) << std::endl;
}
}

View file

@ -0,0 +1,39 @@
#pragma once
#include <cmath>
#include <memory>
#include <moggle/core/gl.hpp>
#include <moggle/core/texture.hpp>
#include "coordinates.h"
#include "simplex.h"
// takes size of texture (width x height), and a generator function, which is given positions on the sphere, and should return some kind of pixel
template <typename F>
inline moggle::texture create_noise_for_sphere(int width, int height, F const & f){
std::unique_ptr<GLubyte[]> data(new GLubyte[4 * width * height]);
auto const & generator = f;
for(int y = 0; y < height; ++y){
for(int x = 0; x < width; ++x){
GLubyte* pixel = &data[4 * (y*width + x)];
moggle::vector3<float> sp{1.0, 2 * M_PI * x/double(width), M_PI * (y/double(height) - 0.5)};
auto position = from_spherical(sp);
auto result = generator(position);
pixel[0] = 255*result[0];
pixel[1] = 255*result[1];
pixel[2] = 255*result[2];
pixel[3] = 255*result[3];
}
}
moggle::texture t(width, height);
t.bind();
moggle::gl::texture_image2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.get());
t.set_parameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
t.set_parameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
return t;
}

131
src/beamer/simplex.h Normal file
View file

@ -0,0 +1,131 @@
#pragma once
#include <cmath>
// I couldn't find the one we had for the old sdlgame, but i found this one
static float grad[12][3] = {
{1.0,1.0,0.0},{-1.0,1.0,0.0},{1.0,-1.0,0.0},{-1.0,-1.0,0.0},
{1.0,0.0,1.0},{-1.0,0.0,1.0},{1.0,0.0,-1.0},{-1.0,0.0,-1.0},
{0.0,1.0,1.0},{0.0,-1.0,1.0},{0.0,1.0,-1.0},{0.0,-1.0,-1.0}
};
static int perm[512] = {151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180, 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180};
inline float dot(float x, float y, float z, float* g){
return x*g[0] + y*g[1] + z*g[2];
}
inline float noise(float xin, float yin, float zin){
float F3, G3, t, X0, Y0, Z0, x0, y0, z0, s, x1, y1, z1, x2, y2, z2, x3, y3, z3, t0, t1, t2, t3, n0, n1, n2, n3;
int i, j, k, ii, jj, kk, i1, j1, k1, i2, j2, k2, gi0, gi1, gi2, gi3;
F3 = 1.0f/3.0f;
s = (xin+yin+zin)*F3;
i = std::floor(xin+s);
j = std::floor(yin+s);
k = std::floor(zin+s);
G3 = 1.0/6.0;
t = (i+j+k)*G3;
X0 = i-t;
Y0 = j-t;
Z0 = k-t;
x0 = xin-X0;
y0 = yin-Y0;
z0 = zin-Z0;
if(x0 >= y0){
if(y0 >= z0){
i1=1; j1=0; k1=0; i2=1; j2=1; k2=0;
}
else if(x0 >= z0){
i1=1; j1=0; k1=0; i2=1; j2=0; k2=1;
}
else{
i1=0; j1=0; k1=1; i2=1; j2=0; k2=1;
}
}
else{
if(y0 < z0){
i1=0; j1=0; k1=1; i2=0; j2=1; k2=1;
}
else if(x0 < z0){
i1=0; j1=1; k1=0; i2=0; j2=1; k2=1;
}
else{
i1=0; j1=1; k1=0; i2=1; j2=1; k2=0;
}
}
x1 = x0 - i1 + G3;
y1 = y0 - j1 + G3;
z1 = z0 - k1 + G3;
x2 = x0 - i2 + 2.0*G3;
y2 = y0 - j2 + 2.0*G3;
z2 = z0 - k2 + 2.0*G3;
x3 = x0 - 1.0 + 3.0*G3;
y3 = y0 - 1.0 + 3.0*G3;
z3 = z0 - 1.0 + 3.0*G3;
ii = i & 255;
jj = j & 255;
kk = k & 255;
gi0 = perm[ii+perm[jj+perm[kk]]] % 12;
gi1 = perm[ii+i1+perm[jj+j1+perm[kk+k1]]] % 12;
gi2 = perm[ii+i2+perm[jj+j2+perm[kk+k2]]] % 12;
gi3 = perm[ii+1+perm[jj+1+perm[kk+1]]] % 12;
t0 = 0.6 - x0*x0 - y0*y0 - z0*z0;
if(t0<0){
n0 = 0.0;
}
else{
t0 *= t0;
n0 = t0 * t0 * dot(x0, y0, z0, grad[gi0]);
}
t1 = 0.6 - x1*x1 - y1*y1 - z1*z1;
if(t1<0){
n1 = 0.0;
}
else{
t1 *= t1;
n1 = t1 * t1 * dot(x1, y1, z1, grad[gi1]);
}
t2 = 0.6 - x2*x2 - y2*y2 - z2*z2;
if(t2<0){
n2 = 0.0;
}
else{
t2 *= t2;
n2 = t2 * t2 * dot(x2, y2, z2, grad[gi2]);
}
t3 = 0.6 - x3*x3 - y3*y3 - z3*z3;
if(t3<0){
n3 = 0.0;
}
else{
t3 *= t3;
n3 = t3 * t3 * dot(x3, y3, z3, grad[gi3]);
}
// The result is scaled to stay just inside [-1,1]
// source: http://webstaff.itn.liu.se/~stegu/simplexnoise/
return 32.0*(n0 + n1 + n2 + n3);
}
inline float simplex_noise(int octaves, float x, float y, float z){
float value = 0.0;
int i;
for(i=0; i<octaves; i++){
value += noise(
x*pow(2, i),
y*pow(2, i),
z*pow(2, i)
);
}
return value;
}

21
src/beamer_main.cpp Normal file
View file

@ -0,0 +1,21 @@
#include "generic_main.hpp"
#include "beamer/beamer.hpp"
#include <memory>
typedef games::Beamer Game;
constexpr char Game::bundle_name[];
motor::Bundle const bundle(Game::bundle_name);
int main(int __unused argc, __unused char** argv){
const bool fullscreen = false;
const int window_width = 800;
const int window_height = 600;
GenericMain<Game> m(fullscreen, window_width, window_height);
m.main();
return 0;
}

131
src/generic_main.hpp Normal file
View file

@ -0,0 +1,131 @@
#include <iostream>
#include <memory>
#include <map>
#include <SDL/SDL.h>
#include <moggle/core/gl.hpp>
#include <motor/sound/sound.hpp>
#ifndef __unused
#define __unused __attribute__((unused))
#endif
template <typename Game>
struct GenericMain {
private:
motor::AL al_context;
int screen_width = 0;
int screen_height = 0;
void init_sdl(bool const fullscreen, int const wanted_resolution_width, int const wanted_resolution_height){
SDL_Init(SDL_INIT_VIDEO);
char const * caption = "onegame";
SDL_WM_SetCaption(caption, caption);
auto const double_buffer_result = SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, true);
if(double_buffer_result){
CERR << "Failed to enable double_buffering" << std::endl;
}
SDL_Surface * screen = nullptr;
if(fullscreen){
screen = SDL_SetVideoMode(0, 0, 24, SDL_OPENGL | SDL_FULLSCREEN);
} else {
screen = SDL_SetVideoMode(wanted_resolution_width, wanted_resolution_height, 24, SDL_OPENGL);
}
if(!screen){
std::string const sdl_error{SDL_GetError()};
throw std::runtime_error("Failed to create SDL_Screen: " + sdl_error);
}
screen_width = screen->w;
screen_height = screen->h;
}
void init_glew(){
#if defined(TARGET_GLEW)
if (glewInit() != GLEW_OK) {
throw std::runtime_error("Failed to initialize GLEW");
}
#endif
}
public:
GenericMain(bool const fullscreen, int const wanted_resolution_width, int const wanted_resolution_height)
: al_context()
{
init_sdl(fullscreen, wanted_resolution_width, wanted_resolution_height);
init_glew();
}
template <typename... T>
void main(T... args){
std::unique_ptr<Game> game{new Game {screen_width, screen_height, args...}};
bool done = false;
std::map<SDLKey, bool> keys_pressed;
// for calculation fps
auto fps_time = SDL_GetTicks();
int frame_count_in_second = 0;
auto now = SDL_GetTicks();
while (!done) {
SDL_Event event;
std::map<SDLKey, bool> keys_went_down;
std::map<SDLKey, bool> keys_went_up;
bool any_key_pressed = false;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
done = true;
break;
case SDL_KEYDOWN:
{
auto const& key = event.key.keysym.sym;
keys_pressed[key] = true;
keys_went_down[key] = true;
if (key == SDLK_ESCAPE){
done = true;
}
}
break;
case SDL_KEYUP:
{
any_key_pressed = true;
auto const& key = event.key.keysym.sym;
keys_pressed[key] = false;
keys_went_up[key] = true;
break;
}
default:
break;
}
}
if(any_key_pressed && game->has_ended()){
game.reset(new Game {screen_width, screen_height, args...});
}
float const dt = (SDL_GetTicks() - now)/1000.0f;
now = SDL_GetTicks();
game->update(dt, keys_went_down, keys_pressed, keys_went_up);
game->draw();
SDL_GL_SwapBuffers();
++frame_count_in_second;
// one second has past
if(SDL_GetTicks() - fps_time > 1000.0f){
fps_time = SDL_GetTicks();
COUT << "Frames in last second: " << frame_count_in_second << std::endl;
frame_count_in_second = 0;
}
}
}
};

3
src/globals.hpp Normal file
View file

@ -0,0 +1,3 @@
#include <motor/basic/bundle.hpp>
extern motor::Bundle const bundle;

84
vanillabuild Executable file
View file

@ -0,0 +1,84 @@
#!/bin/bash
set -o nounset #Error when unset vars are used
set -o errexit #Exit on errors
set -o pipefail #Causes failure when input-pipe-program fails
set -x
#########################################################################
# #
# Usage: vanillabuild [CMakeBuildType=Debug] [path_to_toolchain_file] #
# #
# path_to_toolchain_file will only be used when "CMakeBuildType=mingw" #
# #
# Further the number of cores are detected for certain OSes. #
# Add your own OS specific detection when needed. #
# #
#########################################################################
set +x
linux_number_of_cores_command="nproc"
nr_cores=8
list="None Debug Release RelWithDebInfo MinSizeRel"
contains() {
for word in $1; do
if [ $word = $2 ]; then
return 1
fi
done
return 0
}
cmake_command='cmake --warn-uninitialized -Wdev'
mingw_cmake_command="$cmake_command -DBUILD_ASSIMP_TOOLS=OFF -DBUILD_DEMOS=OFF -DBUILD_EXTRAS=OFF -DBUILD_STATIC_LIB=ON -Dfreetype-gl_BUILD_DEMOS=OFF"
if [ $# -ge 1 ]; then
if [ $1 = "mingw" ]; then
if [ -d "build-$1" ]; then
mkdir -p build-$1
cd build-$1
$mingw_cmake_command ..
else
if [ ! $# eq 2 ]; then
set -x
echo "Missing cross-build toolchain."
echo "Please give the toolchain file as second argument to this script."
set +x
else
mkdir -p build-$1
cd build-$1
$mingw_cmake_command -DCMAKE_TOOLCHAIN_FILE=$2 ..
fi
fi
elif contains "$list" $1 ; then
set -x
echo "No CMake build type detected exiting"
set +x
exit
else
mkdir -p build-$1
cd build-$1
$cmake_command -DCMAKE_BUILD_TYPE=$1 ..
fi
else
mkdir -p build-Debug
cd build-Debug
$cmake_command -DCMAKE_BUILD_TYPE=Debug ..
fi
if [ "$OSTYPE" = "linux-gnu" ]; then
nr_cores=$(eval $linux_number_of_cores_command)
fi
set +x
if [ "$OSTYPE" = "linux-gnu" ]; then
echo "Detected number of cores: $nr_cores"
else
echo "OS detection failed, detected OS: $OSTYPE."
echo "Defaulting number of cores to $nr_cores"
fi
set -x
make -j$nr_cores
cd ..