if WIN32
-installer: all
+
+INSTALLER_NAME = yoinksetup-$(VERSION).exe
+
+.PHONY: package
+package: $(INSTALLER_NAME)
+
+$(INSTALLER_NAME): all
@echo "Creating win32 installer..."
- @(sh make-win32-installer.sh 2> installer.log 1>&2 && \
+ @(sh make-win32-installer.sh $(INSTALLER_NAME) 2> installer.log 1>&2 && \
rm installer.log && echo "Done.") || \
(echo "Installer compilation failed!"; \
echo "Check installer.log for details."; exit 1)
-endif
+else
+if LINUX
-RPMBUILD = rpmbuild
+.PHONY: package
+package: rpm
rpm: dist-bzip2
- $(RPMBUILD) -ba --nodeps extra/yoink.spec
+ @echo "Creating RPM package..."
+ @($(RPMBUILD) -ba --nodeps extra/yoink.spec 2> rpmbuild.log 1>&2 && \
+ rm rpmbuild.log && echo "Done.") || \
+ (echo "rpmbuild failed!"; \
+ echo "Check rpmbuild.log for details."; exit 1)
+
+endif
+endif
-Yoink is a game originally developed by Neil Carter for Mac OS X. You play
-the part of a flying alien heroine who must defend her home on Earth from
-other airborne alien invaders.
+Yoink is a game originally developed by Neil Carter for Mac OS. You play the
+part of a flying alien heroine who must defend her home on Earth from other
+airborne alien invaders.
-This version of the game uses rewritten code and modern frameworks to bring
+This version of the game uses all new code and modern frameworks to bring
this simple, fast-moving action game to a wider audience.
-The new code is released under the Simplified BSD License. The old code and
-original resources are provided under the zlib/libpng License. See COPYING
-for complete details.
+The new code is released under the BSD-2 license. The old code and original
+resources are provided under the zlib/libpng License. See COPYING for complete
+details.
Dependencies:
boost headers
OpenGL (libGL, libGL or opengl32, glu32)
-libSDL
-libSDL_image (with libpng support)
-libSDL_sound (with libogg support)
-libopenal
-libalut
+SDL
+SDL_image (with libpng support)
+libvorbisfile
+OpenAL
+freealut
Notes regarding the code:
MACOSX=yes
LIBS="$LIBS -Wl,-framework"
;;
+ *-linux-gnu*)
+ LINUX=yes
+ AC_PATH_PROGS([RPMBUILD], [rpmbuild])
+ AC_SUBST(RPMBUILD)
+ ;;
esac
+AM_CONDITIONAL([LINUX], test "$LINUX" = "yes")
AM_CONDITIONAL([WIN32], test "$WIN32" = "yes")
COMPRESSION="/solid lzma"
DEST="tmp-yoink-win32"
SCRIPT="$DEST/yoink.nsi"
+OUT_FILE=${1:-yoinksetup-@VERSION@.exe}
# DLL dependencies
DLLS="SDL SDL_image zlib1 libpng12-0 OpenAL32 libalut-0 libvorbis-0 libogg-0"
VIAddVersionKey "LegalCopyright" "Copyright 2009 Charles McGarvey et al."
;General
-OutFile "$ROOT_DIR/yoinksetup-@VERSION@.exe"
+OutFile "$ROOT_DIR/$OUT_FILE"
SetCompressor $COMPRESSION
ShowInstDetails show
ShowUninstDetails show
for (CallbackIter jt = first; jt != last; ++jt)
{
- if (((*jt).second).first == id)
+ if ((*jt).second.first == id)
{
callbacks.erase(jt);
break;
for (Impl::CallbackIter it = callbacks.first; it != callbacks.second; ++it)
{
- Function callback = ((*it).second).second;
+ Function callback = (*it).second.second;
callback(param);
}
}
#include <string>
+#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
} // namespace dispatch
+
} // namespace Mf
#endif // _MOOF_DISPATCHER_HH_
interface(outer)
{
#if defined(_WIN32) || defined (_WIN64) || defined(__WIN32__)
- if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0)
#else
- if (SDL_Init(SDL_INIT_EVERYTHING | SDL_INIT_EVENTTHREAD) != 0)
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTTHREAD) != 0)
#endif
{
logError("sdl is complaining: %s", SDL_GetError());
int run()
{
- Scalar ticksNow = getTicks();
+ Scalar ticksNow = Timer::getTicks();
Scalar nextStep = ticksNow;
Scalar nextDraw = ticksNow;
running = true;
do
{
- Scalar newTicks = getTicks();
+ Scalar newTicks = Timer::getTicks();
deltaTime = newTicks - ticksNow;
ticksNow = newTicks;
if (deltaTime >= 0.25) deltaTime = 0.25;
accumulator += deltaTime;
+ Timer::fireIfExpired(ticksNow);
+
while (accumulator >= timestep)
{
dispatchEvents();
}
// be a good citizen and give back what you don't need
- sleep(std::min(nextStep, nextDraw), true);
+ Timer::sleep(std::min(std::min(nextStep, nextDraw),
+ Timer::getNextFire()), true);
}
while (running);
}
-//template<typename T>
-//inline T spring(Scalar k, Scalar b)
-//{
- //current.force = -15 * (current.position - Mf::Vector2(200.0, 200.0))
- //- 15.0 * current.velocity;
- //return
-//}
-
-
} // namespace Mf
#endif // _MOOF_RK4_HH_
#include "Log.hh"
#include "Mippleton.hh"
#include "Sound.hh"
+#include "Timer.hh"
#define BUFFER_SIZE (64 * 1024)
//#define BUFFER_SIZE (5*2048)
}
- void beginStream(ALuint source, int nBuffers = 4)
+ void beginStream(ALuint source, int nBuffers = 8)
{
if (!oggStream.datasource) openFile();
if (!oggStream.datasource) return;
alSourcei(source_, AL_LOOPING, AL_FALSE);
alSourcePlay(source_);
playing_ = true;
+
+ streamTimer.init(boost::bind(&Impl::streamUpdate, this, _1, _2), 1.0,
+ Timer::REPEAT);
}
inline void update()
std::queue<BufferP> queue_;
std::vector<BufferP> expired_;
+
+ Timer streamTimer;
+
+ void streamUpdate(Timer& timer, Scalar t)
+ {
+ // don't let the music die!
+ update();
+ }
};
Sound::Sound(const std::string& name) :
impl_->play();
}
-
void Sound::stream()
{
// pass through
impl_->stream();
}
-void Sound::update(Scalar t, Scalar dt)
-{
- // pass through
- impl_->update();
-}
-
void Sound::stop()
{
void play();
-
void stream();
- void update(Scalar t, Scalar dt);
void stop();
void pause();
/**
* @file Thread.hh
- * Light C++ wrapper around SDL threads.
+ * Light C++ wrapper around the SDL threads API.
*/
#include <boost/function.hpp>
typedef boost::function<int(void)> Function;
-int detach_(void* arg)
+inline int detach_(void* arg)
{
- Function function = *(Function*)arg;
- int ret = function();
+ //Function function = *(Function*)arg;
+ int code = (*(Function*)arg)();
delete (Function*)arg;
- return ret;
+ return code;
}
-Thread detachFunction(const Function& function)
+inline Thread detachFunction(const Function& function)
{
- Thread thread;
Function* fcopy = new Function(function);
+ Thread thread = SDL_CreateThread(detach_, (void*)fcopy);
- thread = SDL_CreateThread(detach_, (void*)fcopy);
if (thread == 0) delete fcopy;
return thread;
}
-int waitOnThread(Thread thread)
+inline int waitOnThread(Thread thread)
{
int i;
SDL_WaitThread(thread, &i);
return i;
}
-void killThread(Thread thread)
+inline void killThread(Thread thread)
{
SDL_KillThread(thread);
}
// The identifier function returns a unique integer for the calling thread.
//
-unsigned int getThreadIdentifier()
+inline unsigned getThreadIdentifier()
{
return SDL_ThreadID();
}
-unsigned int getThreadIdentifier(Thread thread)
+inline unsigned getThreadIdentifier(Thread thread)
{
return SDL_GetThreadID(thread);
}
#include <cerrno>
#include <ctime>
+#include <limits>
#include <stdexcept>
#include "Log.hh"
namespace Mf {
+Scalar Timer::nextFire_ = std::numeric_limits<Scalar>::max();
+std::map<unsigned,Timer&> Timer::timers_;
+
+
+unsigned Timer::getNewID()
+{
+ static unsigned id = 1;
+ return id++;
+}
+
+
+void Timer::init(const Function& function, Scalar seconds, Mode mode)
+{
+ invalidate();
+
+ mode_ = mode;
+
+ if (mode_ != INVALID)
+ {
+ function_ = function;
+
+ if (mode == ABSOLUTEE)
+ {
+ absolute_ = seconds;
+ }
+ else
+ {
+ absolute_ = seconds - getTicks();
+ interval_ = seconds;
+ }
+
+ id_ = getNewID();
+ timers_.insert(std::pair<unsigned,Timer&>(id_, *this));
+
+ if (absolute_ < nextFire_) nextFire_ = absolute_;
+ }
+}
+
+
+bool Timer::isValid() const
+{
+ return mode_ != INVALID;
+}
+
+void Timer::invalidate()
+{
+ if (mode_ != INVALID)
+ {
+ timers_.erase(id_);
+ mode_ = INVALID;
+
+ if (isEqual(absolute_, nextFire_)) nextFire_ = findNextFire();
+ }
+}
+
+
+void Timer::fire()
+{
+ Scalar t = getTicks();
+
+ if (function_) function_(*this, t);
+
+ if (isRepeating())
+ {
+ Scalar absolute = absolute_;
+
+ if (isEqual(absolute_, t, 1.0)) absolute_ += interval_;
+ else absolute_ = interval_ + t;
+
+ if (isEqual(absolute, nextFire_)) nextFire_ = findNextFire();
+ }
+ else
+ {
+ invalidate();
+ }
+}
+
+
+Scalar Timer::findNextFire()
+{
+ std::map<unsigned,Timer&>::iterator it;
+ Scalar nextFire = std::numeric_limits<Scalar>::max();
+
+ for (it = timers_.begin(); it != timers_.end(); ++it)
+ {
+ Scalar absolute = (*it).second.absolute_;
+ if (absolute < nextFire) nextFire = absolute;
+ }
+
+ return nextFire;
+}
+
+
+Scalar Timer::getSecondsRemaining() const
+{
+ return absolute_ - getTicks();
+}
+
+bool Timer::isExpired() const
+{
+ return getSecondsRemaining() < 0.0;
+}
+
+bool Timer::isRepeating() const
+{
+ return mode_ == REPEAT;
+}
+
+
+void Timer::fireIfExpired(Scalar t)
+{
+ std::map<unsigned,Timer&>::iterator it;
+
+ if (nextFire_ > t) return;
+
+ for (it = timers_.begin(); it != timers_.end(); ++it)
+ {
+ Timer& timer = (*it).second;
+ if (timer.isExpired()) timer.fire();
+ }
+}
+
+
#if HAVE_CLOCK_GETTIME
// Since the monotonic clock will provide us with the timer since the computer
static const time_t reference = setReference_();
-Scalar getTicks()
+Scalar Timer::getTicks()
{
struct timespec ts;
return Scalar(ts.tv_sec - reference) + Scalar(ts.tv_nsec) / 1000000000.0;
}
-void sleep(Scalar seconds, bool absolute)
+void Timer::sleep(Scalar seconds, bool absolute)
{
struct timespec ts;
int ret;
// SDL only promises centisecond accuracy, but that's better than a kick in the
// butt.
-Scalar getTicks()
+Scalar Timer::getTicks()
{
Uint32 ms = SDL_GetTicks();
return Scalar(ms / 1000) + Scalar(ms % 1000) / 1000.0;
}
-void sleep(Scalar seconds, bool absolute)
+void Timer::sleep(Scalar seconds, bool absolute)
{
if (absolute) seconds -= getTicks();
SDL_Delay(Uint32(cml::clamp(int(seconds * 1000.0), 0, 1000)));
* Functions for measuring time in a friendly unit.
*/
+#include <map>
+
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+
#include <Moof/Math.hh>
namespace Mf {
-/**
- * Get the number of seconds since a fixed, arbitrary point in the past.
- * @return Seconds.
- */
+struct Timer
+{
+ enum Mode
+ {
+ INVALID = -1,
+ NORMAL = 0,
+ ABSOLUTEE = 1, // the ABSOLUTE keyword isn't available on win32...
+ REPEAT = 2
+ };
-Scalar getTicks();
+ typedef boost::function<void(Timer&,Scalar)> Function;
-/**
- * Put the thread to sleep for a certain period of time. If absolute is true,
- * then it will sleep until seconds after the fixed time in the past. If
- * absolute is false, it will sleep for seconds starting now. Unlike system
- * sleep functions, this one automatically resumes sleep if sleep was
- * interrupted by a signal. Therefore, calling this function is guaranteed to
- * sleep for the requested amount of time.
- */
+ Timer() :
+ mode_(INVALID) {}
+
+ Timer(const Function& function, Scalar seconds, Mode mode = NORMAL)
+ {
+ init(function, seconds, mode);
+ }
+
+ ~Timer()
+ {
+ invalidate();
+ }
+
+ void init(const Function& function, Scalar seconds, Mode mode = NORMAL);
+
+ bool isValid() const;
+ void invalidate();
+
+ void fire();
+
+ Scalar getSecondsRemaining() const;
+ bool isExpired() const;
+ bool isRepeating() const;
+
+
+ /**
+ * Get the number of seconds since a fixed, arbitrary point in the past.
+ * @return Seconds.
+ */
+
+ static Scalar getTicks();
+
+
+ /**
+ * Put the thread to sleep for a certain period of time. If absolute is true,
+ * then it will sleep until seconds after the fixed time in the past. If
+ * absolute is false, it will sleep for seconds starting now. Unlike system
+ * sleep functions, this one automatically resumes sleep if sleep was
+ * interrupted by a signal. Therefore, calling this function is guaranteed to
+ * sleep for the requested amount of time (and maybe longer).
+ */
+
+ static void sleep(Scalar seconds, bool absolute = false);
+
+
+ static Scalar getNextFire()
+ {
+ return nextFire_;
+ }
+
+ static void fireIfExpired(Scalar t);
+
+private:
+
+ static unsigned getNewID();
+ static Scalar findNextFire();
+
+ Function function_;
+ Mode mode_;
+ Scalar absolute_;
+ Scalar interval_;
+ unsigned id_;
-void sleep(Scalar seconds, bool absolute = false);
+ static Scalar nextFire_;
+ static std::map<unsigned,Timer&> timers_;
+};
} // namespace Mf
#include <SDL/SDL_image.h>
#include "Dispatcher.hh"
+#include "Log.hh"
#include "Serializable.hh"
#include "Settings.hh"
#include "Video.hh"
SDL_FreeSurface(context_);
context_ = 0;
setVideoMode(attribs_.mode);
- Mf::Dispatcher::getInstance().dispatch("video.context_recreated");
}
void Video::setOpenGLAttributes()
attribs_.mode[0] = mode[0];
attribs_.mode[1] = mode[1];
attribs_.mode[2] = mode[2];
+
+#if defined(_WIN32) || defined (_WIN64) || defined(__WIN32__)
+ // on win32, creating a new context via SDL_SetVideoMode will wipe
+ // out the GL state, so we gotta notify everyone to reload their
+ // state after the change
+ Mf::dispatcher::dispatch("video.context_recreated");
+ logInfo("video context recreated");
+#endif
}
else throw Exception(SDL_GetError());
}
#include <iostream>
#include <string>
-#include <boost/bind.hpp>
-
#include <Moof/Exception.hh>
#include <Moof/Log.hh>
#include <Moof/Math.hh>
#include <Moof/OpenGL.hh>
#include <Moof/Settings.hh>
+#include <Moof/Thread.hh>
#include <Moof/Timer.hh>
#include <Moof/Video.hh>
}
+void YoinkApp::myFunc(Mf::Timer& timer, Mf::Scalar t)
+{
+ std::cout << "timer: " << t << std::endl;
+
+ //timer.invalidate();
+}
+
+int YoinkApp::myThread()
+{
+ Mf::Scalar timer = Mf::Timer::getTicks();
+
+ for (;;)
+ {
+ std::cout << "thread awake: " << Mf::Timer::getTicks() << std::endl;
+
+ timer += 3.0;
+ Mf::Timer::sleep(timer, true);
+ }
+ return 0;
+}
+
+
YoinkApp::YoinkApp(int argc, char* argv[]) :
Mf::Engine(argc, argv, configFiles(), PACKAGE_STRING, iconFile()),
music("NightFusionIntro"),
octree = Mf::loadScene("Test");
heroine->treeNode = octree->insert(heroine);
+
+ //myTimer.init(boost::bind(&YoinkApp::myFunc, this, _1, _2),
+ //0.0, Mf::Timer::REPEAT);
+ //Mf::Thread thread = Mf::detachFunction(boost::bind(&YoinkApp::myThread, this));
+ //std::cout << "thread " << thread << " detached." << std::endl;
}
YoinkApp::~YoinkApp()
{
//dt *= 0.7;
- music.update(t, dt);
fadeIn.update(dt);
camera.update(t, dt);
heroine->update(t, dt);
octree->print(heroine->treeNode);
//camera.lookAt(heroine->getSphere().point);
- camera.setPosition(Mf::Vector3(-heroine->current.position[0], -heroine->current.position[1], -256));
+ camera.setPosition(Mf::Vector3(-heroine->current.position[0],
+ -heroine->current.position[1], -256));
interp.update(dt);
hud.setBar1Progress(interp.getState(dt));
case SDL_VIDEORESIZE:
glViewport(0, 0, event.resize.w, event.resize.h);
hud.resize(event.resize.w, event.resize.h);
- camera.setProjection(cml::rad(60.0), double(event.resize.w / event.resize.h), 32.0, 2500.0);
+ camera.setProjection(cml::rad(60.0),
+ double(event.resize.w) / double(event.resize.h), 32.0, 2500.0);
camera.uploadProjectionToGL();
break;
}
Mf::Camera camera;
Mf::OctreeP octree;
+ void myFunc(Mf::Timer& timer, Mf::Scalar t);
+ Mf::Timer myTimer;
+ int myThread();
+
Hud hud;
};