~ndiddy/libremo

d8952716311cf7f3046781b2a471a8cf4a56d498 — Nathan Misner 2 years ago 6889496
added raster effects
M VisualStudio/VisualStudio.vcxproj => VisualStudio/VisualStudio.vcxproj +6 -2
@@ 167,6 167,7 @@
    <ClCompile Include="..\enemy.cpp" />
    <ClCompile Include="..\fade.cpp" />
    <ClCompile Include="..\font.cpp" />
    <ClCompile Include="..\logo.cpp" />
    <ClCompile Include="..\menu_text.cpp" />
    <ClCompile Include="..\path.cpp" />
    <ClCompile Include="..\game.cpp" />


@@ 175,13 176,14 @@
    <ClCompile Include="..\intro.cpp" />
    <ClCompile Include="..\laser.cpp" />
    <ClCompile Include="..\level.cpp" />
    <ClCompile Include="..\logo.cpp" />
    <ClCompile Include="..\otherlogo.cpp" />
    <ClCompile Include="..\main.cpp" />
    <ClCompile Include="..\menu.cpp" />
    <ClCompile Include="..\mover.cpp" />
    <ClCompile Include="..\pad.cpp" />
    <ClCompile Include="..\palette.cpp" />
    <ClCompile Include="..\random.cpp" />
    <ClCompile Include="..\raster.cpp" />
    <ClCompile Include="..\read.cpp" />
    <ClCompile Include="..\sound.cpp" />
    <ClCompile Include="..\speed.cpp" />


@@ 210,7 212,9 @@
    <ClInclude Include="..\cutscene.h" />
    <ClInclude Include="..\em_inflate.h" />
    <ClInclude Include="..\enemy.h" />
    <ClInclude Include="..\logo.h" />
    <ClInclude Include="..\menu_text.h" />
    <ClInclude Include="..\raster.h" />
    <ClInclude Include="..\stage.h" />
    <ClInclude Include="..\tutorial.h" />
    <ClInclude Include="..\util.h" />


@@ 222,7 226,7 @@
    <ClInclude Include="..\intro.h" />
    <ClInclude Include="..\laser.h" />
    <ClInclude Include="..\level.h" />
    <ClInclude Include="..\logo.h" />
    <ClInclude Include="..\otherlogo.h" />
    <ClInclude Include="..\menu.h" />
    <ClInclude Include="..\mover.h" />
    <ClInclude Include="..\pad.h" />

M VisualStudio/VisualStudio.vcxproj.filters => VisualStudio/VisualStudio.vcxproj.filters +14 -2
@@ 69,7 69,7 @@
    <ClCompile Include="..\level.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\logo.cpp">
    <ClCompile Include="..\otherlogo.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\main.cpp">


@@ 144,6 144,12 @@
    <ClCompile Include="..\bonus.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\raster.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\logo.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="..\anim.h">


@@ 200,7 206,7 @@
    <ClInclude Include="..\level.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="..\logo.h">
    <ClInclude Include="..\otherlogo.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="..\menu.h">


@@ 296,5 302,11 @@
    <ClInclude Include="..\bonus.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="..\raster.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="..\logo.h">
      <Filter>Header Files</Filter>
    </ClInclude>
  </ItemGroup>
</Project>
\ No newline at end of file

