From 8a1acac01b444dccf8b57cedf08392ada2e473c1 Mon Sep 17 00:00:00 2001 From: Charles McGarvey Date: Sun, 29 Nov 2009 02:56:14 -0700 Subject: [PATCH] big batch of changes gtk/qt4 support for dialogs no more class-specific exceptions better sound class (still needs refactoring) separated script from scenes somewhat scaled down the Classic scene from 32x to unit other random changes --- README | 19 +- configure.ac | 48 ++ data/scenes/Classic.lua | 896 ++++++++++++++++-------------------- data/scenes/loader.lua | 5 + data/yoinkrc | 33 +- extra/yoink.ebuild | 5 +- src/Character.cc | 58 ++- src/Character.hh | 8 +- src/GameLayer.cc | 66 ++- src/GameLayer.hh | 15 +- src/Heroine.cc | 2 +- src/MainLayer.cc | 33 +- src/Makefile.am | 1 + src/Moof/Engine.cc | 13 +- src/Moof/Engine.hh | 16 +- src/Moof/Exception.hh | 62 ++- src/Moof/Library.hh | 1 - src/Moof/ModalDialog.hh | 155 +++++++ src/Moof/Resource.cc | 17 +- src/Moof/Resource.hh | 16 +- src/Moof/Script.hh | 75 ++- src/Moof/Sound.cc | 270 ++++++----- src/Moof/Sound.hh | 34 +- src/Moof/Sphere.hh | 7 + src/Moof/Texture.cc | 7 +- src/Moof/Texture.hh | 36 +- src/Moof/Timer.cc | 28 +- src/Moof/Timer.hh | 10 +- src/Moof/Video.cc | 7 +- src/Moof/Video.hh | 16 +- src/Scene.cc | 408 +++++++--------- src/Scene.hh | 7 +- src/Tilemap.hh | 2 +- src/version.h | 2 +- win32/build-installer.sh.in | 2 +- 35 files changed, 1232 insertions(+), 1148 deletions(-) create mode 100644 data/scenes/loader.lua create mode 100644 src/Moof/ModalDialog.hh diff --git a/README b/README index 7dba113..eaea5ad 100644 --- a/README +++ b/README @@ -13,7 +13,7 @@ II. Developers b) Porting III. Packagers a) The build system - b) Help requested + b) Targeting Win32 I. Users @@ -95,10 +95,17 @@ autoconf and automake. It should be fairly sane. If you find any problems, especially any bugs which complicate packaging on certain systems, please send back patches. -b) Help requested +b) Targeting Win32 -If you can create packages for your favorite platform, please send them -back to me and/or place the package in a public repository appropriate for -your distribution or platform. I would especially appreciate packages in -common formats such as deb, rpm, or OS X app bundles. +If you have a working mingw32 toolchain with all the dependencies, you can +build a win32 binary using a command such as this: + +./configure --host=mingw32 --prefix=/usr/mingw32/usr + +where mingw32 is the correct name of your toolchain. You can get all the +non-standard dependencies from the git repository at win32/win32-libs.zip. +Just unzip the contents of that archive into your toolchain. If everything +goes smoothly, you should have a yoink.exe appropriate for the win32 +platform. You can then build a complete installer using "make package" if +you have nsis installed. diff --git a/configure.ac b/configure.ac index 0d9f5fd..3fdbe84 100644 --- a/configure.ac +++ b/configure.ac @@ -27,6 +27,8 @@ AC_PROG_INSTALL AC_PROG_RANLIB AM_PROG_CC_C_O +PKG_PROG_PKG_CONFIG + AC_PATH_PROGS([DOXYGEN], [doxygen]) AC_SUBST(DOXYGEN) @@ -93,6 +95,16 @@ AC_ARG_ENABLE([threads], [threads=$enableval], [threads=no]) +AC_ARG_ENABLE([gtk], + [ --enable-gtk enable GTK+ info/warning dialogs], + [gtk=$enableval], + [gtk=no]) + +AC_ARG_ENABLE([qt4], + [ --enable-qt4 enable QT info/warning dialogs], + [qt4=$enableval], + [qt4=no]) + AC_ARG_WITH([log-level], [AS_HELP_STRING([--with-log-level=NUM], [0, none... 1, errors... 4, everything (default: 3)])], @@ -135,6 +147,18 @@ then [Define to 1 if you want to use threads for parallel tasks.]) fi +if test x$gtk = xyes +then + AC_DEFINE([USE_GTK], 1, + [Define to 1 if you want to use GTK+ info/error dialogs.]) +else +if test x$qt4 = xyes +then + AC_DEFINE([USE_QT4], 1, + [Define to 1 if you want to use QT info/error dialogs.]) +fi +fi + AC_DEFINE_UNQUOTED([YOINK_LOGLEVEL], [$log_level], [Define to detail level of logging.]) @@ -280,6 +304,30 @@ AC_SEARCH_LIBS([lua_load], [lua],, [missing=yes echo "***** Missing liblua ($website) *****"]) +if test x$gtk = xyes +then + ##### GTK+ 2.0 ##### + website="http://www.gtk.org/" + PKG_CHECK_MODULES([GTK], [gtk+-2.0], + [LIBS="$LIBS $GTK_LIBS" + CFLAGS="$CFLAGS $GTK_CFLAGS" + CXXFLAGS="$CXXFLAGS $GTK_CFLAGS"], + [missing=yes + echo "***** Missing GTK+-2.0 ($website) *****"]) +fi + +if test x$qt4 = xyes +then + ##### QT4 ##### + website="http://qt.nokia.com/" + PKG_CHECK_MODULES([QT], [QtGui], + [LIBS="$LIBS $QT_LIBS" + CFLAGS="$CFLAGS $QT_CFLAGS" + CXXFLAGS="$CXXFLAGS $QT_CFLAGS"], + [missing=yes + echo "***** Missing QT ($website) *****"]) +fi + ##### librt (optional) ##### AC_SEARCH_LIBS([clock_gettime], [rt], [AC_DEFINE([HAVE_CLOCK_GETTIME], 1, diff --git a/data/scenes/Classic.lua b/data/scenes/Classic.lua index 4cae26a..963db84 100644 --- a/data/scenes/Classic.lua +++ b/data/scenes/Classic.lua @@ -6,22 +6,20 @@ -- Scene API: -- -- Functions: --- SetPlayfieldBounds(point1, point2) --- SetMaximumBounds(point1, point2) +-- SetBounds(point1, point2) -- ResetTransform() -- Translate(x, y, z) -- Scale(x, y, z) or Scale(xyz) -- Rotate(axis, degree) or Rotate(x, y, z) -- SetTexture(name) --- MakeTilemap({width = ..., surface_type = ..., tiles = {}}) --- MakeBillboard({tile = ..., u_scale = ...}) +-- DrawTilemap({width = $num, [surface = TOP | LEFT | RIGHT], tiles}) +-- DrawTile(tile, [u_scale]) -- -- Globals: --- detail - level of detail of the scene +-- detail - level of detail of the scene (HIGH, MEDIUM, or LOW) -SetPlayfieldBounds({0, 0, -100}, {1280, 500, 100}) -SetMaximumBounds({-160, 0, -192}, {1440, 480, 224}) +SetBounds({-5, 0, -6}, {45, 15, 7}) -- Left end tower block @@ -31,134 +29,110 @@ SetMaximumBounds({-160, 0, -192}, {1440, 480, 224}) ResetTransform() Translate(-5, 0, 5) -Scale(32) SetTexture("TowerBlock1") -MakeTilemap({ +DrawTilemap({ width = 5, - tiles = { - 2, 2, 2, 2, 2, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 4, 4, 4, 4, 4 - } -}) + 2, 2, 2, 2, 2, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 4, 4, 4, 4, 4}) -- Right side ResetTransform() Rotate(Y, 90) Translate(0, 0, 5) -Scale(32) -MakeTilemap({ +DrawTilemap({ width = 5, - surface_type = RIGHT, - tiles = { - 2, 2, 2, 2, 2, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 6, - 4, 5, 5, 5, 4 - } -}) + surface = RIGHT, + 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, + 4, 5, 5, 5, 4}) -- Top ResetTransform() Rotate(X, 90) Translate(-5, 15, 0) -Scale(32) -MakeTilemap({ +DrawTilemap({ width = 5, - surface_type = TOP, - tiles = { - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3 - } -}) + surface = TOP, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3}) -- Leftmost background tower block -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- Front -if detail > 1 then +if detail > LOW then ResetTransform() - Scale(32) - MakeTilemap({ + DrawTilemap({ width = 7, - tiles = { - 2, 2, 2, 2, 2, 2, 2, - 0, 1, 0, 0, 0, 1, 0, - 0, 1, 0, 0, 0, 1, 0, - 0, 1, 0, 0, 6, 1, 0, - 0, 1, 0, 0, 0, 1, 0, - 0, 1, 0, 0, 0, 1, 0, - 0, 1, 0, 0, 0, 1, 0, - 4, 4, 5, 5, 5, 4, 4 - } - }) + 2, 2, 2, 2, 2, 2, 2, + 0, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 6, 1, 0, + 0, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 0, + 4, 4, 5, 5, 5, 4, 4}) -- Right side ResetTransform() Rotate(Y, 90) Translate(7, 0, 0) - Scale(32) - MakeTilemap({ + DrawTilemap({ width = 6, - tiles = { - 2, 2, 2, 2, 2, 2, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 4, 4, 4, 4, 4, 4 - } - }) + 2, 2, 2, 2, 2, 2, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 4, 4, 4, 4, 4, 4}) -- Top ResetTransform() Rotate(X, 90) Translate(-2, 8, -6) - Scale(32) - MakeTilemap({ + DrawTilemap({ width = 9, - tiles = { - 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3 - } - }) + 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3}) end -- Foreground building with pitched roof @@ -169,51 +143,39 @@ end ResetTransform() Rotate(Y, -90) Translate(10, 0, 1) -Scale(32) SetTexture("Building") -MakeTilemap({ +DrawTilemap({ width = 4, - surface_type = LEFT, - tiles = { - -1, 9, 11, -1, - 9, 10, 12, 11, - 15, 7, 7, 16, - 3, 5, 6, 4, - 3, 6, 5, 4 - } -}) + surface = LEFT, + -1, 9, 11, -1, + 9, 10, 12, 11, + 15, 7, 7, 16, + 3, 5, 6, 4, + 3, 6, 5, 4}) -- Right wall ResetTransform() Rotate(Y, -90) Translate(13, 0, 1) -Scale(32) -MakeTilemap({ +DrawTilemap({ width = 4, - surface_type = RIGHT, - tiles = { - -1, 9, 11, -1, - 9, 10, 12, 11, - 15, 7, 7, 16, - 3, 5, 6, 4, - 3, 8, 5, 4 - } -}) + surface = RIGHT, + -1, 9, 11, -1, + 9, 10, 12, 11, + 15, 7, 7, 16, + 3, 5, 6, 4, + 3, 8, 5, 4}) -- Front wall ResetTransform() Translate(10, 0, 5) -Scale(32) -MakeTilemap({ +DrawTilemap({ width = 3, - tiles = { - 15, 7, 16, - 3, 5, 4, - 3, 6, 4 - } -}) + 15, 7, 16, + 3, 5, 4, + 3, 6, 4}) -- Pitched roof @@ -221,39 +183,27 @@ ResetTransform() Rotate(X, 135) Scale(1, 1.5, 1.5) Translate(10, 5, 3) -Scale(32) -MakeTilemap({ +DrawTilemap({ width = 3, - tiles = { - 13, 13, 13, - 13, 13, 13 - } -}) + 13, 13, 13, + 13, 13, 13}) -- Finial ResetTransform() Translate(10, 5, 3) -Scale(32) -MakeTilemap({ +DrawTilemap({ width = 3, - tiles = { - 18, 18, 18 - } -}) + 18, 18, 18}) -- Cheaty invisible platform ResetTransform() Translate(10, 4, 3) -Scale(32) -MakeTilemap({ +DrawTilemap({ width = 3, - surface_type = TOP, - tiles = { - -1, -1, -1 - } -}) + surface = TOP, + -1, -1, -1}) -- The ground -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -263,42 +213,35 @@ MakeTilemap({ ResetTransform() Rotate(X, 90) Translate(-3, 0, 0) -Scale(32) SetTexture("Scenery") -MakeTilemap({ +DrawTilemap({ width = 13, - surface_type = TOP, - tiles = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, - -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, - -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, - -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, - -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - } -}) + surface = TOP, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, + -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, + -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, + -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, + -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}) -- Front grass -if detail > 2 then +if detail > MEDIUM then ResetTransform() Scale(8, 1, 1) Translate(1, -0.5, 5) - Scale(32) - MakeBillboard({ - tile = 2, - u_scale = 8 - }) + DrawTile({ + 2, + u_scale = 8}) -- Back grass ResetTransform() Scale(8, 1, 1) Translate(1, -0.5, 1) - Scale(32) - MakeBillboard({ - tile = 2, + DrawTile({ + 2, u_scale = 8 }) @@ -308,9 +251,8 @@ if detail > 2 then Scale(4, 1, 1) Rotate(Y, -90) Translate(1, -0.5, 1) - Scale(32) - MakeBillboard({ - tile = 2, + DrawTile({ + 2, u_scale = 4 }) @@ -320,9 +262,8 @@ if detail > 2 then Scale(4, 1, 1) Rotate(Y, -90) Translate(9, -0.5, 1) - Scale(32) - MakeBillboard({ - tile = 2, + DrawTile({ + 2, u_scale = 4 }) @@ -331,9 +272,8 @@ if detail > 2 then ResetTransform() Scale(11, 1, 1) Translate(7, 0, 0) - Scale(32) - MakeBillboard({ - tile = 4, + DrawTile({ + 4, u_scale = 11 }) end @@ -343,54 +283,42 @@ end -- Front wall -if detail > 1 then +if detail > LOW then ResetTransform() Translate(19, 0, 0) - Scale(32) SetTexture("Building") - MakeTilemap({ + DrawTilemap({ width = 4, - tiles = { - -1, 9, 11, -1, - 9, 10, 12, 11, - 15, 7, 7, 16, - 3, 6, 5, 4, - 3, 5, 6, 4, - 3, 8, 5, 4 - } - }) + -1, 9, 11, -1, + 9, 10, 12, 11, + 15, 7, 7, 16, + 3, 6, 5, 4, + 3, 5, 6, 4, + 3, 8, 5, 4}) -- Left wall ResetTransform() Rotate(Y, -90) Translate(19, 0, -3) - Scale(32) - MakeTilemap({ + DrawTilemap({ width = 3, - tiles = { - 15, 1, 16, - 3, 7, 4, - 3, 5, 4, - 3, 0, 4 - } - }) + 15, 1, 16, + 3, 7, 4, + 3, 5, 4, + 3, 0, 4}) -- Right wall ResetTransform() Rotate(Y, -90) Translate(23, 0, -3) - Scale(32) - MakeTilemap({ + DrawTilemap({ width = 3, - tiles = { - 15, 0, 16, - 3, 7, 4, - 3, 6, 4, - 3, 2, 4 - } - }) + 15, 0, 16, + 3, 7, 4, + 3, 6, 4, + 3, 2, 4}) -- Left pitched roof @@ -399,14 +327,10 @@ if detail > 1 then Scale(1, 1.5, 1.5) Rotate(Y, -90) Translate(21, 6, -3) - Scale(32) - MakeTilemap({ + DrawTilemap({ width = 3, - tiles = { - 13, 13, 13, - 13, 13, 13 - } - }) + 13, 13, 13, + 13, 13, 13}) -- Right pitched roof @@ -415,27 +339,19 @@ if detail > 1 then Scale(1, 1.5, 1.5) Rotate(Y, -90) Translate(21, 6, -3) - Scale(32) - MakeTilemap({ + DrawTilemap({ width = 3, - tiles = { - 13, 13, 13, - 13, 13, 13 - } - }) + 13, 13, 13, + 13, 13, 13}) -- Finial ResetTransform() Rotate(Y, -90) Translate(21, 6, -3) - Scale(32) - MakeTilemap({ + DrawTilemap({ width = 3, - tiles = { - 18, 18, 18 - } - }) + 18, 18, 18}) end -- More ground to the right @@ -446,51 +362,42 @@ end ResetTransform() Rotate(X, 90) Translate(10, 0, 0) -Scale(32) SetTexture("Scenery") -MakeTilemap({ +DrawTilemap({ width = 3, - surface_type = TOP, - tiles = { - 1, 1, 1, - 1, 1, 1, - -1, -1, -1, - -1, -1, -1, - -1, -1, -1, - -1, -1, -1, - 1, 1, 1 - } -}) + surface = TOP, + 1, 1, 1, + 1, 1, 1, + -1, -1, -1, + -1, -1, -1, + -1, -1, -1, + -1, -1, -1, + 1, 1, 1}) -- Left part of center courtyard ResetTransform() Rotate(X, 90) Translate(13, 0, 0) -Scale(32) -MakeTilemap({ +DrawTilemap({ width = 8, - surface_type = TOP, - tiles = { - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 1, 1, - 0, 0, 0, 0, 0, 0, 1, 1, - 1, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 0, 0, 0 - } -}) + surface = TOP, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0}) -- Front grass -if detail > 2 then +if detail > MEDIUM then ResetTransform() Scale(12, 1, 1) Translate(14, -0.5, 5) - Scale(32) - MakeBillboard({ - tile = 2, + DrawTile({ + 2, u_scale = 12 }) @@ -499,9 +406,8 @@ if detail > 2 then ResetTransform() Scale(4, 1, 1) Translate(14, -0.5, 1) - Scale(32) - MakeBillboard({ - tile = 2, + DrawTile({ + 2, u_scale = 4 }) @@ -509,9 +415,8 @@ if detail > 2 then ResetTransform() Translate(13, -0.5, 3) - Scale(32) - MakeBillboard({ - tile = 2, + DrawTile({ + 2, u_scale = 1 }) @@ -519,9 +424,8 @@ if detail > 2 then ResetTransform() Translate(13, -0.5, 2) - Scale(32) - MakeBillboard({ - tile = 2, + DrawTile({ + 2, u_scale = 1 }) @@ -530,22 +434,17 @@ if detail > 2 then ResetTransform() Rotate(Y, -90) Translate(14, -0.5, 1) - Scale(32) - MakeTilemap({ + DrawTilemap({ width = 4, - tiles = { - 2, -1, 2, 2 - } - }) + 2, -1, 2, 2}) -- Grass left of house ResetTransform() Rotate(Y, -90) Translate(18, -0.5, 0) - Scale(32) - MakeBillboard({ - tile = 2, + DrawTile({ + 2, u_scale = 1 }) @@ -554,9 +453,8 @@ if detail > 2 then ResetTransform() Rotate(Y, -90) Translate(24, -0.5, 0) - Scale(32) - MakeBillboard({ - tile = 2, + DrawTile({ + 2, u_scale = 1 }) @@ -565,9 +463,8 @@ if detail > 2 then ResetTransform() Scale(4, 1, 1) Translate(19, -0.5, 4) - Scale(32) - MakeBillboard({ - tile = 2, + DrawTile({ + 2, u_scale = 4 }) @@ -576,9 +473,8 @@ if detail > 2 then ResetTransform() Scale(4, 1, 1) Translate(19, -0.5, 2) - Scale(32) - MakeBillboard({ - tile = 2, + DrawTile({ + 2, u_scale = 4 }) @@ -588,9 +484,8 @@ if detail > 2 then Scale(2, 1, 1) Rotate(Y, -90) Translate(19, -0.5, 2) - Scale(32) - MakeBillboard({ - tile = 2, + DrawTile({ + 2, u_scale = 2 }) @@ -600,9 +495,8 @@ if detail > 2 then Scale(2, 1, 1) Rotate(Y, -90) Translate(23, -0.5, 2) - Scale(32) - MakeBillboard({ - tile = 2, + DrawTile({ + 2, u_scale = 2 }) end @@ -612,30 +506,25 @@ end ResetTransform() Rotate(X, 90) Translate(21, 0, 0) -Scale(32) -MakeTilemap({ +DrawTilemap({ width = 7, - surface_type = TOP, - tiles = { - 1, 1, 1, 1, 1, 0, 0, - 1, 1, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 1, 1, 0, 0, 0, 0, 0, - 1, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 1, 1, 1 - } -}) + surface = TOP, + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1}) -- Fence to right of back house -if detail > 2 then +if detail > MEDIUM then ResetTransform() Scale(4, 1, 1) Translate(24, 0, 0) - Scale(32) - MakeBillboard({ - tile = 4, + DrawTile({ + 4, u_scale = 4 }) @@ -644,9 +533,8 @@ if detail > 2 then ResetTransform() Scale(4, 1, 1) Translate(24, -0.5, 1) - Scale(32) - MakeBillboard({ - tile = 2, + DrawTile({ + 2, u_scale = 4 }) @@ -656,9 +544,8 @@ if detail > 2 then Scale(2, 1, 1) Rotate(Y, -90) Translate(26, -0.5, 5) - Scale(32) - MakeBillboard({ - tile = 2, + DrawTile({ + 2, u_scale = 2 }) @@ -668,9 +555,8 @@ if detail > 2 then Scale(2, 1, 1) Rotate(Y, -90) Translate(35, -0.5, 5) - Scale(32) - MakeBillboard({ - tile = 2, + DrawTile({ + 2, u_scale = 2 }) @@ -679,9 +565,8 @@ if detail > 2 then ResetTransform() Scale(5, 1, 1) Translate(35, -0.5, 5) - Scale(32) - MakeBillboard({ - tile = 2, + DrawTile({ + 2, u_scale = 5 }) @@ -690,9 +575,8 @@ if detail > 2 then ResetTransform() Scale(6, 1, 1) Translate(34, -0.5, 1) - Scale(32) - MakeBillboard({ - tile = 2, + DrawTile({ + 2, u_scale = 6 }) @@ -701,9 +585,8 @@ if detail > 2 then ResetTransform() Rotate(Y, -90) Translate(34, -0.5, 0) - Scale(32) - MakeBillboard({ - tile = 2, + DrawTile({ + 2, u_scale = 1 }) end @@ -713,36 +596,28 @@ end ResetTransform() Rotate(X, 90) Translate(28, 0, 4) -Scale(32) -MakeTilemap({ +DrawTilemap({ width = 5, - surface_type = TOP, - tiles = { - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0 - } -}) + surface = TOP, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}) -- Rightmost ground ResetTransform() Rotate(X, 90) Translate(33, 0, 0) -Scale(32) -MakeTilemap({ +DrawTilemap({ width = 10, - surface_type = TOP, - tiles = { - 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, - 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, - 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, - 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, - 0, 1, 1, 1, 1, 1, 1, -1, -1, -1 - } -}) + surface = TOP, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, + 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, + 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, + 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, + 0, 1, 1, 1, 1, 1, 1, -1, -1, -1}) -- Right foreground tower block -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -751,79 +626,63 @@ MakeTilemap({ ResetTransform() Translate(28, 0, 4) -Scale(32) SetTexture("TowerBlock1") -MakeTilemap({ +DrawTilemap({ width = 5, - tiles = { - 2, 2, 2, 2, 2, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 6, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 6, 0, - 4, 4, 4, 4, 4 - } -}) + 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 6, 0, + 4, 4, 4, 4, 4}) -- Right side ResetTransform() Rotate(Y, 90) Translate(33, 0, 4) -Scale(32) -MakeTilemap({ +DrawTilemap({ width = 6, - surface_type = RIGHT, - tiles = { - 2, 2, 2, 2, 2, 2, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 5, 4, 5, 5, 4, 5 - } -}) + surface = RIGHT, + 2, 2, 2, 2, 2, 2, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 5, 4, 5, 5, 4, 5}) -- Left side ResetTransform() Rotate(Y, 90) Translate(28, 0, 4) -Scale(32) -MakeTilemap({ +DrawTilemap({ width = 6, - surface_type = LEFT, - tiles = { - 2, 2, 2, 2, 2, 2, - 0, 1, 6, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 5, 4, 5, 5, 4, 5 - } -}) + surface = LEFT, + 2, 2, 2, 2, 2, 2, + 0, 1, 6, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 5, 4, 5, 5, 4, 5}) -- Top ResetTransform() Rotate(X, 90) Translate(28, 7, -2) -Scale(32) -MakeTilemap({ +DrawTilemap({ width = 5, - surface_type = TOP, - tiles = { - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3 - } -}) + surface = TOP, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3}) -- Right end tower block -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -832,87 +691,75 @@ MakeTilemap({ ResetTransform() Translate(40, 0, 5) -Scale(32) -MakeTilemap({ +DrawTilemap({ width = 5, - tiles = { - 2, 2, 2, 2, 2, - 0, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 6, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 6, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 4, 4, 4, 4, 4 - } -}) + 2, 2, 2, 2, 2, + 0, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 6, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 6, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 4, 4, 4, 4, 4}) -- Left side ResetTransform() Rotate(Y, 90) Translate(40, 0, 5) -Scale(32) -MakeTilemap({ +DrawTilemap({ width = 5, - surface_type = LEFT, - tiles = { - 2, 2, 2, 2, 2, - 6, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 6, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 6, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 4, 5, 5, 5, 4 - } -}) + surface = LEFT, + 2, 2, 2, 2, 2, + 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 4, 5, 5, 5, 4}) -- Top ResetTransform() Rotate(X, 90) Translate(40, 15, 0) -Scale(32) -MakeTilemap({ +DrawTilemap({ width = 5, - surface_type = TOP, - tiles = { - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3 - } -}) + surface = TOP, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3}) -- Background -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ResetTransform() -Translate(-0.3, -0.17, -900) -Scale(3200, 1600, 1) +Translate(-0.3, -0.17, -28) +Scale(100, 50, 1) SetTexture("BackgroundFar") -MakeBillboard() +DrawTile() -Translate(0, 0, 300) +Translate(0, 0, 5) SetTexture("BackgroundNear") -MakeBillboard({ - blend = detail > 1 and true or false +DrawTile({ + blend = detail > LOW and true or false }) -- Trees @@ -922,53 +769,126 @@ SetTexture("Trees") -- Left courtyard -if detail > 1 then +if detail > LOW then ResetTransform() - Scale(96) - Translate(250, -2.5, 16) - MakeBillboard({ - tile = 1 - }) + Scale(3) + Translate(7.75, -0.1, 0.5) + DrawTile(1) end -- Center courtyard ResetTransform() -Scale(96) -Translate(610, -2.5, 85) -MakeBillboard({ - tile = 0 -}) +--Translate(610, -2.5, 85) +Scale(3) +Translate(19, -0.1, 2.5) +DrawTile(0) ResetTransform() -Scale(96) -Translate(650, -2.5, 115) -MakeBillboard({ - tile = 1 -}) +Scale(3) +Translate(20.25, -0.1, 3.5) +DrawTile(1) -- Right courtyard -if detail > 1 then +if detail > LOW then ResetTransform() - Scale(96) - Translate(1080, -2.5, 10) - MakeBillboard({ - tile = 1 - }) + Scale(3) + Translate(34, -0.1, 0.25) + DrawTile(1) ResetTransform() - Scale(96) - Translate(1120, -2.5, -15) - MakeBillboard({ - tile = 0 - }) + Scale(3) + Translate(36, -0.1, -0.5) + DrawTile(0) ResetTransform() - Scale(96) - Translate(1220, -2.5, -30) - MakeBillboard({ - tile = 1 - }) + Scale(3) + Translate(37, -0.1, 0.75) + DrawTile(1) +end + + + +function GetZCoord(x, y) + return 3 +end + + +-- Functions: +-- DisplayText(text, seconds) +-- Yield(seconds) +-- SpawnItem(what, coords, timeout) +-- SpawnRandomItem(coords, timeout) +-- SpawnCharacter(what, coords, ai level) +-- SpawnHeroine(coords) +-- PlaySound(name) +-- PlayMusic(name) +-- BeginNewWave() + +-- Events: +-- BadGuyDied(enemy) +-- PlayedDied(player) +-- SceneLoaded() + +-- Globals: +-- numberOfBadGuys + + +-- Events +--------- + +Event = {} + +function Event:SceneLoaded() + SpawnHeroine({500, 500}) + local waveNum = BeginNewWave() + PopulateScene(waveNum) +end + +function Event:BadGuyDied(enemy) + if numberOfBadGuys == 0 then + local waveNum = BeginNewWave() + PopulateScene(waveNum) + end + if math.random() <= 0.2 then + SpawnRandomItem(enemy.position) + end +end + + +-- Helper functions +------------------- + +function PopulateScene(waveNum) + -- spawn some robot troopers + local numBadGuys = math.random(3, 2 * waveNum) + for i = 0, numBadGuys do + SpawnCharacter("RobotTrooper", RandomSpawnPlace(), RandomSkillLevel()) + end + + -- spawn some alien warriors + if waveNum >= 10 then + numBadGuys = math.random(3, 2 * waveNum) + for i = 0, numBadGuys do + SpawnCharacter("AlienWarrior", RandomSpawnPlace(), RandomSkillLevel()) + end + end + + -- spawn some jetbots + if waveNum >= 20 then + numBadGuys = math.random(3, 2 * waveNum) + for i = 0, numBadGuys do + SpawnCharacter("Jetbot", RandomSpawnPlace(), RandomSkillLevel()) + end + end +end + +function RandomSpawnPlace() + return {500, 500} +end + +function RandomSkillLevel() + return "dumb" end diff --git a/data/scenes/loader.lua b/data/scenes/loader.lua new file mode 100644 index 0000000..efb5867 --- /dev/null +++ b/data/scenes/loader.lua @@ -0,0 +1,5 @@ + +-- Scene loader script + +scenes = {"Classic"} + diff --git a/data/yoinkrc b/data/yoinkrc index 86b333d..5660ffa 100644 --- a/data/yoinkrc +++ b/data/yoinkrc @@ -1,23 +1,22 @@ -- Example Yoink Configuration File --- vim: ft=lua +-- vim: ft=lua ts=4 -print "loading yoinkrc..." +print "loading default settings..." -- Set the level of detail to use when drawing scenes. This can be 1, 2 or -- 3, where 1 shows the least amount of detail and 3 draws the scene with -- the most detail. -detail = 3 +detail = 3 --- Set the amount of time in seconds between each update of the physics --- state. A value of 100 or higher is ideal for accurate physics --- approximations. Values that are much lower cause the CPU to do less --- work, but accuracy will suffer. Errors could be introduced in the game --- with extremely low values. +-- Set the number of times each second the physics state will be updated. A +-- value of 100 or higher is ideal for accurate physics approximations. Values +-- that are much lower cause the CPU to do less work, but accuracy will suffer. +-- Errors could be introduced in the game with extremely low values. -timestep = 80 +timestep = 80 -- Set the maximum number of frames that can be drawn per second. A value -- of 50 is pretty good. If your computer is really old, you can get away @@ -30,41 +29,41 @@ timestep = 80 -- not be able to update the physics on schedule which could actually -- significantly lower the quality of the animation. -maxfps = 40 +maxfps = timestep / 2 -- Set whether or not to print the current actual framerate to the console. -printfps = false +printfps = false -- Set whether or not the game will run in full-screen mode. If false, the -- game will run in a window. -fullscreen = false +fullscreen = false -- If the game is running in a window, set whether or not the window will -- be resizable. -resizable = true +resizable = true -- Set the resolution or size of the window. The value is an array with -- three number elements representing the width, height, and bits per pixel -- that make up the video mode. A typical value is 800,600 for a size of -- 800x600 pixels with millions of colors (the third number is optional). -videomode = {1024, 786} +videomode = {1024, 786} -- Set whether or not the cursor will be visible when you mouse over the -- display of the game. -showcursor = true +showcursor = false -- Set whether or not the drawing should use two buffers. This results in -- a higher quality animation. You should usually leave this as true. -doublebuffer = true +doublebuffer = true -- Set whether or not to sync with the display in order to reduce -- distortion. -swapcontrol = true +swapcontrol = true diff --git a/extra/yoink.ebuild b/extra/yoink.ebuild index 2bd8d27..3b1d585 100644 --- a/extra/yoink.ebuild +++ b/extra/yoink.ebuild @@ -14,7 +14,7 @@ SRC_URI="http://www.dogcows.com/yoink/${P}.tar.bz2 LICENSE="BSD-2 BSD LGPL-2.1 ZLIB" SLOT="0" KEYWORDS="amd64 ~ppc x86" -IUSE="debug double-precision profile threads" +IUSE="debug double-precision gtk qt4 threads" RDEPEND="dev-lang/lua media-libs/freealut @@ -46,7 +46,8 @@ src_configure() { --disable-dependency-tracking \ $(use_enable debug) \ $(use_enable double-precision) \ - $(use_enable profile) \ + $(use_enable gtk) \ + $(use_enable qt4) \ $(use_enable threads) } diff --git a/src/Character.cc b/src/Character.cc index f12ed5f..7110449 100644 --- a/src/Character.cc +++ b/src/Character.cc @@ -32,8 +32,10 @@ #include "Log.hh" -struct SpringForce +class SpringForce { +public: + explicit SpringForce(Mf::Vector2 x) : location(x) {} @@ -56,8 +58,10 @@ private: Mf::Vector2 location; }; -struct ResistanceForce +class ResistanceForce { +public: + explicit ResistanceForce(Mf::Scalar scale = 1.0) : k(scale) {} @@ -87,10 +91,10 @@ Character::Character(const std::string& name) : mState.force = Mf::Vector2(0.0, 0.0); //mState.forces.push_back(SpringForce(Mf::Vector2(500.0, 200.0))); mState.forces.push_back(ResistanceForce(2.0)); - //mState.forces.push_back(Mf::LinearState<2>::GravityForce(-100.0)); + //mState.forces.push_back(Mf::LinearState<2>::GravityForce(-400.0)); // starting position - mState.position = Mf::Vector2(64.0, 64.0); + mState.position = Mf::Vector2(5.0, 5.0); mState.momentum = Mf::Vector2(0.0, 0.0); mState.recalculate(); @@ -104,9 +108,9 @@ void Character::update(Mf::Scalar t, Mf::Scalar dt) animation.update(t, dt); - Mf::Vector3 center(mState.position[0], mState.position[1], z); - Mf::Vector3 a(mState.position[0] - 16.0, mState.position[1] - 16.0, z); - Mf::Vector3 b(mState.position[0] + 16.0, mState.position[1] + 16.0, z); + Mf::Vector3 center(mState.position[0], mState.position[1], mZCoord); + Mf::Vector3 a(mState.position[0] - 0.5, mState.position[1] - 0.5, mZCoord); + Mf::Vector3 b(mState.position[0] + 0.5, mState.position[1] + 0.5, mZCoord); mAabb.init(a, b); mSphere.init(center, a); @@ -131,29 +135,23 @@ void Character::draw(Mf::Scalar alpha) const Mf::Scalar coords[8]; tilemap.getTileCoords(frame, coords, orientation); - Mf::Scalar s = 16.0; + Mf::Scalar s = 0.5; glBegin(GL_TRIANGLE_FAN); glTexCoord2f(coords[0], coords[1]); - glVertex3(position[0]-s, position[1]-s, z); + glVertex3(position[0]-s, position[1]-s, mZCoord); glTexCoord2f(coords[2], coords[3]); - glVertex3(position[0]+s, position[1]-s, z); + glVertex3(position[0]+s, position[1]-s, mZCoord); glTexCoord2f(coords[4], coords[5]); - glVertex3(position[0]+s, position[1]+s, z); + glVertex3(position[0]+s, position[1]+s, mZCoord); glTexCoord2f(coords[6], coords[7]); - glVertex3(position[0]-s, position[1]+s, z); - glEnd(); - - //glColor3f(0.0f, 0.0f, 0.0f); - Mf::Texture::resetBind(); - - glBegin(GL_TRIANGLES); - glVertex3(480.0, 190.0, 64.0); - glVertex3(520.0, 190.0, 64.0); - glVertex3(500.0, 210.0, 64.0); + glVertex3(position[0]-s, position[1]+s, mZCoord); glEnd(); +} - //glColor3f(1.0f, 1.0f, 1.0f); +void Character::setZCoord(Mf::Scalar z) +{ + mZCoord = z; } @@ -267,5 +265,21 @@ int Character::getOctant(const Mf::Aabb& aabb) const } +void Character::addImpulse(Mf::Vector2 impulse) +{ + mState.momentum += impulse; +} + +void Character::addForce(Mf::Vector2 force) +{ + mState.force += force; +} + +void Character::setPosition(Mf::Vector2 position) +{ + mState.position = position; +} + + /** vim: set ts=4 sw=4 tw=80: *************************************************/ diff --git a/src/Character.hh b/src/Character.hh index 5dfde01..d70da88 100644 --- a/src/Character.hh +++ b/src/Character.hh @@ -62,6 +62,12 @@ public: virtual void update(Mf::Scalar t, Mf::Scalar dt); virtual void draw(Mf::Scalar alpha) const; + void setZCoord(Mf::Scalar z); + + void addImpulse(Mf::Vector2 impulse); + void addForce(Mf::Vector2 force); + void setPosition(Mf::Vector2 position); + virtual int getOctant(const Mf::Aabb& aabb) const; Tilemap tilemap; @@ -69,7 +75,7 @@ public: private: - static const Mf::Scalar z = 96.0; + mutable Mf::Scalar mZCoord; }; diff --git a/src/GameLayer.cc b/src/GameLayer.cc index a80946f..a37f175 100644 --- a/src/GameLayer.cc +++ b/src/GameLayer.cc @@ -27,6 +27,7 @@ *******************************************************************************/ #include +#include #include #include #include @@ -39,22 +40,76 @@ #endif + +Mf::Scalar GameLayer::getZCoord(const Mf::Vector2& position) const +{ + Mf::Scalar z; + + mScript.getGlobalTable().pushField("GetZCoord"); + mScript.push(position[0]); + mScript.push(position[1]); + mScript.call(2, 1); + mScript.getTop().get(z); + mScript.pop(); + + return z; +} + +void GameLayer::loadSceneLoader() +{ + std::string loaderPath = Scene::getPath("loader"); + if (loaderPath == "") + { + throw Mf::Exception(Mf::ErrorCode::RESOURCE_NOT_FOUND, "loader"); + } + + Mf::Script::Status status = mScript.doFile(loaderPath); + if (status != Mf::Script::SUCCESS) + { + std::string str; + mScript[-1].get(str); + + Mf::logScript("%s", str.c_str()); + throw Mf::Exception(Mf::ErrorCode::SCRIPT_ERROR, str.c_str()); + } + + mScript.getGlobalTable().pushField("scenes"); + mScript.getTop().get(mSceneList); + if (mSceneList.size() == 0) + { + Mf::logScript("no variable `scenes' within loader"); + throw Mf::Exception(Mf::ErrorCode::SCRIPT_ERROR, "no scenes to load"); + } +} + +void GameLayer::advanceScene() +{ + if (mSceneList.size() != 0) + { + mScene = Scene::alloc(mSceneList[0]); + mSceneList.erase(mSceneList.begin()); + mScene->load(mScript); + } +} + + GameLayer::GameLayer() : - mMusic("BeatTheCube"), + mMusic("NightFusionIntro"), mPunchSound("Thump") { mMusic.setLooping(true); mMusic.enqueue("NightFusionLoop"); mMusic.stream(); + loadSceneLoader(); + advanceScene(); // load the first scene + mHeroine = Heroine::alloc(); mHeroine->animation.startSequence("FlyDiagonallyUp"); Mf::Scalar a[6] = {0.0, 1.5, -0.5, 3.0, -2.0, 1.0}; mInterp.init(a, 2.0, Mf::Interpolator::OSCILLATE); - mScene = Scene::alloc("Classic"); - setProjection(); mHud = Hud::alloc(); @@ -75,7 +130,7 @@ void GameLayer::update(Mf::Scalar t, Mf::Scalar dt) mScene->checkForCollision(*mHeroine); mCamera.setPosition(Mf::Vector3(-mHeroine->getState().position[0], - -mHeroine->getState().position[1], -256)); + -mHeroine->getState().position[1], -10)); //mCamera.lookAt(Mf::promote(mHeroine->getState().position)); //Mf::Vector3 heroinePosition = Mf::promote(mHeroine->getState().position); @@ -99,6 +154,7 @@ void GameLayer::draw(Mf::Scalar alpha) const mScene->drawIfVisible(alpha, mCamera.getFrustum()); + mHeroine->setZCoord(getZCoord(mHeroine->getState().position)); mHeroine->draw(alpha); } @@ -150,7 +206,7 @@ void GameLayer::setProjection() void GameLayer::setProjection(Mf::Scalar width, Mf::Scalar height) { - mCamera.setProjection(cml::rad(60.0), width / height, 32.0, 2500.0); + mCamera.setProjection(cml::rad(60.0), width / height, 1.0, 200.0); } diff --git a/src/GameLayer.hh b/src/GameLayer.hh index a1b5d6d..4e26e68 100644 --- a/src/GameLayer.hh +++ b/src/GameLayer.hh @@ -36,6 +36,7 @@ #include #include +#include #include @@ -44,6 +45,7 @@ #include #include #include +#include #include #include "Character.hh" @@ -66,21 +68,32 @@ public: } void pushed(Mf::Engine& engine); + void update(Mf::Scalar t, Mf::Scalar dt); void draw(Mf::Scalar alpha) const; bool handleEvent(const Mf::Event& event); private: + void loadSceneLoader(); + void advanceScene(); + + Mf::Scalar getZCoord(const Mf::Vector2& position) const; + void setProjection(); void setProjection(Mf::Scalar width, Mf::Scalar height); + // the script object must be mutable because some script functions must be + // called during draw + mutable Mf::Script mScript; + std::vector mSceneList; + Mf::Sound mMusic; + Mf::Sound mPunchSound; HeroineP mHeroine; SceneP mScene; - Mf::Sound mPunchSound; Mf::PolynomialInterpolator<5> mInterp; diff --git a/src/Heroine.cc b/src/Heroine.cc index 2071a7b..e2b69b2 100644 --- a/src/Heroine.cc +++ b/src/Heroine.cc @@ -36,7 +36,7 @@ Heroine::Heroine() : bool Heroine::handleEvent(const Mf::Event& event) { - Mf::Scalar force = 4000.0; + Mf::Scalar force = 40.0; switch (event.type) { diff --git a/src/MainLayer.cc b/src/MainLayer.cc index 85828c7..3429f52 100644 --- a/src/MainLayer.cc +++ b/src/MainLayer.cc @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -219,7 +220,7 @@ void printInfo(int argc, char* argv[]) std::cout << " Executable: " << argv[0] << std::endl << " Version: "VERSION << std::endl -#ifdef __DATE__ +#if defined(__DATE__) && defined(__TIME__) << " Built: "__DATE__" "__TIME__ << std::endl #endif << " Compiler: "COMPILER_STRING << std::endl @@ -233,10 +234,18 @@ void printInfo(int argc, char* argv[]) << "-" #endif << "double-precision " +#ifndef USE_GTK + << "-" +#endif + << "gtk " #ifndef PROFILING_ENABLED << "-" #endif << "profile " +#ifndef USE_QT4 + << "-" +#endif + << "qt4 " #ifndef USE_THREADS << "-" #endif @@ -251,9 +260,6 @@ void goodbye() } -typedef cml::matrix< Mf::Scalar, cml::fixed<5,5>, - cml::col_basis, cml::col_major > Matrix5; - int main(int argc, char* argv[]) { if (argc > 1) @@ -304,7 +310,7 @@ int main(int argc, char* argv[]) Mf::Resource::addSearchPath(YOINK_DATADIR); - std::string iconFile = Mf::Resource::getPath("yoink.png"); + std::string iconFile = Mf::Resource::getPath(PACKAGE".png"); // Build the list of config files to search for, in this order: @@ -325,7 +331,6 @@ int main(int argc, char* argv[]) configFiles += configFile; } - try { Mf::Engine app(argc, argv, PACKAGE_STRING, iconFile, configFiles); @@ -333,11 +338,19 @@ int main(int argc, char* argv[]) app.run(); } - catch (Mf::Exception e) + catch (const Mf::Exception& e) { - Mf::logError("unhandled exception: <<%s>>", e.what()); - Mf::logInfo("it's time to crash now :-("); - throw e; + Mf::logError("unhandled exception (code %d): \"%s\"", + e.code(), e.what()); + + Mf::ModalDialog dialog; + dialog.title = PACKAGE_STRING; + dialog.text1 = "Unhandled Exception"; + dialog.text2 = e.what(); + dialog.type = Mf::ModalDialog::CRITICAL; + dialog.run(); + + return 1; } return 0; diff --git a/src/Makefile.am b/src/Makefile.am index c10b586..c5cddeb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -37,6 +37,7 @@ libmoof_a_SOURCES = \ Moof/Log.cc \ Moof/Log.hh \ Moof/Math.hh \ + Moof/ModalDialog.hh \ Moof/Octree.hh \ Moof/OpenGL.hh \ Moof/Plane.cc \ diff --git a/src/Moof/Engine.cc b/src/Moof/Engine.cc index ccf2347..9ff5e1a 100644 --- a/src/Moof/Engine.cc +++ b/src/Moof/Engine.cc @@ -38,6 +38,7 @@ #include "Dispatcher.hh" #include "Engine.hh" #include "Event.hh" +#include "Exception.hh" #include "Log.hh" #include "Random.hh" #include "Settings.hh" @@ -59,19 +60,21 @@ public: mTimestep(0.01), mPrintFps(false) { -#if defined(_WIN32) || defined (_WIN64) || defined(__WIN32__) +#if defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) #else if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTTHREAD) != 0) #endif { - logError("sdl is complaining: %s", SDL_GetError()); - throw Exception(Exception::SDL_ERROR); + const char* error = SDL_GetError(); + logError("sdl is complaining: %s", error); + throw Exception(ErrorCode::SDL_INIT, error); } if (FE_Init() != 0) { - logError("fast events error: %s", FE_GetError()); - throw Exception(Exception::SDL_ERROR); + const char* error = FE_GetError(); + logError("fast events error: %s", error); + throw Exception(ErrorCode::FASTEVENTS_INIT, error); } alutInit(&argc, argv); diff --git a/src/Moof/Engine.hh b/src/Moof/Engine.hh index e42510d..84b1f58 100644 --- a/src/Moof/Engine.hh +++ b/src/Moof/Engine.hh @@ -31,7 +31,6 @@ #include -#include #include #include @@ -44,9 +43,6 @@ class Video; class Engine { - class Impl; - boost::shared_ptr mImpl; - public: Engine(int argc, char* argv[], const std::string& name, @@ -72,16 +68,10 @@ public: LayerP pop(Layer* layer); void clear(); - struct Exception : public Mf::Exception - { - explicit Exception(unsigned error) : - Mf::Exception(error) {} +private: - void raise() - { - throw *this; - } - }; + class Impl; + boost::shared_ptr mImpl; }; diff --git a/src/Moof/Exception.hh b/src/Moof/Exception.hh index 2478ca1..a63f761 100644 --- a/src/Moof/Exception.hh +++ b/src/Moof/Exception.hh @@ -29,25 +29,25 @@ #ifndef _MOOF_EXCEPTION_HH_ #define _MOOF_EXCEPTION_HH_ +#include #include -#include + +#include namespace Mf { -struct Exception : public std::exception +class Exception : public std::exception { - enum +public: + + explicit Exception(unsigned code, const char* what = "") { - FILE_NOT_FOUND = 1, - OPENGL_ERROR = 2, - OPENAL_ERROR = 3, - SDL_ERROR = 4 - }; - - explicit Exception(unsigned error) : - code(error) {} + mWhat[sizeof(mWhat)-1] = '\0'; + strncpy(mWhat, what, sizeof(mWhat)-1); + mCode = code; + } virtual ~Exception() throw() {} virtual void raise() @@ -55,24 +55,36 @@ struct Exception : public std::exception throw *this; } - virtual const char* what() const throw() + unsigned code() const throw() + { + return mCode; + } + + const char* what() const throw() { - switch (code) - { - case FILE_NOT_FOUND: - return "file not found"; - case OPENGL_ERROR: - return "opengl error"; - case OPENAL_ERROR: - return "openal error"; - case SDL_ERROR: - return "sdl error"; - } - return "unknown error"; + return mWhat; } - unsigned code; +private: + + unsigned mCode; + char mWhat[1024]; +}; + +namespace ErrorCode { +enum Code +{ + NONE = 0, + FASTEVENTS_INIT, // description + FILE_NOT_FOUND, // path of missing file + RESOURCE_NOT_FOUND, // name of missing resource + SCRIPT_ERROR, // description + SDL_INIT, // description + SDL_VIDEOMODE, // - + UNKNOWN_AUDIO_FORMAT, // - + UNKNOWN_IMAGE_FORMAT, // - }; +} // namespace ErrorCode } // namespace Mf diff --git a/src/Moof/Library.hh b/src/Moof/Library.hh index 1d5af36..c215567 100644 --- a/src/Moof/Library.hh +++ b/src/Moof/Library.hh @@ -36,7 +36,6 @@ * interested code. */ -#include #include #include diff --git a/src/Moof/ModalDialog.hh b/src/Moof/ModalDialog.hh new file mode 100644 index 0000000..11d9d79 --- /dev/null +++ b/src/Moof/ModalDialog.hh @@ -0,0 +1,155 @@ + +/******************************************************************************* + + Copyright (c) 2009, Charles McGarvey + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef _MOOF_MODALDIALOG_HH_ +#define _MOOF_MODALDIALOG_HH_ + +#include + +#if defined(_WIN32) || defined(__WIN32__) +#include +#elif defined(__APPLE__) && defined(__MACH__) +#include +#elif USE_GTK +#include +#elif USE_QT4 +#include +#include +#include +#endif + +#include + +#if HAVE_CONFIG_H +#include "config.h" +#endif + + +namespace Mf { + + +/** + * Small wrapper over various user interface modal dialog windows. + */ + +struct ModalDialog +{ + enum Type + { + INFO = 1, + WARNING = 2, + CRITICAL = 3 + }; + + std::string title; + Type type; + std::string text1; + std::string text2; + + void run() const + { +#if USE_GTK + + int argc = 0; + char** argv; + gtk_init(&argc, &argv); + + GtkMessageType iconType; + switch (type) + { + case WARNING: + iconType = GTK_MESSAGE_WARNING; + break; + case CRITICAL: + iconType = GTK_MESSAGE_ERROR; + break; + default: + iconType = GTK_MESSAGE_INFO; + break; + } + + GtkWidget* dialog = gtk_message_dialog_new(NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, iconType, + GTK_BUTTONS_CLOSE, "%s", text1.c_str()); + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), + "%s", text2.c_str()); + gtk_window_set_title(GTK_WINDOW(dialog), title.c_str()); + + std::string iconPath = Resource::getPath(PACKAGE".png"); + GdkPixbuf* iconPixbuf = gdk_pixbuf_new_from_file(iconPath.c_str(), NULL); + gtk_window_set_icon(GTK_WINDOW(dialog), iconPixbuf); + + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + // FIXME - this doesn't seem to actually remove the window from the + // screen when it closes, not sure why... + +#elif USE_QT4 + + int argc = 0; + char** argv; + QApplication qtApp(argc, argv); + + QMessageBox::Icon iconType; + switch (type) + { + case WARNING: + iconType = QMessageBox::Warning; + break; + case CRITICAL: + iconType = QMessageBox::Critical; + break; + default: + iconType = QMessageBox::Information; + break; + } + + QMessageBox dialog; + dialog.setWindowTitle(title.c_str()); + dialog.setIcon(iconType); + dialog.setText(text1.c_str()); + dialog.setInformativeText(text2.c_str()); + dialog.setStandardButtons(QMessageBox::Close); + + std::string iconPath = Resource::getPath(PACKAGE".png"); + QIcon icon(iconPath.c_str()); + dialog.setWindowIcon(icon); + + dialog.exec(); + +#endif + } +}; + + +} // namespace Mf + +#endif // _MOOF_MODALDIALOG_HH_ + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/Moof/Resource.cc b/src/Moof/Resource.cc index a9ff22d..6f09601 100644 --- a/src/Moof/Resource.cc +++ b/src/Moof/Resource.cc @@ -41,9 +41,6 @@ namespace Mf { std::vector Resource::searchPaths_; -Resource::~Resource() {} - - void Resource::addSearchPath(const std::string& directory) { std::string path(directory); @@ -56,7 +53,7 @@ void Resource::addSearchPath(const std::string& directory) path += '/'; } -#if defined(__WIN32__) || defined(_WIN32) || defined(_WIN64) +#if defined(_WIN32) || defined(__WIN32__) boost::replace_all(path, "/", "\\"); #endif @@ -69,7 +66,7 @@ std::string Resource::getPath(const std::string& name) std::string path(name); -#if defined(__WIN32__) || defined(_WIN32) || defined(_WIN64) +#if defined(_WIN32) || defined(__WIN32__) boost::replace_all(path, "/", "\\"); #endif @@ -78,15 +75,11 @@ std::string Resource::getPath(const std::string& name) std::string fullPath(*it); fullPath += path; - logDebug("looking for resource %s at %s", name.c_str(), path.c_str()); - - if (access(fullPath.c_str(), R_OK) == 0) - { - logDebug("found resource %s at %s", name.c_str(), path.c_str()); - return fullPath; - } + if (access(fullPath.c_str(), R_OK) == 0) return fullPath; } + logWarning("cannot find resource %s", name.c_str()); + // empty string return std::string(); } diff --git a/src/Moof/Resource.hh b/src/Moof/Resource.hh index 2740fc3..39b76a4 100644 --- a/src/Moof/Resource.hh +++ b/src/Moof/Resource.hh @@ -37,8 +37,6 @@ #include #include -#include - namespace Mf { @@ -51,7 +49,7 @@ class Resource { public: - virtual ~Resource(); + virtual ~Resource() {} /** @@ -70,18 +68,6 @@ public: static std::string getPath(const std::string& name); - - struct Exception : public Mf::Exception - { - explicit Exception(unsigned error) : - Mf::Exception(error) {} - - void raise() - { - throw *this; - } - }; - private: static std::vector searchPaths_; diff --git a/src/Moof/Script.hh b/src/Moof/Script.hh index 4db93d5..a1b536c 100644 --- a/src/Moof/Script.hh +++ b/src/Moof/Script.hh @@ -49,7 +49,6 @@ #include -#include #include @@ -64,7 +63,7 @@ struct Script { typedef boost::function Function; - enum TYPE + enum Type { NONE = LUA_TNONE, NIL = LUA_TNIL, @@ -78,7 +77,7 @@ struct Script THREAD = LUA_TTHREAD }; - enum STATUS + enum Status { SUCCESS = 0, YIELD = LUA_YIELD, @@ -89,7 +88,7 @@ struct Script FILE_ERROR = LUA_ERRFILE }; - enum PSEUDO_INDEX + enum PseudoIndex { REGISTRY = LUA_REGISTRYINDEX, ENVIRONMENT = LUA_ENVIRONINDEX, @@ -97,7 +96,7 @@ struct Script }; /** - * This is the most noticeable abstraction on top of the standard Lua API. + * This is the most prominent abstraction on top of the standard Lua API. * A Value object represents a value on the stack. More specifically, it * represents a position on the stack. The distinction is only important * when values are moved around on the stack or if the Value represents a @@ -153,17 +152,19 @@ struct Script bool isLightData() const { return (bool)lua_islightuserdata(state, index); } /** - * Check the value and throw and error if its the wrong type. This - * method never returns because it does a long jump. Consequently, - * constructed C++ objects which exist on the stack between the current - * frame and some lua function will not be destructed. That's not a - * problem for objects that only exist on the stack, but any objects - * that allocate memory on the heap (such as containers or strings) will - * leak. Therefore, you should only call this method after cleaning up - * such objects. + * Check the value and throw an error if its the wrong type. There's a + * little caveat: This method never returns because it does a long jump. + * Consequently, constructed C++ objects which exist on the stack + * between the current frame and some lua function will not be + * destructed. That's not a problem for objects that only exist on the + * stack, but any objects that allocate memory on the heap (such as + * containers or strings) will leak. Therefore, you should only call + * this method after cleaning up such objects. The best thing to do for + * defining functions is to simply check all the parameters at the + * get-go before any C++ objects are even constructed. */ - void requireType(TYPE type) const + void requireType(Type type) const { if (type != getType()) { @@ -223,9 +224,9 @@ struct Script * Get the type of the value. */ - TYPE getType() const + Type getType() const { - return (TYPE)lua_type(state, index); + return (Type)lua_type(state, index); } /** @@ -498,14 +499,14 @@ struct Script } - STATUS doString(const std::string& commands) + Status doString(const std::string& commands) { - return (STATUS)luaL_dostring(mState, commands.c_str()); + return (Status)luaL_dostring(mState, commands.c_str()); } - STATUS doFile(const std::string& file) + Status doFile(const std::string& file) { - return (STATUS)luaL_dofile(mState, file.c_str()); + return (Status)luaL_dofile(mState, file.c_str()); } @@ -523,14 +524,14 @@ struct Script lua_pushthread(mState); } - STATUS resume(int nargs) + Status resume(int nargs) { - return (STATUS)lua_resume(mState, nargs); + return (Status)lua_resume(mState, nargs); } - STATUS getStatus() const + Status getStatus() const { - return (STATUS)lua_status(mState); + return (Status)lua_status(mState); } int yield(int results) @@ -688,14 +689,14 @@ struct Script lua_xmove(thread.mState, mState, n); } - STATUS pushCode(const std::string& filename) + Status pushCode(const std::string& filename) { - return (STATUS)luaL_loadfile(mState, filename.c_str()); + return (Status)luaL_loadfile(mState, filename.c_str()); } - STATUS pushCode(const std::string& name, const char* buffer, size_t size) + Status pushCode(const std::string& name, const char* buffer, size_t size) { - return (STATUS)luaL_loadbuffer(mState, buffer, size, name.c_str()); + return (Status)luaL_loadbuffer(mState, buffer, size, name.c_str()); } void* pushNewData(size_t size) @@ -716,9 +717,9 @@ struct Script * is any number of return values, depending on the callee). */ - STATUS call(int nargs, int nresults = LUA_MULTRET) + Status call(int nargs, int nresults = LUA_MULTRET) { - return (STATUS)lua_pcall(mState, nargs, nresults, 0); + return (Status)lua_pcall(mState, nargs, nresults, 0); } @@ -793,20 +794,6 @@ struct Script lua_gc(mState, LUA_GCSETSTEPMUL, step); } - - - struct Exception : public Mf::Exception - { - explicit Exception(unsigned error) : - Mf::Exception(error) {} - - void raise() - { - throw *this; - } - }; - - private: Script(lua_State* state) : diff --git a/src/Moof/Sound.cc b/src/Moof/Sound.cc index a04d29b..a615624 100644 --- a/src/Moof/Sound.cc +++ b/src/Moof/Sound.cc @@ -27,14 +27,15 @@ *******************************************************************************/ #include +#include #include -#include #include #include #include #include +#include "Exception.hh" #include "Library.hh" #include "Log.hh" #include "Sound.hh" @@ -62,15 +63,11 @@ public: class Buffer : public Library { - OggVorbis_File mOggStream; - ALenum mFormat; - ALsizei mFreq; - std::vector mObjects; - public: Buffer(const std::string& name) : - Library(name) + Library(name), + mBuffer(-1) { mOggStream.datasource = 0; openFile(); @@ -78,16 +75,11 @@ public: ~Buffer() { - while (!mObjects.empty()) - { - alDeleteBuffers(1, &mObjects.back()); - mObjects.pop_back(); - } - if (mOggStream.datasource) { ov_clear(&mOggStream); } + if (int(mBuffer) != -1) alDeleteBuffers(1, &mBuffer); } @@ -106,7 +98,7 @@ public: { logWarning("error while loading sound %s", getName().c_str()); - throw Exception(Exception::BAD_AUDIO_FORMAT); + throw Exception(ErrorCode::UNKNOWN_AUDIO_FORMAT); } vorbis_info* vorbisInfo = ov_info(&mOggStream, -1); @@ -145,57 +137,22 @@ public: if (size == 0) { logWarning("decoded no bytes from %s", getName().c_str()); - //throw Exception(Exception::FILE_NOT_FOUND); + //throw Exception("file_not_found"); return; } - ALuint obj; - alGenBuffers(1, &obj); - - alBufferData(obj, mFormat, data, size, mFreq); - - mObjects.push_back(obj); + alGenBuffers(1, &mBuffer); - alSourcei(source, AL_BUFFER, obj); + alBufferData(mBuffer, mFormat, data, size, mFreq); + alSourcei(source, AL_BUFFER, mBuffer); - // don't need this anymore + // don't need to keep this loaded ov_clear(&mOggStream); mOggStream.datasource = 0; } - - void beginStream(ALuint source, int nBuffers = 8) - { - if (!mOggStream.datasource) openFile(); - if (!mOggStream.datasource) return; - - ALuint objs[nBuffers]; - alGenBuffers(nBuffers, objs); - - for (int i = 0; i < nBuffers; ++i) - { - mObjects.push_back(objs[i]); - stream(objs[i]); - } - - alSourceQueueBuffers(source, nBuffers, objs); - } - - enum StreamStatus - { - STREAM_OK = 0, - STREAM_EOF = 1, - STREAM_WRONG = 2 - }; - - StreamStatus stream(ALuint buffer) + bool stream(ALuint buffer) { - std::vector::iterator it = - std::find(mObjects.begin(), mObjects.end(), buffer); - - // that buffer doesn't belong to us - if (it == mObjects.end()) return STREAM_WRONG; - char data[BUFFER_SIZE]; int size = 0; @@ -216,47 +173,41 @@ public: } } - if (size == 0) return STREAM_EOF; + if (size == 0) return false; alBufferData(buffer, mFormat, data, size, mFreq); - return STREAM_OK; + return true; } - inline void rewind() + void rewind() { if (!mOggStream.datasource) openFile(); else ov_raw_seek(&mOggStream, 0); } - // delete unused buffers, return true if all buffers deleted - inline bool clear() - { - // clear any openal errors - alGetError(); + private: - while (!mObjects.empty()) - { - ALuint buffer = mObjects.back(); - alDeleteBuffers(1, &buffer); - - // if an error occured, the buffer was not deleted because it's - // still in use by some source - if (alGetError() != AL_NO_ERROR) return false; + OggVorbis_File mOggStream; + ALenum mFormat; + ALsizei mFreq; + ALuint mBuffer; + }; - mObjects.pop_back(); - } - return true; - } - }; + Impl() + { + init(); + } + Impl(const std::string& name) + { + init(); + enqueue(name); + } - Impl(const std::string& name) : - mBuffer(Buffer::getInstance(name)), - mIsPlaying(false), - mIsLooping(false) + void init() { ALfloat zero[] = {0.0f, 0.0f, 0.0f}; @@ -266,22 +217,35 @@ public: alSourcef(mSource, AL_GAIN, 1.0f); alSourcefv(mSource, AL_POSITION, zero); alSourcefv(mSource, AL_VELOCITY, zero); + + mIsPlaying = false; + mIsLooping = false; } ~Impl() { + stop(); + alDeleteSources(1, &mSource); + + while (!mBufferObjects.empty()) + { + alDeleteBuffers(1, &mBufferObjects.back()); + mBufferObjects.pop_back(); + } } void play() { + if (mQueue.empty()) return; + ALenum type; alGetSourcei(mSource, AL_SOURCE_TYPE, &type); if (type != AL_STATIC) { - mBuffer->loadAll(mSource); + mQueue.front()->loadAll(mSource); } alSourcei(mSource, AL_LOOPING, mIsLooping); @@ -292,12 +256,11 @@ public: void stream() { - ALenum type; - alGetSourcei(mSource, AL_SOURCE_TYPE, &type); + stop(); alSourcei(mSource, AL_BUFFER, AL_NONE); - mBuffer->rewind(); - mBuffer->beginStream(mSource); + mQueue.front()->rewind(); + beginStream(); alSourcei(mSource, AL_LOOPING, AL_FALSE); alSourcePlay(mSource); @@ -307,7 +270,24 @@ public: Timer::REPEAT); } - inline void update() + void beginStream() + { + ALuint buffer; + for (int i = mBufferObjects.size(); i < 4; ++i) + { + alGenBuffers(1, &buffer); + mBufferObjects.push_back(buffer); + } + for (int i = 0; i < 4; ++i) + { + buffer = mBufferObjects[i]; + mQueue.front()->stream(buffer); + alSourceQueueBuffers(mSource, 1, &buffer); + } + } + + + void update() { ALint finished = 0; @@ -315,111 +295,112 @@ public: while (finished-- > 0) { - ALuint buffer; + ALuint bufferObj; + alSourceUnqueueBuffers(mSource, 1, &bufferObj); - alSourceUnqueueBuffers(mSource, 1, &buffer); + BufferP buffer = mQueue.front(); + bool streamed = buffer->stream(bufferObj); - Buffer::StreamStatus status = mBuffer->stream(buffer); - - if (status == Buffer::STREAM_OK) + if (streamed) { - alSourceQueueBuffers(mSource, 1, &buffer); + alSourceQueueBuffers(mSource, 1, &bufferObj); } - else if (status == Buffer::STREAM_EOF) + else { + // the buffer couldn't be streamed, so get rid of it + mQueue.pop_front(); + if (!mQueue.empty()) { // begin the next buffer in the queue - mExpired.push_back(mBuffer); - mBuffer = mQueue.front(); - mQueue.pop(); - mBuffer->beginStream(mSource, 1); + mQueue.front()->rewind(); + mQueue.front()->stream(bufferObj); + alSourceQueueBuffers(mSource, 1, &bufferObj); + logInfo("loading new buffer"); } else if (mIsLooping) { - // restart from the beginning - mBuffer->rewind(); - mBuffer->stream(buffer); - alSourceQueueBuffers(mSource, 1, &buffer); + // reload the same buffer + mQueue.push_back(buffer); + buffer->rewind(); + buffer->stream(bufferObj); + alSourceQueueBuffers(mSource, 1, &bufferObj); + logInfo("looping same buffer"); } } - else if (status == Buffer::STREAM_WRONG) - { - clear(); - mBuffer->beginStream(mSource, 1); - } } ALenum state; alGetSourcei(mSource, AL_SOURCE_STATE, &state); // restart playing if we're stopped but supposed to be playing... this - // means we didn't queue enough and the audio skipped + // means we didn't queue enough and the audio skipped :-( if (mIsPlaying && state != AL_PLAYING) { alSourcePlay(mSource); } } - inline void clear() - { - // try to remove expired buffers - std::vector::iterator it; - for (it = mExpired.end() - 1; it >= mExpired.begin(); --it) - { - if ((*it)->clear()) mExpired.erase(it); - } - } - void stop() { alSourceStop(mSource); mIsPlaying = false; + + mStreamTimer.invalidate(); } - inline void pause() + void pause() { alSourcePause(mSource); mIsPlaying = false; + + mStreamTimer.invalidate(); } - inline void resume() + void resume() { alSourcePlay(mSource); mIsPlaying = true; + + ALenum type; + alGetSourcei(mSource, AL_SOURCE_TYPE, &type); + + if (type == AL_STREAMING) + { + mStreamTimer.init(boost::bind(&Impl::streamUpdate, this, _1, _2), + 1.0, Timer::REPEAT); + } } - inline void setSample(const std::string& name) + void setSample(const std::string& name) { bool playing = isPlaying(); ALenum type; alGetSourcei(mSource, AL_SOURCE_TYPE, &type); stop(); + mQueue.clear(); //alSourcei(mSource, AL_BUFFER, AL_NONE); - mBuffer = Buffer::getInstance(name); + enqueue(name); - if (type == AL_STREAMING) - { - if (playing) stream(); - } - else + if (playing) { - if (playing) play(); + if (type == AL_STREAMING) stream(); + else play(); } } - inline void enqueue(const std::string& name) + void enqueue(const std::string& name) { BufferP buffer = Buffer::getInstance(name); - mQueue.push(buffer); + mQueue.push_back(buffer); } - inline bool isPlaying() const + bool isPlaying() const { if (mIsPlaying) return true; @@ -430,7 +411,7 @@ public: } - inline void setLooping(bool looping) + void setLooping(bool looping) { mIsLooping = looping; @@ -444,17 +425,6 @@ public: } - ALuint mSource; - BufferP mBuffer; - - bool mIsPlaying; - bool mIsLooping; - - std::queue mQueue; - std::vector mExpired; - - Timer mStreamTimer; - void streamUpdate(Timer& timer, Scalar t) { // don't let the music die! @@ -462,8 +432,24 @@ public: // TODO - might be nice to also allow using threads for streaming rather // than a timer, probably as a compile-time option } + + + ALuint mSource; + std::vector mBufferObjects; + + bool mIsPlaying; + bool mIsLooping; + + std::deque mQueue; + + Timer mStreamTimer; }; + +Sound::Sound() : + // pass through + mImpl(new Sound::Impl) {} + Sound::Sound(const std::string& name) : // pass through mImpl(new Sound::Impl(name)) {} diff --git a/src/Moof/Sound.hh b/src/Moof/Sound.hh index 4e80fbe..982e9b4 100644 --- a/src/Moof/Sound.hh +++ b/src/Moof/Sound.hh @@ -50,9 +50,6 @@ typedef boost::shared_ptr SoundP; class Sound : public Resource { - class Impl; - boost::shared_ptr mImpl; - public: static SoundP alloc(const std::string& name) @@ -60,13 +57,14 @@ public: return SoundP(new Sound(name)); } + Sound(); explicit Sound(const std::string& name); void play(); void stream(); - // TODO - this API sucks + // TODO this API sucks... refactor me!! void stop(); void pause(); @@ -91,32 +89,10 @@ public: static std::string getPath(const std::string& name); +private: - struct Exception : public Mf::Exception - { - enum - { - BAD_AUDIO_FORMAT = 1024 - }; - - explicit Exception(unsigned error) : - Mf::Exception(error) {} - - void raise() - { - throw *this; - } - - const char* what() const throw() - { - switch (code) - { - case BAD_AUDIO_FORMAT: - return "unknown audio format"; - } - return Mf::Exception::what(); - } - }; + class Impl; + boost::shared_ptr mImpl; }; diff --git a/src/Moof/Sphere.hh b/src/Moof/Sphere.hh index d690356..319a3ae 100644 --- a/src/Moof/Sphere.hh +++ b/src/Moof/Sphere.hh @@ -75,6 +75,13 @@ struct Sphere : public Cullable, public Drawable }; +inline bool checkCollision(const Sphere& a, const Sphere& b) +{ + Scalar d = (a.point - b.point).length(); + return d < (a.radius + b.radius); +} + + } // namespace Mf #endif // _MOOF_SPHERE_HH_ diff --git a/src/Moof/Texture.cc b/src/Moof/Texture.cc index 78dc0c8..341b559 100644 --- a/src/Moof/Texture.cc +++ b/src/Moof/Texture.cc @@ -34,6 +34,7 @@ #include #include "Dispatcher.hh" +#include "Exception.hh" #include "Library.hh" #include "Log.hh" #include "OpenGL.hh" @@ -245,7 +246,7 @@ public: if (!surface) { logWarning("texture not found: %s", getName().c_str()); - throw Exception(Exception::FILE_NOT_FOUND); + throw Exception(ErrorCode::FILE_NOT_FOUND, getName().c_str()); } SDL_Surface* temp = prepareImageForGL(surface); @@ -253,7 +254,7 @@ public: if (!temp) { - throw Exception(Exception::OPENGL_ERROR); + throw Exception(ErrorCode::UNKNOWN_IMAGE_FORMAT); } if (temp->format->BytesPerPixel == 3) @@ -267,7 +268,7 @@ public: else { SDL_FreeSurface(temp); - throw Exception(Exception::BAD_IMAGE_FORMAT); + throw Exception(ErrorCode::UNKNOWN_IMAGE_FORMAT); } mWidth = temp->w; diff --git a/src/Moof/Texture.hh b/src/Moof/Texture.hh index 5aa38e1..4e311ea 100644 --- a/src/Moof/Texture.hh +++ b/src/Moof/Texture.hh @@ -34,11 +34,8 @@ * Image-loading and OpenGL texture loading. */ -#include - #include -#include #include #include @@ -52,9 +49,6 @@ typedef boost::shared_ptr TextureP; class Texture : public Resource { - class Impl; - boost::shared_ptr mImpl; - public: static TextureP alloc(const std::string& name) @@ -62,7 +56,7 @@ public: return TextureP(new Texture(name)); } - Texture(const std::string& name); + explicit Texture(const std::string& name); void bind() const; GLuint getObject() const; @@ -79,32 +73,10 @@ public: static std::string getPath(const std::string& name); +private: - struct Exception : public Mf::Exception - { - enum - { - BAD_IMAGE_FORMAT = 1024 - }; - - explicit Exception(unsigned error) : - Mf::Exception(error) {} - - void raise() - { - throw *this; - } - - const char* what() const throw() - { - switch (code) - { - case BAD_IMAGE_FORMAT: - return "unknown image format"; - } - return Mf::Exception::what(); - } - }; + class Impl; + boost::shared_ptr mImpl; }; diff --git a/src/Moof/Timer.cc b/src/Moof/Timer.cc index d17882a..733f54c 100644 --- a/src/Moof/Timer.cc +++ b/src/Moof/Timer.cc @@ -29,7 +29,6 @@ #include #include #include -#include #include "Log.hh" #include "Timer.hh" @@ -44,8 +43,8 @@ namespace Mf { -Scalar Timer::nextFire_ = std::numeric_limits::max(); -std::map Timer::timers_; +Scalar Timer::gNextFire = std::numeric_limits::max(); +std::map Timer::gTimers; unsigned Timer::getNewID() @@ -76,9 +75,9 @@ void Timer::init(const Function& function, Scalar seconds, Mode mode) } mId = getNewID(); - timers_.insert(std::pair(mId, *this)); + gTimers.insert(std::pair(mId, *this)); - if (mAbsolute < nextFire_) nextFire_ = mAbsolute; + if (mAbsolute < gNextFire) gNextFire = mAbsolute; } } @@ -92,10 +91,10 @@ void Timer::invalidate() { if (mMode != INVALID) { - timers_.erase(mId); + gTimers.erase(mId); mMode = INVALID; - if (isEqual(mAbsolute, nextFire_)) nextFire_ = findNextFire(); + if (isEqual(mAbsolute, gNextFire)) gNextFire = findNextFire(); } } @@ -113,7 +112,7 @@ void Timer::fire() if (isEqual(mAbsolute, t, 1.0)) mAbsolute += mInterval; else mAbsolute = mInterval + t; - if (isEqual(absolute, nextFire_)) nextFire_ = findNextFire(); + if (isEqual(absolute, gNextFire)) gNextFire = findNextFire(); } else { @@ -127,7 +126,7 @@ Scalar Timer::findNextFire() std::map::iterator it; Scalar nextFire = std::numeric_limits::max(); - for (it = timers_.begin(); it != timers_.end(); ++it) + for (it = gTimers.begin(); it != gTimers.end(); ++it) { Scalar absolute = (*it).second.mAbsolute; if (absolute < nextFire) nextFire = absolute; @@ -157,9 +156,9 @@ void Timer::fireIfExpired(Scalar t) { std::map::iterator it; - if (nextFire_ > t) return; + if (gNextFire > t) return; - for (it = timers_.begin(); it != timers_.end(); ++it) + for (it = gTimers.begin(); it != gTimers.end(); ++it) { Timer& timer = (*it).second; if (timer.isExpired()) timer.fire(); @@ -169,7 +168,7 @@ void Timer::fireIfExpired(Scalar t) #if HAVE_CLOCK_GETTIME -// Since the monotonic clock will provide us with the timer since the computer +// Since the monotonic clock will provide us with the time since the computer // started, the number of seconds since that time could easily become so large // that it cannot be accurately stored in a float (even with as little two days // uptime), therefore we need to start from a more recent reference (when the @@ -195,10 +194,7 @@ Scalar Timer::getTicks() { struct timespec ts; - if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) - { - throw std::runtime_error("cannot access monotonic clock"); - } + ASSERT(clock_gettime(CLOCK_MONOTONIC, &ts) == 0 && "cannot access clock"); return Scalar(ts.tv_sec - reference) + Scalar(ts.tv_nsec) / 1000000000.0; } diff --git a/src/Moof/Timer.hh b/src/Moof/Timer.hh index ed4e2f0..bb0b483 100644 --- a/src/Moof/Timer.hh +++ b/src/Moof/Timer.hh @@ -45,8 +45,10 @@ namespace Mf { -struct Timer +class Timer { +public: + enum Mode { INVALID = -1, @@ -105,7 +107,7 @@ struct Timer static Scalar getNextFire() { - return nextFire_; + return gNextFire; } static void fireIfExpired(Scalar t); @@ -121,8 +123,8 @@ private: Scalar mInterval; unsigned mId; - static Scalar nextFire_; - static std::map timers_; + static Scalar gNextFire; + static std::map gTimers; }; diff --git a/src/Moof/Video.cc b/src/Moof/Video.cc index c49bb1e..9fdd478 100644 --- a/src/Moof/Video.cc +++ b/src/Moof/Video.cc @@ -26,11 +26,10 @@ *******************************************************************************/ -#include - #include #include "Dispatcher.hh" +#include "Exception.hh" #include "Log.hh" #include "Settings.hh" #include "Video.hh" @@ -129,7 +128,7 @@ void Video::setVideoMode(const long mode[3]) mAttribs.mode[1] = mode[1]; mAttribs.mode[2] = mode[2]; -#if defined(_WIN32) || defined (_WIN64) || defined(__WIN32__) +#if defined(_WIN32) || 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 @@ -137,7 +136,7 @@ void Video::setVideoMode(const long mode[3]) logInfo("video context recreated"); #endif } - else throw Exception(Exception::SDL_ERROR); + else throw Exception(ErrorCode::SDL_VIDEOMODE); } } diff --git a/src/Moof/Video.hh b/src/Moof/Video.hh index 736832f..193274f 100644 --- a/src/Moof/Video.hh +++ b/src/Moof/Video.hh @@ -35,8 +35,6 @@ #include -#include - namespace Mf { @@ -84,7 +82,7 @@ public: Video(); explicit Video(const Attributes& attribs); - explicit Video(const std::string& caption, const std::string& icon); + Video(const std::string& caption, const std::string& icon); ~Video(); void setVideoMode(const long mode[3]); @@ -118,18 +116,6 @@ public: int getWidth() const; int getHeight() const; - - struct Exception : public Mf::Exception - { - explicit Exception(unsigned error) : - Mf::Exception(error) {} - - void raise() - { - throw *this; - } - }; - private: void init(const Attributes& attribs); diff --git a/src/Scene.cc b/src/Scene.cc index bad59bf..9b4d1fd 100644 --- a/src/Scene.cc +++ b/src/Scene.cc @@ -32,10 +32,11 @@ #include #include #include +#include +#include #include #include -#include -#include +//#include #include #include @@ -44,11 +45,11 @@ #include "Tilemap.hh" -struct Scene::Impl : public Mf::Mippleton +struct Scene::Impl : public Mf::Library { - struct Quad : public Mf::Entity, public Mf::OctreeInsertable + struct Quad : public Mf::Entity { - enum SURFACE_TYPE + enum SURFACE { NONE = 0, LEFT = 1, @@ -58,69 +59,74 @@ struct Scene::Impl : public Mf::Mippleton Quad(const Mf::Vector3 vertices[4], const std::string& texture, Tilemap::Index tileIndex) : - tilemap_(texture), - blending_(false), - fog_(false), - surfaceType_(NONE) + mTilemap(texture), + mBlending(false), + mFog(false), + mSurface(NONE) { for (int i = 0, num = 0; i < 4; ++i) { for (int j = 0; j < 3; ++j, ++num) { - vertices_[num] = vertices[i][j]; + mVertices[num] = vertices[i][j]; } } - if (!tilemap_.getTileCoords(tileIndex, texCoords_)) + if (!mTilemap.getTileCoords(tileIndex, mTexCoords)) { Mf::logWarning("no index %d in texture %s", tileIndex, texture.c_str()); - texCoords_[0] = texCoords_[1] = - texCoords_[3] = texCoords_[6] = 0.0; - texCoords_[2] = texCoords_[4] = - texCoords_[5] = texCoords_[7] = 1.0; + mTexCoords[0] = mTexCoords[1] = + mTexCoords[3] = mTexCoords[6] = 0.0; + mTexCoords[2] = mTexCoords[4] = + mTexCoords[5] = mTexCoords[7] = 1.0; } - aabb_.encloseVertices(vertices, 4); - sphere_.point = aabb_.getCenter(); - sphere_.radius = (aabb_.min - sphere_.point).length(); + mAabb.encloseVertices(vertices, 4); + mSphere.point = mAabb.getCenter(); + mSphere.radius = (mAabb.min - mSphere.point).length(); } void setBlending(bool blending) { - blending_ = blending; + mBlending = blending; } void setFog(bool fog) { - fog_ = fog; + mFog = fog; } - void setSurfaceType(SURFACE_TYPE type) + void setSurface(SURFACE type) { - surfaceType_ = type; + mSurface = type; + } + + SURFACE getSurface() const + { + return mSurface; } void draw(Mf::Scalar alpha = 0.0) const { - if (blending_) + if (mBlending) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - if (fog_) + if (mFog) { glEnable(GL_FOG); glFogi(GL_FOG_MODE, GL_LINEAR); } //glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - tilemap_.bind(); + mTilemap.bind(); - glVertexPointer(3, GL_SCALAR, 0, vertices_); - glTexCoordPointer(2, GL_SCALAR, 0, texCoords_); + glVertexPointer(3, GL_SCALAR, 0, mVertices); + glTexCoordPointer(2, GL_SCALAR, 0, mTexCoords); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -130,158 +136,29 @@ struct Scene::Impl : public Mf::Mippleton bool isVisible(const Mf::Frustum& frustum) const { - return sphere_.isVisible(frustum); - } - - - bool isInsideAabb(const Mf::Aabb& aabb) const - { - // make sure the entity is fully inside the volume - if (!(aabb_.max[0] < aabb.max[0] && - aabb_.min[0] > aabb.min[0] && - aabb_.max[1] < aabb.max[1] && - aabb_.min[1] > aabb.min[1] && - aabb_.max[2] < aabb.max[2] && - aabb_.min[2] > aabb.min[2])) - { - return false; - } - - return true; - } - - int getOctant(const Mf::Aabb& aabb) const - { - int octantNum = -1; - - Mf::Plane::Halfspace halfspace; - - Mf::Plane xy = aabb.getPlaneXY(); - halfspace = xy.intersects(sphere_); - if (halfspace == Mf::Plane::INTERSECT) - { - halfspace = xy.intersects(aabb_); - } - - if (halfspace == Mf::Plane::POSITIVE) - { - Mf::Plane xz = aabb.getPlaneXZ(); - halfspace = xz.intersects(sphere_); - if (halfspace == Mf::Plane::INTERSECT) - { - halfspace = xz.intersects(aabb_); - } - - if (halfspace == Mf::Plane::POSITIVE) - { - Mf::Plane yz = aabb.getPlaneYZ(); - halfspace = yz.intersects(sphere_); - if (halfspace == Mf::Plane::INTERSECT) - { - halfspace = yz.intersects(aabb_); - } - - if (halfspace == Mf::Plane::POSITIVE) - { - octantNum = 2; - } - else if (halfspace == Mf::Plane::NEGATIVE) - { - octantNum = 3; - } - } - else if (halfspace == Mf::Plane::NEGATIVE) - { - Mf::Plane yz = aabb.getPlaneYZ(); - halfspace = yz.intersects(sphere_); - if (halfspace == Mf::Plane::INTERSECT) - { - halfspace = yz.intersects(aabb_); - } - - if (halfspace == Mf::Plane::POSITIVE) - { - octantNum = 1; - } - else if (halfspace == Mf::Plane::NEGATIVE) - { - octantNum = 0; - } - } - } - else if (halfspace == Mf::Plane::NEGATIVE) - { - Mf::Plane xz = aabb.getPlaneXZ(); - halfspace = xz.intersects(sphere_); - if (halfspace == Mf::Plane::INTERSECT) - { - halfspace = xz.intersects(aabb_); - } - - if (halfspace == Mf::Plane::POSITIVE) - { - Mf::Plane yz = aabb.getPlaneYZ(); - halfspace = yz.intersects(sphere_); - if (halfspace == Mf::Plane::INTERSECT) - { - halfspace = yz.intersects(aabb_); - } - - if (halfspace == Mf::Plane::POSITIVE) - { - octantNum = 6; - } - else if (halfspace == Mf::Plane::NEGATIVE) - { - octantNum = 7; - } - } - else if (halfspace == Mf::Plane::NEGATIVE) - { - Mf::Plane yz = aabb.getPlaneYZ(); - halfspace = yz.intersects(sphere_); - if (halfspace == Mf::Plane::INTERSECT) - { - halfspace = yz.intersects(aabb_); - } - - if (halfspace == Mf::Plane::POSITIVE) - { - octantNum = 5; - } - else if (halfspace == Mf::Plane::NEGATIVE) - { - octantNum = 4; - } - } - } - - return octantNum; + return mSphere.isVisible(frustum); } - Mf::Scalar vertices_[12]; - Mf::Scalar texCoords_[8]; + Mf::Scalar mVertices[12]; + Mf::Scalar mTexCoords[8]; - Tilemap tilemap_; - - bool blending_; - bool fog_; - SURFACE_TYPE surfaceType_; + Tilemap mTilemap; - Mf::Aabb aabb_; - Mf::Sphere sphere_; + bool mBlending; + bool mFog; + SURFACE mSurface; }; - Mf::Matrix4 transform; - std::string texture; + Mf::Matrix4 mTransform; + std::string mTexture; - Mf::Octree::Ptr octree; + //Mf::Octree::Ptr mOctree; + std::list< boost::shared_ptr > mObjects; - Mf::Aabb playfieldBounds; - Mf::Aabb maximumBounds; + Mf::Aabb mBounds; enum AXIS @@ -292,19 +169,13 @@ struct Scene::Impl : public Mf::Mippleton }; - explicit Impl(const std::string& name) : - Mf::Mippleton(name) - { - loadFromFile(); - } + Mf::Library(name) {} void importSceneBindings(Mf::Script& script) { - script.importFunction("SetPlayfieldBounds", - boost::bind(&Impl::setPlayfieldBounds, this, _1)); - script.importFunction("SetMaximumBounds", - boost::bind(&Impl::setMaximumBounds, this, _1)); + script.importFunction("SetBounds", + boost::bind(&Impl::setBounds, this, _1)); script.importFunction("ResetTransform", boost::bind(&Impl::resetTransform, this, _1)); script.importFunction("Translate", @@ -315,15 +186,19 @@ struct Scene::Impl : public Mf::Mippleton boost::bind(&Impl::rotate, this, _1)); script.importFunction("SetTexture", boost::bind(&Impl::setTexture, this, _1)); - script.importFunction("MakeTilemap", - boost::bind(&Impl::makeTilemap, this, _1)); - script.importFunction("MakeBillboard", - boost::bind(&Impl::makeBillboard, this, _1)); + script.importFunction("DrawTilemap", + boost::bind(&Impl::drawTilemap, this, _1)); + script.importFunction("DrawTile", + boost::bind(&Impl::drawTile, this, _1)); int detail = 3; Mf::Settings::getInstance().get("detail", detail); script.push(detail); script.set("detail"); + script.push(1); script.set("LOW"); + script.push(2); script.set("MEDIUM"); + script.push(3); script.set("HIGH"); + script.push(X); script.set("X"); script.push(Y); script.set("Y"); script.push(Z); script.set("Z"); @@ -334,21 +209,13 @@ struct Scene::Impl : public Mf::Mippleton } - void loadFromFile() + Mf::Script::Status load(Mf::Script& script) { - Mf::Script script; std::string filePath = Scene::getPath(getName()); + if (filePath == "") return Mf::Script::FILE_ERROR; - script.importStandardLibraries(); - importLogScript(script); importSceneBindings(script); - - if (script.doFile(filePath) != Mf::Script::SUCCESS) - { - std::string str; - script[-1].get(str); - Mf::logScript("%s", str.c_str()); - } + return script.doFile(filePath); } @@ -379,21 +246,16 @@ struct Scene::Impl : public Mf::Mippleton return 0; } - int setPlayfieldBounds(Mf::Script& script) + int setBounds(Mf::Script& script) { - return loadBox(script, playfieldBounds); - } - - int setMaximumBounds(Mf::Script& script) - { - int ret = loadBox(script, maximumBounds); - octree = Mf::Octree::alloc(maximumBounds); + int ret = loadBox(script, mBounds); + //mOctree = Mf::Octree::alloc(mBounds); return ret; } int resetTransform(Mf::Script& script) { - transform.identity(); + mTransform.identity(); return 0; } @@ -410,7 +272,7 @@ struct Scene::Impl : public Mf::Mippleton Mf::Matrix4 translation; cml::matrix_translation(translation, vec); - transform = translation * transform; + mTransform = translation * mTransform; return 0; } @@ -426,7 +288,7 @@ struct Scene::Impl : public Mf::Mippleton Mf::Matrix4 scaling; cml::matrix_scale(scaling, vec); - transform = scaling * transform; + mTransform = scaling * mTransform; } else if (script.getSize() == 1) { @@ -435,7 +297,7 @@ struct Scene::Impl : public Mf::Mippleton Mf::Matrix4 scaling; cml::matrix_uniform_scale(scaling, value); - transform = scaling * transform; + mTransform = scaling * mTransform; } else { @@ -456,35 +318,37 @@ struct Scene::Impl : public Mf::Mippleton Mf::Scalar value; angle.get(value); - cml::matrix_rotate_about_world_axis(transform, index, cml::rad(value)); + cml::matrix_rotate_about_world_axis(mTransform, index, cml::rad(value)); return 0; } int setTexture(Mf::Script& script) { - script[1].requireString().get(texture); + script[1].requireString().get(mTexture); return 0; } - int makeTilemap(Mf::Script& script) + int drawTilemap(Mf::Script& script) { Mf::Script::Value table = script[1].requireTable(); Mf::Script::Value top = script[-1]; - Quad::SURFACE_TYPE surfaceType; - table.pushField("surface_type"); - top.get(surfaceType); + Quad::SURFACE surface; + table.pushField("surface"); + top.get(surface); + script.pop(); int width = 1; int height = 1; table.pushField("width"); top.get(width); + script.pop(); int nTiles = 0; - table.pushField("tiles"); + //table.pushField("tiles"); Mf::Script::Value tiles = script.getTop(); nTiles = tiles.getLength(); @@ -522,7 +386,7 @@ struct Scene::Impl : public Mf::Mippleton Mf::Vector4 vertices[height+1][width+1]; - Mf::Matrix4 transposedTransform = transform; + Mf::Matrix4 transposedTransform = mTransform; transposedTransform.transpose(); for (int h = 0; h <= height; ++h) @@ -546,20 +410,21 @@ struct Scene::Impl : public Mf::Mippleton demotedVertices[2] = Mf::demote(vertices[h+1][w+1]); demotedVertices[3] = Mf::demote(vertices[h+1][w]); - Quad* quad = new Quad(demotedVertices, texture, indices[h][w]); - quad->setSurfaceType(surfaceType); + Quad* quad = new Quad(demotedVertices, mTexture, indices[h][w]); + quad->setSurface(surface); boost::shared_ptr quadPtr(quad); - octree->insert(quadPtr); + //mOctree->insert(quadPtr); + mObjects.push_back(quadPtr); } } return 0; } - int makeBillboard(Mf::Script& script) + int drawTile(Mf::Script& script) { - Mf::Script::Value table = script[1]; + Mf::Script::Value param = script[1]; Mf::Script::Value top = script[-1]; Tilemap::Index index = 0; @@ -567,24 +432,29 @@ struct Scene::Impl : public Mf::Mippleton bool blending = false; bool fog = false; - if (table.isTable()) + if (param.isTable()) { - table.pushField("tile"); + script.push(1); + param.pushField(); top.get(index); - table.pushField("u_scale"); + param.pushField("u_scale"); top.get(width); - table.pushField("blend"); + param.pushField("blend"); top.get(blending); - table.pushField("fog"); + param.pushField("fog"); top.get(fog); } + else if (param.isNumber()) + { + param.get(index); + } Mf::Vector4 vertices[2][width+1]; - Mf::Matrix4 transposedTransform = transform; + Mf::Matrix4 transposedTransform = mTransform; transposedTransform.transpose(); Mf::Scalar xf; @@ -609,12 +479,13 @@ struct Scene::Impl : public Mf::Mippleton demotedVertices[2] = Mf::demote(vertices[1][w+1]); demotedVertices[3] = Mf::demote(vertices[1][w]); - Quad* quad = new Quad(demotedVertices, texture, index); + Quad* quad = new Quad(demotedVertices, mTexture, index); quad->setBlending(blending); quad->setFog(fog); boost::shared_ptr quadPtr(quad); - octree->insert(quadPtr); + //mOctree->insert(quadPtr); + mObjects.push_back(quadPtr); } return 0; @@ -627,25 +498,100 @@ Scene::Scene(const std::string& name) : mImpl(Scene::Impl::getInstance(name)) {} +Mf::Script::Status Scene::load(Mf::Script& script) +{ + // pass through + return mImpl->load(script); +} + + void Scene::draw(Mf::Scalar alpha) const { - mImpl->octree->draw(alpha); + //mImpl->mOctree->draw(alpha); + std::list< boost::shared_ptr >& objects = mImpl->mObjects; + std::list< boost::shared_ptr >::const_iterator it; + + for (it = objects.begin(); it != objects.end(); ++it) + { + (*it)->draw(alpha); + } + + mImpl->mBounds.draw(); } void Scene::drawIfVisible(Mf::Scalar alpha, const Mf::Frustum& frustum) const { - mImpl->octree->drawIfVisible(alpha, frustum); + //mImpl->mOctree->drawIfVisible(alpha, frustum); + std::list< boost::shared_ptr >& objects = mImpl->mObjects; + std::list< boost::shared_ptr >::const_iterator it; + + for (it = objects.begin(); it != objects.end(); ++it) + { + (*it)->drawIfVisible(alpha, frustum); + } + + mImpl->mBounds.draw(); } bool Scene::checkForCollision(Character& character) { - std::list< boost::shared_ptr > objects; + return false; + //std::list< boost::shared_ptr > objects; //std::list::InsertableP> objects; - mImpl->octree->getNearbyObjects(objects, character); - mImpl->maximumBounds.draw(); + //mImpl->mOctree->getNearbyObjects(objects, character); + + std::list< boost::shared_ptr >& objects = mImpl->mObjects; + std::list< boost::shared_ptr >::const_iterator it; + + int collisions = 0; + Mf::Sphere sphere = character.getSphere(); + + for (it = objects.begin(); it != objects.end(); ++it) + { + Impl::Quad::SURFACE type = (*it)->getSurface(); + if (type == Impl::Quad::NONE) continue; + + if (Mf::checkCollision(sphere, (*it)->getSphere())) + { + ++collisions; + + Mf::Vector2 impulse(0.0, 0.0); + Mf::Vector2 p = character.getState().momentum; + + Mf::State2 state = character.getState(1.0); + sphere = character.getSphere(); + Mf::Scalar alpha = 1.0; + while (Mf::checkCollision(sphere, (*it)->getSphere())) + { + alpha -= 0.05; + state = character.getState(alpha); + } + + character.setPosition(state.position); + + //switch (type) + //{ + //case Impl::Quad::TOP: + //if (p[1] < 0.0) impulse[1] = -p[1]; + //break; + //case Impl::Quad::LEFT: + //if (p[0] > 0.0) impulse[0] = 1.5*-p[0]; + //break; + //case Impl::Quad::RIGHT: + //if (p[0] < 0.0) impulse[0] = 1.5*-p[0]; + //break; + //} + + //character.addImpulse(impulse); + } + } + + if (collisions > 0) + { + Mf::logInfo("collisions: %d", collisions); + } - Mf::logDebug("nearby objects: %d", objects.size()); return false; } diff --git a/src/Scene.hh b/src/Scene.hh index b858c64..f9963e8 100644 --- a/src/Scene.hh +++ b/src/Scene.hh @@ -36,6 +36,7 @@ #include #include #include +#include class Character; @@ -51,16 +52,20 @@ class Scene : public Mf::Cullable, public Mf::Drawable, public Mf::Resource public: - Scene(const std::string& name); + explicit Scene(const std::string& name); static SceneP alloc(const std::string& name) { return SceneP(new Scene(name)); } + Mf::Script::Status load(Mf::Script& script); + void draw(Mf::Scalar alpha) const; void drawIfVisible(Mf::Scalar alpha, const Mf::Frustum& frustum) const; + Mf::Scalar getZCoord(const Mf::Vector2& position) const; + bool checkForCollision(Character& character); static std::string getPath(const std::string& name); diff --git a/src/Tilemap.hh b/src/Tilemap.hh index 671780a..9277387 100644 --- a/src/Tilemap.hh +++ b/src/Tilemap.hh @@ -67,7 +67,7 @@ public: } Orientation; - Tilemap(const std::string& name); + explicit Tilemap(const std::string& name); /** * Calculate texture coordinates for a tile at a certain index. Tiles are diff --git a/src/version.h b/src/version.h index 5937771..3ea5cf2 100644 --- a/src/version.h +++ b/src/version.h @@ -55,7 +55,7 @@ #define COMPILER_NAME "COMO" #define COMPILER_VERSION __COMO_VERSION__ #elif defined(_CRAYC) && defined(_REVISION) -#define COMPILER_NAME "GRAYC" +#define COMPILER_NAME "CRAYC" #define COMPILER_VERSION _REVISION #elif defined(__DECCXX) && defined(__DECCXX) #define COMPILER_NAME "DECCXX" diff --git a/win32/build-installer.sh.in b/win32/build-installer.sh.in index 115599d..33d5b14 100644 --- a/win32/build-installer.sh.in +++ b/win32/build-installer.sh.in @@ -265,7 +265,7 @@ Section "$SEC_INSTALL" SecInstallYoink File /r /x Makefile* /x *.desktop "$ROOT_DIR/data" ; documentation File "$ROOT_DIR/AUTHORS" "$ROOT_DIR/ChangeLog" "$ROOT_DIR/COPYING" - File "$ROOT_DIR/README" "$ROOT_DIR/TODO" "$ROOT_DIR/doc/screenshot.png" + File "$ROOT_DIR/README" "$ROOT_DIR/TODO" "$ROOT_DIR/doc/screenshot.jpg" File /r "$ROOT_DIR/doc/licenses" ; uninstall WriteUninstaller "uninstall.exe" -- 2.43.0