diff --git a/CMakeLists.txt b/CMakeLists.txt index e883a38..82e2367 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,30 @@ cmake_minimum_required(VERSION 2.8) project(CloonelJump CXX) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/include") + +include(TargetArch) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra -pedantic -Wconversion") -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11 -Wall -Wextra -pedantic -Wconversion") -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11 -Wall -Wextra -pedantic -Wconversion") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11 -Wall -Wextra -pedantic -Wconversion -DWITH_DEBUG_VISUALS -O0") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11 -Wall -Wextra -pedantic -Wconversion -O3") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -O0") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3") + +target_architecture(TARGET_ARCH) +message (STATUS "Target architecture: ${TARGET_ARCH}") option(WITH_BUILTIN_PHYSFS "Force using the version of PhysFS accompanying the code even if a system library is available" OFF) option(FORCE_OPENGLES "Try to chose the openGL ES renderer if available. Enable this on Raspberry Pi" OFF) option(RASPBERRY_PI "Compile for Raspberry Pi" OFF) +if (TARGET_ARCH MATCHES "^x86_64$") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -msse3") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -msse3") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -msse3") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -msse3") +endif (TARGET_ARCH MATCHES "^x86_64$") + if (FORCE_OPENGLES OR RASPBERRY_PI) add_definitions(-DFORCE_OPENGLES) if (RASPBERRY_PI) @@ -103,6 +119,7 @@ add_executable(${PROJECT_NAME} src/line.cpp src/collider.cpp src/platformset.cpp + src/drawableline.cpp ) target_link_libraries(${PROJECT_NAME} diff --git a/cmake/include/TargetArch.cmake b/cmake/include/TargetArch.cmake new file mode 100644 index 0000000..3761e4d --- /dev/null +++ b/cmake/include/TargetArch.cmake @@ -0,0 +1,134 @@ +# Based on the Qt 5 processor detection code, so should be very accurate +# https://qt.gitorious.org/qt/qtbase/blobs/master/src/corelib/global/qprocessordetection.h +# Currently handles arm (v5, v6, v7), x86 (32/64), ia64, and ppc (32/64) + +# Regarding POWER/PowerPC, just as is noted in the Qt source, +# "There are many more known variants/revisions that we do not handle/detect." + +set(archdetect_c_code " +#if defined(__arm__) || defined(__TARGET_ARCH_ARM) + #if defined(__ARM_ARCH_7__) \\ + || defined(__ARM_ARCH_7A__) \\ + || defined(__ARM_ARCH_7R__) \\ + || defined(__ARM_ARCH_7M__) \\ + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 7) + #error cmake_ARCH armv7 + #elif defined(__ARM_ARCH_6__) \\ + || defined(__ARM_ARCH_6J__) \\ + || defined(__ARM_ARCH_6T2__) \\ + || defined(__ARM_ARCH_6Z__) \\ + || defined(__ARM_ARCH_6K__) \\ + || defined(__ARM_ARCH_6ZK__) \\ + || defined(__ARM_ARCH_6M__) \\ + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 6) + #error cmake_ARCH armv6 + #elif defined(__ARM_ARCH_5TEJ__) \\ + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 5) + #error cmake_ARCH armv5 + #else + #error cmake_ARCH arm + #endif +#elif defined(__i386) || defined(__i386__) || defined(_M_IX86) + #error cmake_ARCH i386 +#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) + #error cmake_ARCH x86_64 +#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64) + #error cmake_ARCH ia64 +#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \\ + || defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \\ + || defined(_M_MPPC) || defined(_M_PPC) + #if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__) + #error cmake_ARCH ppc64 + #else + #error cmake_ARCH ppc + #endif +#endif + +#error cmake_ARCH unknown +") + +# Set ppc_support to TRUE before including this file or ppc and ppc64 +# will be treated as invalid architectures since they are no longer supported by Apple + +function(target_architecture output_var) + if(APPLE AND CMAKE_OSX_ARCHITECTURES) + # On OS X we use CMAKE_OSX_ARCHITECTURES *if* it was set + # First let's normalize the order of the values + + # Note that it's not possible to compile PowerPC applications if you are using + # the OS X SDK version 10.6 or later - you'll need 10.4/10.5 for that, so we + # disable it by default + # See this page for more information: + # http://stackoverflow.com/questions/5333490/how-can-we-restore-ppc-ppc64-as-well-as-full-10-4-10-5-sdk-support-to-xcode-4 + + # Architecture defaults to i386 or ppc on OS X 10.5 and earlier, depending on the CPU type detected at runtime. + # On OS X 10.6+ the default is x86_64 if the CPU supports it, i386 otherwise. + + foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES}) + if("${osx_arch}" STREQUAL "ppc" AND ppc_support) + set(osx_arch_ppc TRUE) + elseif("${osx_arch}" STREQUAL "i386") + set(osx_arch_i386 TRUE) + elseif("${osx_arch}" STREQUAL "x86_64") + set(osx_arch_x86_64 TRUE) + elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support) + set(osx_arch_ppc64 TRUE) + else() + message(FATAL_ERROR "Invalid OS X arch name: ${osx_arch}") + endif() + endforeach() + + # Now add all the architectures in our normalized order + if(osx_arch_ppc) + list(APPEND ARCH ppc) + endif() + + if(osx_arch_i386) + list(APPEND ARCH i386) + endif() + + if(osx_arch_x86_64) + list(APPEND ARCH x86_64) + endif() + + if(osx_arch_ppc64) + list(APPEND ARCH ppc64) + endif() + else() + file(WRITE "${CMAKE_BINARY_DIR}/arch.c" "${archdetect_c_code}") + + enable_language(C) + + # Detect the architecture in a rather creative way... + # This compiles a small C program which is a series of ifdefs that selects a + # particular #error preprocessor directive whose message string contains the + # target architecture. The program will always fail to compile (both because + # file is not a valid C program, and obviously because of the presence of the + # #error preprocessor directives... but by exploiting the preprocessor in this + # way, we can detect the correct target architecture even when cross-compiling, + # since the program itself never needs to be run (only the compiler/preprocessor) + try_run( + run_result_unused + compile_result_unused + "${CMAKE_BINARY_DIR}" + "${CMAKE_BINARY_DIR}/arch.c" + COMPILE_OUTPUT_VARIABLE ARCH + CMAKE_FLAGS CMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} + ) + + # Parse the architecture name from the compiler output + string(REGEX MATCH "cmake_ARCH ([a-zA-Z0-9_]+)" ARCH "${ARCH}") + + # Get rid of the value marker leaving just the architecture name + string(REPLACE "cmake_ARCH " "" ARCH "${ARCH}") + + # If we are compiling with an unknown architecture this variable should + # already be set to "unknown" but in the case that it's empty (i.e. due + # to a typo in the code), then set it to unknown + if (NOT ARCH) + set(ARCH unknown) + endif() + endif() + + set(${output_var} "${ARCH}" PARENT_SCOPE) +endfunction() diff --git a/src/character.cpp b/src/character.cpp index f59b7e3..2b69044 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -39,6 +39,9 @@ namespace cloonel { m_screenRatio(parMain), m_bounceCallback(&DoNothing), m_texture(new Texture(parPath, parMain, false)) +#if defined(WITH_DEBUG_VISUALS) + , m_bottomBarDrawable(parMain, Colour(250, 5, 1), static_cast(m_bottomBar.From()), static_cast(m_bottomBar.To())) +#endif { assert(parMain); m_bottomBar.SetCallback(std::bind(&Character::OnBounce, this, std::placeholders::_1, std::placeholders::_2)); @@ -53,6 +56,9 @@ namespace cloonel { m_screenRatio(parMain), m_bounceCallback(&DoNothing), m_texture(new Texture(parPath, parMain, false)) +#if defined(WITH_DEBUG_VISUALS) + , m_bottomBarDrawable(parMain, Colour(250, 5, 1), static_cast(m_bottomBar.From()), static_cast(m_bottomBar.To())) +#endif { assert(parMain); m_bottomBar.SetCallback(std::bind(&Character::OnBounce, this, std::placeholders::_1, std::placeholders::_2)); @@ -88,6 +94,9 @@ namespace cloonel { ///------------------------------------------------------------------------- void Character::Draw() const { m_texture->Render(GetPos(), WidthHeight(), m_screenRatio.Ratio(), true); +#if defined(WITH_DEBUG_VISUALS) + m_bottomBarDrawable.Render(GetPos(), m_screenRatio.Ratio()); +#endif } ///------------------------------------------------------------------------- diff --git a/src/character.hpp b/src/character.hpp index 97f44a8..e2c5143 100644 --- a/src/character.hpp +++ b/src/character.hpp @@ -27,6 +27,9 @@ #include "sizenotifiable.hpp" #include "horzcollisionbar.hpp" #include "collidertypedef.hpp" +#if defined(WITH_DEBUG_VISUALS) +# include "drawableline.hpp" +#endif #include #include #include @@ -64,6 +67,9 @@ namespace cloonel { SizeNotifiable m_screenRatio; BounceCallbackType m_bounceCallback; const std::unique_ptr m_texture; +#if defined(WITH_DEBUG_VISUALS) + DrawableLine m_bottomBarDrawable; +#endif }; } //unnamed namespace diff --git a/src/colour.hpp b/src/colour.hpp new file mode 100644 index 0000000..c3e41bf --- /dev/null +++ b/src/colour.hpp @@ -0,0 +1,62 @@ +/* + Copyright 2014 Michele "King_DuckZ" Santullo + + This file is part of CloonelJump. + + CloonelJump is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CloonelJump is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CloonelJump. If not, see . + +*/ + +#ifndef id1DA767EB516A4F4588347DFC14D1A999 +#define id1DA767EB516A4F4588347DFC14D1A999 + +#if defined(WITH_DEBUG_VISUALS) +#include + +namespace cloonel { + struct Colour { + typedef uint8_t ChannelType; + + Colour ( void ) = default; + Colour ( ChannelType parR, ChannelType parG, ChannelType parB, ChannelType parA ); + Colour ( ChannelType parR, ChannelType parG, ChannelType parB ) : Colour(parR, parG, parB, 0xFF) {} + explicit Colour ( ChannelType parFill ); + Colour ( const Colour& parOther ) = default; + + ChannelType r, g, b, a; + }; + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + inline Colour::Colour (ChannelType parR, ChannelType parG, ChannelType parB, ChannelType parA) : + r(parR), + g(parG), + b(parB), + a(parA) + { + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + inline Colour::Colour (ChannelType parFill) : + r(parFill), + g(parFill), + b(parFill), + a(parFill) + { + } +} //namespace cloonel + +#endif +#endif diff --git a/src/drawableline.cpp b/src/drawableline.cpp new file mode 100644 index 0000000..006bb06 --- /dev/null +++ b/src/drawableline.cpp @@ -0,0 +1,137 @@ +/* + Copyright 2014 Michele "King_DuckZ" Santullo + + This file is part of CloonelJump. + + CloonelJump is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CloonelJump is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CloonelJump. If not, see . + +*/ + +#include "drawableline.hpp" +#include "sdlmain.hpp" +#include "geometry_2d.hpp" +#if !defined(NDEBUG) +# include "line_helpers.hpp" +#endif +#include +#include + +#if defined(WITH_DEBUG_VISUALS) +namespace cloonel { + namespace { + ///---------------------------------------------------------------------- + ///---------------------------------------------------------------------- + void ClipLine (const SDL_Rect& parArea, Line& parLine) { + Line line(static_cast(parLine[0]), static_cast(parLine[1])); + const float al = static_cast(parArea.x); + const float at = static_cast(parArea.y); + const float ar = static_cast(parArea.x + parArea.w); + const float ab = static_cast(parArea.y + parArea.h); + + { + const Line leftLine(al, at, al, ab); + const auto intersection(Intersection(line, leftLine)); + if (intersection.first) { + if (line[0] < leftLine) + line[0] = intersection.second; + if (line[1] < leftLine) + line[1] = intersection.second; + } + } + { + const Line rightLine(ar, at, ar, ab); + const auto intersection(Intersection(line, rightLine)); + if (intersection.first) { + if (line[0] > rightLine) + line[0] = intersection.second; + if (line[1] > rightLine) + line[1] = intersection.second; + } + } + { + const Line topLine(al, at, ar, at); + const auto intersection(Intersection(line, topLine)); + if (intersection.first) { + if (line[0] < topLine) + line[0] = intersection.second; + if (line[1] < topLine) + line[1] = intersection.second; + } + } + { + const Line bottomLine(al, ab, ar, ab); + const auto intersection(Intersection(line, bottomLine)); + if (intersection.first) { + if (line[0] > bottomLine) + line[0] = intersection.second; + if (line[1] > bottomLine) + line[1] = intersection.second; + } + } + + parLine[0] = static_cast(line[0]); + parLine[1] = static_cast(line[1]); + } + } //unnamed namespace + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + DrawableLine::DrawableLine (SDLMain* parMain, Colour parColour, const LineBase& parLine) : + LineBase(parLine), + m_sdlmain(parMain), + m_colour(parColour) + { + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + DrawableLine::DrawableLine (SDLMain* parMain, Colour parColour, const LineBase::Point& parStart, const LineBase::Point& parEnd) : + LineBase(parStart, parEnd), + m_sdlmain(parMain), + m_colour(parColour) + { + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + void DrawableLine::Render (const float2& parPos, const float2& parScaling) const { + SDL_SetRenderDrawColor(m_sdlmain->GetRenderer(), m_colour.r, m_colour.g, m_colour.b, m_colour.a); + + LineBase scaledLine(*this); + scaledLine += static_cast(parPos); + scaledLine *= parScaling; + { + SDL_Rect screen; + screen.x = screen.y = 0; + const short2 wh(static_cast(m_sdlmain->WidthHeight())); + screen.w = wh.x(); + screen.h = wh.y(); + + ClipLine(screen, scaledLine); + } + const int16_t h = static_cast(m_sdlmain->WidthHeight().y()); + if (scaledLine[0] != scaledLine[1]) { + SDL_RenderDrawLine( + m_sdlmain->GetRenderer(), + scaledLine[0].x(), + h - scaledLine[0].y(), + scaledLine[1].x(), + h - scaledLine[1].y() + ); + } + //Returns 0 on success or a negative error code on failure; call SDL_GetError() for more information. + //http://www.ginkgobitter.org/sdl/?SDL_RenderDrawLine + } +} //namespace cloonel +#endif diff --git a/src/drawableline.hpp b/src/drawableline.hpp new file mode 100644 index 0000000..e0cc3a2 --- /dev/null +++ b/src/drawableline.hpp @@ -0,0 +1,71 @@ +/* + Copyright 2014 Michele "King_DuckZ" Santullo + + This file is part of CloonelJump. + + CloonelJump is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CloonelJump is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CloonelJump. If not, see . + +*/ + +#ifndef idE8A33294FB164199B0A23E0385DD0E09 +#define idE8A33294FB164199B0A23E0385DD0E09 + +#if defined(WITH_DEBUG_VISUALS) + +#include "colour.hpp" +#include "line.hpp" +#include + +namespace cloonel { + class SDLMain; + + class DrawableLine : public Line { + typedef Line LineBase; + public: + explicit DrawableLine ( SDLMain* parMain ); + explicit DrawableLine ( SDLMain* parMain, Colour parColour ); + DrawableLine ( SDLMain* parMain, Colour parColour, const LineBase& parLine ); + DrawableLine ( SDLMain* parMain, Colour parColour, const LineBase::Point& parStart, const LineBase::Point& parEnd ); + DrawableLine ( const DrawableLine& parOther ) = default; + virtual ~DrawableLine ( void ) noexcept = default; + + DrawableLine& operator= ( const DrawableLine& ) = delete; + + void Render ( const float2& parPos, const float2& parScaling ) const; + + private: + SDLMain* const m_sdlmain; + Colour m_colour; + }; + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + inline DrawableLine::DrawableLine (SDLMain* parMain) : + m_sdlmain(parMain), + m_colour() + { + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + inline DrawableLine::DrawableLine (SDLMain* parMain, Colour parColour) : + m_sdlmain(parMain), + m_colour(parColour) + { + } +} //namespace cloonel + +#endif + +#endif diff --git a/src/geometry.cpp b/src/geometry.cpp new file mode 100644 index 0000000..4894c29 --- /dev/null +++ b/src/geometry.cpp @@ -0,0 +1,25 @@ +/* + Copyright 2014 Michele "King_DuckZ" Santullo + + This file is part of CloonelJump. + + CloonelJump is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CloonelJump is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CloonelJump. If not, see . +*/ + +#include "geometry.hpp" + +namespace cloonel { + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- +} //namespace cloonel diff --git a/src/geometry.hpp b/src/geometry.hpp new file mode 100644 index 0000000..eb253b5 --- /dev/null +++ b/src/geometry.hpp @@ -0,0 +1,34 @@ +/* + Copyright 2014 Michele "King_DuckZ" Santullo + + This file is part of CloonelJump. + + CloonelJump is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CloonelJump is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CloonelJump. If not, see . +*/ + +#ifndef id3E40B29606D048569E18083DB682280F +#define id3E40B29606D048569E18083DB682280F + +#include "vector.hpp" +#include +#include + +namespace cloonel { + template + bool IsPointOnSegment ( const Vector& parPoint, const Vector& parSegA, const Vector& parSegB ) __attribute__((pure)); +} //namespace cloonel + +#include "geometry.inl" + +#endif diff --git a/src/geometry.inl b/src/geometry.inl new file mode 100644 index 0000000..429415c --- /dev/null +++ b/src/geometry.inl @@ -0,0 +1,31 @@ +/* + Copyright 2014 Michele "King_DuckZ" Santullo + + This file is part of CloonelJump. + + CloonelJump is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CloonelJump is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CloonelJump. If not, see . +*/ + +namespace cloonel { + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + bool IsPointOnSegment (const Vector& parPoint, const Vector& parSegA, const Vector& parSegB) { + for (uint32_t z = 0; z < S; ++z) { + if (parPoint[z] <= std::max(parSegA[z], parSegB[z]) and parPoint[z] >= std::min(parSegA[z], parSegB[z])) + return false; + } + return true; + } +} //namespace cloonel diff --git a/src/geometry_2d.cpp b/src/geometry_2d.cpp new file mode 100644 index 0000000..a778376 --- /dev/null +++ b/src/geometry_2d.cpp @@ -0,0 +1,23 @@ +/* + Copyright 2014 Michele "King_DuckZ" Santullo + + This file is part of CloonelJump. + + CloonelJump is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CloonelJump is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CloonelJump. If not, see . +*/ + +#include "geometry_2d.hpp" + +namespace cloonel { +} //namespace cloonel diff --git a/src/geometry_2d.hpp b/src/geometry_2d.hpp new file mode 100644 index 0000000..7b2f08d --- /dev/null +++ b/src/geometry_2d.hpp @@ -0,0 +1,43 @@ +/* + Copyright 2014 Michele "King_DuckZ" Santullo + + This file is part of CloonelJump. + + CloonelJump is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CloonelJump is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CloonelJump. If not, see . +*/ + +#include "vector.hpp" +#include "line.hpp" +#include "geometry.hpp" +#include +#include +#include + +#ifndef id2B404E7CFDD3470680E572779CB819F6 +#define id2B404E7CFDD3470680E572779CB819F6 + +namespace cloonel { + template + int GetOrientation ( const Vector& parPointA, const Vector& parPointB, const Vector& parPointC ) __attribute__((pure)); + + template + bool Intersection2D ( const Vector& parSegA1, const Vector& parSegA2, const Vector& parSegB1, const Vector& parSegB2 ) __attribute__((pure)); + + template + std::pair> Intersection ( const Line& parSegA, const Line& parSegB ) __attribute__((pure)); +} //namespace cloonel + +#include "geometry_2d.inl" + +#endif diff --git a/src/geometry_2d.inl b/src/geometry_2d.inl new file mode 100644 index 0000000..f059d5a --- /dev/null +++ b/src/geometry_2d.inl @@ -0,0 +1,88 @@ +/* + Copyright 2014 Michele "King_DuckZ" Santullo + + This file is part of CloonelJump. + + CloonelJump is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CloonelJump is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CloonelJump. If not, see . +*/ + +namespace cloonel { + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + int GetOrientation (const Vector& parPointA, const Vector& parPointB, const Vector& parPointC) { + const auto ret = + (parPointB.y() - parPointA.y()) * (parPointC.x() - parPointB.x()) - + (parPointB.x() - parPointA.x()) * (parPointC.y() - parPointB.y()); + const T zero(0); + if (ret == zero) + return 0; + else if (ret < zero) + return -1; + else + return 1; + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + bool Intersection2D (const Vector& parSegA1, const Vector& parSegA2, const Vector& parSegB1, const Vector& parSegB2) { + const int o1 = GetOrientation(parSegA1, parSegA2, parSegB1); + const int o2 = GetOrientation(parSegA1, parSegA2, parSegB2); + const int o3 = GetOrientation(parSegB1, parSegB2, parSegA1); + const int o4 = GetOrientation(parSegB1, parSegB2, parSegA2); + + if (o1 != o2 and o3 != o4) + return true; + + if (0 == o1 and IsPointOnSegment(parSegA1, parSegB1, parSegA2)) + return true; + if (0 == o2 and IsPointOnSegment(parSegA1, parSegB2, parSegA2)) + return true; + if (0 == o3 and IsPointOnSegment(parSegB1, parSegA1, parSegB2)) + return true; + if (0 == o4 and IsPointOnSegment(parSegB1, parSegA2, parSegB2)) + return true; + + return false; + } + + ///-------------------------------------------------------------------------- + ///http://www.gidforums.com/t-20866.html + ///-------------------------------------------------------------------------- + template + std::pair> Intersection (const Line& parSegA, const Line& parSegB) { + typedef Line LineType; + + const typename LineType::Point& startA = parSegA[0]; + const typename LineType::Point& endA = parSegA[1]; + const typename LineType::Point& startB = parSegB[0]; + const typename LineType::Point& endB = parSegB[1]; + + const T A1(endA.y() - startA.y()); + const T A2(endB.y() - startB.y()); + const T B1(startA.x() - endA.x()); + const T B2(startB.x() - endB.x()); + const T det(A1 * B2 - A2 * B1); + + if (det == 0) { + return std::make_pair(false, typename LineType::Point(0)); + } + else { + const T C1(A1 * startA.x() + B1 * startA.y()); + const T C2(A2 * startB.x() + B2 * startB.y()); + return std::make_pair(true, typename LineType::Point((B2 * C1 - B1 * C2) / det, (A1 * C2 - A2 * C1) / det)); + } + } +} //namespace cloonel diff --git a/src/horzcollisionbar.cpp b/src/horzcollisionbar.cpp index 445bc47..c36f1a2 100644 --- a/src/horzcollisionbar.cpp +++ b/src/horzcollisionbar.cpp @@ -97,7 +97,8 @@ namespace cloonel { ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- float2 HorzCollisionBar::To() const { - return this->GetPos() + len(m_segment); + assert(m_segment.End().x() - m_segment.Start().x() != 0.0f); + return this->GetPos() + float2(std::abs(m_segment.End().x() - m_segment.Start().x()), 0.0f); } ///-------------------------------------------------------------------------- diff --git a/src/line.hpp b/src/line.hpp index 6af00c8..440d1bc 100644 --- a/src/line.hpp +++ b/src/line.hpp @@ -23,6 +23,8 @@ #include "compatibility.h" #include "vector.hpp" #include "vectormath.hpp" +#include +#include namespace cloonel { template @@ -36,6 +38,7 @@ namespace cloonel { Line ( const Line& parOther ); Line ( const Point& parStart, const Point& parEnd ); Line ( const Point& parStart, const Point& parDirection, Scalar parLength ) : Line(parStart, parStart + parDirection * parLength) { } + Line ( Scalar parX1, Scalar parY1, Scalar parX2, Scalar parY2 ); ~Line ( void ) noexcept = default; Point& Start ( void ) { return m_points.x(); } @@ -43,8 +46,15 @@ namespace cloonel { const Point& Start ( void ) const { return m_points.x(); } const Point& End ( void ) const { return m_points.y(); } + Point& operator[] ( int parIndex ) { assert(parIndex >= 0); return m_points[static_cast(parIndex)]; } + const Point& operator[] ( int parIndex ) const { assert(parIndex >= 0); return m_points[static_cast(parIndex)]; } + Point& operator[] ( uint32_t parIndex ) { return m_points[parIndex]; } + const Point& operator[] ( uint32_t parIndex ) const { return m_points[parIndex]; } + Line& operator+= ( const Point& parRhs ) a_flatten; Line& operator-= ( const Point& parRhs ) a_flatten; + template + Line& operator*= ( const Vector& parRhs ) a_flatten; private: Vector m_points; @@ -58,6 +68,10 @@ namespace cloonel { Line operator+ ( const Vector& parLhs, Line parRhs ) a_pure a_flatten; template Line operator- ( const Vector& parLhs, Line parRhs ) a_pure a_flatten; + template + Line operator* ( const Vector& parLhs, Line parRhs ) a_pure a_flatten; + template + Line operator* ( Line parLhs, const Vector& parRhs ) a_pure a_flatten; template bool operator> ( const Vector& parLhs, const Line& parRhs ) a_pure; diff --git a/src/line.inl b/src/line.inl index 6aae70b..5c35a6e 100644 --- a/src/line.inl +++ b/src/line.inl @@ -23,6 +23,14 @@ namespace cloonel { { } + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + Line::Line (Scalar parX1, Scalar parY1, Scalar parX2, Scalar parY2) : + m_points(Point(parX1, parY1), Point(parX2, parY2)) + { + } + ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- template @@ -44,7 +52,17 @@ namespace cloonel { ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- template - Line operator+ ( const Vector& parLhs, Line parRhs ) { + template + Line& Line::operator*= (const Vector& parRhs) { + m_points.x() = static_cast(m_points.x() * parRhs); + m_points.y() = static_cast(m_points.y() * parRhs); + return *this; + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + Line operator+ (const Vector& parLhs, Line parRhs) { parRhs += parLhs; return parRhs; } @@ -52,7 +70,7 @@ namespace cloonel { ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- template - Line operator- ( const Vector& parLhs, Line parRhs ) { + Line operator- (const Vector& parLhs, Line parRhs) { parRhs -= parLhs; return parRhs; } @@ -60,7 +78,7 @@ namespace cloonel { ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- template - Line operator+ ( Line parLhs, const Vector& parRhs ) { + Line operator+ (Line parLhs, const Vector& parRhs) { parLhs += parRhs; return parLhs; } @@ -68,11 +86,27 @@ namespace cloonel { ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- template - Line operator- ( Line parLhs, const Vector& parRhs ) { + Line operator- (Line parLhs, const Vector& parRhs) { parLhs -= parRhs; return parLhs; } + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + Line operator* (const Vector& parLhs, Line parRhs) { + parRhs *= parLhs; + return parRhs; + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + Line operator* (Line parLhs, const Vector& parRhs) { + parLhs *= parRhs; + return parLhs; + } + ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- template diff --git a/src/movers/moversine.cpp b/src/movers/moversine.cpp index cf86823..87a0e39 100644 --- a/src/movers/moversine.cpp +++ b/src/movers/moversine.cpp @@ -44,6 +44,7 @@ namespace cloonel { void MoverSine::ApplyMotion (float parDelta) { const float pitwo = static_cast(M_PI) * 2.0f; m_alpha += parDelta * 2.6f; + //TODO: optimize - see https://groups.google.com/forum/#!topic/comp.graphics.api.opengl/FFl3djAYERs while (m_alpha >= pitwo) m_alpha -= pitwo; } diff --git a/src/platform.cpp b/src/platform.cpp index 78ac61b..4b8b269 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -74,4 +74,10 @@ namespace cloonel { void Platform::OnRegister (Mover& parMover, Mover::PlaceableTicketType parParentTicket) { parMover.RegisterPlaceable(m_collisionTop.get(), parParentTicket); } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + void Platform::CopyDrawables (std::vector& parOut) const { + parOut.push_back(this); + } } //namespace cloonel diff --git a/src/platform.hpp b/src/platform.hpp index 9d7c267..a2130cf 100644 --- a/src/platform.hpp +++ b/src/platform.hpp @@ -25,6 +25,7 @@ #include "placeable.hpp" #include "collidertypedef.hpp" #include +#include namespace cloonel { class Texture; @@ -33,6 +34,10 @@ namespace cloonel { class Platform : public Drawable, public Placeable { public: + enum { + SurfaceCount = 1 + }; + Platform ( SDLMain* parSdlMain, const float2& parPos, Texture* parTexture, const float2& parSize ); Platform ( Platform&& parOther ) noexcept; Platform ( const Platform& ) = delete; @@ -42,6 +47,7 @@ namespace cloonel { float2 TopLeft ( void ) const { return GetPos(); } float2 BottomRight ( void ) const { return TopLeft() + m_size; } const HorzCollisionBar* TopCollisionBar ( void ) const { return m_collisionTop.get(); } + void CopyDrawables ( std::vector& parOut ) const; //Overrides virtual void Draw ( void ) const; diff --git a/src/platformset.cpp b/src/platformset.cpp index 244d467..ae6535f 100644 --- a/src/platformset.cpp +++ b/src/platformset.cpp @@ -79,9 +79,9 @@ namespace cloonel { void PlatformSet::CopyDrawables (std::vector& parOut) const { auto eleCopy = FindFirstVisible(m_platforms); const size_t count = checked_numcast(m_platforms.end() - eleCopy); - parOut.reserve(parOut.size() + count); + parOut.reserve(parOut.size() + count * Platform::SurfaceCount); while (m_platforms.end() != eleCopy) { - parOut.push_back(&*eleCopy); + eleCopy->CopyDrawables(parOut); ++eleCopy; } } diff --git a/src/vector.hpp b/src/vector.hpp index b222379..af20053 100644 --- a/src/vector.hpp +++ b/src/vector.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #if !defined(NDEBUG) #include @@ -76,21 +77,21 @@ namespace cloonel { template const Vector& operator*= ( U parOther ); template const Vector& operator/= ( U parOther ); - T& operator[] ( uint32_t parIndex ) { return m_mem[parIndex]; } - const T& operator[] ( uint32_t parIndex ) const { return m_mem[parIndex]; } + T& operator[] ( uint32_t parIndex ) { assert(parIndex < S); return m_mem[parIndex]; } + const T& operator[] ( uint32_t parIndex ) const { assert(parIndex < S); return m_mem[parIndex]; } private: T m_mem[S]; }; template - Vector::type, S> operator+ ( Vector parA, const Vector& parB ) a_pure; + Vector::type, S> operator+ ( const Vector& parA, const Vector& parB ) a_pure; template - Vector::type, S> operator- ( Vector parA, const Vector& parB ) a_pure; + Vector::type, S> operator- ( const Vector& parA, const Vector& parB ) a_pure; template - Vector::type, S> operator* ( Vector parA, const Vector& parB ) a_pure; + Vector::type, S> operator* ( const Vector& parA, const Vector& parB ) a_pure; template - Vector::type, S> operator/ ( Vector parA, const Vector& parB ) a_pure; + Vector::type, S> operator/ ( const Vector& parA, const Vector& parB ) a_pure; template ::value>::type> Vector::type, S> operator+ ( U parA, const Vector& parB ) a_pure; template ::value>::type> @@ -126,6 +127,9 @@ namespace cloonel { typedef Vector float2; typedef Vector ushort2; +#if !defined(NDEBUG) + typedef Vector short2; +#endif typedef Vector int2; #if !defined(NDEBUG) @@ -140,6 +144,71 @@ namespace cloonel { } #endif + namespace implem { + template + struct CategorizeTypes { + typedef typename std::common_type::type CommonType; + typedef typename std::conditional::value, U, T>::type OtherType; + }; + template ::value> + struct DoOperation { + static Vector do_mul ( Vector parLho, const Vector& parRho ) { + parLho *= parRho; + return parLho; + } + static Vector do_div ( Vector parLho, const Vector& parRho ) { + parLho /= parRho; + return parLho; + } + static Vector do_sum ( Vector parLho, const Vector& parRho ) { + parLho += parRho; + return parLho; + } + static Vector do_sub ( Vector parLho, const Vector& parRho ) { + parLho -= parRho; + return parLho; + } + }; + template + struct DoOperation { + static Vector do_mul ( Vector parLho, const Vector& parRho ) { + parLho *= parRho; + return parLho; + } + static Vector do_mul ( const Vector& parLho, const Vector& parRho ) { + Vector ret(parLho); + ret *= parRho; + return ret; + } + static Vector do_div ( Vector parLho, const Vector& parRho ) { + parLho /= parRho; + return parLho; + } + static Vector do_div ( const Vector& parLho, const Vector& parRho ) { + Vector ret(parLho); + ret /= parRho; + return ret; + } + static Vector do_sum ( Vector parLho, const Vector& parRho ) { + parLho += parRho; + return parLho; + } + static Vector do_sum ( const Vector& parLho, const Vector& parRho ) { + Vector ret(parLho); + ret += parRho; + return ret; + } + static Vector do_sub ( Vector parLho, const Vector& parRho ) { + parLho -= parRho; + return parLho; + } + static Vector do_sub ( const Vector& parLho, const Vector& parRho ) { + Vector ret(parLho); + ret -= parRho; + return ret; + } + }; + } //namespace implem } //namespace cloonel #include "vector.inl" diff --git a/src/vector.inl b/src/vector.inl index 5d8a48c..e79741d 100644 --- a/src/vector.inl +++ b/src/vector.inl @@ -121,27 +121,23 @@ namespace cloonel { ///------------------------------------------------------------------------- template inline - Vector::type, S> operator+ (Vector parA, const Vector& parB) { - parA += parB; - return parA; + Vector::type, S> operator+ (const Vector& parA, const Vector& parB) { + return implem::DoOperation, S>::do_sum(parA, parB); } template inline - Vector::type, S> operator- (Vector parA, const Vector& parB) { - parA -= parB; - return parA; + Vector::type, S> operator- (const Vector& parA, const Vector& parB) { + return implem::DoOperation, S>::do_sub(parA, parB); } template inline - Vector::type, S> operator* (Vector parA, const Vector& parB) { - parA *= parB; - return parA; + Vector::type, S> operator* (const Vector& parA, const Vector& parB) { + return implem::DoOperation, S>::do_mul(parA, parB); } template inline - Vector::type, S> operator/ (Vector parA, const Vector& parB) { - parA /= parB; - return parA; + Vector::type, S> operator/ (const Vector& parA, const Vector& parB) { + return implem::DoOperation, S>::do_div(parA, parB); } ///------------------------------------------------------------------------- @@ -243,11 +239,7 @@ namespace cloonel { } template inline bool operator!= (const Vector& parA, const Vector& parB) { - bool retVal = true; - for (uint32_t z = 0; z < S; ++z) { - retVal &= static_cast(parA[z] != parB[z]); - } - return retVal; + return not operator==(parA, parB); } template