diff --git a/Evade2/CMakeLists.txt b/Evade2/CMakeLists.txt index 251b9eb..2d20388 100644 --- a/Evade2/CMakeLists.txt +++ b/Evade2/CMakeLists.txt @@ -25,62 +25,54 @@ INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/creative-engine/CreativeEngine.cmake) SET(EVADE2_INCLUDE_DIRS - ${CMAKE_SOURCE_DIR}/src - ${CMAKE_SOURCE_DIR}/src/resources -# ${CMAKE_SOURCE_DIR}/src/LoadGameState -# ${CMAKE_SOURCE_DIR}/src/GameState -# ${CMAKE_SOURCE_DIR}/src/GameState/environment -# ${CMAKE_SOURCE_DIR}/src/GameState/player -# ${CMAKE_SOURCE_DIR}/src/GameState/inventory -# ${CMAKE_SOURCE_DIR}/src/GameState/enemies -# ${CMAKE_SOURCE_DIR}/src/GameState/enemies/final-boss -# ${CMAKE_SOURCE_DIR}/src/GameState/enemies/grunts -# ${CMAKE_SOURCE_DIR}/src/GameState/enemies/mid-bosses -# ${CMAKE_SOURCE_DIR}/src/GameState/status -# ${CMAKE_SOURCE_DIR}/src/img/ -# ${CMAKE_SOURCE_DIR}/src/AttractState -# ${CMAKE_SOURCE_DIR}/src/GameMenuState -# ${CMAKE_SOURCE_DIR}/src/DebugMenuState -# ${CMAKE_SOURCE_DIR}/src/GameOverState -# ${CMAKE_SOURCE_DIR}/src/VictoryState -# ${CMAKE_SOURCE_DIR}/src/MainMenuState -# ${CMAKE_SOURCE_DIR}/src/MainOptionsState -# ${CMAKE_SOURCE_DIR}/src/SplashState -# ${CMAKE_SOURCE_DIR}/src/CreditsState -# ${CMAKE_SOURCE_DIR}/src/ResetState - ${CMAKE_BINARY_DIR}/usr/local/include -) + ${CMAKE_SOURCE_DIR}/src + ${CMAKE_SOURCE_DIR}/src/resources + ${CMAKE_SOURCE_DIR}/src/common + ${CMAKE_SOURCE_DIR}/src/SplashState + ${CMAKE_SOURCE_DIR}/src/AttractState + ${CMAKE_SOURCE_DIR}/src/MainMenuState + ${CMAKE_SOURCE_DIR}/src/GameState + # ${CMAKE_SOURCE_DIR}/src/img/ + # ${CMAKE_SOURCE_DIR}/src/GameMenuState + # ${CMAKE_SOURCE_DIR}/src/DebugMenuState + # ${CMAKE_SOURCE_DIR}/src/GameOverState + # ${CMAKE_SOURCE_DIR}/src/VictoryState + # ${CMAKE_SOURCE_DIR}/src/MainOptionsState + # ${CMAKE_SOURCE_DIR}/src/CreditsState + # ${CMAKE_SOURCE_DIR}/src/ResetState + ${CMAKE_BINARY_DIR}/usr/local/include + ) INCLUDE_DIRECTORIES( - ${EVADE2_INCLUDE_DIRS} - ${CREATIVE_ENGINE_INCLUDE_DIRS} + ${EVADE2_INCLUDE_DIRS} + ${CREATIVE_ENGINE_INCLUDE_DIRS} ) # gather Modite sources FILE(GLOB_RECURSE EVADE2_SRC RELATIVE ${CMAKE_SOURCE_DIR} "src/*.cpp") ADD_EXECUTABLE( - ${PROJECT_NAME} - Resources.bin - ${CREATIVE_ENGINE_SOURCE_FILES} - ${EVADE2_SRC} - creative-engine/src/main.cpp src/GameState/GGameState.cpp src/GameState/GGameState.h src/GameState/GGamePlayfield.cpp src/GameState/GGamePlayfield.h) + ${PROJECT_NAME} + Resources.bin + ${CREATIVE_ENGINE_SOURCE_FILES} + ${EVADE2_SRC} + src/GameState/GGameState.cpp src/GameState/GGameState.h src/common/GStarfield.cpp src/common/GStarfield.h src/GameState/GPlayerBulletProcess.cpp src/GameState/GPlayerBulletProcess.h src/main.cpp src/GameState/GEnemyProcess.cpp src/GameState/GEnemyProcess.h src/GameState/GEnemyBulletProcess.cpp src/GameState/GEnemyBulletProcess.h src/AttractState/GAttractState.cpp src/AttractState/GAttractState.h src/AttractState/GAttractProcess.cpp src/AttractState/GAttractProcess.h src/MainMenuState/GMainMenuState.cpp src/MainMenuState/GMainMenuState.h src/MainMenuState/GMainMenuProcess.cpp src/MainMenuState/GMainMenuProcess.h src/GameState/GNextWaveProcess.cpp src/GameState/GNextWaveProcess.h src/GameState/GBossProcess.cpp src/GameState/GBossProcess.h) ProcessorCount(N) if (NOT N EQUAL 0) - set(${PROJECT_NAME}_FLAGS -j${N}) - set(${PROJECT_NAME}_BUILD_FLAGS -j${N}) - set(${PROJECT_NAME}_args ${${PROJECT_NAME}_args} PARALLEL_LEVEL ${N}) + set(${PROJECT_NAME}_FLAGS -j${N}) + set(${PROJECT_NAME}_BUILD_FLAGS -j${N}) + set(${PROJECT_NAME}_args ${${PROJECT_NAME}_args} PARALLEL_LEVEL ${N}) endif () BUILD_COMMAND( - $(MAKE) --silent + $(MAKE) --silent ) # make Modite.app if (APPLE) - SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE TRUE) - INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ".") + SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE TRUE) + INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ".") endif (APPLE) TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${CREATIVE_ENGINE_LINK_LIBRARIES}) diff --git a/Evade2/old/GameState/enemies/GBossSprite.cpp b/Evade2/old/GameState/enemies/GBossSprite.cpp index 30c117f..55f2be8 100644 --- a/Evade2/old/GameState/enemies/GBossSprite.cpp +++ b/Evade2/old/GameState/enemies/GBossSprite.cpp @@ -2,7 +2,7 @@ #include "GResources.h" #include "GBossSprite.h" #include "GPlayer.h" -#include "GCamera.h" +#include "common/GCamera.h" static const TFloat z_dist = 256; static const TFloat frames = 32; diff --git a/Evade2/old/GameState/enemies/GEnemySprite.cpp b/Evade2/old/GameState/enemies/GEnemySprite.cpp index 19c91c1..265d4e9 100644 --- a/Evade2/old/GameState/enemies/GEnemySprite.cpp +++ b/Evade2/old/GameState/enemies/GEnemySprite.cpp @@ -2,7 +2,7 @@ #include "GResources.h" #include "GEnemySprite.h" #include "GPlayer.h" -#include "GCamera.h" +#include "common/GCamera.h" const TInt8 *enemy_graphic(TInt16 n) { diff --git a/Evade2/old/GameState/player/GPlayerProcess.cpp b/Evade2/old/GameState/player/GPlayerProcess.cpp index 09cdb61..b897b60 100644 --- a/Evade2/old/GameState/player/GPlayerProcess.cpp +++ b/Evade2/old/GameState/player/GPlayerProcess.cpp @@ -1,7 +1,7 @@ #include "GPlayerProcess.h" #include "GPlayer.h" #include "GPlayerSprite.h" -#include "GGamePlayfield.h" +#include "GStarfield.h" #include "GStatProcess.h" #include "GResources.h" #include "GPlayerBulletProcess.h" diff --git a/Evade2/old/SplashState/Splash.cpp b/Evade2/old/SplashState/Splash.cpp deleted file mode 100644 index e0b04ef..0000000 --- a/Evade2/old/SplashState/Splash.cpp +++ /dev/null @@ -1,66 +0,0 @@ -//#define DEBUGME -////#undef DEBUGME -// -//#include "Evade2.h" -// -//BOOL Splash::attract_mode = TRUE; -// -//struct splash_data { -//#ifdef ENABLE_ROTATING_TEXT -// FLOAT theta; // angle of rotating text -//#endif -// WORD timer; -//}; -// -///** -// * Wait for the human to press the A button -// */ -//void Splash::wait(Process *me, Object *o) { -// splash_data *d = (splash_data *)&o->x; -// -// Font::scale = 2 * 0x200; -//#ifdef ENABLE_ROTATING_TEXT -// Font::print_string_rotatedx(SHMOO_COLOR, 60, 90, d->theta, "EVADE 2"); -// d->theta += 10; -// if (d->theta > 90 + 360 * 2) { -// d->theta = 90 + 360 * 2; -// } -//#else -// Font::printf(SHMOO_COLOR, 60, 90, "EVADE 2"); -//#endif -// Font::scale = 0x100; -// -// d->timer--; -// if (d->timer < 0 || Controls::debounced(BUTTON_START)) { -// game_mode = attract_mode ? MODE_ATTRACT : MODE_CREDITS; -// attract_mode = !attract_mode; -// ProcessManager::birth(Attract::entry); -// me->suicide(); -// return; -// } -// if (d->timer & 16) { -// Font::scale = 0x200; -// Font::printf(SHMOO_COLOR, 130, 155, "START"); -// } -// -// if (Controls::debounced(BUTTON_A) || Controls::debounced(BUTTON_B)) { -// ProcessManager::birth(Game::entry); -// me->suicide(); -// return; -// } -// me->sleep(1); -//} -// -//void Splash::entry(Process *me, Object *o) { -// splash_data *d = (splash_data *)&o->x; -// -// game_mode = MODE_SPLASH; -//#ifdef ENABLE_ROTATING_TEXT -// d->theta = 90; -//#endif -// d->timer = 240; -// -// Camera::vz = CAMERA_VZ; -// Sound::play_score(INTRO_SONG); -// me->sleep(1, Splash::wait); -//} diff --git a/Evade2/old/SplashState/Splash.h b/Evade2/old/SplashState/Splash.h deleted file mode 100644 index d9a5148..0000000 --- a/Evade2/old/SplashState/Splash.h +++ /dev/null @@ -1,20 +0,0 @@ -//#ifndef SPLASH_H -//#define SPLASH_H -// -//#include "Evade2.h" -// -//class Splash { -//private: -// static BOOL attract_mode; -// -//private: -// // states -// static void show_logo(Process *me); -// static void wait(Process *me, Object *o); -// -//public: -// // initial state -// static void entry(Process *me, Object *o); -//}; -// -//#endif diff --git a/Evade2/src/AttractState/GAttractProcess.cpp b/Evade2/src/AttractState/GAttractProcess.cpp new file mode 100644 index 0000000..8af019e --- /dev/null +++ b/Evade2/src/AttractState/GAttractProcess.cpp @@ -0,0 +1,227 @@ +// +// Created by Michael Schwartz on 11/4/20. +// + +#include "GAttractProcess.h" +#include "GEnemyProcess.h" + + +static const TInt8 TYPEWRITER_SPEED = 10; +static const TInt8 LINE_HEIGHT = 26; + +static const char scout_text[] = "SCOUT"; +static const char bomber_text[] = "BOMBER"; +static const char assault_text[] = "ASSAULT"; + +static const char credits1[] = "CRAFTED BY:\nMODUS CREATE\nDECEMBER 2017"; +static const char credits2[] = "MUSIC and SFX:\nJ. GARCIA"; +static const char credits3[] = + "ART:\nM. TINTIUC\nJV DALEN\nJD JONES\nJ. GARCIA"; +static const char credits4[] = + "PROGRAMMING:\nM. SCHWARTZ\nJ. GARCIA\nM. TINTIUC\n"; +static const char credits5[] = + "PROGRAMMING:\nD. BRIGNOLI\nS. LEMMONS\nA. DENNIS"; +static const char credits6[] = "PROGRAMMING:\nV. POPA\nL. STILL\nG. GRISOGONO"; + +const TInt8 MAX_SCREEN = 2; +const TInt8 MAX_CREDITS = 5; + +enum { + STATE_TYPEWRITER, + STATE_NEXT, +}; + +GAttractProcess::GAttractProcess() : BProcess() { +// mSprite = new GVectorSprite(); +// gGameEngine->AddSprite(mSprite); + auto *ad = (TAttractData *) &mData; + ad->screen = 0; + InitScreen(); +// Sound::play_sound(SFX_NEXT_ATTRACT_SCREEN); + mState = STATE_TYPEWRITER; +} + +GAttractProcess::~GAttractProcess() { + // +} + +TBool GAttractProcess::RunBefore() { + return ETrue; +} + +TBool GAttractProcess::RunAfter() { + switch (mState) { + case STATE_TYPEWRITER: + return TypewriterState(); + case STATE_NEXT: + return NextState(); + default: + Panic("invalid state: mState(%d)", mState); + } + + return ETrue; +} + +void GAttractProcess::InitScreen(TInt16 x, TInt16 y) { + auto *ad = &mData; + if (gGame->GetState() == GAME_STATE_ATTRACT_MODE) { + switch (ad->screen) { + case 0: + ad->enemy = ENEMY_SCOUT; + ad->text = scout_text; + x = 125; + y = 60; + break; + case 1: + ad->enemy = ENEMY_BOMBER; + ad->text = bomber_text; + x = 117; + y = 60; + break; + case 2: + ad->enemy = ENEMY_ASSAULT; + ad->text = assault_text; + x = 110; + y = 60; + break; + } + } else { + ad->enemy = -1; + switch (ad->screen) { + case 0: + ad->text = credits1; + break; + case 1: + ad->text = credits2; + break; + case 2: + ad->text = credits3; + break; + case 3: + ad->text = credits4; + break; + case 4: + ad->text = credits5; + break; + case 5: + ad->text = credits6; + break; + } + } + + ad->offset = 1; + ad->x = x; + ad->y = y; + ad->timer = TYPEWRITER_SPEED; + ad->done = EFalse; +} + +TBool GAttractProcess::NextState() { + auto *ad = (TAttractData *) &mData; + TInt game_mode = gGame->GetState(); + + ad->timer--; + if (ad->timer < 0) { + ad->screen++; + if ((game_mode == GAME_STATE_ATTRACT_MODE && ad->screen > MAX_SCREEN)) { + gGame->SetState(GAME_STATE_CREDITS); + return EFalse; + } + if (game_mode == GAME_STATE_CREDITS && ad->screen > MAX_CREDITS) { + gGame->SetState(GAME_STATE_MAIN_MENU); + return EFalse; + } +// Sound::play_sound(SFX_NEXT_ATTRACT_SCREEN); + InitScreen(); + mState = STATE_TYPEWRITER; + } + return ETrue; +} + +TBool GAttractProcess::TypewriterState() { + auto *ad = (TAttractData *) &mData; + TInt game_mode = gGame->GetState(); + + ad->timer--; + + if (gControls.WasPressed(CONTROL_FIRE)) { + gGame->SetState(GAME_STATE_GAME); + return EFalse; + } + + if (gControls.WasPressed(BUTTON_START)) { + ad->timer = -1; + gGame->SetState(GAME_STATE_GAME); + return EFalse; + } + + if (ad->timer < 0) { + if (ad->done) { + ad->timer = 50; +// me->sleep(1, next); + mState = STATE_NEXT; + return ETrue; + } + ad->timer = TYPEWRITER_SPEED; + ad->offset++; +// Sound::play_sound(SFX_NEXT_ATTRACT_CHAR); + } + + switch (ad->enemy) { + case ENEMY_ASSAULT: + GVectorSprite::DrawVectorGraphic(GEnemyProcess::Graphic(ad->enemy), + TFloat(SCREEN_WIDTH) / 2, TFloat(SCREEN_HEIGHT) / 2, 0.0, + .75, // Originally 2.0 + ASSAULT_COLOR); + break; + case ENEMY_BOMBER: + GVectorSprite::DrawVectorGraphic(GEnemyProcess::Graphic(ad->enemy), + TFloat(SCREEN_WIDTH) / 2, TFloat(SCREEN_HEIGHT) / 2, 0.0, + .75, // Originally 2.0 + BOMBER_COLOR); + break; + case ENEMY_SCOUT: + GVectorSprite::DrawVectorGraphic(GEnemyProcess::Graphic(ad->enemy), + TFloat(SCREEN_WIDTH) / 2, TFloat(SCREEN_HEIGHT) / 2, 0.0, + .75, // Originally 2.0 + SCOUT_COLOR); + break; + } + if (game_mode == GAME_STATE_CREDITS) { + gVectorFont->scale = 2.0; + } + + const char *p = ad->text; + TInt16 x = ad->x, + y = ad->y; + + for (TInt8 i = 0; i < ad->offset;) { + char c = *p++; + if (c == '\0') { + if (!ad->done) { + ad->timer = 60; // 2 seconds + ad->done = ETrue; + } + break; + } else if (c == '\n') { + x = 20; + y += LINE_HEIGHT; + } else { + x += gVectorFont->write(x, y, c); + i++; + } + } + // if (game_mode == MODE_CREDITS) { + gVectorFont->scale = 2; + // } + return ETrue; +} + +//void Attract::entry() { +// TAttractData *ad = (TAttractData *) &mData; +// ad->screen = 0; +// InitScreen(); +// Sound::play_sound(SFX_NEXT_ATTRACT_SCREEN); +// +// me->sleep(1, typewriter); +//} diff --git a/Evade2/src/AttractState/GAttractProcess.h b/Evade2/src/AttractState/GAttractProcess.h new file mode 100644 index 0000000..31865a4 --- /dev/null +++ b/Evade2/src/AttractState/GAttractProcess.h @@ -0,0 +1,45 @@ +// +// Created by Michael Schwartz on 11/4/20. +// + +#ifndef EVADE2_GATTRACTPROCESS_H +#define EVADE2_GATTRACTPROCESS_H + +#include "Game.h" +#include "GVectorSprite.h" + +struct TAttractData { + TInt8 screen; + TInt8 x; + TInt8 y; + TInt8 offset; + TInt16 timer; + TBool done; + const char *text; + TInt8 enemy; +}; + +class GAttractProcess : public BProcess { +public: + GAttractProcess(); + + ~GAttractProcess(); + +public: + TBool RunBefore() OVERRIDE; + + TBool RunAfter() OVERRIDE; + +protected: + void InitScreen(TInt16 x = 20, TInt16 y = 30) ; + TBool NextState(); + TBool TypewriterState(); + +protected: + TInt mState; + TAttractData mData; + GVectorSprite *mSprite; +}; + + +#endif //EVADE2_GATTRACTPROCESS_H diff --git a/Evade2/src/AttractState/GAttractState.cpp b/Evade2/src/AttractState/GAttractState.cpp new file mode 100644 index 0000000..7a65e72 --- /dev/null +++ b/Evade2/src/AttractState/GAttractState.cpp @@ -0,0 +1,23 @@ +// +// Created by Michael Schwartz on 11/4/20. +// + +#include "Game.h" +#include "GAttractState.h" +#include "GGame.h" +#include "GEnemyProcess.h" +#include "GAttractProcess.h" +#include "GStarfield.h" +#include "GCamera.h" + +GAttractState::GAttractState() : BGameEngine(gViewPort) { + gGameEngine = this; + mPlayfield = new GStarfield(); + AddProcess(new GAttractProcess()); + gCamera->vx = gCamera->vy = 0; + gCamera->vz = 2; +} + +GAttractState::~GAttractState() noexcept { +} + diff --git a/Evade2/src/AttractState/GAttractState.h b/Evade2/src/AttractState/GAttractState.h new file mode 100644 index 0000000..b8f7923 --- /dev/null +++ b/Evade2/src/AttractState/GAttractState.h @@ -0,0 +1,18 @@ +// +// Created by Michael Schwartz on 11/4/20. +// + +#ifndef EVADE2_GATTRACTSTATE_H +#define EVADE2_GATTRACTSTATE_H + +#include "Game.h" + +class GAttractState : public BGameEngine { +public: + GAttractState(); + + ~GAttractState() OVERRIDE; +}; + + +#endif //EVADE2_GATTRACTSTATE_H diff --git a/Evade2/src/Font.cpp b/Evade2/src/Font.cpp deleted file mode 100644 index 3bd1fdf..0000000 --- a/Evade2/src/Font.cpp +++ /dev/null @@ -1,421 +0,0 @@ -#define DEBUGME - -/** - * Some of this code lifted from Arduino serial Print class and modified. - * See: - * https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/Print.cpp - */ - -#include "Font.h" -#include "charset.h" - -#include -#include - -#ifdef MIKE_REMOVED_THHIS -static TInt8 *pgm_read_TInt16(const void *addr) { - const TUint16 *p = (const TUint16 *)addr; - return (TInt8 *)*p; -} -#endif - -static const TInt8 *charset[] = { - ENull, // space - font_emark, -#ifdef FULL_CHARSET - font_dquote, -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_pound, // # -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_dollar, // $ -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_percent, // % -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_amp, // & -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_squote, // ' -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_lparen, // ( -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_rparen, // ) -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_asterisk, // * -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_plus, -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_comma, -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_minus, -#else - ENull, -#endif - font_period, font_fslash, font_0, font_1, font_2, font_3, font_4, - font_5, font_6, font_7, font_8, font_9, font_colon, -#ifdef FULL_CHARSET - font_semicolon, -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_lt, // < -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_eq, // = -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_gt, // > -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_qmark, -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_at, // @ -#else - ENull, -#endif - font_a, font_b, font_c, font_d, font_e, font_f, font_g, - font_h, font_i, font_j, font_k, font_l, font_m, font_n, - font_o, font_p, font_q, font_r, font_s, font_t, font_u, - font_v, font_w, font_x, font_y, font_z, -#ifdef FULL_CHARSET - font_lt, // [ -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_bslash, // '\' -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_gt, // ] -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_caret, // ^ -#else - ENull, -#endif -#ifdef FULL_CHARSET - font_uscore, // _ -#else - ENull, -#endif - ENull, // `` -}; - -TInt16 Font::scale = 0x100; - -TInt8 Font::print_string_rotatedx(TUint8 color, TInt16 x, TInt16 y, TFloat theta, const char *p) { - theta = TFloat(theta) * 3.1415926 / 180; - TFloat cost = cos(theta), sint = sin(theta); - - TFloat fscale = TFloat(scale >> 8) + TFloat(scale & 0xff) / 256.0; - - const TInt8 size = 9; - - TInt8 xo = x; - while (char c = *p++) { - const TInt8 *glyph = charset[toupper(c) - 32]; - if (glyph) { - TInt8 lines = *glyph++; - - for (TInt8 i = 0; i < lines; i++) { - TFloat x0 = (TInt8)*glyph++ * fscale + x, - y0 = (TInt8)*glyph++ * fscale + y, - x1 = (TInt8)*glyph++ * fscale + x, - y1 = (TInt8)*glyph++ * fscale + y; - - gDisplay.renderBitmap->DrawLine(ENull,x0, ((y0 - y) * sint + cost + y), x1, - ((y1 - y) * sint + cost + y), color); - } - x += size * fscale; - } else { - x += 6 * fscale; - } - } - return x - xo; -} - -TInt8 Font::print_string_rotatedx(TInt16 x, TInt16 y, TFloat theta, const char *p) { - theta = TFloat(theta) * 3.1415926 / 180; - TFloat cost = cos(theta), sint = sin(theta); - - TFloat fscale = TFloat(scale >> 8) + TFloat(scale & 0xff) / 256.0; - - const TInt8 size = 9; - - TInt8 xo = x; - while (char c = *p++) { - const TInt8 *glyph = charset[toupper(c) - 32]; - if (glyph) { - TInt8 lines = *glyph++; - - for (TInt8 i = 0; i < lines; i++) { - TFloat x0 = (TInt8)*glyph++ * fscale + x, - y0 = (TInt8)*glyph++ * fscale + y, - x1 = (TInt8)*glyph++ * fscale + x, - y1 = (TInt8)*glyph++ * fscale + y; - - gDisplay.renderBitmap->DrawLine(ENull,x0, ((y0 - y) * sint + cost + y), x1, - ((y1 - y) * sint + cost + y), SHMOO_COLOR); - } - x += size * fscale; - } else { - x += 6 * fscale; - } - } - return x - xo; -} - -TInt8 Font::write(TUint8 color, TInt16 x, TInt16 y, char c) { - const TInt8 *glyph; - const TInt8 width = 9; - - TFloat fscale = TFloat(scale >> 8) + TFloat(scale & 0xff) / 256.0; - - glyph = charset[toupper(c) - 32]; - // ::printf("write %x\n", palette[COLOR_RED]); - // ::printf("c %c glyph %lx charset %lx\n", c, (long)glyph, (long)charset); - if (glyph) { - TInt8 lines = *glyph++; - - for (TInt8 i = 0; i < lines; i++) { - TInt16 x0 = *glyph++, y0 = *glyph++, x1 = *glyph++, y1 = *glyph++; - - gDisplay.renderBitmap->DrawLine( - ENull, - x + x0 * fscale, - y + y0 * fscale, - x + x1 * fscale, - y + y1 * fscale, - color - ); - } - } - return width * fscale; -} - -TInt8 Font::write(TInt16 x, TInt16 y, char c) { return write(SHMOO_COLOR, x, y, c); } - -TInt8 Font::print_string(TUint8 color, TInt16 x, TInt16 y, char *s) { - TInt8 xx = x; - while (char c = *s++) { - TInt8 width = Font::write(x, y, c); - x += width; - } - return x - xx; // width of string printed -} - -TInt8 Font::print_long(TUint8 color, TInt16 x, TInt16 y, TInt32 n, TInt8 base) { - // TODO: Fix me -- - char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. - char *str = &buf[sizeof(buf) - 1]; - - *str = '\0'; - - // prevent crash if called with base == 1 - if (base < 2) - base = 10; - - do { - char c = n % base; - n /= base; - - *--str = c < 10 ? c + '0' : c + 'A' - 10; - } while (n); - - return print_string(color, x, y, str); -} - -#ifdef PRINTF_TFloat -TInt8 Font::print_float(TUint8 color, TInt16 x, TInt16 y, double number, - TInt8 digits) { - // TODO: Fix me -- - return 1; - TInt8 xx = x; - if (isnan(number)) { - x += write(x, y, 'n'); - x += write(x, y, 'a'); - x += write(x, y, 'n'); - return x; - } - if (isinf(number)) { - x += write(x, y, 'i'); - x += write(x, y, 'n'); - x += write(x, y, 'f'); - return x; - } - if (number > 4294967040.0 || number < -4294967040.0) { - x += write(x, y, 'o'); - x += write(x, y, 'v'); - x += write(x, y, 'f'); - return x; - } - - // Handle negative numbers - if (number < 0.0) { - x += write(x, y, '-'); - number = -number; - } - - // Round correctly so that print(1.999, 2) prints as "2.00" - double rounding = 0.5; - for (uint8_t i = 0; i < digits; ++i) - rounding /= 10.0; - - number += rounding; - - // Extract the integer part of the number and print it - unsigned long int_part = (unsigned long)number; - double remainder = number - (double)int_part; - x += print_long(color, x, y, int_part, 10); - - // Print the decimal point, but only if there are digits beyond - if (digits > 0) { - x += write(x, y, '.'); - } - - // Extract digits from the remainder one at a time - while (digits-- > 0) { - remainder *= 10.0; - unsigned int toPrint = (unsigned int)(remainder); - x += print_long(color, x, y, toPrint, 10); - remainder -= toPrint; - } - - return x - xx; -} -#endif - -TInt8 Font::printf(TUint8 color, TInt16 x, TInt16 y, const char *ifsh, ...) { - va_list ap; - TInt8 xx = x; - char c; - const char * p = reinterpret_cast(ifsh); - va_start(ap, ifsh); - - while ((c = *p++)) { - if (c == '%') { - c = *p++; - switch (c) { - case '\0': - va_end(ap); - return x - xx; -#ifdef PRINTF_TFloat - case '%': - x += Font::write(color, x, y, '%'); - break; - case 'f': - x += print_float(color, x, y, va_arg(ap, double)); - break; -#endif - case 'd': - x += print_long(color, x, y, (long)va_arg(ap, int)); - break; -#ifdef PRINTF_TFloat - case 'x': - x += print_long(color, x, y, (long)va_arg(ap, int) & 0xffff, 16); - break; - case 'l': - x += print_long(color, x, y, va_arg(ap, long)); - break; -#endif - default: - x += Font::write(color, x, y, c); - break; - } - } else { - x += Font::write(color, x, y, c); - } - } - va_end(ap); - return xx - x; -} - -TInt8 Font::printf(TInt16 x, TInt16 y, const char *ifsh, ...) { - va_list ap; - TInt8 xx = x; - char c; - const char * p = reinterpret_cast(ifsh); - va_start(ap, ifsh); - - while ((c = *p++)) { - if (c == '%') { - c = *p++; - switch (c) { - case '\0': - va_end(ap); - return x - xx; -#ifdef PRINTF_TFloat - case '%': - x += Font::write(SHMOO_COLOR, x, y, '%'); - break; - case 'f': - x += print_float(SHMOO_COLOR, x, y, va_arg(ap, double)); - break; -#endif - case 'd': - x += print_long(SHMOO_COLOR, x, y, (TInt32)va_arg(ap, TInt)); - break; -#ifdef PRINTF_TFloat - case 'x': - x += print_long(SHMOO_COLOR, x, y, (long)va_arg(ap, int) & 0xffff, 16); - break; - case 'l': - x += print_long(SHMOO_COLOR, x, y, va_arg(ap, long)); - break; -#endif - default: - x += Font::write(SHMOO_COLOR, x, y, c); - break; - } - } else { - x += Font::write(SHMOO_COLOR, x, y, c); - } - } - va_end(ap); - return xx - x; -} diff --git a/Evade2/src/Font.h b/Evade2/src/Font.h deleted file mode 100644 index 799c198..0000000 --- a/Evade2/src/Font.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef FONT_H -#define FONT_H - -#include "Game.h" - -// this doesn't seem right, but it will probably work -// as in, Font::fprint(fmt, args...) - -class Font { - public: - static TInt16 scale; // 8.8 fixed point - - public: - // these routine return the width of whatever is printed to the screen - static TInt8 write(TUint8 color, TInt16 x, TInt16 y, char c); - static TInt8 write(TInt16 x, TInt16 y, char c); - static TInt8 printf(TInt16 x, TInt16 y, const char* ifsh, ...); - static TInt8 printf(TUint8 color, TInt16 x, TInt16 y, const char* ifsh, ...); - -#ifdef ENABLE_ROTATING_TEXT - static TInt8 print_string_rotatedx(TUint8 color, TInt16 x, TInt16 y, TFloat angle, const char* ifsh); - static TInt8 print_string_rotatedx(TInt16 x, TInt16 y, TFloat angle, const char* ifsh); -#endif - static TInt8 print_string(TUint8 color, TInt16 x, TInt16 y, char* s); - static TInt8 print_long(TUint8 color, TInt16 x, TInt16 y, TInt32 n, TInt8 base = 10); - -#ifdef PRINTF_TFloat - static TInt8 print_float(TUint8 color, TInt16 x, TInt16 y, double number, TInt8 digits = 2); -#endif -}; - -#endif diff --git a/Evade2/src/GCamera.cpp b/Evade2/src/GCamera.cpp deleted file mode 100644 index e01328b..0000000 --- a/Evade2/src/GCamera.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "GCamera.h" -// -// -// - - -TFloat GCamera::mX = 0; -TFloat GCamera::mY = 0; -TFloat GCamera::mZ = 0; - -TFloat GCamera::mVX = 0; -TFloat GCamera::mVY = 0; -TFloat GCamera::mVZ = CAMERA_VZ; - -// -//Camera::Camera() { -// mX = mY = mZ = 0; -// mVX = mVY = mVZ = 0; -//} -// -//public: -// static TFloat mX, mY, mZ; -// static TFloat mVX, mVY, mVZ; -// -// static void Move() { -// mX += mVX; -// mY += mVY; -// mZ += mVZ; -// } -// -//}; - -//extern Camera *gCamera; - -//TFloat Camera::mX = 0; -//TFloat Camera::mY = 0; -//TFloat Camera::mZ = 0; -// -//TFloat Camera::mVX = 0; -//TFloat Camera::mVY = 0; -//TFloat Camera::mVZ = 0; -// -// -//void Camera::Move() { -// Camera::mX += Camera::mVX; -// Camera::mY += Camera::mVY; -// Camera::mZ += Camera::mVZ; -//} -//// -//TBool Camera::CollidesWith(GVectorSprite *aVSprite) { -// // If enemy bullet collides with player -// if (abs(aVSprite->mZ - Camera::mZ) < abs(aVSprite->mVZ) && abs(aVSprite->mX - Camera::mX) < 64 && abs(aVSprite->mY - Camera::mY) < 64) { -// return ETrue; -// } -// return EFalse; -//} -// -//extern Camera *gCamera; diff --git a/Evade2/src/GCamera.h b/Evade2/src/GCamera.h deleted file mode 100644 index a9a8565..0000000 --- a/Evade2/src/GCamera.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef GCAMERA_H -#define GCAMERA_H - -#include "Game.h" -#include - -class GCamera { -public: - static TFloat mX, mY, mZ; - static TFloat mVX, mVY, mVZ; - -public: - static void Move() { - GCamera::mX += GCamera::mVX; - GCamera::mY += GCamera::mVY; - GCamera::mZ += GCamera::mVZ; - } - - static TBool CollidesWith(GVectorSprite *aVSprite) { - // If enemy bullet collides with player - if (abs(aVSprite->mZ - GCamera::mZ) < abs(aVSprite->mVZ) && abs(aVSprite->mX - GCamera::mX) < 64 && abs(aVSprite->mY - GCamera::mY) < 64) { - return ETrue; - } - return EFalse; - } -}; - - - -#endif diff --git a/Evade2/src/GGame.cpp b/Evade2/src/GGame.cpp index 4f27f0c..40e1aea 100644 --- a/Evade2/src/GGame.cpp +++ b/Evade2/src/GGame.cpp @@ -1,16 +1,17 @@ #include "Game.h" #include "GGame.h" //#include "GPlayer.h" -#include "GCamera.h" +#include "common/GCamera.h" #include "GResources.h" + +// states #include "./GameState/GGameState.h" +#include "./SplashState/GSplashState.h" +#include "./MainMenuState/GMainMenuState.h" +#include "./AttractState/GAttractState.h" static TUint32 start; -BFont *gFont8x8, *gFont16x16; - -BViewPort gFullViewPort; - #ifdef DEBUG_MODE //TBool GGame::mDebug = ETrue; TBool GGame::mDebug = EFalse; @@ -23,63 +24,14 @@ TBool GGame::mDebug = EFalse; *******************************************************************************/ GGame::GGame() { + gGame = this; printf("Construct GGame\n"); - gGameEngine = new GGameState(); -#if 0 - mLocalData = ENull; - mLocalDataSize = 0; - - gFullViewPort.SetRect(TRect (0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1)); - - // Load Game Options -#ifdef ENABLE_OPTIONS - gOptions = new TOptions(); -#endif - -#ifdef ENABLE_AUDIO - gSoundPlayer.Init(6 /*channels*/); -#endif - - gDisplay.SetColor(COLOR_WHITE, 255, 255, 255); - gDisplay.SetColor(ASSAULT_COLOR, 255, 50, 50); - gDisplay.SetColor(BOMBER_COLOR, 50, 255, 50); - gDisplay.SetColor(SCOUT_COLOR, 255, 50, 255); - Camera::mZ = CAMERA_VZ; - -// const TUint8 BULLET_COLOR = 217; -// const TUint8 EBULLET_COLOR = 218; -// const TUint8 BOSS_COLOR = 219; -// const TUint8 SCOUT_COLOR = 222; -// const TUint8 STAR_COLOR = 223; - // preload bitmaps - // MAX_BITMAP is defined in GResource.h. - // for (TInt16 slot = 0; slot <= MAX_BBITMAP; slot++) { - // gResourceManager.PreloadBitmap(slot); - // } - - gResourceManager.LoadBitmap(CHARSET_8X8_BMP, FONT_8x8_SLOT, IMAGE_8x8); - gResourceManager.CacheBitmapSlot(FONT_8x8_SLOT); - gFont8x8 = new BFont(gResourceManager.GetBitmap(FONT_8x8_SLOT), FONT_8x8); - gResourceManager.LoadBitmap(CHARSET_16X16_BMP, FONT_16x16_SLOT, IMAGE_16x16); - gResourceManager.CacheBitmapSlot(FONT_16x16_SLOT); - gFont16x16 = new BFont(gResourceManager.GetBitmap(FONT_16x16_SLOT), FONT_16x16); - - gViewPort = new BViewPort(); - gViewPort->SetRect(TRect(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1)); - gViewPort->Offset(0, 0); - - mState = mNextState = -1; + gVectorFont = new GVectorFont(); + mDifficulty = 1; gGameEngine = ENull; - mGameMenu = ENull; - mDebugMenu = ENull; - mInventory = ENull; -// SetState(GAME_STATE_SPLASH); <-- DEFAULT - SetState(GAME_STATE_MAIN_MENU); // <--- For debugging - start = Milliseconds(); - mShmoo.Set(0, 0, 0); - - mStarField = new GStarFieldProcess(); -#endif + mState = 0; + SetState(GAME_STATE_SPLASH); +// SetState(GAME_STATE_GAME); } GGame::~GGame() { @@ -95,126 +47,72 @@ GGame::~GGame() { ******************************************************************************* *******************************************************************************/ -BGameEngine *GGame::CurrentState() { -#if 0 - if (gGameEngine->IsPaused()) { - if (mGameMenu) return mGameMenu; - else if (mInventory) return mInventory; - else if (mDebugMenu) return mDebugMenu; - } -#endif - return gGameEngine; -} - -#if 0 -void GGame::ToggleInGameMenu() { - if (GPlayer::mGameOver || mDebugMenu || mInventory) { - return; - } - if (mGameMenu) { - delete mGameMenu; - mGameMenu = ENull; - gGameEngine->Resume(); - } - else { - mGameMenu = new GGameMenuState((GGameState *)gGameEngine); - gGameEngine->Pause(); - } - gControls.dKeys = 0; -} - -#endif - -#if 0 -void GGame::ToggleDebugMenu() { - if (GPlayer::mGameOver || mGameMenu || mInventory) { - return; - } - if (mDebugMenu) { - delete mDebugMenu; - mDebugMenu = ENull; - gGameEngine->Resume(); - } - else { - mDebugMenu = new GDebugMenuState(); - gGameEngine->Pause(); - } - gControls.dKeys = 0; -} -#endif +//BGameEngine *GGame::CurrentState() { +// return gGameEngine; +//} -/******************************************************************************* - ******************************************************************************* - *******************************************************************************/ -#if 0 -void GGame::ToggleInventory() { -// if (GPlayer::mGameOver || mGameMenu) { -// return; -// } -// if (mInventory) { -// delete mInventory; -// mInventory = ENull; -// if (!mDebugMenu) { -// gGameEngine->Resume(); -// } -// } -// else { -// gGameEngine->Pause(); -// } -// gControls.dKeys = 0; +TInt GGame::GetState() const { + return mState; } -#endif - -/******************************************************************************* - ******************************************************************************* - *******************************************************************************/ -#if 0 -void GGame::SetState(TInt aNewState, TAny *aLocalData, TUint32 aSize) { - mNextState = aNewState; - if (aLocalData) { - delete (TUint8 *)mLocalData; - mLocalDataSize = aSize; - mLocalData = new TUint8[mLocalDataSize]; - memcpy((TUint8 *)mLocalData, (TUint8 *)aLocalData, mLocalDataSize); - } - else { - delete (TUint8 *)mLocalData; - mLocalData = ENull; - mLocalDataSize = 0; +void GGame::SetState(GAMESTATE aNewState) { + for (TInt i = 0; i < 256; i++) { + gDisplay.SetColor(i, 255, 255, 255); } -} -#endif -TInt GGame::GetState() { - return mState; -} + gDisplay.SetColor(COLOR_BLACK, 0, 0, 0); + gDisplay.SetColor(COLOR_WHITE, 255, 255, 255); -void GGame::StartGame(char *aGameName) { -#if 0 -#ifdef DEBUG_MODE - printf("START GAME (%s)\n", aGameName); -#endif - SetState( - mState == GAME_STATE_RESUME_GAME ? GAME_STATE_LOAD_SAVEGAME : GAME_STATE_RESUME_GAME, - aGameName, - strlen(aGameName)+1 - ); -#endif -} + gDisplay.SetColor(COLOR_STAR, 255,255,255); -TBool GGame::IsGameState() { - TBool state = mState == GAME_STATE_RESUME_GAME || - mState == GAME_STATE_GAME || - mState == GAME_STATE_LOAD_SAVEGAME; + gDisplay.SetColor(ASSAULT_COLOR, 255, 50, 50); + gDisplay.SetColor(BOMBER_COLOR, 50, 255, 50); + gDisplay.SetColor(SCOUT_COLOR, 255, 50, 255); - if (!state) { - return EFalse; + gDisplay.SetColor(EBULLET_COLOR, 50, 50, 255); + gDisplay.SetColor(BOMB_COLOR, 255, 255, 50); + + mState = aNewState; + switch (aNewState) { + case GAME_STATE_SPLASH: + printf("new State SPLASH\n"); + delete gGameEngine; + gGameEngine = new GSplashState(); + break; + case GAME_STATE_ATTRACT_MODE: + printf("new State ATTRACT\n"); + delete gGameEngine; + gGameEngine = new GAttractState(); + break; + case GAME_STATE_GAME: + printf("new State GAME\n"); + delete gGameEngine; + gGameEngine = new GGameState(); + break; + case GAME_STATE_MAIN_MENU: + printf("new State MAIN MENU\n"); + delete gGameEngine; + gGameEngine = new GMainMenuState(); + break; + case GAME_STATE_VICTORY: + printf("new State VICTORY\n"); + delete gGameEngine; + gGameEngine = new GGameState(); + break; + case GAME_STATE_CREDITS: + printf("new State CREDITS\n"); + delete gGameEngine; + gGameEngine = new GAttractState(); + break; +// case GAME_STATE_NEXT_WAVE: +// printf("new State NEXT WAVE\n"); +// break; } - return ETrue; -// GGameState *s = (GGameState *)gGameEngine; -// return !s->IsGameOver(); +}; + +TBool GGame::IsGameState() const { + return mState == GAME_STATE_GAME; } /******************************************************************************* @@ -222,15 +120,16 @@ TBool GGame::IsGameState() { *******************************************************************************/ void GGame::Run() { - printf("run\n"); TBool done = EFalse; + while (!done) { Random(); // randomize mShmoo.Set(TUint8(mShmoo.r + 16), TUint8(mShmoo.g + 16), TUint8(mShmoo.b + 16)); gDisplay.displayBitmap->SetColor(COLOR_SHMOO, mShmoo); - GCamera::Move(); + gCamera->Move(); gGameEngine->GameLoop(); gDisplay.Update(); + if (gControls.WasPressed(BUTTONQ)) { done = ETrue; } diff --git a/Evade2/src/GGame.h b/Evade2/src/GGame.h index 6031993..26f9abb 100644 --- a/Evade2/src/GGame.h +++ b/Evade2/src/GGame.h @@ -6,20 +6,15 @@ //#include "GStarFieldProcess.h" class BGameEngine; + class BFont; -enum { +enum GAMESTATE { GAME_STATE_SPLASH, GAME_STATE_MAIN_MENU, - GAME_STATE_LOAD_GAME, - GAME_STATE_MAIN_OPTIONS, - GAME_STATE_RESET_OPTIONS, GAME_STATE_ATTRACT_MODE, - GAME_STATE_RESET_GAME, GAME_STATE_GAME, - GAME_STATE_RESUME_GAME, - GAME_STATE_LOAD_SAVEGAME, - GAME_STATE_QUIT, +// GAME_STATE_NEXT_WAVE, GAME_STATE_VICTORY, GAME_STATE_CREDITS, }; @@ -34,35 +29,21 @@ class GGame : public BApplication { void Run(); public: -// void SetState(TInt aNewState, TAny *aLocalData = ENull, TUint32 aSize = 0); - void StartGame(char *aGameName); + void SetState(GAMESTATE aNewStae); - TInt GetState(); + TInt GetState() const; -// void ToggleInGameMenu(); -// void ToggleInventory(); -// void ToggleDebugMenu(); - TBool IsGameState(); - BGameEngine *CurrentState(); - TUint16 mWave; + TBool IsGameState() const; + TUint8 mDifficulty; static TBool mDebug; -protected: protected: TInt mState; - TInt mNextState; -// TAny *mLocalData; // arbitrary local data that is passed to SetState. -// TUint32 mLocalDataSize; - BGameEngine *mGameMenu; -// BGameEngine *mInventory; -// BGameEngine *mDebugMenu; - TRGB mShmoo; - -// GStarFieldProcess *mStarField; + TRGB mShmoo; }; -extern GGame *gGame; +extern GGame *gGame; extern BGameEngine *gGameEngine; -extern BFont *gFont8x8, *gFont16x16; +extern BFont *gFont8x8, *gFont16x16; #endif //BRICKOUT_GGAME_H diff --git a/Evade2/src/GResources.h b/Evade2/src/GResources.h index fbe9007..cc3740a 100644 --- a/Evade2/src/GResources.h +++ b/Evade2/src/GResources.h @@ -10,6 +10,7 @@ const TUint16 EVENT_SPELL_PROCESS_EXIT = 1; enum { FONT_8x8_SLOT, FONT_16x16_SLOT, + BKG_SLOT, SLOT_MAX, }; @@ -94,9 +95,9 @@ const TUint16 IMG_DAMAGE_UP = 40; const TUint8 COLOR_BLACK = 0; const TUint8 COLOR_WHITE = 1; const TUint8 COLOR_TEXT = 2; -const TUint8 COLOR_STAR = 3; -const TUint8 COLOR_ENEMY1 = 4; -const TUint8 COLOR_SHMOO = 255; +const TUint8 COLOR_TEXT_BG = 3; +const TUint8 COLOR_STAR = 4; +const TUint8 COLOR_HUD = 5; const TUint8 COLOR_BLUE = 201; const TUint8 COLOR_GREEN = 202; @@ -113,6 +114,7 @@ const TUint8 COLOR_BRIGHT_RED = 212; const TUint8 COLOR_BRIGHT_MAGENTA = 213; const TUint8 COLOR_YELLOW = 214; const TUint8 COLOR_SPACE = 215; +const TUint8 COLOR_SHMOO = 255; @@ -122,11 +124,12 @@ const TUint8 COLOR_SPACE = 215; const TUint8 SHMOO_COLOR = 216; const TUint8 BULLET_COLOR = 217; const TUint8 EBULLET_COLOR = 218; -const TUint8 BOSS_COLOR = 219; -const TUint8 ASSAULT_COLOR = 220; -const TUint8 BOMBER_COLOR = 221; -const TUint8 SCOUT_COLOR = 222; -const TUint8 STAR_COLOR = 223; +const TUint8 BOMB_COLOR = 219; +const TUint8 BOSS_COLOR = 220; +const TUint8 ASSAULT_COLOR = 221; +const TUint8 BOMBER_COLOR = 222; +const TUint8 SCOUT_COLOR = 223; +const TUint8 STAR_COLOR = 224; #define MAX_BBITMAP 5 diff --git a/Evade2/src/Game.h b/Evade2/src/Game.h index 3fb09f5..00c643c 100644 --- a/Evade2/src/Game.h +++ b/Evade2/src/Game.h @@ -1,19 +1,31 @@ #ifndef MODITE_GAME_H #define MODITE_GAME_H +#include + #define WIDTH 640 #define HEIGHT 400 -#define SCREEN_WIDTH 320 -#define SCREEN_HEIGHT 200 -#define SCREEN_DEPTH 8 - -const float CAMERA_VZ = 4; +//#define SCREEN_WIDTH 320 +//#define SCREEN_HEIGHT 200 +//#define SCREEN_DEPTH 8 + +const TFloat CAMERA_VZ = 2; // 4; +const TFloat CAMERA_WARP_VZ = 4; +const TFloat DELTACONTROL = 6; // 11; +const TInt8 MAX_BULLETS = 6; +const TFloat BULLET_VZ = 8; // 15; +const TFloat ALERT_TOP = 30; + +// COLLISION_RADIUS = distance from player bullet to enemy required for a hit +const TFloat COLLISION_RADIUS = 64; +#define BANK_LEFT TUint32(1< @@ -47,6 +62,7 @@ const float CAMERA_VZ = 4; //const TUint16 FACTOR = FRAMES_PER_SECOND / 30; #include "GResources.h" +#include "common/GVectorFont.h" #include "GGame.h" //#include "common/GDialogWidget.h" //#include "common/GButtonWidget.h" @@ -78,10 +94,10 @@ const TUint16 CONTROL_JOYDOWN = JOYDOWN; const TUint16 CONTROL_JOYLEFT = JOYLEFT; const TUint16 CONTROL_JOYRIGHT = JOYRIGHT; const TUint16 CONTROL_FIRE = BUTTONA; -const TUint16 CONTROL_RUN = BUTTONB; -const TUint16 CONTROL_SPELL = BUTTONX; -const TUint16 CONTROL_INVENTORY = BUTTONR; -const TUint16 CONTROL_TARGET = BUTTONL; +const TUint16 CONTROL_BURST = BUTTONB; +/* const TUint16 CONTROL_SPELL = BUTTONX; */ +/* const TUint16 CONTROL_INVENTORY = BUTTONR; */ +/* const TUint16 CONTROL_TARGET = BUTTONL; */ const TUint16 CONTROL_DEBUG = BUTTON_SELECT; struct EnemyConfig { @@ -97,19 +113,19 @@ struct EnemyConfig { TInt16 mVZ; }; -const TUint16 OFLAG_TYPE_MASK = 0x07; -// Object is an enemy -const TUint16 OTYPE_ENEMY = 0; -// Object is player's bullet -const TUint16 OTYPE_PLAYER_BULLET = 1; -// Object is enemy bullet -const TUint16 OTYPE_ENEMY_BULLET = 2; -// STRING means lines is a character string to be rendered in 3D -const TUint16 OTYPE_STRING = 3; -const TUint16 OTYPE_ASTEROID = 4; -// MOON means lines is ignored and a circle is rendered, as in a moon or planet -// theta becomes radius -const TUint16 OTYPE_MOON = 5; +//const TUint16 OFLAG_TYPE_MASK = 0x07; +//// Object is an enemy +//const TUint16 OTYPE_ENEMY = 0; +//// Object is player's bullet +//const TUint16 OTYPE_PLAYER_BULLET = 1; +//// Object is enemy bullet +//const TUint16 OTYPE_ENEMY_BULLET = 2; +//// STRING means lines is a character string to be rendered in 3D +//const TUint16 OTYPE_STRING = 3; +//const TUint16 OTYPE_ASTEROID = 4; +//// MOON means lines is ignored and a circle is rendered, as in a moon or planet +//// theta becomes radius +//const TUint16 OTYPE_MOON = 5; // FLAGS // if set, the lines will explode diff --git a/Evade2/src/GameState/GBossProcess.cpp b/Evade2/src/GameState/GBossProcess.cpp new file mode 100644 index 0000000..9c1cc8d --- /dev/null +++ b/Evade2/src/GameState/GBossProcess.cpp @@ -0,0 +1,593 @@ +// +// Created by Michael Schwartz on 11/6/20. +// + +#include "GBossProcess.h" +#include "GNextWaveProcess.h" +#include "GGameState.h" +#include "GPlayerProcess.h" +#include "GEnemyBulletProcess.h" +#include "GCamera.h" + +#include "img/boss_1_img.h" +#include "img/boss_2_img.h" +#include "img/boss_3_img.h" + +static const TFloat z_dist = 256; +static const TFloat frames = 32; + +const TInt TIMER = 240; + +enum { + WARP_STATE, + EXPLODE_STATE, + ACTION_STATE, +}; + +GBossProcess::GBossProcess() : BProcess() { + mSprite = new GVectorSprite(); + mSprite->z = gCamera->z + TIMER * 30 + 512; + mSprite->x = gCamera->x; + mSprite->y = gCamera->y; + mSprite->vx = mSprite->vy = mSprite->vz = 0; + mSprite->mState = 0; + + gGameState->AddSprite(mSprite); + mTimer = TIMER; + mState = WARP_STATE; + gGameState->mState = STATE_BOSS; + + if (gGameState->mWave % 3 == 0) { + mType = 3; + mLines = boss_3_img; + mSprite->SetLines(boss_3_img); + mSprite->x = gCamera->x - 512; + mSprite->vx = 10; + mSprite->vy = Random(-3, 3); + } else if (gGameState->mWave % 2 == 0) { + mType = 2; + mLines = boss_2_img; + mSprite->SetLines(boss_2_img); + InitOrbit(); + } else { + mType = 1; + mLines = boss_1_img; + mSprite->SetLines(boss_1_img); + mSprite->x = gCamera->x + 512; + mSprite->vx = -10; + mSprite->y = gCamera->y; + } + mHitPoints = 20 + (gGame->mDifficulty * mType); +} + +GBossProcess::~GBossProcess() { + mSprite->Remove(); + delete mSprite; +} + +TBool GBossProcess::RunBefore() { + if (gGameState->mState != STATE_PLAY) { + return ETrue; + } + return ETrue; +} + +TBool GBossProcess::Hit() { + if (mSprite->flags & OFLAG_COLLISION) { + mHitPoints--; + mSprite->flags &= ~OFLAG_COLLISION; + return ETrue; + } + return EFalse; +} + +void GBossProcess::InitOrbit() { + TBool left = Random() & 1; + TFloat angle = left ? 0 : (2 * PI); + mSprite->x = cos(angle) * 256; + mSprite->z = gCamera->z + sin(angle) * 256; + mSprite->y = gCamera->y + Random(30, 90); + mSprite->vy = Random(-6 + (gGame->mDifficulty * -1), 6 + (gGame->mDifficulty)); + mSprite->vx = 0; + mSprite->vz = -50 - (gGame->mDifficulty * 2); + mSprite->mState = left ? 0 : 180; +} + +TBool GBossProcess::WarpState() { + if (mTimer-- < 0) { + mState = ACTION_STATE; + gGameState->mState = STATE_BOSS; + gCamera->vz = CAMERA_VZ; + mSprite->vz = CAMERA_VZ; + return ETrue; + } + + gVectorFont->scale = 1.5; + gCamera->vz = 30; + gVectorFont->printf(90, ALERT_TOP, "WARP TO ACE!"); + gGameState->mPlayerProcess->recharge_shield(); + gGameState->mPlayerProcess->recharge_power(); + return ETrue; +} + +TBool GBossProcess::ExplodeState() { + const TInt16 NUM_FRAMES = 58 * 2; + mSprite->flags |= OFLAG_EXPLODE; + mSprite->mState++; + +// EBullet::genocide(); // Kill all enemy bullets + // Done exploding, move forward to the next wave + if (mSprite->mState > NUM_FRAMES) { + mState = STATE_NEXT_WAVE; + gCamera->vz = CAMERA_VZ; + + gGameState->AddProcess(new GNextWaveProcess()); + return EFalse; + } else { + return ETrue; + } +} + +void GBossProcess::EngagePlayerRandomXY() { + mSprite->z = gCamera->z + z_dist - 150; + + // Debugging stuff + // Font::scale = .7 * 256; + // Font::printf(5, 5, "%f", mSprite->x - gCamera->x); + // Font::printf(5, 15, "%f", mSprite->y - gCamera->y); + + if (mSprite->mState == 1) { + mSprite->mTheta += 5. + gGame->mDifficulty; + } else { + mSprite->mTheta -= 5. + gGame->mDifficulty; + } + // Debug + // mSprite->x = gCamera->x; + // mSprite->y = gCamera->y; + + if (--mSprite->mTimer > 0) { + return; + } + + gGameState->AddProcess(new GEnemyBulletProcess(mSprite, EBULLET_BOMB)); + mSprite->mTimer = gGameState->mWave > 20 ? 10 : (40 - gGame->mDifficulty); + // Keep within bounds of the screen + if (mSprite->x - gCamera->x < -300) { + mSprite->vx = Random(3, 10 + gGame->mDifficulty); + } else if (mSprite->x - gCamera->x > 300) { + mSprite->vx = Random(-3, -10 + gGame->mDifficulty * -1); + } else { + mSprite->vx = Random(-10 + (gGame->mDifficulty * -1), 10 + gGame->mDifficulty); + } + + if (mSprite->y - gCamera->y < -300) { + mSprite->vy = Random(3, 10 + gGame->mDifficulty); + } else if (mSprite->y - gCamera->y > 300) { + mSprite->vy = Random(-3, -10 + gGame->mDifficulty * -1); + } else { + mSprite->vy = Random(-10 + (gGame->mDifficulty * -1), 10 + gGame->mDifficulty); + } +} + +void GBossProcess::RandomizeFlee() { + mSprite->y = gCamera->y + Random(-150, 150); + mSprite->vy = Random(-7, 7); + mSprite->vx = Random(-7, 7); + mSprite->z = gCamera->z - 50; + mSprite->vz = gCamera->vz + TFloat(Random(1, 7) * gGame->mDifficulty); + mSprite->mTheta = Random(-180, 180); +} + +void GBossProcess::EngagePlayerFlee() { + if (mSprite->flags & ORBIT_LEFT) { + mSprite->mState -= gGame->mDifficulty; + if (mSprite->mState < 0) { + mSprite->mState = 0; + RandomizeFlee(); + mSprite->flags &= ~ORBIT_LEFT; + } + } else { + mSprite->mState += gGame->mDifficulty; + if (mSprite->mState > 90) { + mSprite->mState = 90; + RandomizeFlee(); + mSprite->flags |= ORBIT_LEFT; + } + } + + if (--mSprite->mTimer > 0) { + return; + } + gGameState->AddProcess(new GEnemyBulletProcess(mSprite, EBULLET_BOMB)); + + mSprite->mTimer = gGameState->mWave > 20 ? 20 : (50 - gGame->mDifficulty); + // mSprite->x = gCamera->x; + // mSprite->y = gCamera->y; + mSprite->vx += Random(-7, 7); + mSprite->vy += Random(-7, 7); +} + +void GBossProcess::EngagePlayerOrbit() { + if (mSprite->flags & ORBIT_LEFT) { + mSprite->mState -= gGame->mDifficulty; + if (mSprite->mState < 0) { + mSprite->y = gCamera->y + Random(-150, 150); + // mSprite->vy = random(-7,7); + + mSprite->mState = 0; + mSprite->flags &= ~ORBIT_LEFT; + } else { + mSprite->mTheta -= 12; + } + } else { + mSprite->mState += gGame->mDifficulty; + if (mSprite->mState > 180) { + mSprite->y = gCamera->y + Random(-150, 150); + mSprite->mState = 180; + mSprite->flags |= ORBIT_LEFT; + } else { + mSprite->mTheta += 12; + } + } + + TFloat rad = RADIANS(mSprite->mState); + mSprite->x = cos(rad) * 512; + mSprite->z = gCamera->z + sin(rad) * 512; + + if (--mSprite->mTimer <= 0) { + mSprite->mTimer = gGameState->mWave > 20 ? 20 : (50 - gGame->mDifficulty); + gGameState->AddProcess(new GEnemyBulletProcess(mSprite, EBULLET_BOMB)); + } +} + +TBool GBossProcess::ActionState() { + if (Hit()) { + if (mHitPoints <= 2) { + mSprite->flags &= OFLAG_EXPLODE; + mSprite->mState = 0; + mSprite->vz = gCamera->vz - 3; + +// Sound::play_sound(SFX_BOSS_EXPLODE); + mState = EXPLODE_STATE; + return ETrue; + } + + mSprite->SetLines(ENull); + + if (mType == 1) { + // mSprite->y = Random(-5, 5); + mSprite->mState = (mSprite->mState == 1) ? 0 : 1; + } + // else if (Boss::boss_type == 2) { + // init_orbit(o, Random() & 1); + // } + // else { + // randomize_flee(o); + // } + } else { + mSprite->SetLines(mLines); + + if (mType == 1) { + EngagePlayerRandomXY(); + } else if (mType == 2) { + EngagePlayerOrbit(); + } else { + EngagePlayerFlee(); + } + } + + return ETrue; +} + + +TBool GBossProcess::RunAfter() { + switch (mState) { + case WARP_STATE: + return WarpState(); + case EXPLODE_STATE: + return ExplodeState(); + } + return ETrue; + +// if (mTimer-- < 0) { +// gGameState->mState = STATE_BOSS; +// gCamera->vz = CAMERA_VZ; +// mSprite->vz = CAMERA_VZ; +// } else { +// } +// return ETrue; +} + +#if 0 +TUint16 Boss::hit_points = 0; +UTInt8 Boss::boss_type; + +static BOOL hit(Object *o) { + if (mSprite->flags & OFLAG_COLLISION) { + Boss::hit_points--; + mSprite->flags &= ~OFLAG_COLLISION; + return TRUE; + } + return FALSE; +} + +const TInt8 *getBossLines() { + switch (Boss::boss_type) { + case 3: + return boss_3_img; + break; + case 2: + return boss_2_img; + break; + default: + return boss_1_img; + } +} + +/** +Ideas: +instead of randomizing vx, vy, you can set y to sin(theta)*64 or something like +that (edited) [18:43] and change theta over time [18:43] it'll make it a +sinusoidal pattern +*/ + +static void engage_player_random_xy(Object *o) { + mSprite->z = gCamera->z + z_dist - 150; + + // Debugging stuff + // Font::scale = .7 * 256; + // Font::printf(5, 5, "%f", mSprite->x - gCamera->x); + // Font::printf(5, 15, "%f", mSprite->y - gCamera->y); + + if (mSprite->mState == 1) { + mSprite->theta += 5 + gGame->mDifficulty; + } else { + mSprite->theta -= 5 + gGame->mDifficulty; + } + // Debug + // mSprite->x = gCamera->x; + // mSprite->y = gCamera->y; + + if (--mSprite->timer > 0) { + return; + } + gGameState->AddProcess(new GEnemyBulletProcess(mSprite, EBULLET_BOMB)); + mSprite->timer = gGame->mWave > 20 ? 10 : (40 - gGame->mDifficulty); + // Keep within bounds of the screen + if (mSprite->x - gCamera->x < -300) { + mSprite->vx = random(3, 10 + gGame->mDifficulty); + } else if (mSprite->x - gCamera->x > 300) { + mSprite->vx = random(-3, -10 + gGame->mDifficulty * -1); + } else { + mSprite->vx = random(-10 + (gGame->mDifficulty * -1), 10 + gGame->mDifficulty); + } + + if (mSprite->y - gCamera->y < -300) { + mSprite->vy = random(3, 10 + gGame->mDifficulty); + } else if (mSprite->y - gCamera->y > 300) { + mSprite->vy = random(-3, -10 + gGame->mDifficulty * -1); + } else { + mSprite->vy = random(-10 + (gGame->mDifficulty * -1), 10 + gGame->mDifficulty); + } +} + +static void randomize_flee(Object *o) { + mSprite->y = gCamera->y + random(-150, 150); + mSprite->vy = random(-7, 7); + mSprite->vx = random(-7, 7); + mSprite->z = gCamera->z - 50; + mSprite->vz = gCamera->vz + (random(1, 7) * gGame->mDifficulty); + mSprite->theta = random(-180, 180); +} + +static void engage_player_flee(Object *o) { + + if (mSprite->flags & ORBIT_LEFT) { + mSprite->mState -= gGame->mDifficulty; + if (mSprite->mState < 0) { + mSprite->mState = 0; + randomize_flee(o); + mSprite->flags &= ~ORBIT_LEFT; + } + } else { + mSprite->mState += gGame->mDifficulty; + if (mSprite->mState > 90) { + mSprite->mState = 90; + randomize_flee(o); + mSprite->flags |= ORBIT_LEFT; + } + } + + if (--mSprite->timer > 0) { + return; + } + gGameState->AddProcess(new GEnemyBulletProcess(mSprite, EBULLET_BOMB)); + + mSprite->timer = gGame->mWave > 20 ? 20 : (50 - gGame->mDifficulty); + // mSprite->x = gCamera->x; + // mSprite->y = gCamera->y; + mSprite->vx += random(-7, 7); + mSprite->vy += random(-7, 7); +} + +// Copy of init_assault +static void init_orbit(Object *o, BOOL left) { + TFloat angle = left ? 0 : (2 * PI); + mSprite->x = cos(angle) * 256; + mSprite->z = gCamera->z + sin(angle) * 256; + mSprite->y = gCamera->y + random(30, 90); + mSprite->vy = random(-6 + (gGame->mDifficulty * -1), 6 + (gGame->mDifficulty)); + mSprite->vx = 0; + mSprite->vz = -50 - (gGame->mDifficulty * 2); + mSprite->mState = left ? 0 : 180; +} + +static void engage_player_orbit(Object *o) { + + if (mSprite->flags & ORBIT_LEFT) { + mSprite->mState -= gGame->mDifficulty; + if (mSprite->mState < 0) { + mSprite->y = gCamera->y + random(-150, 150); + // mSprite->vy = random(-7,7); + + mSprite->mState = 0; + mSprite->flags &= ~ORBIT_LEFT; + } else { + mSprite->theta -= 12; + } + } else { + mSprite->mState += gGame->mDifficulty; + if (mSprite->mState > 180) { + mSprite->y = gCamera->y + random(-150, 150); + mSprite->mState = 180; + mSprite->flags |= ORBIT_LEFT; + } else { + mSprite->theta += 12; + } + } + + TFloat rad = RADIANS(mSprite->mState); + mSprite->x = cos(rad) * 512; + mSprite->z = gCamera->z + sin(rad) * 512; + + if (--mSprite->timer <= 0) { + mSprite->timer = gGame->mWave > 20 ? 20 : (50 - gGame->mDifficulty); + gGameState->AddProcess(new GEnemyBulletProcess(mSprite, EBULLET_BOMB)); + } +} + +/** + * Boss is exploding state. + */ +void Boss::explode(Process *me, Object *o) { + const WORD NUM_FRAMES = 58; + mSprite->flags |= OFLAG_EXPLODE; + mSprite->mState++; + EBullet::genocide(); // Kill all enemy bullets + // Done exploding, move forward to the next wave + if (mSprite->mState > NUM_FRAMES) { + game_mode = MODE_NEXT_WAVE; + Game::kills = 65; + gCamera->vz = CAMERA_VZ; + Sound::play_score(NEXT_WAVE_SONG); + + ProcessManager::birth(Game::next_wave); + me->suicide(); + } else { + me->sleep(1, explode); + } +} + +void Boss::action(Process *me, Object *o) { + if (hit(o)) { + if (Boss::hit_points <= 2) { + + mSprite->flags &= OFLAG_EXPLODE; + mSprite->mState = 0; + mSprite->vz = gCamera->vz - 3; + + Sound::play_sound(SFX_BOSS_EXPLODE); + me->sleep(1, explode); + return; + } + + mSprite->lines = NULL; + + if (Boss::boss_type == 1) { + // mSprite->y = random(-5, 5); + mSprite->mState = (mSprite->mState == 1) ? 0 : 1; + } + // else if (Boss::boss_type == 2) { + // init_orbit(o, random() & 1); + // } + // else { + // randomize_flee(o); + // } + } else { + mSprite->lines = getBossLines(); + + if (Boss::boss_type == 1) { + engage_player_random_xy(o); + } else if (Boss::boss_type == 2) { + engage_player_orbit(o); + } else { + engage_player_flee(o); + } + } + + me->sleep(1); +} + +void Boss::start_action(Process *me, Object *o) { + + if (Boss::boss_type == 2) { + if (--mSprite->timer > 0) { + game_mode = MODE_GAME; + me->sleep(1, action); + } else { + me->sleep(1); + } + } else { + mSprite->y = gCamera->y; + mSprite->z = gCamera->z + z_dist; + if (Boss::boss_type == 1) { + mSprite->z = gCamera->z + z_dist - 150; + if (mSprite->x <= gCamera->x) { + game_mode = MODE_GAME; + me->sleep(1, action); + } else { + me->sleep(1); + } + } else { + if (mSprite->x > gCamera->x) { + game_mode = MODE_GAME; + me->sleep(1, action); + } else { + me->sleep(1); + } + } + } +} + +void Boss::entry(Process *me, Object *o) { + // production + game_mode = MODE_NEXT_WAVE; + Game::kills = 0; + gCamera->vz = -10; + + mSprite->set_type(OTYPE_ENEMY); + mSprite->z = gCamera->z + z_dist - 150; + + mSprite->mState = 0; + mSprite->vz = gCamera->vz; + mSprite->color = BOSS_COLOR; + + if (gGame->mWave % 3 == 0) { + Boss::boss_type = 3; + mSprite->x = gCamera->x - 512; + mSprite->vx = +10; + mSprite->vy = random(-3, 3); + Sound::play_score(STAGE_3_BOSS_SONG); + } else if (gGame->mWave % 2 == 0) { + Boss::boss_type = 2; + init_orbit(o, random() & 1); + Sound::play_score(STAGE_2_BOSS_SONG); + } else { + Boss::boss_type = 1; + mSprite->x = gCamera->x + 512; + mSprite->vx = -10; + mSprite->y = gCamera->y; + Sound::play_score(STAGE_1_BOSS_SONG); + } + + mSprite->lines = getBossLines(); + + // PRODUCTION + Boss::hit_points = 20 + (gGame->mDifficulty * Boss::boss_type); + // DEV/TEST + // Boss::hit_points = 1; + me->sleep(1, Boss::start_action); +} + + +#endif \ No newline at end of file diff --git a/Evade2/src/GameState/GBossProcess.h b/Evade2/src/GameState/GBossProcess.h new file mode 100644 index 0000000..27c5361 --- /dev/null +++ b/Evade2/src/GameState/GBossProcess.h @@ -0,0 +1,43 @@ +// +// Created by Michael Schwartz on 11/6/20. +// + +#ifndef EVADE2_GBOSSPROCESS_H +#define EVADE2_GBOSSPROCESS_H + +#include "Game.h" +#include "GVectorSprite.h" + +class GBossProcess : public BProcess { +public: + GBossProcess(); + + ~GBossProcess() OVERRIDE; + +public: + TBool RunBefore() OVERRIDE; + + TBool RunAfter() OVERRIDE; + +protected: + void InitOrbit(); + TBool Hit(); + void EngagePlayerRandomXY(); + void EngagePlayerOrbit(); + void RandomizeFlee(); + void EngagePlayerFlee(); +protected: + TBool WarpState(); + TBool ExplodeState(); + TBool ActionState(); + +protected: + GVectorSprite *mSprite; + const TInt8 *mLines; + TInt mTimer; + TInt mState; + TInt mType; + TInt mHitPoints; +}; + +#endif //EVADE2_GBOSSPROCESS_H diff --git a/Evade2/src/GameState/GEnemyBulletProcess.cpp b/Evade2/src/GameState/GEnemyBulletProcess.cpp new file mode 100644 index 0000000..cf90c53 --- /dev/null +++ b/Evade2/src/GameState/GEnemyBulletProcess.cpp @@ -0,0 +1,57 @@ +// +// Created by Michael Schwartz on 11/2/20. +// + +#include "GGameState.h" +#include "GEnemyBulletProcess.h" +#include "GPlayerProcess.h" +#include "GCamera.h" +#include "img/ebomb_img.h" +#include "img/ebullet_img.h" + +GEnemyBulletProcess::GEnemyBulletProcess(GVectorSprite *enemy, TInt8 type) { + const TFloat FRAMES = 90 / gGame->mDifficulty; + mSprite = new GVectorSprite(STYPE_EBULLET); + mSprite->SetLines((type == EBULLET_BOMB) ? ebomb_img : ebullet_img); + mSprite->mColor = (type == EBULLET_BOMB) ? BOMB_COLOR : EBULLET_COLOR; + mSprite->mTimer = 256; // timeout + mSprite->x = enemy->x - 8; + mSprite->y = enemy->y - 8; + mSprite->z = enemy->z; + mSprite->vx = (gCamera->x - mSprite->x) / FRAMES; + mSprite->vy = (gCamera->y - mSprite->y) / FRAMES; + mSprite->vz = gCamera->vz - (mSprite->z - gCamera->z) / FRAMES; +// printf("Bullet vx,vy,vz = %f,%f,%f mState(%d)\n", mSprite->vx, mSprite->vy, mSprite->vz, mSprite->mTimer); + gGameEngine->AddSprite(mSprite); +} + +GEnemyBulletProcess::~GEnemyBulletProcess() noexcept { + mSprite->Remove(); + delete mSprite; + mSprite = ENull; +} + +TBool GEnemyBulletProcess::RunBefore() { + if (gGameState->mState != STATE_PLAY) { + return EFalse; + } + mSprite->mTheta += (mSprite->GetLines() == ebomb_img) ? mSprite->x : 40; + return ETrue; +} + +TBool GEnemyBulletProcess::RunAfter() { + if (gCamera->CollidesWith(mSprite)) { + if (gGame->IsGameState()) { + gGameState->mPlayerProcess->Hit(10); + return EFalse; + } + } + + if (mSprite->BehindCamera()) { + return EFalse; + } + if (--mSprite->mTimer <= 0) { + return EFalse; + } + return ETrue; +} \ No newline at end of file diff --git a/Evade2/src/GameState/GEnemyBulletProcess.h b/Evade2/src/GameState/GEnemyBulletProcess.h new file mode 100644 index 0000000..29851db --- /dev/null +++ b/Evade2/src/GameState/GEnemyBulletProcess.h @@ -0,0 +1,30 @@ +// +// Created by Michael Schwartz on 11/2/20. +// + +#ifndef EVADE2_GENEMYBULLETPROCESS_H +#define EVADE2_GENEMYBULLETPROCESS_H + +#include "Game.h" +#include "GVectorSprite.h" + +#define EBULLET_BULLET 1 +#define EBULLET_BOMB 2 + +class GEnemyBulletProcess : public BProcess { +public: + GEnemyBulletProcess(GVectorSprite *enemy, TInt8 type); + + ~GEnemyBulletProcess(); + +public: + TBool RunBefore(); + + TBool RunAfter(); + +protected: + GVectorSprite *mSprite; +}; + + +#endif //EVADE2_GENEMYBULLETPROCESS_H diff --git a/Evade2/src/GameState/GEnemyProcess.cpp b/Evade2/src/GameState/GEnemyProcess.cpp new file mode 100644 index 0000000..d326e4d --- /dev/null +++ b/Evade2/src/GameState/GEnemyProcess.cpp @@ -0,0 +1,314 @@ +// +// Created by Michael Schwartz on 11/2/20. +// + +#include "GGame.h" +#include "GGameState.h" +#include "GEnemyProcess.h" +#include "GEnemyBulletProcess.h" +#include "GCamera.h" +#include "img/enemy_assault_1_img.h" +#include "img/enemy_heavy_bomber_1_img.h" +#include "img/enemy_scout_1_img.h" + +#define FIRE_TIME (60 / gGame->mDifficulty + Random(1, 60 / gGame->mDifficulty)) + +const TInt8 *GEnemyProcess::Graphic(TInt aType) { + switch (aType) { + case ENEMY_ASSAULT: + return (const TInt8 *) &enemy_assault_1_img; + case ENEMY_BOMBER: + return (const TInt8 *) &enemy_heavy_bomber_1_img; + case ENEMY_SCOUT: + return (const TInt8 *) &enemy_scout_1_img; + default: + Panic("Invalid enemy type: %d\n", aType); + } + return ENull; +} + +GEnemyProcess::GEnemyProcess() { + mSprite = new GVectorSprite(STYPE_ENEMY); + gGameEngine->AddSprite(mSprite); + mState = ESTATE_WAITINIT; + respawn(); +} + +GEnemyProcess::~GEnemyProcess() noexcept { + mSprite->Remove(); + delete mSprite; + mSprite = ENull; +} + +TBool GEnemyProcess::death() { + if (mSprite->flags & OFLAG_COLLISION) { + gGameState->mKills++; + mSprite->flags &= OFLAG_EXPLODE; + mSprite->mState = 0; + return ETrue; + } + return EFalse; +} + +void GEnemyProcess::fire() { + if (gGameState->mState != STATE_PLAY) { + return; + } + mSprite->mTimer--; + if (mSprite->mTimer <= 0) { + if (gCamera->vx || gCamera->vy) { + mSprite->mTimer = 1; + return; + } + // FIRE! +// printf("Fire!!!\n"); + gGameEngine->AddProcess(new GEnemyBulletProcess(mSprite, Random(0, 5) ? EBULLET_BULLET : EBULLET_BOMB)); + mSprite->mTimer = FIRE_TIME; + } else { + // TODO: @jay why is this being decremented a second time? + mSprite->mTimer--; + } +} + +//#define DELTA_THETA 8 +#define DELTA_THETA 4 + +void GEnemyProcess::bank(TInt16 delta) { + if (mSprite->flags & BANK_LEFT) { + mSprite->mTheta -= DELTA_THETA; + if (mSprite->mTheta < -delta) { + mSprite->flags &= ~BANK_LEFT; + } + } else { + mSprite->mTheta += DELTA_THETA; + if (mSprite->mTheta > delta) { + mSprite->flags |= BANK_LEFT; + } + } +} + +void GEnemyProcess::respawn() { + mSprite->mTimer = Random(gGameState->mWave > 6 ? 30 : 30, 60) + 30; +// printf("RESPAWN %d\n", mSprite->mTimer); + + mState = ESTATE_WAITINIT; +} + +void GEnemyProcess::init_assault(TBool left) { + TFloat angle = left ? 0 : (2 * PI); + mSprite->x = cos(angle) * 256; + mSprite->z = gCamera->z + sin(angle) * 256; + mSprite->y = gCamera->y; // + 64 - random(0, 128); + mSprite->vx = mSprite->vy = mSprite->vz = 0; + mSprite->mState = 0; + mSprite->mColor = ASSAULT_COLOR; +} + +/** + * Initialize object for scout enemy + */ +void GEnemyProcess::init_scout() { + mSprite->x = gCamera->x + Random(-256, 256); + mSprite->y = gCamera->y + Random(-256, 256); + mSprite->z = gCamera->z + 1024; + mSprite->vz = CAMERA_VZ - 3; // 12; + mSprite->vx = mSprite->vy = 0; + mSprite->mTheta = Random(-50, 50); + mSprite->mColor = SCOUT_COLOR; +} + +/** + * Initialize object for bomber enemy + */ +void GEnemyProcess::init_bomber() { + mSprite->x = gCamera->x + 128 - Random(0, 127); + mSprite->y = gCamera->y + 128 - Random(0, 127); + mSprite->z = gCamera->z - 30; + mSprite->vz = CAMERA_VZ + 1 + gGameState->mWave; + mSprite->vx = mSprite->vy = 0; + mSprite->mColor = BOMBER_COLOR; +} + +void GEnemyProcess::init() { + mSprite->flags &= ~OFLAG_EXPLODE; + mSprite->flags &= ~OFLAG_COLLISION; + mSprite->mTimer = FIRE_TIME; + mSprite->mTheta = 0; + + // One enemy type enters per wave + switch (Random(0, (gGameState->mWave > 3) ? 3 : gGameState->mWave)) { + case 0: + mSprite->SetLines((const TInt8 *) &enemy_scout_1_img); + init_scout(); + mState = ESTATE_SEEK; + break; + case 1: + mSprite->SetLines((const TInt8 *) &enemy_heavy_bomber_1_img); + init_bomber(); + mState = ESTATE_EVADE; + break; + case 2: + mSprite->SetLines((const TInt8 *) &enemy_assault_1_img); + init_assault(Random() & 1); + mState = ESTATE_ORBIT; + break; + } +} + +TBool GEnemyProcess::StateSeek() { + GVectorSprite *o = mSprite; + if (o->BehindCamera()) { + respawn(); + return ETrue; + } + if (death()) { + mState = ESTATE_EXPLODE; + return ETrue; + } + // bank(o); + fire(); + o->mTheta += 8; + if (o->z - gCamera->z < Random(256, 512)) { + o->mState = -1; + mState = ESTATE_RUNAWAY; + return ETrue; + } + + return ETrue; +} + +TBool GEnemyProcess::StateEvade() { + GVectorSprite *o = mSprite; + if (o->z - gCamera->z > 512) { + o->mState = 1; + mState = ESTATE_RUNAWAY; + return ETrue; + } + if (death()) { + mState = ESTATE_EXPLODE; + return ETrue; + } + bank(15); + fire(); + return ETrue; +} + +TBool GEnemyProcess::StateOrbit() { + GVectorSprite *o = mSprite; + if (death()) { + mState = ESTATE_EXPLODE; + return ETrue; + } + fire(); + + if (o->flags & ORBIT_LEFT) { + o->mState -= gGame->mDifficulty; + if (o->mState < 0) { + o->mState = 0; + o->flags &= ~ORBIT_LEFT; + } else { + o->mTheta -= 12; + } + } else { + o->mState += gGame->mDifficulty; + if (o->mState > 180) { + o->mState = 180; + o->flags |= ORBIT_LEFT; + } else { + o->mTheta += 12; + } + } + + TFloat rad = RADIANS(o->mState); + o->vy = (gCamera->y > o->y) ? -2 : 2; + o->y = gCamera->y; + o->x = cos(rad) * 256; + if (gGame->GetState() == GAME_STATE_GAME) { + o->z = gCamera->z + sin(rad) * 256; + } + + return ETrue; +} + +TBool GEnemyProcess::StateWaitInit() { + GVectorSprite *o = mSprite; + if (o->mTimer <= 0 && gGame->GetState() == GAME_STATE_GAME) { + init(); + return ETrue; + } else { + o->mTimer = 1; + } + o->mTimer--; + return ETrue; +} + +TBool GEnemyProcess::StateRunAway() { + GVectorSprite *o = mSprite; + if (gGame->GetState() != GAME_STATE_GAME) { + o->vz += o->mState * 8; + } else { + o->vz += o->mState; + } + o->vx += o->vx > 0 ? .1 : -.1; + o->vy += o->vy > 0 ? .1 : -.1; + if (o->BehindCamera() || (o->z - gCamera->z) > 1024) { + respawn(); + return ETrue; + } + if (death()) { + mState = ESTATE_EXPLODE; + return ETrue; + } + bank(); + fire(); + return ETrue; +} + +TBool GEnemyProcess::StateExplode() { + mSprite->flags |= OFLAG_EXPLODE; + mSprite->mState++; + if (mSprite->BehindCamera() || mSprite->mState > 50) { + if (gGameState->mState != STATE_PLAY) { + return EFalse; + } + respawn(); + } + return ETrue; +} + +TBool GEnemyProcess::RunBefore() { + if (gGameState->mState != STATE_PLAY) { + return EFalse; + } + switch (mState) { + case ESTATE_SEEK: + return StateSeek(); + case ESTATE_EVADE: + return StateEvade(); + case ESTATE_ORBIT: + return StateOrbit(); + case ESTATE_WAITINIT: + return StateWaitInit(); + case ESTATE_RUNAWAY: + return StateRunAway(); + case ESTATE_EXPLODE: + return StateExplode(); + default: + Panic("Bad Genemy State %d", mState); + } + return ETrue; +} + +TBool GEnemyProcess::RunAfter() { +// BSpriteList &l = gGameState->mSpriteList; +// for (GVectorSprite *s = (GVectorSprite *)l.Prev(mSprite); !l.End(s); s = (GVectorSprite *) l.Prev(s)) { +// if (s->type & STYPE_PBULLET) { +// printf("%f %f %f %d/%d\n", ABS(mSprite->z - s->z), ABS(mSprite->y - s->y), ABS(mSprite->x - s->x), mSprite->w, mSprite->h); +// if (ABS(mSprite->z - s->z) < BULLET_VZ && ABS(mSprite->x - s->x) < mSprite->w && ABS(mSprite->y - s->y) < mSprite->h) { +// s->flags |= OFLAG_COLLISION; +// mSprite->flags |= OFLAG_COLLISION; +// } +// } +// } + return ETrue; +} diff --git a/Evade2/src/GameState/GEnemyProcess.h b/Evade2/src/GameState/GEnemyProcess.h new file mode 100644 index 0000000..761f835 --- /dev/null +++ b/Evade2/src/GameState/GEnemyProcess.h @@ -0,0 +1,77 @@ +// +// Created by Michael Schwartz on 11/2/20. +// + +#ifndef EVADE2_GENEMYPROCESS_H +#define EVADE2_GENEMYPROCESS_H + +#include "Game.h" +#include "GVectorSprite.h" + +#define ENEMY_ASSAULT 0 +#define ENEMY_BOMBER 1 +#define ENEMY_SCOUT 2 + +enum EState { + ESTATE_SEEK, + ESTATE_EVADE, + ESTATE_ORBIT, + ESTATE_WAITINIT, + ESTATE_RUNAWAY, + ESTATE_EXPLODE, +}; + +class GEnemyProcess : public BProcess { +public: + GEnemyProcess(); + + ~GEnemyProcess() OVERRIDE; + +public: + static const TInt8 *Graphic(TInt aType); + +public: + TBool RunBefore() OVERRIDE; + + TBool RunAfter() OVERRIDE; + +private: + void init_assault(TBool left); + + void init_scout(); + + void init_bomber(); + + void init(); + + void respawn(); + + TBool death(); + + void fire(); + + void bank(TInt16 delta = 45); + +protected: + GVectorSprite *mSprite; + +protected: + TBool StateSeek(); + + TBool StateEvade(); + + TBool StateOrbit(); + + TBool StateWaitInit(); + + TBool StateRunAway(); + + TBool StateExplode(); + +protected: + EState mState; + +}; + + +#endif //EVADE2_GENEMYPROCESS_H diff --git a/Evade2/src/GameState/GGameState.cpp b/Evade2/src/GameState/GGameState.cpp index 8884bc3..4cb73ce 100644 --- a/Evade2/src/GameState/GGameState.cpp +++ b/Evade2/src/GameState/GGameState.cpp @@ -3,21 +3,39 @@ // #include "GGameState.h" -#include "GGamePlayfield.h" +#include "GStarfield.h" +#include "GPlayerProcess.h" +#include "GEnemyProcess.h" +#include "GNextWaveProcess.h" +#include "GBossProcess.h" + +GGameState *gGameState; GGameState::GGameState() : BGameEngine(gViewPort) { - mPlayfield = new GGamePlayfield(); + gGameEngine = this; + gGameState = this; + mState = STATE_PLAY; + mWave = 1; + mKills = 0; + mPlayfield = new GStarfield(); // set colors - gDisplay.SetColor(COLOR_BLACK, 0,0,0); - for (TInt i=1; i<256; i++) { - gDisplay.SetColor(i, 255,255,255); - } -// gDisplay.SetColor(COLOR_WHITE, 255,255,255); -// gDisplay.SetColor(COLOR_STAR, 255,255,255); + AddProcess(new GEnemyProcess()); + AddProcess(new GEnemyProcess()); + AddProcess(new GEnemyProcess()); + mPlayerProcess = new GPlayerProcess(); + AddProcess(mPlayerProcess); } GGameState::~GGameState() { // delete mPlayfield; } +void GGameState::PostRender() { + if (mState != STATE_PLAY) { + return; + } + if (mKills > (10 + mWave) * gGame->mDifficulty) { + AddProcess(new GBossProcess()); + } +} diff --git a/Evade2/src/GameState/GGameState.h b/Evade2/src/GameState/GGameState.h index 73b10bb..320e2ad 100644 --- a/Evade2/src/GameState/GGameState.h +++ b/Evade2/src/GameState/GGameState.h @@ -7,13 +7,31 @@ #include +enum { + STATE_PLAY, + STATE_BOSS, + STATE_NEXT_WAVE, +}; + +class GPlayerProcess; + class GGameState : public BGameEngine { public: GGameState(); - ~GGameState(); + + ~GGameState() OVERRIDE; + +public: + void PostRender() OVERRIDE; + public: -// void GameLoop() OVERRIDE; + GPlayerProcess *mPlayerProcess; + TInt32 mState; + TInt16 mKills; + TInt16 mWave; + }; +extern GGameState *gGameState; #endif //EVADE2_GGAMESTATE_H diff --git a/Evade2/src/GameState/GNextWaveProcess.cpp b/Evade2/src/GameState/GNextWaveProcess.cpp new file mode 100644 index 0000000..7f65cb4 --- /dev/null +++ b/Evade2/src/GameState/GNextWaveProcess.cpp @@ -0,0 +1,36 @@ +// +// Created by Michael Schwartz on 11/6/20. +// + +#include "GNextWaveProcess.h" +#include "GPlayerProcess.h" +#include "GGameState.h" +#include "GCamera.h" + +GNextWaveProcess::GNextWaveProcess() : BProcess() { + mTimer = 240; + gCamera->vz = 30; + gGameState->mState = STATE_NEXT_WAVE; +} + +GNextWaveProcess::~GNextWaveProcess() noexcept { + gGameState->mState = STATE_PLAY; + gGameState->mKills = 0; + gGameState->mWave++; + if (gGameState->mWave % 4 == 0) { + gGame->mDifficulty++; + } + gCamera->vz = CAMERA_VZ; +} + +TBool GNextWaveProcess::RunBefore() { + return ETrue; +} + +TBool GNextWaveProcess::RunAfter() { + gVectorFont->scale = 1.5; + gVectorFont->printf(85, ALERT_TOP, "START WAVE %d", gGameState->mWave + 1); + gGameState->mPlayerProcess->recharge_shield(); + gGameState->mPlayerProcess->recharge_power(); + return --mTimer > 0; +} \ No newline at end of file diff --git a/Evade2/src/GameState/GNextWaveProcess.h b/Evade2/src/GameState/GNextWaveProcess.h new file mode 100644 index 0000000..185a6a3 --- /dev/null +++ b/Evade2/src/GameState/GNextWaveProcess.h @@ -0,0 +1,25 @@ +// +// Created by Michael Schwartz on 11/6/20. +// + +#ifndef EVADE2_GNEXTWAVEPROCESS_H +#define EVADE2_GNEXTWAVEPROCESS_H + +#include "Game.h" + +class GNextWaveProcess : public BProcess { +public: + GNextWaveProcess(); + + ~GNextWaveProcess(); + +public: + TBool RunBefore(); + + TBool RunAfter(); +protected: + TInt mTimer; +}; + + +#endif //EVADE2_GNEXTWAVEPROCESS_H diff --git a/Evade2/src/GameState/GPlayerBulletProcess.cpp b/Evade2/src/GameState/GPlayerBulletProcess.cpp new file mode 100644 index 0000000..96dc6ad --- /dev/null +++ b/Evade2/src/GameState/GPlayerBulletProcess.cpp @@ -0,0 +1,59 @@ +// +// Created by Michael Schwartz on 11/2/20. +// + +#include "GGameState.h" +#include "GPlayerProcess.h" +#include "GPlayerBulletProcess.h" +#include "GCamera.h" + +#include "img/bullet_img.h" + +GPlayerBulletProcess::GPlayerBulletProcess(TFloat deltaX, TFloat deltaY, TBool alt) { + mSprite = new GVectorSprite(STYPE_PBULLET); + if (alt) { + mSprite->x = gCamera->x + 28; + mSprite->y = gCamera->y - 28; + mSprite->z = gCamera->z; + mSprite->mState = 20; + } else { + mSprite->x = gCamera->x - 28; + mSprite->y = gCamera->y - 28; + mSprite->z = gCamera->z; + mSprite->mState = -20; + } + mSprite->vx = deltaX; + mSprite->vy = deltaY; + mSprite->vz = gCamera->vz + BULLET_VZ; + mSprite->SetLines(bullet_img); + gGameEngine->AddSprite(mSprite); +} + +GPlayerBulletProcess::~GPlayerBulletProcess() noexcept { + gGameState->mPlayerProcess->mNumBullets--; + mSprite->Remove(); + delete mSprite; + mSprite = ENull; +} + +TBool GPlayerBulletProcess::RunBefore() { + mSprite->mTheta += mSprite->mState; + return ETrue; +} + +TBool GPlayerBulletProcess::RunAfter() { + if (mSprite->z - gCamera->z > 512) { + return EFalse; + } + BSpriteList &l = gGameState->mSpriteList; + for (auto *s = (GVectorSprite *)l.First(); !l.End(s); s = (GVectorSprite *) l.Next(s)) { + if (s->type & (STYPE_EBULLET | STYPE_ENEMY)) { + TFloat d = mSprite->DistanceTo(s); + if (d < COLLISION_RADIUS) { + s->flags |= OFLAG_COLLISION; + mSprite->flags |= OFLAG_COLLISION; + } + } + } + return ETrue; +} \ No newline at end of file diff --git a/Evade2/src/GameState/GPlayerBulletProcess.h b/Evade2/src/GameState/GPlayerBulletProcess.h new file mode 100644 index 0000000..ac11566 --- /dev/null +++ b/Evade2/src/GameState/GPlayerBulletProcess.h @@ -0,0 +1,23 @@ +// +// Created by Michael Schwartz on 11/2/20. +// + +#ifndef EVADE2_GPLAYERBULLETPROCESS_H +#define EVADE2_GPLAYERBULLETPROCESS_H + +#include "Game.h" +#include "GVectorSprite.h" + +class GPlayerBulletProcess : public BProcess { +public: + GPlayerBulletProcess(TFloat deltaX, TFloat deltaY, TBool alt); + ~GPlayerBulletProcess() OVERRIDE; +public: + TBool RunBefore() OVERRIDE; + TBool RunAfter() OVERRIDE; +protected: + GVectorSprite *mSprite; +}; + + +#endif //EVADE2_GPLAYERBULLETPROCESS_H diff --git a/Evade2/src/GameState/GPlayerProcess.cpp b/Evade2/src/GameState/GPlayerProcess.cpp new file mode 100644 index 0000000..25e6c48 --- /dev/null +++ b/Evade2/src/GameState/GPlayerProcess.cpp @@ -0,0 +1,383 @@ +#include "GPlayerProcess.h" + +#define DEBUGME +//#undef DEBUGME + +#include "Game.h" +#include "GCamera.h" +#include "GPlayerBulletProcess.h" +#include "img/hud_console_img.h" + +//TODO: Put in own files +const TUint8 crosshair_left_4x8[] = { + // width, height4, 8, + 0x81, 0x42, 0x24, 0x99 +}; + +// crosshair_right.png +// 4x8 +const TUint8 crosshair_right_4x8[] = { + // width, height 4, 8, + 0x99, 0x24, 0x42, 0x81 +}; + +#define MAX_POWER 100 +#define MAX_LIFE 100 + +GPlayerProcess::GPlayerProcess() { + color = COLOR_WHITE; + gCamera->vz = CAMERA_VZ; + power = MAX_POWER; + shield = MAX_LIFE; + mNumBullets = 0; + mAlt = EFalse; + mHit = EFalse; + printf("screen %d,%d\n", gDisplay.renderBitmap->Width(), gDisplay.renderBitmap->Height()); +} + +void GPlayerProcess::DrawPixel(TFloat x, TFloat y) const { + gDisplay.renderBitmap->WritePixel(x, y, color); +} + +void GPlayerProcess::DrawPixel(TFloat x, TFloat y, TUint8 aColor) { + gDisplay.renderBitmap->WritePixel(x, y, aColor); +} + +void GPlayerProcess::DrawLine(TFloat x1, TFloat y1, TFloat x2, TFloat y2) const { + gDisplay.renderBitmap->DrawLine(gViewPort, x1, y1, x2, y2, color); +} + +void GPlayerProcess::DrawBitmap(TInt16 x, TInt16 y, const TUint8 *bitmap, TUint8 w, TUint8 h, TUint8 aColor) const { + if (x + w < 0 || x > SCREEN_WIDTH - 1 || y + h < 0 || y > SCREEN_HEIGHT - 1) { + return; + } +#if 0 + // no need to draw at all if we're offscreen + if (x + w < 0 || x > WIDTH - 1 || y + h < 0 || y > HEIGHT - 1) + return; + + return; + int yOffset = abs(y) % 8; + int sRow = y / 8; + if (y < 0) { + sRow--; + yOffset = 8 - yOffset; + } + int rows = h / 8; + if (h % 8 != 0) + rows++; + for (int a = 0; a < rows; a++) { + int bRow = sRow + a; + if (bRow > (HEIGHT / 8) - 1) + break; + if (bRow > -2) { + for (int iCol = 0; iCol < w; iCol++) { + if (iCol + x > (WIDTH - 1)) + break; + if (iCol + x >= 0) { + const TUint8 bmp_bits = pgm_read_byte(bitmap + (a * w) + iCol); + if (bRow >= 0) { + if (color == WHITE) + sBuffer[(bRow * WIDTH) + x + iCol] |= bmp_bits << yOffset; + else if (color == BLACK) + sBuffer[(bRow * WIDTH) + x + iCol] &= ~(bmp_bits << yOffset); + else + sBuffer[(bRow * WIDTH) + x + iCol] ^= bmp_bits << yOffset; + } + if (yOffset && bRow < (HEIGHT / 8) - 1 && bRow > -2) { + if (color == WHITE) + sBuffer[((bRow + 1) * WIDTH) + x + iCol] |= bmp_bits >> (8 - yOffset); + else if (color == BLACK) + sBuffer[((bRow + 1) * WIDTH) + x + iCol] &= ~(bmp_bits >> (8 - yOffset)); + else + sBuffer[((bRow + 1) * WIDTH) + x + iCol] ^= bmp_bits >> (8 - yOffset); + } + } + } + } + } +#endif +} + +void GPlayerProcess::Hit(TInt8 amount) { + shield -= amount; + if (shield <= 0) { + // ProcessManager::birth(GameOver::entry); + } else { + mHit = ETrue; + // Sound::play_sound(SFX_PLAYER_HIT_BY_ENEMY); + } +} + +void GPlayerProcess::recharge_shield() { + if (shield < MAX_LIFE) { + shield++; + } +} + +void GPlayerProcess::recharge_power() { + if (power < MAX_POWER) { + power++; + } +} + +TBool GPlayerProcess::RunBefore() { + if (gGame->GetState() != GAME_STATE_GAME) { + // if (game_mode != MODE_GAME) { + gCamera->vx = gCamera->vy = 0; + return ETrue; + } + + if (gControls.WasPressed(CONTROL_FIRE)) { + if (mNumBullets < MAX_BULLETS) { + + TInt8 deltaX = 0, + deltaY = 0; + + deltaX = gControls.IsPressed(CONTROL_JOYRIGHT) ? -12 : deltaX; + deltaX = gControls.IsPressed(CONTROL_JOYLEFT) ? 12 : deltaX; + + deltaY = gControls.IsPressed(CONTROL_JOYUP) ? -11 : deltaY; + deltaY = gControls.IsPressed(CONTROL_JOYDOWN) ? 13 : deltaY; + + + gGameEngine->AddProcess(new GPlayerBulletProcess(deltaX, deltaY, mAlt)); + + mAlt = !mAlt; + } + } + + if (gControls.IsPressed(CONTROL_BURST)) { + if (power > 0) { + gCamera->vz = CAMERA_WARP_VZ; + power--; + if (power < 0) { + power = 0; + } + } else { + gCamera->vz = CAMERA_VZ; + } + } else { + gCamera->vz = CAMERA_VZ; + power++; + if (power > MAX_POWER) { + power = MAX_POWER; + } + } + + if (gControls.IsPressed(CONTROL_JOYRIGHT)) { + gCamera->vx = -DELTACONTROL; + } else if (gControls.IsPressed(CONTROL_JOYLEFT)) { + gCamera->vx = DELTACONTROL; + } else { + gCamera->vx = 0; + } + + if (gControls.IsPressed(CONTROL_JOYDOWN)) { + gCamera->vy = DELTACONTROL; + } else if (gControls.IsPressed(CONTROL_JOYUP)) { + gCamera->vy = -DELTACONTROL; + } else { + gCamera->vy = 0; + } + return ETrue; +} + +/************************************************************************/ +/** HUD */ +/************************************************************************/ + +void GPlayerProcess::DrawHud(TFloat x, TFloat y) { + + const TUint8 color = COLOR_WHITE; + const TFloat width = 0x30, height = 0x08; + const TUint8 *bitmap = hud_console_img; + + for (TInt xx = 0, xxx = 0; xx < width; xx++, xxx += 2) { + for (TInt yy = 0, yyy = 0; yy < height; yy++, yyy += 2) { + if (y + yy > SCREEN_HEIGHT-1) { + continue; + } + TInt8 byte = bitmap[xx + (yy / 8)]; + TInt8 bit = (yy % 8); + if (byte & (1 << bit)) { + // Graphics::drawPixel(x + xx, y + yy, color); + DrawPixel(x + xxx, y + yyy, COLOR_HUD); + DrawPixel(x + xxx + 1, y + yyy, COLOR_HUD); + DrawPixel(x + xxx, y + yyy + 1, COLOR_HUD); + DrawPixel(x + xxx + 1, y + yyy + 1, COLOR_HUD); + // Graphics::drawPixel(x + xx * 2 + 1, y + yy * 2 + 1, color); + } + } + } +} + +#ifdef ENABLE_HUD_MOVEMENTS + +// 13 == full. Anything less, and we draw "less meter" +void GPlayerProcess::DrawMeter(TInt8 side, TInt8 value, TInt8 deltaXMeter, TInt8 deltaYMeter) { + + //start at X:14 + // Draw 2 lines, skip one line, iterate 13 total times + // if left, X:0, else X:128 + // Y Step is 3 + + // TODO: Tighten up! + TInt8 y = 45; + value /= 10; + if (side == 0) { // LEFT + for (TInt8 i = 0; i < 10; i++) { + if (i >= value) { + DrawPixel(1 + deltaXMeter, y + deltaYMeter); + DrawPixel(1 + deltaXMeter, y + 1 + deltaYMeter); + } else { + DrawLine(1 + deltaXMeter, y + deltaYMeter, 3 + deltaXMeter, y + deltaYMeter); + DrawLine(1 + deltaXMeter, y + 1 + deltaYMeter, 4 + deltaXMeter, y + 1 + deltaYMeter); + } + y -= 3; + } + } else { // RIGHT + const TInt RIGHT_SIDE = SCREEN_WIDTH - 2; + for (TInt8 i = 0; i < 10; i++) { + if (i >= value) { + DrawPixel(RIGHT_SIDE + deltaXMeter, y + deltaYMeter); + DrawPixel(RIGHT_SIDE + deltaXMeter, y + 1 + deltaYMeter); + } else { + DrawLine(RIGHT_SIDE - 2 + deltaXMeter, y + deltaYMeter, RIGHT_SIDE + deltaXMeter, y + deltaYMeter); + DrawLine(RIGHT_SIDE - 3 + deltaXMeter, y + 1 + deltaYMeter, RIGHT_SIDE + deltaXMeter, y + 1 + deltaYMeter); + } + y -= 3; + } + + } +} + +#else + +// 13 == full. Anything less, and we draw "less meter" +void GPlayerProcess::DrawMeter(TInt8 side, TInt8 value) { + + //start at X:14 + // Draw 2 lines, skip one line, iterate 13 total times + // if left, X:0, else X:128 + // Y Step is 3 + + // TODO: Tighten up! + TInt8 y = 45; + value /= 10; + if (side == 0) { // LEFT + for (TInt8 i = 0; i < 10; i++) { + if (i >= value) { + DrawPixel(0, y); + DrawPixel(0, y + 1); + } else { + DrawLine(0, y, 2, y); + DrawLine(0, y + 1, 3, y + 1); + } + y -= 3; + } + } else { // RIGHT + for (TInt8 i = 0; i < 10; i++) { + if (i >= value) { + DrawPixel(SCREEN_WIDTH-1, y); + DrawPixel(SCREEN_WIDTH-1, y + 1); + } else { + DrawLine(SCREEN_WIDTH-2, y, SCREEN_WIDTH, y); + DrawLine(SCREEN_WIDTH-3, y + 1, SCREEN_WIDTH, y + 1); + } + y -= 3; + } + } +} + +#endif // #if ENABLE_HUD_MOVEMENTS + +TBool GPlayerProcess::RunAfter() { + if (mHit) { + gDisplay.SetColor(0, 255, 255, 255); + } else { + gDisplay.SetColor(0, 0, 0, 0); + } + mHit = EFalse; + +#ifdef ENABLE_HUD_MOVEMENTS + TFloat consoleX = 0, consoleY = 0, deltaXMeter = 0, deltaYMeter = 0, + deltaXCrossHairs = 0, deltaYCrossHairs = 0; + + + if (gGame->IsGameState()) { + + if (gControls.IsPressed(CONTROL_JOYRIGHT)) { + consoleX = -4; + deltaXMeter = -1; + deltaXCrossHairs = 4; + } else if (gControls.IsPressed(CONTROL_JOYLEFT)) { + consoleX = 4; + deltaXMeter = 1; + deltaXCrossHairs = -4; + } + + if (gControls.IsPressed(CONTROL_JOYUP)) { + consoleY = -4; + deltaYMeter = -1; + deltaYCrossHairs = 4; + } else if (gControls.IsPressed(CONTROL_JOYDOWN)) { + consoleY = 4; + deltaYMeter = 1; + deltaYCrossHairs = -4; + } + } + + const TFloat screenMidX = TFloat(SCREEN_WIDTH)/2, screenMidY = TFloat(SCREEN_HEIGHT)/2; + + DrawHud(screenMidX - (0x30) + consoleX, (240 + consoleY) - 12); + + /** Reticle **/ + // Top left + DrawLine(screenMidX + deltaXCrossHairs - 5, + screenMidY + deltaYCrossHairs, + screenMidX + deltaXCrossHairs - 12, + screenMidY + deltaYCrossHairs - 7); + + DrawPixel(screenMidX + deltaXCrossHairs - 5, + screenMidY + deltaYCrossHairs - 5, 255); + + // Top Right + DrawLine(screenMidX + deltaXCrossHairs + 5, + screenMidY + deltaYCrossHairs, + screenMidX + deltaXCrossHairs + 12, + screenMidY + deltaYCrossHairs - 7); + + DrawPixel(screenMidX + deltaXCrossHairs + 5, + screenMidY + deltaYCrossHairs - 5, 255); + + // Bottom Right + DrawLine(screenMidX + deltaXCrossHairs + 5, + screenMidY + deltaYCrossHairs, + screenMidX + deltaXCrossHairs + 12, + screenMidY + deltaYCrossHairs + 7); + + DrawPixel(screenMidX + deltaXCrossHairs + 5, + screenMidY + deltaYCrossHairs + 5, 255); + + // Bottom left + DrawLine(screenMidX + deltaXCrossHairs - 5, + screenMidY + deltaYCrossHairs, + screenMidX + deltaXCrossHairs - 12, + screenMidY + deltaYCrossHairs + 7); + + DrawPixel(screenMidX + deltaXCrossHairs - 5, + screenMidY + deltaYCrossHairs + 5, 255); + + DrawMeter(0, shield, deltaXMeter, deltaYMeter); + DrawMeter(1, power, deltaXMeter, deltaYMeter); + +#else + DrawBitmap(40, 58, hud_console_img, 0x30, 0x08); + + DrawMeter(0, shield); + DrawMeter(1, power); +#endif + + return ETrue; +} diff --git a/Evade2/src/GameState/GPlayerProcess.h b/Evade2/src/GameState/GPlayerProcess.h new file mode 100644 index 0000000..eb48be0 --- /dev/null +++ b/Evade2/src/GameState/GPlayerProcess.h @@ -0,0 +1,57 @@ +#ifndef EVADE2_GPLAYERPROCESS_H +#define EVADE2_GPLAYERPROCESS_H + +// player hit by enemy bullet +#define PLAYER_FLAG_HIT (1 << 0) +// which gun (left/right) to fire from +#define PLAYER_FLAG_ALT (1 << 1) + +#include "Game.h" + +class GPlayerProcess : public BProcess { +public: + GPlayerProcess(); + +public: + TInt8 power; + TInt8 shield; + TInt8 mNumBullets; +// TUint8 flags; + TUint8 color; + TBool mAlt; + TBool mHit; + +public: + void recharge_shield(); + + void recharge_power(); + + void Hit(TInt8 amount); + + void DrawPixel(TFloat x, TFloat y) const; + + void DrawPixel(TFloat x, TFloat y, TUint8 aColor); + + void DrawLine(TFloat x1, TFloat y1, TFloat x2, TFloat y2) const; + +protected: +#ifdef ENABLE_HUD_MOVEMENTS + + void DrawHud(TFloat x, TFloat y); + + void DrawMeter(TInt8 side, TInt8 value, TInt8 deltaXMeter, TInt8 deltaYMeter); + +#else + } + void DrawMeter(TInt8 side, TInt8 value); +#endif + + void DrawBitmap(TInt16 x, TInt16 y, const TUint8 *bitmap, TUint8 w, TUint8 h, TUint8 aColor = COLOR_WHITE) const; + +public: + TBool RunBefore() OVERRIDE; + + TBool RunAfter() OVERRIDE; +}; + +#endif diff --git a/Evade2/src/MainMenuState/GMainMenuProcess.cpp b/Evade2/src/MainMenuState/GMainMenuProcess.cpp new file mode 100644 index 0000000..3a70c3b --- /dev/null +++ b/Evade2/src/MainMenuState/GMainMenuProcess.cpp @@ -0,0 +1,49 @@ +// +// Created by Michael Schwartz on 11/4/20. +// + +#include "GMainMenuProcess.h" +#include "GCamera.h" + +GMainMenuProcess::GMainMenuProcess() : BProcess() { +// gCamera->vx = 0; +// gCamera->vy = 0; +// gCamera->vz = CAMERA_VZ; + mTimer = 280 * 2; + mTheta = 90; +} + +GMainMenuProcess::~GMainMenuProcess() noexcept {} + +TBool GMainMenuProcess::RunAfter() { + gVectorFont->scale = 4; + gVectorFont->color = COLOR_SHMOO; + gVectorFont->print_string_rotatedx(70, 90, mTheta, "EVADE2"); + gVectorFont->color = COLOR_WHITE; + + mTimer--; + gVectorFont->scale = 1; + if (mTimer & 32) { + gVectorFont->scale = 2; + gVectorFont->printf(130, 155, "START"); + } + + mTheta += 5; + if (mTheta > 90 + 360 * 2) { + mTheta = 90 + 360 * 2; + } + + return ETrue; +} + +TBool GMainMenuProcess::RunBefore() { + if (gControls.WasPressed(BUTTON_START)) { + gGame->SetState(GAME_STATE_GAME); + return EFalse; + } + if (mTimer < 0 || gControls.WasPressed(BUTTONA|BUTTONB)) { + gGame->SetState(GAME_STATE_ATTRACT_MODE); + return EFalse; + } + return ETrue; +} diff --git a/Evade2/src/MainMenuState/GMainMenuProcess.h b/Evade2/src/MainMenuState/GMainMenuProcess.h new file mode 100644 index 0000000..935f130 --- /dev/null +++ b/Evade2/src/MainMenuState/GMainMenuProcess.h @@ -0,0 +1,27 @@ +// +// Created by Michael Schwartz on 11/4/20. +// + +#ifndef EVADE2_GMAINMENUPROCESS_H +#define EVADE2_GMAINMENUPROCESS_H + +#include "Game.h" + +class GMainMenuProcess : public BProcess { +public: + GMainMenuProcess(); + + ~GMainMenuProcess(); + +public: + TBool RunBefore(); + + TBool RunAfter(); + +protected: + TFloat mTheta; + TInt32 mTimer; +}; + + +#endif //EVADE2_GMAINMENUPROCESS_H diff --git a/Evade2/src/MainMenuState/GMainMenuState.cpp b/Evade2/src/MainMenuState/GMainMenuState.cpp new file mode 100644 index 0000000..fc98a9d --- /dev/null +++ b/Evade2/src/MainMenuState/GMainMenuState.cpp @@ -0,0 +1,18 @@ +// +// Created by Michael Schwartz on 11/4/20. +// + +#include "GMainMenuState.h" +#include "GMainMenuProcess.h" +#include "GStarfield.h" +#include "GCamera.h" + +GMainMenuState::GMainMenuState() : BGameEngine(gViewPort) { +// gGameEngine = this; + mPlayfield = new GStarfield(); + gCamera->vx = gCamera->vy = 0; + gCamera->vz = CAMERA_VZ; + AddProcess(new GMainMenuProcess()); +} + +GMainMenuState::~GMainMenuState() noexcept {} \ No newline at end of file diff --git a/Evade2/src/MainMenuState/GMainMenuState.h b/Evade2/src/MainMenuState/GMainMenuState.h new file mode 100644 index 0000000..edccfd3 --- /dev/null +++ b/Evade2/src/MainMenuState/GMainMenuState.h @@ -0,0 +1,18 @@ +// +// Created by Michael Schwartz on 11/4/20. +// + +#ifndef EVADE2_GMAINMENUSTATE_H +#define EVADE2_GMAINMENUSTATE_H + +#include "Game.h" + +class GMainMenuState : public BGameEngine { +public: + GMainMenuState(); + + ~GMainMenuState() OVERRIDE; +}; + + +#endif //EVADE2_GMAINMENUSTATE_H diff --git a/Evade2/old/SplashState/GSplashPlayfield.cpp b/Evade2/src/SplashState/GSplashPlayfield.cpp similarity index 100% rename from Evade2/old/SplashState/GSplashPlayfield.cpp rename to Evade2/src/SplashState/GSplashPlayfield.cpp diff --git a/Evade2/old/SplashState/GSplashPlayfield.h b/Evade2/src/SplashState/GSplashPlayfield.h similarity index 100% rename from Evade2/old/SplashState/GSplashPlayfield.h rename to Evade2/src/SplashState/GSplashPlayfield.h diff --git a/Evade2/old/SplashState/GSplashProcess.cpp b/Evade2/src/SplashState/GSplashProcess.cpp similarity index 93% rename from Evade2/old/SplashState/GSplashProcess.cpp rename to Evade2/src/SplashState/GSplashProcess.cpp index 277d5dd..dcdbaea 100644 --- a/Evade2/old/SplashState/GSplashProcess.cpp +++ b/Evade2/src/SplashState/GSplashProcess.cpp @@ -4,8 +4,8 @@ //static const char *splash_message2 = "Press any button"; GSplashProcess::GSplashProcess() : BProcess() { - mColor = 0; - mState = STATE_FADEIN; + mColor = 0; + mState = STATE_FADEIN; // mFont = new BFont(gResourceManager.GetBitmap(FONT_16x16_SLOT), FONT_16x16); // mCurrentText = splash_message1; } @@ -66,11 +66,11 @@ void GSplashProcess::RenderText() { TBool GSplashProcess::RunAfter() { if (gControls.WasPressed(BUTTON_ANY)) { // } || --mTimer <= 0) { gGame->SetState(GAME_STATE_MAIN_MENU); -// gGame->SetState(GAME_STATE_VICTORY); #ifdef ENABLE_AUDIO - //gSoundPlayer.SfxStartGame(); + gSoundPlayer.SfxStartGame(); #endif + return EFalse; } // switch (mState) { diff --git a/Evade2/old/SplashState/GSplashProcess.h b/Evade2/src/SplashState/GSplashProcess.h similarity index 100% rename from Evade2/old/SplashState/GSplashProcess.h rename to Evade2/src/SplashState/GSplashProcess.h diff --git a/Evade2/old/SplashState/GSplashState.cpp b/Evade2/src/SplashState/GSplashState.cpp similarity index 62% rename from Evade2/old/SplashState/GSplashState.cpp rename to Evade2/src/SplashState/GSplashState.cpp index 931fd42..91f31bf 100644 --- a/Evade2/old/SplashState/GSplashState.cpp +++ b/Evade2/src/SplashState/GSplashState.cpp @@ -1,11 +1,16 @@ #include "Game.h" #include "GSplashPlayfield.h" #include "GSplashProcess.h" +#include "GSplashState.h" GSplashState::GSplashState() : BGameEngine(gViewPort) { + gGameEngine = this; mPlayfield = new GSplashPlayfield(); AddProcess(new GSplashProcess()); } -GSplashState::~GSplashState() = default; +GSplashState::~GSplashState() { + delete mPlayfield; + mPlayfield = ENull; +} diff --git a/Evade2/old/SplashState/GSplashState.h b/Evade2/src/SplashState/GSplashState.h similarity index 86% rename from Evade2/old/SplashState/GSplashState.h rename to Evade2/src/SplashState/GSplashState.h index 96286e2..0735338 100644 --- a/Evade2/old/SplashState/GSplashState.h +++ b/Evade2/src/SplashState/GSplashState.h @@ -7,7 +7,7 @@ class GSplashState : public BGameEngine { public: GSplashState(); - virtual ~GSplashState(); + ~GSplashState() OVERRIDE; }; diff --git a/Evade2/src/common/GCamera.cpp b/Evade2/src/common/GCamera.cpp new file mode 100644 index 0000000..d81c2c5 --- /dev/null +++ b/Evade2/src/common/GCamera.cpp @@ -0,0 +1,15 @@ +#include "GCamera.h" + +GCamera *gCamera; + +GCamera::GCamera() { + x = 0; + y = 0; + z = 0; + + vx = 0; + vy = 0; + vz = CAMERA_VZ; +} + + diff --git a/Evade2/src/common/GCamera.h b/Evade2/src/common/GCamera.h new file mode 100644 index 0000000..39be235 --- /dev/null +++ b/Evade2/src/common/GCamera.h @@ -0,0 +1,33 @@ +#ifndef GCAMERA_H +#define GCAMERA_H + +#include "Game.h" +#include + +class GCamera { +public: + GCamera(); + +public: + TFloat x, y, z; + TFloat vx, vy, vz; + +public: + void Move() { + x += vx; + y += vy; + z += vz; + } + + TBool CollidesWith(GVectorSprite *aVSprite) const { + // If enemy bullet collides with player + if (abs(aVSprite->z - z) < abs(aVSprite->vz) && abs(aVSprite->x - x) < 64 && abs(aVSprite->y - y) < 64) { + return ETrue; + } + return EFalse; + } +}; + +extern GCamera *gCamera; + +#endif diff --git a/Evade2/src/GameState/GGamePlayfield.cpp b/Evade2/src/common/GStarfield.cpp similarity index 63% rename from Evade2/src/GameState/GGamePlayfield.cpp rename to Evade2/src/common/GStarfield.cpp index 5f3c90d..72b1713 100644 --- a/Evade2/src/GameState/GGamePlayfield.cpp +++ b/Evade2/src/common/GStarfield.cpp @@ -2,22 +2,23 @@ // Created by Michael Schwartz on 10/29/20. // -#include "GGamePlayfield.h" +#include "GStarfield.h" #include "GCamera.h" -GGamePlayfield::GGamePlayfield() : BPlayfield() { +GStarfield::GStarfield() : BPlayfield() { + gCamera = new GCamera(); for (TInt i = 0; i < NUM_STARS; i++) { InitStar(i); } } -GGamePlayfield::~GGamePlayfield() noexcept { +GStarfield::~GStarfield() noexcept { } -void GGamePlayfield::Render() { +void GStarfield::Render() { gDisplay.renderBitmap->Clear(0); - TFloat cz = GCamera::mZ, + TFloat cz = gCamera->z, sw = TFloat(SCREEN_WIDTH), sh = TFloat(SCREEN_HEIGHT); @@ -29,8 +30,8 @@ void GGamePlayfield::Render() { } TFloat ratioX = sw / (zz + sw); TFloat ratioY = sh / (zz + sh); - TFloat x = (sw / 2) - (mStarX[i] - GCamera::mX) * ratioX; - TFloat y = (sh / 2) - (mStarY[i] - GCamera::mY) * ratioY; + TFloat x = (sw / 2) - (mStarX[i] - gCamera->x) * ratioX; + TFloat y = (sh / 2) - (mStarY[i] - gCamera->y) * ratioY; if (x < 0) { // printf("InitStar x %f < 0\n", x); @@ -50,9 +51,8 @@ void GGamePlayfield::Render() { } } -void GGamePlayfield::InitStar(TInt aIndex) { - mStarX[aIndex] = 256 - Random(0, 512) + GCamera::mX; - mStarY[aIndex] = 256 - Random(0, 512) + GCamera::mY; - mStarZ[aIndex] = GCamera::mZ + Random(200, 512); - +void GStarfield::InitStar(TInt aIndex) { + mStarX[aIndex] = TFloat(256) - Random(0, 512) + gCamera->x; + mStarY[aIndex] = TFloat(256) - Random(0, 512) + gCamera->y; + mStarZ[aIndex] = gCamera->z + Random(200, 512); } \ No newline at end of file diff --git a/Evade2/src/GameState/GGamePlayfield.h b/Evade2/src/common/GStarfield.h similarity index 60% rename from Evade2/src/GameState/GGamePlayfield.h rename to Evade2/src/common/GStarfield.h index 19c662d..cca0e8f 100644 --- a/Evade2/src/GameState/GGamePlayfield.h +++ b/Evade2/src/common/GStarfield.h @@ -2,18 +2,18 @@ // Created by Michael Schwartz on 10/29/20. // -#ifndef EVADE2_GGAMEPLAYFIELD_H -#define EVADE2_GGAMEPLAYFIELD_H +#ifndef EVADE2_GSTARFIELD_H +#define EVADE2_GSTARFIELD_H #include const int NUM_STARS = 128; -class GGamePlayfield : public BPlayfield { +class GStarfield : public BPlayfield { public: - GGamePlayfield(); + GStarfield(); - ~GGamePlayfield(); + ~GStarfield(); public: void Render() OVERRIDE; @@ -26,4 +26,4 @@ class GGamePlayfield : public BPlayfield { }; -#endif //EVADE2_GGAMEPLAYFIELD_H +#endif //EVADE2_GSTARFIELD_H diff --git a/Evade2/src/common/GVectorFont.cpp b/Evade2/src/common/GVectorFont.cpp new file mode 100644 index 0000000..3c15082 --- /dev/null +++ b/Evade2/src/common/GVectorFont.cpp @@ -0,0 +1,215 @@ +#include "GVectorFont.h" + +#define DEBUGME + +/** + * Some of this code lifted from Arduino serial Print class and modified. + * See: https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/Print.cpp + */ + +#include "Game.h" +#include "charset.h" + +GVectorFont *gVectorFont; + +// constructor +GVectorFont::GVectorFont() { + scale = 1.0; + color = COLOR_TEXT; + gVectorFont = this; +} + +#ifdef ENABLE_ROTATING_TEXT +TInt16 GVectorFont::print_string_rotatedx(TFloat x, TFloat y, TFloat theta, const char *s) { + theta = TFloat(theta) * 3.1415926 / 180; + TFloat cost = cos(theta), + sint = sin(theta); + const char *p = s; + + const TInt16 size = 9; + + TInt16 xo = x; + while (char c = *p++) { + auto *glyph = (const TInt8 *)charset[toupper(c) - 32]; + if (glyph) { + TInt8 lines = *glyph++; + + for (TInt16 i = 0; i < lines; i++) { + TFloat x0 = *glyph++ * scale + x, + y0 = *glyph++ * scale + y, + x1 = *glyph++ * scale + x, + y1 = *glyph++ * scale + y; + + gDisplay.renderBitmap->DrawLine( + gViewPort, + x0, + ((y0 - y) * sint + cost + y), + x1, + ((y1 - y) * sint + cost + y), + color); + } + x += size * scale; + } + else { + x += 6 * scale; + } + } + return x - xo; +} +#endif + +TInt16 GVectorFont::write(TFloat x, TFloat y, char c) { + const TInt8 *glyph; + const TInt16 width = 9; + + glyph = (TInt8 *)charset[toupper(c) - 32]; + if (glyph) { + TInt8 lines = *glyph++; + + for (TInt16 i = 0; i < lines; i++) { + TInt8 x0 = *glyph++, + y0 = *glyph++, + x1 = *glyph++, + y1 = *glyph++; + + gDisplay.renderBitmap->DrawLine( + gViewPort, + x + x0 * scale, y + y0 * scale, + x + x1 * scale, y + y1 * scale, + color); + } + } + return width * scale; +} + +TInt16 GVectorFont::print_string(TFloat x, TFloat y, char *s) { + TInt16 xx = x; + while (char c = *s++) { + TInt16 width = write(x, y, c); + x += width; + } + return x - xx; // width of string printed +} + +TInt16 GVectorFont::print_long(TFloat x, TFloat y, TInt64 n, TInt16 base) { + char buf[8 * sizeof(TInt64) + 1]; // Assumes 8-bit chars plus zero byte. + char *str = &buf[sizeof(buf) - 1]; + + *str = '\0'; + + // prevent crash if called with base == 1 + if (base < 2) + base = 10; + + do { + char c = n % base; + n /= base; + + *--str = c < 10 ? c + '0' : c + 'A' - 10; + } while (n); + + return print_string(x, y, str); +} + +#ifdef PRINTF_TFloat +TInt16 GVectorFont::print_float(TInt16 x, TInt16 y, double number, TInt16 digits) { + TInt16 xx = x; + if (isnan(number)) { + x += write(x, y, 'n'); + x += write(x, y, 'a'); + x += write(x, y, 'n'); + return x; + } + if (isinf(number)) { + x += write(x, y, 'i'); + x += write(x, y, 'n'); + x += write(x, y, 'f'); + return x; + } + if (number > 4294967040.0 || number < -4294967040.0) { + x += write(x, y, 'o'); + x += write(x, y, 'v'); + x += write(x, y, 'f'); + return x; + } + + // Handle negative numbers + if (number < 0.0) { + x += write(x, y, '-'); + number = -number; + } + + // Round correctly so that print(1.999, 2) prints as "2.00" + double rounding = 0.5; + for (uint8_t i = 0; i < digits; ++i) + rounding /= 10.0; + + number += rounding; + + // Extract the integer part of the number and print it + unsigned long int_part = (unsigned long)number; + double remainder = number - (double)int_part; + x += print_long(x, y, int_part, 10); + + // Print the decimal point, but only if there are digits beyond + if (digits > 0) { + x += write(x, y, '.'); + } + + // Extract digits from the remainder one at a time + while (digits-- > 0) { + remainder *= 10.0; + unsigned int toPrint = (unsigned int)(remainder); + x += print_long(x, y, toPrint, 10); + remainder -= toPrint; + } + + return x - xx; +} +#endif + +TInt16 GVectorFont::printf(TFloat x, TFloat y, const char *s, ...) { + va_list ap; + TInt16 xx = x; + char c; + const char *p = s; + va_start(ap, s); + + while ((c = *p++)) { + if (c == '%') { + c = *p++; + switch (c) { + case '\0': + va_end(ap); + return x - xx; +#ifdef PRINTF_TFloat + case '%': + x += write(x, y, '%'); + break; + case 'f': + x += print_float(x, y, va_arg(ap, double)); + break; +#endif + case 'd': + x += print_long(x, y, (unsigned long)va_arg(ap, int)); + break; +#ifdef PRINTF_TFloat + case 'x': + x += print_long(x, y, (unsigned long)va_arg(ap, int) & 0xffff, 16); + break; + case 'l': + x += print_long(x, y, va_arg(ap, long)); + break; +#endif + default: + x += write(x, y, c); + break; + } + } + else { + x += write(x, y, c); + } + } + va_end(ap); + return xx - x; +} diff --git a/Evade2/src/common/GVectorFont.h b/Evade2/src/common/GVectorFont.h new file mode 100644 index 0000000..dca252c --- /dev/null +++ b/Evade2/src/common/GVectorFont.h @@ -0,0 +1,28 @@ +#ifndef EVADE2_GVECTORFONT_H +#define EVADE2_GVECTORFONT_H + +#include "Game.h" + +class GVectorFont{ +public: + GVectorFont(); + +public: + TFloat scale; + TUint8 color; // color to render text in + +public: + // these routine return the width of whatever is printed to the screen + TInt16 write(TFloat x, TFloat y, char c); + TInt16 printf(TFloat x, TFloat y, const char *s, ...); +#ifdef ENABLE_ROTATING_TEXT + TInt16 print_string_rotatedx(TFloat x, TFloat y, TFloat angle, const char *s); +#endif + TInt16 print_string(TFloat x, TFloat y, char *s); + TInt16 print_long(TFloat x, TFloat y, TInt64 n, TInt16 base = 10); +// TInt16 print_float(TInt16 x, TInt16 y, TFloat number, TInt16 digits = 2); +}; + +extern GVectorFont *gVectorFont; + +#endif diff --git a/Evade2/src/common/GVectorSprite.cpp b/Evade2/src/common/GVectorSprite.cpp index 4246350..f069138 100644 --- a/Evade2/src/common/GVectorSprite.cpp +++ b/Evade2/src/common/GVectorSprite.cpp @@ -1,9 +1,15 @@ #include "GVectorSprite.h" #include "GCamera.h" +void GVectorSprite::SetLines(const TInt8 *aLines) { + mLines = aLines; + auto *p = (const TUint16 *) mLines; + w = p[0]; + h = p[1]; +} TBool GVectorSprite::ExplodeVectorGraphic(const TInt8 *graphic, TFloat x, TFloat y, - TFloat theta, TFloat scaleFactor, TInt8 step, TUint8 color) { + TFloat theta, TFloat scaleFactor, TInt8 step, TUint8 color) { graphic += 2; TBool drawn = false; @@ -13,7 +19,7 @@ TBool GVectorSprite::ExplodeVectorGraphic(const TInt8 *graphic, TFloat x, TFloat for (TInt8 i = 0; i < numRows; i++) { struct vec_segment_u8 seg; - TFloat x0, y0, x1, y1; + TFloat x0, y0, x1, y1; memcpy(&seg, graphic, sizeof(seg)); graphic += sizeof(seg); @@ -38,16 +44,15 @@ TBool GVectorSprite::ExplodeVectorGraphic(const TInt8 *graphic, TFloat x, TFloat } - TInt16 drawX1 = x0 * cost - y0 * sint + x, - drawY1 = y0 * cost + x0 * sint + y, - drawX2 = x1 * cost - y1 * sint + x, - drawY2 = y1 * cost + x1 * sint + y; + drawY1 = y0 * cost + x0 * sint + y, + drawX2 = x1 * cost - y1 * sint + x, + drawY2 = y1 * cost + x1 * sint + y; TBool xInBounds = (drawX1 >= 0) && (drawX1 <= DISPLAY_WIDTH) && (drawY1 >= 0) && (drawY1 < DISPLAY_HEIGHT), - yInBounds = (drawX2 >= 0) && (drawX2 <= DISPLAY_WIDTH) && (drawY2 >= 0) && (drawY2 < DISPLAY_HEIGHT); + yInBounds = (drawX2 >= 0) && (drawX2 <= DISPLAY_WIDTH) && (drawY2 >= 0) && (drawY2 < DISPLAY_HEIGHT); - if ((! xInBounds) && !(yInBounds)) { + if ((!xInBounds) && !(yInBounds)) { continue; } @@ -64,41 +69,57 @@ TBool GVectorSprite::ExplodeVectorGraphic(const TInt8 *graphic, TFloat x, TFloat return drawn; } +static TFloat square(TFloat f) { + return f * f; +} + +TFloat GVectorSprite::DistanceTo(GVectorSprite *aOther) { + return sqrt(square(aOther->x - x) + square(aOther->y - y) + square(aOther->z - z)); +}; + TBool GVectorSprite::Render(BViewPort *aViewPort) { - if (!mLines || mZ <= GCamera::mZ) { + if (!mLines || z <= gCamera->z) { // nothing to draw return EFalse; } - TFloat zz = (mZ - GCamera::mZ) * 2; + TFloat zz = (z - gCamera->z) * 2; TFloat ratio = 128 / (zz + 128); + TFloat sw = TFloat(SCREEN_WIDTH), + sh = TFloat(SCREEN_HEIGHT); - bool isEnemy = Type() == OTYPE_ENEMY; + bool isEnemy = type == STYPE_ENEMY; // printf("is enemy = %i\n", isEnemy); - TFloat cx = (GCamera::mX - mX) * ratio + SCREEN_WIDTH / 2; - TFloat cy = (GCamera::mY - mY) * ratio + SCREEN_HEIGHT / 2; + TFloat cx = (gCamera->x - x) * ratio + sw / 2; + TFloat cy = (gCamera->y - y) * ratio + sh / 2; // uint8_t color = isEnemy ? 5 : 255; if (flags & OFLAG_EXPLODE) { ExplodeVectorGraphic(mLines, cx, cy, mTheta, 1 / ratio, mState, this->mColor); - } - else { + } else { bool drawn = DrawVectorGraphic(mLines, cx, cy, mTheta, 1 / ratio, this->mColor); if ((!drawn) && isEnemy) { // draw radar blip - TFloat dx = GCamera::mX - mX, - dy = GCamera::mY - mY, - angle = atan2(dy, dx); + TFloat dx = gCamera->x - x, + dy = gCamera->y - y, + angle = atan2(dy, dx), + midx = sw / 2, + midy = sh / 2, + cxx = midx + cos(angle) * (midx - 10), + cyy = midy + sin(angle) * (midy - 10); // printf("TODO: Fill Circle for enemy radar\n"); - aViewPort->FillCircle(gDisplay.renderBitmap, - (int16_t)(SCREEN_WIDTH / 2 + cos(angle) * 75), - (int16_t)(SCREEN_HEIGHT / 2 + sin(angle) * 75), - 3, - EBULLET_COLOR - ); + +// printf("Angle: %f, x: %f, y: %f, cx,cy: %f,%f\n", angle, x, y, cx, cy); + aViewPort->FillCircle(gDisplay.renderBitmap, + (TInt16) cxx, + (TInt16) cyy, + 4, + COLOR_SHMOO +// mColor + ); } } @@ -107,6 +128,6 @@ TBool GVectorSprite::Render(BViewPort *aViewPort) { } -TBool GVectorSprite::BehindCamera() { - return mZ <= GCamera::mZ; +TBool GVectorSprite::BehindCamera() { + return z <= gCamera->z; } \ No newline at end of file diff --git a/Evade2/src/common/GVectorSprite.h b/Evade2/src/common/GVectorSprite.h index 94546fa..2386f52 100644 --- a/Evade2/src/common/GVectorSprite.h +++ b/Evade2/src/common/GVectorSprite.h @@ -12,59 +12,61 @@ struct vec_segment_u8 { TInt8 y1; }; -#define FIRE_TIME (60 / Game::difficulty + random(1, 60 / Game::Game::difficulty)) +//#define FIRE_TIME (60 / Game::difficulty + random(1, 60 / Game::Game::difficulty)) class GVectorSprite : public BSprite { public: - GVectorSprite() : BSprite(0 , 0, ENull, STYPE_DEFAULT) { + explicit GVectorSprite(TUint64 aType = STYPE_DEFAULT) : BSprite(0 , 0, ENull, aType) { mColor = COLOR_WHITE; mPad = 0; - mX = mY = mZ = 0; - mVX = mVY = mVZ = 0; - mFlags = mState = mTheta = 0; + x = y = z = 0; + vx = vy = vz = 0; + flags = mState = mTheta = 0; mTimer = 0; mLines = ENull; } - void StartAnimation() { - printf("GVectorSprite::StartAnimation()\n"); - } - - TBool DrawVectorGraphic(const TInt8 *graphic, TFloat x, TFloat y, TFloat theta, TFloat scaleFactor, TUint8 color) { + static TBool DrawVectorGraphic(const TInt8 *graphic, TFloat x, TFloat y, TFloat theta, TFloat scaleFactor, TUint8 color) { return ExplodeVectorGraphic(graphic, x, y, theta, scaleFactor, 0, color); } - TBool ExplodeVectorGraphic(const TInt8 *graphic, TFloat x, TFloat y, + static TBool ExplodeVectorGraphic(const TInt8 *graphic, TFloat x, TFloat y, TFloat theta, TFloat scaleFactor, TInt8 step, TUint8 color); TBool Render(BViewPort *aViewPort) OVERRIDE; void Move() OVERRIDE { - mX += mVX; - mY += mVY; - mZ += mVZ; + x += vx; + y += vy; + z += vz; } +public: + void SetLines(const TInt8 *aLines); + const TInt8 *GetLines() { return mLines; } +protected: // if lines is NULL, then the variables in the Object structure can be used // for any purpose const TInt8 *mLines; - TFloat mX, mY, mZ; // coordinates - TFloat mVX, mVY, mVZ; // velocity in x,y,z - TUint8 mFlags; - TInt8 mTimer; +public: + + TFloat z; // coordinates + TFloat vz; // velocity in x,y,z + TInt16 mTimer; TInt16 mState; // arbitrary data TInt8 for AI use (can be explosion step, etc.) TFloat mTheta; // rotation around Z (in degrees, 0-60) TUint8 mColor; TUint8 mPad; - inline void SetType(TUint8 aType) { - mFlags = (mFlags & ~OFLAG_TYPE_MASK) | aType; - } +// inline void SetType(TUint8 aType) { +// mFlags = (mFlags & ~OFLAG_TYPE_MASK) | aType; +// } TBool BehindCamera(); + TFloat DistanceTo(GVectorSprite *aOther); TBool do_death() { // if (o->flags & OFLAG_COLLISION) { @@ -77,10 +79,6 @@ class GVectorSprite : public BSprite { // } return EFalse; } - - inline TUint8 Type() { - return mFlags & OFLAG_TYPE_MASK; - } }; diff --git a/Evade2/src/charset.h b/Evade2/src/common/charset.h similarity index 88% rename from Evade2/src/charset.h rename to Evade2/src/common/charset.h index 9bfb1b6..bcdff3e 100644 --- a/Evade2/src/charset.h +++ b/Evade2/src/common/charset.h @@ -1,12 +1,10 @@ #ifndef CHARSET_H #define CHARSET_H -#define FULL_CHARSET // number of characters: 61 -#include "Game.h" +/* #include "Evade2.h" */ -// clang-format off const TInt8 font_a[] = { // 9, // width // 9, // height @@ -764,4 +762,164 @@ const TInt8 font_amp[] = { }; #endif +const TInt8 *charset[] = { + ENull, // space + font_emark, +#ifdef FULL_CHARSET + font_dquote, +#else + ENull, +#endif +#ifdef FULL_CHARSET + font_pound, // # +#else + ENull, +#endif +#ifdef FULL_CHARSET + font_dollar, // $ +#else + ENull, +#endif +#ifdef FULL_CHARSET + font_percent, // % +#else + ENull, +#endif +#ifdef FULL_CHARSET + font_amp, // & +#else + ENull, +#endif +#ifdef FULL_CHARSET + font_squote, // ' +#else + ENull, +#endif +#ifdef FULL_CHARSET + font_lparen, // ( +#else + ENull, +#endif +#ifdef FULL_CHARSET + font_rparen, // ) +#else + ENull, +#endif +#ifdef FULL_CHARSET + font_asterisk, // * +#else + ENull, +#endif +#ifdef FULL_CHARSET + font_plus, +#else + ENull, +#endif +#ifdef FULL_CHARSET + font_comma, +#else + ENull, +#endif +#ifdef FULL_CHARSET + font_minus, +#else + ENull, +#endif + font_period, + font_fslash, + font_0, + font_1, + font_2, + font_3, + font_4, + font_5, + font_6, + font_7, + font_8, + font_9, + font_colon, +#ifdef full_charset + font_semicolon, +#else + ENull, +#endif +#ifdef full_charset + font_lt, // < +#else + ENull, +#endif +#ifdef full_charset + font_eq, // = +#else + ENull, +#endif +#ifdef full_charset + font_gt, // > +#else + ENull, +#endif +#ifdef full_charset + font_qmark, +#else + ENull, +#endif +#ifdef full_charset + font_at, // @ +#else + ENull, +#endif + font_a, + font_b, + font_c, + font_d, + font_e, + font_f, + font_g, + font_h, + font_i, + font_j, + font_k, + font_l, + font_m, + font_n, + font_o, + font_p, + font_q, + font_r, + font_s, + font_t, + font_u, + font_v, + font_w, + font_x, + font_y, + font_z, +#ifdef full_charset + font_lt, // [ +#else + ENull, +#endif +#ifdef full_charset + font_bslash, // '\' +#else + ENull, +#endif +#ifdef full_charset + font_gt, // ] +#else + ENull, +#endif +#ifdef full_charset + font_caret, // ^ +#else + ENull, +#endif +#ifdef full_charset + font_uscore, // _ +#else + ENull, +#endif + ENull, // `` +}; + #endif diff --git a/Evade2/src/img/README.md b/Evade2/src/img/README.md new file mode 100644 index 0000000..c552948 --- /dev/null +++ b/Evade2/src/img/README.md @@ -0,0 +1,4 @@ +# Vector images + +This directory contains vector images used in the game. They were created as SVG, and converted into +code suitable for our rendering routines. diff --git a/Evade2/src/img/ebomb_img.h b/Evade2/src/img/ebomb_img.h index c60a517..1fc4cc5 100644 --- a/Evade2/src/img/ebomb_img.h +++ b/Evade2/src/img/ebomb_img.h @@ -4,7 +4,7 @@ #include "BTypes.h" -const TInt16 ebomb_img[] = { +const TInt8 ebomb_img[] = { 16, // width 16, // height 9, // num rows diff --git a/Evade2/src/img/ebullet_img.h b/Evade2/src/img/ebullet_img.h index a58fba4..c1b3a37 100644 --- a/Evade2/src/img/ebullet_img.h +++ b/Evade2/src/img/ebullet_img.h @@ -3,7 +3,7 @@ #include "BTypes.h" -const TInt16 ebullet_img[] = { +const TInt8 ebullet_img[] = { 8, // width 8, // height 4, // num rows diff --git a/Evade2/src/main.cpp b/Evade2/src/main.cpp new file mode 100644 index 0000000..a447b5b --- /dev/null +++ b/Evade2/src/main.cpp @@ -0,0 +1,23 @@ +#include "Game.h" + +BViewPort *gViewPort; +BGameEngine *gGameEngine; + +GGame *gGame; +TOptions *gOptions; + +/** @file + * \brief Main entry point for game engine. + * + * Initializes the engine and runs the main event loop. + */ +extern "C" void app_main() { + gGame = new GGame(); + gGame->Run(); +} + +int main() { + app_main(); + return 0; +} +