~ndiddy/libremo

834528afaa501561c15ed45bfc28c288eab07299 — Nathan Misner 2 years ago 207bf76
ship changes when laser powerup is acquired
M README => README +30 -17
@@ 7,6 7,7 @@ the GNU General Public License.
Note: I might choose to relicense the project as GPLv2 in the future. If you
submit any patches, you're agreeing that your code can be relicensed as GPLv2.
See the libremo-devel mailing list for development discussion and patch submission.
https://lists.sr.ht/~ndiddy/libremo-devel

How to use:
1. Follow the instructions in the moexconv repository to extract all the graphics


@@ 27,24 28,16 @@ Controls are WSAD for movmement and J, K, Enter, and Esc for buttons. Note that 
of the time, I hardcode the game to start in the game playing state, so if you want it to
boot from the start you can change the state variable in main.cpp to STATE_LOGO.

Current status:
General: Sound effects aren't implemented. X68000 sound isn't implemented. Eventually
I would like to run Z-Music, the sound engine from the original game, in some
sort of headless emulator in order to get accurate X68000 sound effects and music.
Compilation note: Because Windows and Linux have different feature sets (Linux has better
C language debugging software, and Windows has X68000 emulators with debugging support),
I will flip-flop between them depending on what I'm doing. This might mean that at some
points, the Makefile will not have some files, and at other points the Visual Studio project
won't have some files. It should be easy enough to add the missing files to either of these
depending on what platform you use.

Intro: Mostly done, I need to implement the palette changing animation on the credits
and figure out where the "Cyberblock" and "EX" graphics are stored in the executable.

Menu: Very simplistic compared to the X68000 version, I need to make it data-driven.

Tutorial screens: Mostly implemented.

Cutscenes: Show background but not animation or text.

Game: Hud needs work (specifically with representing powerup state). Chip doesn't move her
mouth when the player collects a powerup. Game over and continue states aren't implemented.
Scoring isn't accurate. The "guns" on the walls that change based on what powerup you have
aren't implemented. The ship doesn't extend its guns when the player gets the laser powerup.
Status:
For current stuff to work on, look at the libremo issues tracker.
https://todo.sr.ht/~ndiddy/libremo

Used software:



@@ 68,6 61,26 @@ freely, subject to the following restrictions:
   misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

sdl2_image
----------
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>

This software is provided 'as-is', without any express or implied
warranty.  In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not
   claim that you wrote the original software. If you use this software
   in a product, an acknowledgment in the product documentation would be
   appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

stb_vorbis
----------
Copyright (c) 2017 Sean Barrett

M VisualStudio/VisualStudio.vcxproj => VisualStudio/VisualStudio.vcxproj +2 -0
@@ 159,6 159,7 @@
    <ClCompile Include="..\block_shine.cpp" />
    <ClCompile Include="..\block_shrink.cpp" />
    <ClCompile Include="..\block_stretch.cpp" />
    <ClCompile Include="..\bonus.cpp" />
    <ClCompile Include="..\capsule.cpp" />
    <ClCompile Include="..\chip.cpp" />
    <ClCompile Include="..\cutscene.cpp" />


@@ 203,6 204,7 @@
    <ClInclude Include="..\block_shine.h" />
    <ClInclude Include="..\block_shrink.h" />
    <ClInclude Include="..\block_stretch.h" />
    <ClInclude Include="..\bonus.h" />
    <ClInclude Include="..\capsule.h" />
    <ClInclude Include="..\chip.h" />
    <ClInclude Include="..\cutscene.h" />

M VisualStudio/VisualStudio.vcxproj.filters => VisualStudio/VisualStudio.vcxproj.filters +6 -0
@@ 141,6 141,9 @@
    <ClCompile Include="..\speed.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\bonus.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="..\anim.h">


@@ 290,5 293,8 @@
    <ClInclude Include="..\cutscene.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="..\bonus.h">
      <Filter>Header Files</Filter>
    </ClInclude>
  </ItemGroup>
</Project>
\ No newline at end of file

M ball.cpp => ball.cpp +6 -6
@@ 153,8 153,8 @@ void Ball::move() {
    texture = ballTextures[ballMode - POWER_BALL]->texture;

    if (state == BALL_STATE_INIT) {
        x = shipSprite.x + BALL_SPAWN_XOFFSET;
        y = shipSprite.y + BALL_SPAWN_YOFFSET;
        x = shipLeft + ((shipRight - shipLeft) / 2) - (BALL_WIDTH / 2);
        y = SHIP_YPOS;

        //don't allow ball launch until level is done loading and ship is done
        if ((padData & PAD_LASER) && (gameLevel->doneLoad()) && (shipState == SHIP_STATE_NORM)) {


@@ 220,11 220,11 @@ void Ball::move() {
        //bottom
        if (((x + BALL_WIDTH) >= shipLeft) &&
            (x <= shipRight) && 
            ((y + BALL_HEIGHT) >= (shipSprite.y + SHIP_YMARGIN)) &&
            (y < (shipSprite.y + SHIP_HEIGHT))) {
            ((y + BALL_HEIGHT) >= (SHIP_YPOS + SHIP_YMARGIN)) &&
            (y < (SHIP_YPOS + SHIP_HEIGHT))) {

            // calculate ball's offset from paddle center
            float ballOffset = (shipSprite.x + (SHIP_WIDTH / 2)) - (x + (BALL_WIDTH / 2));
            float ballOffset = shipLeft + ((shipRight - shipLeft) / 2) - (x + (BALL_WIDTH / 2));

            // fraction from -1 to 1
            float normalizedOffset = ballOffset / (SHIP_WIDTH / 2);


@@ 240,7 240,7 @@ void Ball::move() {
            }

            // eject the ball if it's inside the paddle
            if (y >= (shipSprite.y + SHIP_YMARGIN)) {
            if (y >= (SHIP_YPOS + SHIP_YMARGIN)) {
                // left hit
                if ((x - shipLeft) < (shipRight - shipLeft) / 2) {
                    x = shipLeft - BALL_WIDTH;

M capsule.cpp => capsule.cpp +2 -2
@@ 92,8 92,8 @@ void Capsule::move() {
    int collision = 0;
    if ((x + CAPSULE_WIDTH >= shipLeft) &&
        (x <= shipRight) && 
        (y + CAPSULE_HEIGHT >= shipSprite.y + SHIP_YMARGIN) &&
        (y < shipSprite.y + SHIP_HEIGHT)) {
        (y + CAPSULE_HEIGHT >= SHIP_YPOS + SHIP_YMARGIN) &&
        (y < SHIP_YPOS + SHIP_HEIGHT)) {
        collision = 1;
        switch (type) {
        case TYPE_POWERUP:

M game.cpp => game.cpp +57 -8
@@ 46,6 46,7 @@ typedef enum {
    STATE_GAME_FADELEVEL,
    STATE_GAME_LOSS,
    STATE_GAME_CENTERSHIP,
    STATE_GAME_RETRACTLASER,
    STATE_GAME_SHIPDOOROPEN,
    STATE_GAME_FLYUP,
    STATE_GAME_FLYDOWN,


@@ 122,7 123,7 @@ std::unique_ptr<Level> gameLevel;
//start of ship's idle animation
#define SHIP_IDLE (ship_charno + 13)

SpriteInfo shipSprite;
static SpriteInfo shipSprite;
#define SHIP_SPRITE_WIDTH (32)
#define SHIP_SPRITE_HEIGHT (32)
//ship's leftmost pixel


@@ 130,10 131,17 @@ float shipLeft;
//ship's rightmost pixel
float shipRight;

// gets overlaid over the ship sprite when the player has the laser powerup
static SpriteInfo laserShipSprite;
#define LASER_SHIP_SPRITE_HEIGHT (24)
#define LASER_SHIP_SPRITE_XOFFSET (8)
#define LASER_SHIP_SPRITESHEET_LAST (96)

#define LASER_SHIP_TIMING (6)
static float laserShipTimer;

int shipState;

//ship's y pos during normal gameplay
#define SHIP_POS (220)
#define SHIP_SPEED (4)
//all the ship's animations take 6 frames
#define SHIP_TIMING (6)


@@ 206,6 214,9 @@ void Game_Init(int level, int numLevels, int isStageClear, int bonusPoints) {
    shipSprite = SpriteInfo("ship.png");
    shipSprite.source.h = SHIP_SPRITE_HEIGHT;

    laserShipSprite = SpriteInfo("gameship.png");
    laserShipSprite.source.h = LASER_SHIP_SPRITE_HEIGHT;

    barrelSprite = SpriteInfo("barrel.png");
    barrelSprite.source.w = BARREL_SIZE;
    barrelSprite.source.h = BARREL_SIZE;


@@ 355,6 366,7 @@ void Game_Loss() {
    Laser_RemoveAll();
    shipSprite.x = SHIP_STARTX;
    shipSprite.y = SHIP_STARTY;
    laserShipSprite.source.y = 0;
}

int Game_Playing() {


@@ 396,12 408,36 @@ void Game_DrawShip() {
    if (bitShip) {
        Game_BitAnim();
        bitSprite.x = bitLeft;
        bitSprite.y = SHIP_POS + SHIP_YMARGIN;
        bitSprite.y = SHIP_YPOS + SHIP_YMARGIN;
        bitSprite.draw();
        bitSprite.x = bitRight;
        bitSprite.draw();
    }

    if (laserMax) {
        if (state >= STATE_GAME_RETRACTLASER) {
            if (laserShipSprite.source.y > 0) {
                laserShipTimer += Speed_Multiplier();
                if (laserShipTimer >= LASER_SHIP_TIMING) {
                    laserShipTimer = 0;
                    laserShipSprite.source.y -= LASER_SHIP_SPRITE_HEIGHT;
                }
            }
        }
        else {
            if (laserShipSprite.source.y < LASER_SHIP_SPRITESHEET_LAST) {
                laserShipTimer += Speed_Multiplier();
                if (laserShipTimer >= LASER_SHIP_TIMING) {
                    laserShipTimer = 0;
                    laserShipSprite.source.y += LASER_SHIP_SPRITE_HEIGHT;
                }
            }
        }
        laserShipSprite.x = shipSprite.x + LASER_SHIP_SPRITE_XOFFSET;
        laserShipSprite.y = shipSprite.y;
        laserShipSprite.draw();
    }

    // draw barrels if ship is done animating in
    if (shipSprite.source.y == SHIP_SPRITESHEET_LAST){
        barrelSprite.x = shipSprite.x;


@@ 429,8 465,8 @@ int Game_Run() {

    case STATE_SHIP_SPAWN:
        shipSprite.y -= (3 * Speed_Multiplier());
        if (shipSprite.y <= SHIP_POS) {
            shipSprite.y = SHIP_POS;
        if (shipSprite.y <= SHIP_YPOS) {
            shipSprite.y = SHIP_YPOS;
        }
        if (Game_ShipAnim()) {
            state = STATE_GAME_PLAY;


@@ 615,11 651,24 @@ int Game_Run() {
        }

        if (shipSprite.x == SHIP_STARTX) {
            state = STATE_GAME_SHIPDOOROPEN;
            if (laserMax) {
                state = STATE_GAME_RETRACTLASER;
            }
            else {
                state = STATE_GAME_SHIPDOOROPEN;
            }
        }
        break;

    // retract the laser sprite if it's being displayed. actual retraction code
    // is in Game_DrawShip
    case STATE_GAME_RETRACTLASER:
        if (laserShipSprite.source.y == 0) {
            state = STATE_GAME_SHIPDOOROPEN;
        }
        break;


    // door at the top opens to allow the ship to pass through
    case STATE_GAME_SHIPDOOROPEN:
        Bonus_Display(bonus, stageClear);


@@ 806,9 855,9 @@ int Game_Run() {
            Enemy_Run();
            Capsule_Draw();
        }
        Laser_Draw();
        Game_DrawShip();
        Ball_Draw(); // draw balls
        Laser_Draw();

        Capsule_FlushRemoveQueue();
        Enemy_FlushRemoveQueue();

M game.h => game.h +6 -3
@@ 29,11 29,14 @@
#define LEFT_WALL (8)
#define RIGHT_WALL (218)
#define TOP_WALL (8)
//leftmost x pos the ship can go
// leftmost x pos the ship can go
#define LEFT_BOUND (LEFT_WALL)
//rightmost x pos the ship can go
// rightmost x pos the ship can go
#define RIGHT_BOUND (RIGHT_WALL - SHIP_WIDTH)

// where the ship is at during gameplay
#define SHIP_YPOS (220)

//the area between where the sprite is and where the actual pixel graphics start
#define SHIP_YMARGIN (8)
#define SHIP_WIDTH (32)


@@ 56,7 59,7 @@ typedef enum {
    P_BARRIER
} POWERUP;

extern SpriteInfo shipSprite;
// extern SpriteInfo shipSprite;
// left & right pixel of ship
extern float shipLeft;
extern float shipRight;

M main.cpp => main.cpp +0 -2
@@ 138,8 138,6 @@ int main(int argc, char **argv) {
	int quit = 0;
    int state = STATE_STAGE;
    Stage_Init();

    
	
    try {
        while (!quit) {

M palette.cpp => palette.cpp +1 -3
@@ 88,9 88,7 @@ void Palette::update(std::vector<uint32_t> &newColors) {
        ERR_PRINTF("Error locking texture: %s\n", SDL_GetError());
    }

    for (int i = 0; i < (original->w * original->h); i++) {
        pixels[i] = ((uint32_t *)original->pixels)[i];
    }
    memcpy(pixels, (uint32_t *)original->pixels, original->w * original->h);
    for (COLOR_VAL &color : colors) {
        pixels[color.offset] = newColors[color.colorIndex];