M intro.cpp => intro.cpp +1 -1
@@ 264,7 264,7 @@ static inline void Intro_DrawStars() {
int Intro_Run() {
    int textNum;

    if ((fadeFrames < 0) && padData) {
    if ((fadeFrames < 0) && padDataE) {
        fadeFrames = 0;
        Fade_Out(60);
    }

M logo.cpp => logo.cpp +75 -143
@@ 1,5 1,5 @@
/* logo.c: logo display code
*  Copyright (C) 2021 Nathan Misner
/* logo.cpp: logo display code
*  Copyright (C) 2022 Nathan Misner
*
*  This file is part of LibreMO.
*


@@ 16,153 16,85 @@
*  You should have received a copy of the GNU General Public License
*  along with LibreMO.  If not, see <https://www.gnu.org/licenses/>.
*/

#include <SDL.h>
#include <math.h>
#include <memory>
#include <string>
#include <vector>

#include "fade.h"
#include "globals.h"
#include "logo.h"
#include "pad.h"
#include "sound.h"
#include "speed.h"
#include "sprite.h"

// each updated frame of chip doing stuff is 128x128
#define CHIP_WIDTH (128)
#define CHIP_HEIGHT (128)
#define CHIP_ROWS (3)
#define CHIP_COLS (5)

#define ROAR_SFX (0)
#include "raster.h"
#include "trig.h"

typedef enum {
	STATE_LOGO_INIT = 0,
	STATE_LOGO_FADEIN,
	STATE_LOGO_RUN,
	STATE_LOGO_DONE,
	STATE_LOGO_FADEOUT,
	STATE_LOGO_END
	LOGO_STATE_INIT,
	LOGO_STATE_MESH,
	LOGO_STATE_FLASH,
	LOGO_STATE_FADEOUT
} LOGO_STATE;

static int timings[] = {186, 10, 10, 8, 66, 16, 8, 52, 9, 12, 16, 18, 39, 12, 5};
static float timer;
static int cursor;
static int state = STATE_LOGO_INIT;
static float frame;

static SpriteInfo bgSprite;
static SpriteInfo chipSprite;
static std::vector<std::unique_ptr<PakFrame>> chipTextures;

static void Logo_Init() {
    Global_SetHiRes();
    bgSprite = SpriteInfo("CUSTOM.png");
    chipTextures = Sprite_LoadPak("CUSTOM.pak");

    bgSprite.x = ((float)WINDOW_WIDTH / 2)  - ((float)bgSprite.source.w / 2);
    bgSprite.y = ((float)WINDOW_HEIGHT / 2) - ((float)bgSprite.source.h / 2);
    
    /*
    if (!Sound_LoadSFX("sfx/roar.wav", ROAR_SFX)) {
        printf("Error loading roar sfx!\n");
        return;
    }*/

    SDL_Rect chipDimensions;
    chipDimensions.x = 0;
    chipDimensions.y = 0;
    chipDimensions.w = CHIP_WIDTH;
    chipDimensions.h = CHIP_HEIGHT;
    chipSprite = SpriteInfo(chipTextures[0]->texture, NULL, &chipDimensions);
    chipSprite.x = bgSprite.x + 83;
    chipSprite.y = bgSprite.y + 7;

    // clear the variables
    timer = 0;
    cursor = 0;
    frame = 0;
    state = STATE_LOGO_INIT;
}

static void Logo_LoadFrame(int num) {
    chipSprite.texture = chipTextures[num]->texture;
}

int Logo_Run(void) {
    if (state != STATE_LOGO_END) {
        bgSprite.draw();
    }

    if ((state < STATE_LOGO_FADEOUT) && padData) {
        state = STATE_LOGO_FADEOUT;
        Fade_Out(60);
        state = STATE_LOGO_FADEOUT;
    }

    switch(state) {
        case STATE_LOGO_INIT:
            Fade_In(60);
            Logo_Init();
            frame = 0;
            state = STATE_LOGO_FADEIN;
            break;
        
        case STATE_LOGO_FADEIN:
            if (Fade_InDone()) {
                if (!Sound_PlayVGM("music/28 Opening (with SFX).vgz")) {
                    printf("Error loading logo music!\n");
                }
                state = STATE_LOGO_RUN;
            }
            break;

        case STATE_LOGO_RUN:
            if (cursor < (int)(sizeof(timings) / sizeof(timings[0]))) {
                timer += Speed_Multiplier();
                if (timer > timings[cursor]) {
                    Logo_LoadFrame(cursor++);
                    timer = 0;
                    if (cursor == 9) {
                        //Sound_PlaySFX(ROAR_SFX);
                    }
                }
            }
            else {
                frame = 0;
                state = STATE_LOGO_DONE;
            }
            if (cursor > 0) {
                chipSprite.draw();
            }
            break;

        case STATE_LOGO_DONE:
            frame += Speed_Multiplier();
            if (frame > 60) {
                Fade_Out(60);
                frame = 0;
                state = STATE_LOGO_FADEOUT;
            }
            chipSprite.draw();
            break;
            
        case STATE_LOGO_FADEOUT:
            if (Fade_OutDone()) {
                state = STATE_LOGO_END;
            }
            chipSprite.draw();
            break;

        case STATE_LOGO_END:
            state = STATE_LOGO_INIT;
            Sound_FreeSFX(ROAR_SFX);
            Sound_StopMusic();
            Fade_Stop();
            return 1;
    }

    return 0;
}
static std::unique_ptr<Raster> logo;
#define LOGO_WIDTH (256)
#define LOGO_HEIGHT (64)
static std::array<RASTER_LINE, 512> lines;
static int state = LOGO_STATE_INIT;


int Logo_Run() {
	static float amplitude = 0;
	static float angle = 0;
	static float wavelength = 0;

	switch (state) {
	case LOGO_STATE_INIT:
		Global_SetLoRes();
		logo = std::make_unique<Raster>("oldlogo.png");
		lines = std::array<RASTER_LINE, 512>();
		for (int i = 0; i < lines.size(); i++) {
			lines[i] = { .x = 0, .y = i };
		}
		state = LOGO_STATE_MESH;
		break;

	case LOGO_STATE_MESH:
		for (int i = 0; i < lines.size(); i++) {
			int x = (int)(amplitude * sin(DEG_TO_RAD(i * wavelength + angle)));
			if ((i % 2) == 0) {
				lines[i] = {.x = x, .y = i};
			}
			else {
				lines[i] = {.x = -x, .y = i};
			}
		}
		if (padData & PAD_UP) {
			angle++;
		}
		if (padData & PAD_DOWN) {
			angle--;
		}
		if (padData & PAD_LEFT) {
			amplitude--;
		}
		if (padData & PAD_RIGHT) {
			amplitude++;
		}
		if (padData & PAD_DBG1) {
			wavelength -= 0.01;
		}
		if (padData & PAD_DBG2) {
			wavelength += 0.01;
		}


		printf("ang: %f, amp: %f, wl: %f\n", angle, amplitude, wavelength);

		logo->disp((WINDOW_LOWIDTH / 2) - (LOGO_WIDTH / 2), (WINDOW_LOHEIGHT / 2) - (LOGO_HEIGHT / 2), lines);
		break;
	}

	if (padDataE & PAD_ENTER) {
		state = LOGO_STATE_INIT;
		return 1;
	}

	return 0;
}
\ No newline at end of file

M logo.h => logo.h +2 -5
@@ 1,5 1,5 @@
/* logo.h: logo display code
*  Copyright (C) 2021 Nathan Misner
*  Copyright (C) 2022 Nathan Misner
*
*  This file is part of LibreMO.
*


@@ 16,9 16,6 @@
*  You should have received a copy of the GNU General Public License
*  along with LibreMO.  If not, see <https://www.gnu.org/licenses/>.
*/

#pragma once

// displays the CUSTOM logo
// returns 1 if done running, 0 otherwise
int Logo_Run(void);
int Logo_Run();
\ No newline at end of file

A otherlogo.cpp => otherlogo.cpp +168 -0
@@ 0,0 1,168 @@
/* otherlogo.c: logo display code
*  Copyright (C) 2021 Nathan Misner
*
*  This file is part of LibreMO.
*
*  LibreMO is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  LibreMO is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with LibreMO.  If not, see <https://www.gnu.org/licenses/>.
*/

#include <SDL.h>
#include <memory>
#include <string>
#include <vector>

#include "fade.h"
#include "globals.h"
#include "otherlogo.h"
#include "pad.h"
#include "sound.h"
#include "speed.h"
#include "sprite.h"

// each updated frame of chip doing stuff is 128x128
#define CHIP_WIDTH (128)
#define CHIP_HEIGHT (128)
#define CHIP_ROWS (3)
#define CHIP_COLS (5)

#define ROAR_SFX (0)

typedef enum {
	STATE_LOGO_INIT = 0,
	STATE_LOGO_FADEIN,
	STATE_LOGO_RUN,
	STATE_LOGO_DONE,
	STATE_LOGO_FADEOUT,
	STATE_LOGO_END
} LOGO_STATE;

static int timings[] = {186, 10, 10, 8, 66, 16, 8, 52, 9, 12, 16, 18, 39, 12, 5};
static float timer;
static int cursor;
static int state = STATE_LOGO_INIT;
static float frame;

static SpriteInfo bgSprite;
static SpriteInfo chipSprite;
static std::vector<std::unique_ptr<PakFrame>> chipTextures;

static void OtherLogo_Init() {
    Global_SetHiRes();
    bgSprite = SpriteInfo("CUSTOM.png");
    chipTextures = Sprite_LoadPak("CUSTOM.pak");

    bgSprite.x = ((float)WINDOW_WIDTH / 2)  - ((float)bgSprite.source.w / 2);
    bgSprite.y = ((float)WINDOW_HEIGHT / 2) - ((float)bgSprite.source.h / 2);
    
    /*
    if (!Sound_LoadSFX("sfx/roar.wav", ROAR_SFX)) {
        printf("Error loading roar sfx!\n");
        return;
    }*/

    SDL_Rect chipDimensions;
    chipDimensions.x = 0;
    chipDimensions.y = 0;
    chipDimensions.w = CHIP_WIDTH;
    chipDimensions.h = CHIP_HEIGHT;
    chipSprite = SpriteInfo(chipTextures[0]->texture, NULL, &chipDimensions);
    chipSprite.x = bgSprite.x + 83;
    chipSprite.y = bgSprite.y + 7;

    // clear the variables
    timer = 0;
    cursor = 0;
    frame = 0;
    state = STATE_LOGO_INIT;
}

static void OtherLogo_LoadFrame(int num) {
    chipSprite.texture = chipTextures[num]->texture;
}

int OtherLogo_Run(void) {
    if (state != STATE_LOGO_END) {
        bgSprite.draw();
    }

    if ((state < STATE_LOGO_FADEOUT) && padData) {
        state = STATE_LOGO_FADEOUT;
        Fade_Out(60);
        state = STATE_LOGO_FADEOUT;
    }

    switch(state) {
        case STATE_LOGO_INIT:
            Fade_In(60);
            OtherLogo_Init();
            frame = 0;
            state = STATE_LOGO_FADEIN;
            break;
        
        case STATE_LOGO_FADEIN:
            if (Fade_InDone()) {
                if (!Sound_PlayVGM("music/28 Opening (with SFX).vgz")) {
                    printf("Error loading logo music!\n");
                }
                state = STATE_LOGO_RUN;
            }
            break;

        case STATE_LOGO_RUN:
            if (cursor < (int)(sizeof(timings) / sizeof(timings[0]))) {
                timer += Speed_Multiplier();
                if (timer > timings[cursor]) {
                    OtherLogo_LoadFrame(cursor++);
                    timer = 0;
                    if (cursor == 9) {
                        //Sound_PlaySFX(ROAR_SFX);
                    }
                }
            }
            else {
                frame = 0;
                state = STATE_LOGO_DONE;
            }
            if (cursor > 0) {
                chipSprite.draw();
            }
            break;

        case STATE_LOGO_DONE:
            frame += Speed_Multiplier();
            if (frame > 60) {
                Fade_Out(60);
                frame = 0;
                state = STATE_LOGO_FADEOUT;
            }
            chipSprite.draw();
            break;
            
        case STATE_LOGO_FADEOUT:
            if (Fade_OutDone()) {
                state = STATE_LOGO_END;
            }
            chipSprite.draw();
            break;

        case STATE_LOGO_END:
            state = STATE_LOGO_INIT;
            Sound_FreeSFX(ROAR_SFX);
            Sound_StopMusic();
            Fade_Stop();
            return 1;
    }

    return 0;
}

A otherlogo.h => otherlogo.h +24 -0
@@ 0,0 1,24 @@
/* otherlogo.h: logo display code
*  Copyright (C) 2021 Nathan Misner
*
*  This file is part of LibreMO.
*
*  LibreMO is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  LibreMO is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with LibreMO.  If not, see <https://www.gnu.org/licenses/>.
*/

#pragma once

// displays the CUSTOM logo
// returns 1 if done running, 0 otherwise
int OtherLogo_Run(void);

A raster.cpp => raster.cpp +138 -0
@@ 0,0 1,138 @@
/* raster.cpp: Simulates raster effects
*  Copyright (C) 2022 Nathan Misner
*
*  This file is part of LibreMO.
*
*  LibreMO is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  LibreMO is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with LibreMO.  If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdexcept>

#include <SDL.h>
#include <SDL_image.h>

#include "globals.h"
#include "path.h"
#include "raster.h"

Raster::Raster(const std::string &filename) {
	// load image
	SDL_Surface *loadSurface = IMG_Load(Path_Graphics("oldlogo.png").c_str());
	if (loadSurface == NULL) {
		throw std::runtime_error(SDL_GetError());
	}
	// convert to a consistent pixel format
	srcSurface = std::make_unique<Surface>(SDL_ConvertSurfaceFormat(loadSurface, gPaletteFormat->format, 0));
	if (srcSurface->raw == NULL) {
		throw std::runtime_error(SDL_GetError());
	}
	SDL_FreeSurface(loadSurface);

	// make the output surfaces
    dstSurface = std::make_unique<Surface>(SDL_CreateRGBSurfaceWithFormat(0,
        WINDOW_WIDTH, WINDOW_HEIGHT, 32, srcSurface->raw->format->format));
    if (dstSurface == NULL) {
        throw std::runtime_error(SDL_GetError());
    }
    if (SDL_SetSurfaceBlendMode(dstSurface->raw, SDL_BLENDMODE_BLEND) < 0) {
        throw std::runtime_error(SDL_GetError());
    }

    dispSurface = std::make_unique<Surface>(SDL_CreateRGBSurfaceWithFormat(0,
        WINDOW_WIDTH, WINDOW_HEIGHT, 32, srcSurface->raw->format->format));
    if (dispSurface == NULL) {
        throw std::runtime_error(SDL_GetError());
    }
    if (SDL_SetSurfaceBlendMode(dispSurface->raw, SDL_BLENDMODE_BLEND) < 0) {
        throw std::runtime_error(SDL_GetError());
    }

    // make the output texture
    dispTexture = std::make_unique<Texture>(SDL_CreateTexture(gRenderer, srcSurface->raw->format->format, SDL_TEXTUREACCESS_STREAMING,
        dispSurface->raw->w, dispSurface->raw->h));
    if (dispTexture == NULL) {
        throw std::runtime_error(SDL_GetError());
    }
    if (SDL_SetTextureBlendMode(dispTexture->raw, SDL_BLENDMODE_BLEND) < 0) {
        throw std::runtime_error(SDL_GetError());
    }
}

void Raster::copyToTexture(SDL_Surface *source) {
    uint32_t *srcPixels = (uint32_t *)source->pixels;
    uint32_t *dstPixels = nullptr;
    int pitch = 0;

    if (SDL_LockTexture(dispTexture->raw, NULL, (void **)&dstPixels, &pitch) < 0) {
        throw std::runtime_error(SDL_GetError());
    }

    int size = (pitch / source->format->BytesPerPixel) * source->h;
    for (int i = 0; i < size; i++) {
        dstPixels[i] = srcPixels[i];
    }

    SDL_UnlockTexture(dispTexture->raw);
}

void Raster::disp(float x, float y, std::array<RASTER_LINE, WINDOW_HEIGHT> &lines) {
    SDL_Rect srcRect, dstRect;

    // clear the surfaces
    SDL_FillRect(dstSurface->raw, NULL, SDL_MapRGBA(dstSurface->raw->format, 0, 0, 0, 0));
    SDL_FillRect(dispSurface->raw, NULL, SDL_MapRGBA(dispSurface->raw->format, 0, 0, 0, 0));

    // blit the graphics surface to the destination surface
    srcRect = {
        .x = 0,
        .y = 0,
        .w = srcSurface->raw->w,
        .h = srcSurface->raw->h
    };
    dstRect = {
        .x = (int)x,
        .y = (int)y,
        .w = srcRect.w,
        .h = srcRect.h
    };
    SDL_BlitSurface(srcSurface->raw, &srcRect, dstSurface->raw, &dstRect);

    // copy each scanline from the destination surface to the display surface
    srcRect = {
        .x = 0,
        .y = 0,
        .w = dstSurface->raw->w,
        .h = 1
    };
    dstRect = {
        .x = 0,
        .y = 0,
        .w = srcRect.w,
        .h = srcRect.h
    };
    for (int i = 0; i < lines.size(); i++) {
        dstRect.x = lines[i].x; // the x controls how the line should be pushed over
        dstRect.y = i;
        srcRect.y = lines[i].y; // the y controls which line gets shown
        SDL_BlitSurface(dstSurface->raw, &srcRect, dispSurface->raw, &dstRect);
    }
    copyToTexture(dispSurface->raw);
    
    SDL_Rect renderRect = {
        .x = 0,
        .y = 0,
        .w = dispSurface->raw->w,
        .h = dispSurface->raw->h
    };
    SDL_RenderCopy(gRenderer, dispTexture->raw, NULL, &renderRect);
}
\ No newline at end of file

A raster.h => raster.h +43 -0
@@ 0,0 1,43 @@
/* raster.h: Simulates raster effects
*  Copyright (C) 2022 Nathan Misner
*
*  This file is part of LibreMO.
*
*  LibreMO is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  LibreMO is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with LibreMO.  If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once

#include <array>
#include <memory>
#include <string>
#include "globals.h"
#include "sdl_wrappers.h"

typedef struct {
	int x;
	int y;
} RASTER_LINE;

class Raster {
private:
	std::unique_ptr<Surface> srcSurface;
	std::unique_ptr<Surface> dstSurface;
	std::unique_ptr<Surface> dispSurface;
	std::unique_ptr<Texture> dispTexture;
	void copyToTexture(SDL_Surface *source);

public:
	Raster(const std::string &filename);
	void disp(float x, float y, std::array<RASTER_LINE, WINDOW_HEIGHT> &lines);
};
\ No newline at end of file