Generate random platforms nicely.
This also fixes the build.
This commit is contained in:
parent
0e2303112f
commit
4166983809
5 changed files with 40 additions and 153 deletions
|
@ -9,7 +9,7 @@ include(FindPkgConfig)
|
||||||
PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2)
|
PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2)
|
||||||
|
|
||||||
find_package(PNG REQUIRED)
|
find_package(PNG REQUIRED)
|
||||||
find_package(Boost 1.35.0 REQUIRED)
|
find_package(Boost 1.55.0 REQUIRED)
|
||||||
|
|
||||||
add_definitions(
|
add_definitions(
|
||||||
${PNG_DEFINITIONS}
|
${PNG_DEFINITIONS}
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
#define DEF_WIN_WIDTH REFERENCE_WIDTH
|
#define DEF_WIN_WIDTH REFERENCE_WIDTH
|
||||||
#define DEF_WIN_HEIGHT REFERENCE_HEIGHT
|
#define DEF_WIN_HEIGHT REFERENCE_HEIGHT
|
||||||
#define DEF_RANDOM_SEED 1984
|
#define DEF_RANDOM_SEED 1984
|
||||||
#define MAX_PLATFORMS_ON_SCREEN 8
|
#define MAX_PLATFORMS_ON_SCREEN 24
|
||||||
|
|
||||||
/* TODO: make this path relative */
|
/* TODO: make this path relative */
|
||||||
#define GAME_BASE_PATH "@CMAKE_SOURCE_DIR@"
|
#define GAME_BASE_PATH "@CMAKE_SOURCE_DIR@"
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
/*
|
|
||||||
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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef idF67A018826604CAFBE25BCA939A1FBC9
|
|
||||||
#define idF67A018826604CAFBE25BCA939A1FBC9
|
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
#include <iterator>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <ciso646>
|
|
||||||
|
|
||||||
namespace cloonel {
|
|
||||||
template <typename Iterator>
|
|
||||||
class CircularBuffer : public boost::noncopyable {
|
|
||||||
public:
|
|
||||||
typedef size_t size_type;
|
|
||||||
typedef typename std::iterator_traits<Iterator>::value_type value_type;
|
|
||||||
typedef typename std::iterator_traits<Iterator>::reference reference;
|
|
||||||
|
|
||||||
CircularBuffer ( Iterator parFirst, Iterator parLast );
|
|
||||||
CircularBuffer ( CircularBuffer&& parOther );
|
|
||||||
~CircularBuffer ( void ) noexcept = default;
|
|
||||||
CircularBuffer& operator= ( CircularBuffer&& parOther );
|
|
||||||
|
|
||||||
reference operator[] ( size_type parIndex );
|
|
||||||
|
|
||||||
size_type size ( void ) const { return (m_used >= capacity() ? capacity() : m_used); }
|
|
||||||
bool empty ( void ) const { return 0 == m_used; }
|
|
||||||
size_type capacity ( void ) const { return m_end - m_start; }
|
|
||||||
void push ( value_type&& parObj );
|
|
||||||
void reset ( void );
|
|
||||||
void reset ( Iterator parFirst, Iterator parLast );
|
|
||||||
reference front ( void );
|
|
||||||
reference back ( void );
|
|
||||||
|
|
||||||
private:
|
|
||||||
Iterator m_start;
|
|
||||||
Iterator m_end;
|
|
||||||
Iterator m_curr;
|
|
||||||
size_type m_used;
|
|
||||||
};
|
|
||||||
} //namespace cloonel
|
|
||||||
|
|
||||||
#include "circularbuffer.inl"
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,68 +0,0 @@
|
||||||
namespace cloonel {
|
|
||||||
template <typename Iterator>
|
|
||||||
CircularBuffer<Iterator>::CircularBuffer (Iterator parFirst, Iterator parLast) :
|
|
||||||
m_start(parFirst),
|
|
||||||
m_end(parLast),
|
|
||||||
m_curr(parFirst),
|
|
||||||
m_used(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
void CircularBuffer<Iterator>::push (value_type&& parObj) {
|
|
||||||
*m_curr = std::move(parObj);
|
|
||||||
++m_curr;
|
|
||||||
++m_used;
|
|
||||||
if (m_curr == m_end) {
|
|
||||||
m_curr = m_start;
|
|
||||||
m_used = capacity();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
void CircularBuffer<Iterator>::reset() {
|
|
||||||
m_used = 0;
|
|
||||||
m_curr = m_start;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
void CircularBuffer<Iterator>::reset (Iterator parFirst, Iterator parLast) {
|
|
||||||
m_start = parFirst;
|
|
||||||
m_end = parLast;
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
typename CircularBuffer<Iterator>::reference CircularBuffer<Iterator>::front() {
|
|
||||||
if (empty())
|
|
||||||
throw std::out_of_range("The circular buffer is empty, but front() was called.");
|
|
||||||
if (m_curr == m_start)
|
|
||||||
return *(m_start + (capacity() - 1));
|
|
||||||
else
|
|
||||||
return *(m_curr - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
typename CircularBuffer<Iterator>::reference CircularBuffer<Iterator>::back() {
|
|
||||||
if (empty())
|
|
||||||
throw std::out_of_range("The circular buffer is empty, but back() was called.");
|
|
||||||
const auto cap = capacity();
|
|
||||||
if (m_used != cap) {
|
|
||||||
return *m_start;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const auto currPos = m_curr - m_start;
|
|
||||||
const auto index = (currPos + cap - 1) % cap;
|
|
||||||
return *(m_start + index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
typename CircularBuffer<Iterator>::reference CircularBuffer<Iterator>::operator[] (size_type parIndex) {
|
|
||||||
if (parIndex < 0 or parIndex >= size())
|
|
||||||
throw std::out_of_range("Index out of range in CircularBuffer");
|
|
||||||
|
|
||||||
const auto index = (m_curr - m_start + parIndex) % capacity();
|
|
||||||
return *(m_start + index);
|
|
||||||
}
|
|
||||||
} //namespace cloonel
|
|
|
@ -23,17 +23,38 @@
|
||||||
#include "texture.hpp"
|
#include "texture.hpp"
|
||||||
#include "gameplayscene.hpp"
|
#include "gameplayscene.hpp"
|
||||||
#include "mover.hpp"
|
#include "mover.hpp"
|
||||||
#include "circularbuffer.hpp"
|
|
||||||
#include <ciso646>
|
#include <ciso646>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <boost/circular_buffer.hpp>
|
||||||
|
|
||||||
namespace cloonel {
|
namespace cloonel {
|
||||||
namespace {
|
namespace {
|
||||||
const uint32_t g_platfWidth = 104;
|
const uint32_t g_platfWidth = 104;
|
||||||
const uint32_t g_platfHeight = 25;
|
const uint32_t g_platfHeight = 25;
|
||||||
|
|
||||||
|
float2 PositionForNewPlatf (float parStart, float parAverage, float parMaxDist, size_t parLeft) {
|
||||||
|
assert(parAverage >= 0.0f);
|
||||||
|
const float& maxDist = parMaxDist;
|
||||||
|
const float minDist = std::max(static_cast<float>(g_platfHeight), (static_cast<float>(REFERENCE_HEIGHT) - parStart) / static_cast<float>(parLeft));
|
||||||
|
assert(minDist <= maxDist); //make sure the player can jump all the way to the top
|
||||||
|
assert(minDist <= parAverage); //that would screw up the player
|
||||||
|
|
||||||
|
const float upperRange = std::max(parAverage, maxDist) - parAverage;
|
||||||
|
const float lowerRange = std::max(parAverage, minDist) - minDist;
|
||||||
|
assert(upperRange >= 0.0f);
|
||||||
|
assert(lowerRange >= 0.0f);
|
||||||
|
|
||||||
|
const float invRandMax = 1.0f / static_cast<float>(RAND_MAX);
|
||||||
|
const float yDist = static_cast<float>(std::rand()) * invRandMax * (lowerRange + upperRange - minDist) + minDist;
|
||||||
|
assert(yDist >= minDist and yDist <= maxDist);
|
||||||
|
|
||||||
|
const auto rndNum = std::rand() % (REFERENCE_WIDTH - g_platfWidth);
|
||||||
|
|
||||||
|
return float2(static_cast<float>(rndNum), yDist + parStart);
|
||||||
|
}
|
||||||
} //unnamed namespace
|
} //unnamed namespace
|
||||||
|
|
||||||
struct PlatformInfo {
|
struct PlatformInfo {
|
||||||
|
@ -69,8 +90,7 @@ namespace cloonel {
|
||||||
LocalData ( const char* parTexturePath, SDLMain* parSDLMain, GameplayScene* parScene, float parMaxDistance );
|
LocalData ( const char* parTexturePath, SDLMain* parSDLMain, GameplayScene* parScene, float parMaxDistance );
|
||||||
~LocalData ( void ) noexcept = default;
|
~LocalData ( void ) noexcept = default;
|
||||||
|
|
||||||
std::vector<PlatformInfo> platformsBuff;
|
boost::circular_buffer<PlatformInfo> platforms;
|
||||||
CircularBuffer<std::vector<PlatformInfo>::iterator> platforms;
|
|
||||||
Texture texture;
|
Texture texture;
|
||||||
SDLMain* const sdlmain;
|
SDLMain* const sdlmain;
|
||||||
GameplayScene* const scene;
|
GameplayScene* const scene;
|
||||||
|
@ -80,8 +100,7 @@ namespace cloonel {
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
PlatformSystem::LocalData::LocalData (const char* parTexturePath, SDLMain* parSDLMain, GameplayScene* parScene, float parMaxDistance) :
|
PlatformSystem::LocalData::LocalData (const char* parTexturePath, SDLMain* parSDLMain, GameplayScene* parScene, float parMaxDistance) :
|
||||||
platformsBuff(MAX_PLATFORMS_ON_SCREEN),
|
platforms(MAX_PLATFORMS_ON_SCREEN),
|
||||||
platforms(platformsBuff.begin(), platformsBuff.end()),
|
|
||||||
texture(parTexturePath, parSDLMain, false),
|
texture(parTexturePath, parSDLMain, false),
|
||||||
sdlmain(parSDLMain),
|
sdlmain(parSDLMain),
|
||||||
scene(parScene),
|
scene(parScene),
|
||||||
|
@ -129,18 +148,20 @@ namespace cloonel {
|
||||||
m_localdata->texture.Reload();
|
m_localdata->texture.Reload();
|
||||||
|
|
||||||
//Spawn the initial platforms
|
//Spawn the initial platforms
|
||||||
m_localdata->platforms.reset();
|
m_localdata->platforms.clear();
|
||||||
const size_t totalPlatf = m_localdata->platforms.capacity();
|
const size_t totalPlatf = MAX_PLATFORMS_ON_SCREEN;
|
||||||
const auto totalPlatfFloatInv = 1.0f / static_cast<float>(totalPlatf);
|
//const auto totalPlatfFloatInv = 1.0f / static_cast<float>(totalPlatf);
|
||||||
const int2 platfWH(g_platfWidth, g_platfHeight);
|
const int2 platfWH(g_platfWidth, g_platfHeight);
|
||||||
|
float prevPlatf = 0.0f;
|
||||||
|
const float averageTarget = m_localdata->maxDistance / 8.0f; //TODO: change this value to make up for the difficulty
|
||||||
for (size_t z = 0; z < totalPlatf; ++z) {
|
for (size_t z = 0; z < totalPlatf; ++z) {
|
||||||
const float y = std::min(
|
const auto newPos(PositionForNewPlatf(prevPlatf, averageTarget, m_localdata->maxDistance, totalPlatf - z));
|
||||||
static_cast<float>(REFERENCE_HEIGHT) - 25.0f,
|
prevPlatf = newPos.y();
|
||||||
static_cast<float>(z) * (static_cast<float>(REFERENCE_HEIGHT) * totalPlatfFloatInv)
|
|
||||||
);
|
m_localdata->platforms.push_back(Platform(m_localdata->sdlmain, newPos, &m_localdata->texture, static_cast<float2>(platfWH)));
|
||||||
const auto rndNum = std::rand() % (REFERENCE_WIDTH - platfWH.x());
|
|
||||||
const float2 newPos(static_cast<float>(rndNum), 100.0f + std::min(m_localdata->maxDistance, y));
|
if (static_cast<float>(REFERENCE_HEIGHT) - newPos.y() < averageTarget)
|
||||||
m_localdata->platforms.push(Platform(m_localdata->sdlmain, newPos, &m_localdata->texture, static_cast<float2>(platfWH)));
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,11 +170,7 @@ namespace cloonel {
|
||||||
void PlatformSystem::Destroy() noexcept {
|
void PlatformSystem::Destroy() noexcept {
|
||||||
m_localdata->texture.Destroy();
|
m_localdata->texture.Destroy();
|
||||||
|
|
||||||
for (size_t z = 0; z < m_localdata->platforms.size(); ++z) {
|
m_localdata->platforms.clear();
|
||||||
m_localdata->mover.UnregisterPlaceable(m_localdata->platforms[z].ticket);
|
|
||||||
}
|
|
||||||
m_localdata->platforms.reset();
|
|
||||||
m_localdata->platformsBuff.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
|
@ -170,6 +187,7 @@ namespace cloonel {
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
void PlatformSystem::OnRegister (Mover& parMover, Mover::PlaceableTicketType parTicket) {
|
void PlatformSystem::OnRegister (Mover& parMover, Mover::PlaceableTicketType parTicket) {
|
||||||
for (size_t z = 0; z < m_localdata->platforms.size(); ++z) {
|
for (size_t z = 0; z < m_localdata->platforms.size(); ++z) {
|
||||||
|
assert(m_localdata->platforms[z].platform != nullptr);
|
||||||
m_localdata->platforms[z].ticket = parMover.RegisterPlaceable(m_localdata->platforms[z].platform.get(), parTicket);
|
m_localdata->platforms[z].ticket = parMover.RegisterPlaceable(m_localdata->platforms[z].platform.get(), parTicket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue