Rendering!! It sorta works.

master
sigonasr2 5 months ago
parent bbeac33ad6
commit 1f20f0c837
  1. 186
      EarthboundBattleBackgrounds/EarthboundBattleBackgrounds/main.cpp
  2. BIN
      EarthboundBattleBackgrounds/x64/Debug/EarthboundBattleBackgrounds.exe

@ -320,8 +320,52 @@ struct Rom{
const float c3{PI/60.f};
Sprite&bitmap;
std::unique_ptr<DistortionEffect>effect;
float amplitude,frequency,compression,speed;
Distorter(Sprite&bitmap)
:bitmap(bitmap){}
void setup(int ticks){
int t2{ticks*2};
amplitude=c1*(effect->amplitude()+effect->amplitudeAcceleration()*t2);
frequency=c2*(effect->frequency()+(effect->frequencyAcceleration()*t2));
compression=1+(effect->compression()+(effect->compressionAcceleration()*t2))/256.f;
speed=c3*speed*ticks;
}
float getAppliedOffset(int y){
float s=std::round(amplitude*sin(frequency*y+speed));
switch(effect->type()){
case DistortionEffect::HORIZONTAL:return s;
case DistortionEffect::HORIZONTAL_INTERLACED:return y%2?s:-s;
case DistortionEffect::VERTICAL:return fmod(floor(s+y*effect->compression()),256.f);
}
}
void computeFrame(PixelGameEngine*pge,int ticks,float alpha,bool erase){
setup(ticks);
for(int y:std::views::iota(0,pge->ScreenHeight())){
float offset{getAppliedOffset(y)};
int L=effect->type()==DistortionEffect::VERTICAL?offset:y;
for(int x:std::views::iota(0,pge->ScreenWidth())){
int dx=x;
if(effect->type()==DistortionEffect::HORIZONTAL||effect->type()==DistortionEffect::HORIZONTAL_INTERLACED)dx=fmod(x+offset,pge->ScreenWidth());
if(erase){
Pixel newCol{bitmap.GetPixel(dx,L)};
newCol.r*=alpha;
newCol.g*=alpha;
newCol.b*=alpha;
pge->Draw(dx,L,newCol);
}else{
Pixel newCol{bitmap.GetPixel(dx,L)};
newCol.r*=alpha;
newCol.g*=alpha;
newCol.b*=alpha;
Pixel mixedCol{pge->GetDrawTarget()->GetPixel(dx,L)};
mixedCol.r+=newCol.r;
mixedCol.g+=newCol.g;
mixedCol.b+=newCol.b;
pge->Draw(dx,L,mixedCol);
}
}
}
}
};
struct PaletteCycle{
@ -334,6 +378,51 @@ struct Rom{
originalCols.emplace_back(originalCols[i]);
}
}
void cycle(){
if(speed==0)return;
cycleCountdown=std::clamp(cycleCountdown-1,0,int(std::numeric_limits<byte>::max()));
if(cycleCountdown<=0){
cycleColors();
cycleCount++;
cycleCountdown=speed;
}
}
void cycleColors(){
if(type==1||type==2){
int cycleLength{end1-start1+1};
int cycle1Position{cycleCount%cycleLength};
for(int i:std::views::iota(int(start1),end1+1)){
int newColor=i-cycle1Position;
if(newColor<start1)newColor+=cycleLength;
currentCols[i]=originalCols[newColor];
}
}
if(type==2){
int cycleLength{end2-start2+1};
int cycle2Position{cycleCount%cycleLength};
for(int i:std::views::iota(int(start2),end2+1)){
int newColor=i-cycle2Position;
if(newColor<start2)newColor+=cycleLength;
currentCols[i]=originalCols[newColor];
}
}
if(type==3){
int cycleLength{end1-start1+1};
int cycle1Position{cycleCount%(cycleLength*2)};
for(int i:std::views::iota(int(start1),end1+1)){
int newColor=i+cycle1Position;
if(newColor>end1){
int difference{newColor-end1-1};
newColor=end1-difference;
if(newColor<start1){
difference=start1-newColor-1;
newColor=start1+difference;
}
}
currentCols[i]=originalCols[newColor];
}
}
}
};
PixelGameEngine*pge;
@ -343,6 +432,43 @@ struct Rom{
BackgroundGraphics&graphics;
PaletteCycle cycle;
uint_fast16_t backgroundInd;
void drawTile(const int x,const int y,const int tile,const int subPalette,const bool verticalFlip,const bool horizontalFlip){
int px{},py{};
for(int i:std::views::iota(0,8)){
if(horizontalFlip)px=x+7-i;
else px=x+i;
for(int j:std::views::iota(0,8)){
if(verticalFlip)py=y+7-j;
else py=y+j;
spr->SetPixel(px,py,cycle.currentCols[graphics.tiles[tile][i][j]]);
}
}
}
void draw(){
int block{};
int tile{};
int subPalette{}; //Subpalette should always be zero....I don't understand?
int n{};
int b1{};
int b2{};
bool verticalFlip{false};
bool horizontalFlip{false};
for(int i:std::views::iota(0,32)){
for(int j:std::views::iota(0,32)){
n=j*32+i;
b1=graphics.arrayGraphicsData[n*2];
b2=graphics.arrayGraphicsData[n*2+1]<<8;
block=b1+b2;
tile=block&0x3FF;
verticalFlip=block&0x8000;
horizontalFlip=block&0x4000;
//subPalette=(block>>10)&7; //THIS SHOULD NOT BE NECESSARY!!!
drawTile(i*8,j*8,tile,0,verticalFlip,horizontalFlip);
}
}
}
BackgroundLayer(PixelGameEngine*pge,uint_fast16_t backgroundInd,std::vector<BattleBackground>&backgrounds,std::vector<BackgroundPalette>&palettes,std::vector<BackgroundGraphics>&graphics,std::u8string_view data)
:pge(pge),spr(new Sprite(256,256)),distorter(*spr),backgroundInd(backgroundInd),background(backgrounds[backgroundInd]),graphics(graphics[background.graphicsInd]),cycle(background,palettes[background.paletteInd]){
uint_fast32_t effectVal{((background.GetAnimation()>>16)&0xFF)};
@ -366,10 +492,20 @@ struct Rom{
backgroundInd=std::clamp(backgroundInd,0U,uint_fast16_t(backgrounds.size()));
layer2=std::make_unique<BackgroundLayer>(nullptr,backgroundInd,backgrounds,palettes,graphics,data);
}
void AdvanceLayers(int tick,float alpha1,float alpha2){
layer1->cycle.cycle();
layer1->draw();
layer1->distorter.computeFrame(pge,tick,alpha1,true);
layer2->cycle.cycle();
layer2->draw();
layer2->distorter.computeFrame(pge,tick,alpha2,false);
}
private:
std::unique_ptr<BackgroundLayer>layer1,layer2;
PixelGameEngine*pge;
public:
Rom(){
Rom(PixelGameEngine*pge)
:pge(pge){
#pragma region Setup Reversed Bytes
reversedBytes.resize(256);
for(int i:std::views::iota(0U,reversedBytes.size())){
@ -398,8 +534,8 @@ public:
graphics.emplace_back(data,i,graphicsBits[i]);
}
layer1=std::make_unique<BackgroundLayer>(nullptr,0U,backgrounds,palettes,graphics,data);
layer2=std::make_unique<BackgroundLayer>(nullptr,0U,backgrounds,palettes,graphics,data);
layer1=std::make_unique<BackgroundLayer>(pge,0U,backgrounds,palettes,graphics,data);
layer2=std::make_unique<BackgroundLayer>(pge,0U,backgrounds,palettes,graphics,data);
}
};
@ -413,11 +549,12 @@ public:
sAppName = "Earthbound Battle Backgrounds";
}
Rom rom;
Rom*rom;
public:
bool OnUserCreate() override
{
rom=new Rom(this);
return true;
}
@ -425,7 +562,7 @@ public:
if(GetMouseWheel()<0)yOffset-=32;
if(GetMouseWheel()>0)yOffset+=32;
for(uint_fast8_t row=0;Rom::BackgroundPalette&palette:rom.palettes){
for(uint_fast8_t row=0;Rom::BackgroundPalette&palette:rom->palettes){
for(uint_fast8_t index=0;Pixel&col:palette.colors){
FillRectDecal(vf2d{index*8.f+8,row*8.f+yOffset},{8,8},col);
index++;
@ -444,17 +581,17 @@ public:
DrawStringDecal({},std::format("Selected Palette: {}",selectedPalette));
if(GetKey(PGUP).bPressed)selectedPalette=std::clamp(int(selectedPalette)-1,0,int(rom.palettes.size()-1));
if(GetKey(PGDN).bPressed)selectedPalette=std::clamp(int(selectedPalette)+1,0,int(rom.palettes.size()-1));;
if(GetKey(PGUP).bPressed)selectedPalette=std::clamp(int(selectedPalette)-1,0,int(rom->palettes.size()-1));
if(GetKey(PGDN).bPressed)selectedPalette=std::clamp(int(selectedPalette)+1,0,int(rom->palettes.size()-1));;
Rom::BackgroundPalette&palette{rom.palettes[selectedPalette]};
Rom::BackgroundPalette&palette{rom->palettes[selectedPalette]};
for(uint_fast8_t index=0;Pixel&col:palette.colors){
FillRectDecal(vf2d{index*8.f,8.f},{8,8},col);
index++;
}
DrawRectDecal(vf2d{8.f,8.f},{8*16,8});
for(uint_fast8_t row=0;Rom::BackgroundGraphics&graphics:rom.graphics){
for(uint_fast8_t row=0;Rom::BackgroundGraphics&graphics:rom->graphics){
for(uint_fast8_t col=0;Rom::Tile&tile:graphics.tiles){
for(int x{};x<tile.size();x++){
for(int y{};y<tile[x].size();y++){
@ -473,26 +610,51 @@ public:
int yOffset{0};
float accumulatedTime{};
int tick{};
uint16_t selectedLayer1{};
uint16_t selectedLayer2{};
void runTick(){
float alpha1{1.f},alpha2{1.f};
if(rom.GetLayer1()->backgroundInd&&!rom.GetLayer2()->backgroundInd){
if(rom->GetLayer1()->backgroundInd&&!rom->GetLayer2()->backgroundInd){
alpha1=1.f;
alpha2=0.f;
}
if(!rom.GetLayer1()->backgroundInd&&rom.GetLayer2()->backgroundInd){
if(!rom->GetLayer1()->backgroundInd&&rom->GetLayer2()->backgroundInd){
alpha1=0.f;
alpha2=1.f;
}
rom->AdvanceLayers(tick,alpha1,alpha2);
}
bool OnUserUpdate(float fElapsedTime) override
{
if(GetKey(RIGHT).bPressed){
selectedLayer1=std::clamp(selectedLayer1+1,0,int(rom->backgrounds.size()));
rom->SetLayer1(selectedLayer1);
}
if(GetKey(LEFT).bPressed){
selectedLayer1=std::clamp(selectedLayer1-1,0,int(rom->backgrounds.size()));
rom->SetLayer1(selectedLayer1);
}
if(GetKey(UP).bPressed){
selectedLayer2=std::clamp(selectedLayer2+1,0,int(rom->backgrounds.size()));
rom->SetLayer2(selectedLayer2);
}
if(GetKey(DOWN).bPressed){
selectedLayer2=std::clamp(selectedLayer2-1,0,int(rom->backgrounds.size()));
rom->SetLayer2(selectedLayer2);
}
accumulatedTime+=fElapsedTime;
while(accumulatedTime>=1/60.f){
runTick();
accumulatedTime-=1/60.f
accumulatedTime-=1/60.f;
tick++;
}
DrawStringDecal({},std::format("Layer 1: {} Layer 2: {}",selectedLayer1,selectedLayer2));
return true;
}
};

Loading…
Cancel
Save