1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-02-03 18:14:01 +00:00
Aquaria/Aquaria/Element.cpp
fgenesis e8c405cd9e more drafting for tile redering optimization
This is the last commit before the old Element class gets ripped
2023-07-11 22:30:28 +02:00

353 lines
7.2 KiB
C++

/*
Copyright (C) 2007, 2010 - Bit-Blot
This file is part of Aquaria.
Aquaria 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 2
of the License, or (at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "Element.h"
#include "Game.h"
#include "RenderGrid.h"
ElementEffectData::ElementEffectData()
: elementEffectType(EFX_NONE)
, wavyAngleOffset(0)
, wavyMagnitude(0)
, wavyLerpIn(0)
, wavyMin(0)
, wavyMax(0)
, hitPerc(0)
, effectMult(0)
, wavyWaving(false)
, wavyFlip(false)
, touching(false)
, elementEffectIndex(-1)
{
}
Element::Element() : Quad()
{
elementFlag = EF_NONE;
bgLayer = 0;
tag = 0;
templateIdx = -1;
eff = NULL;
}
void Element::ensureEffectData()
{
if (!eff)
eff = new ElementEffectData;
}
void Element::freeEffectData()
{
if (eff)
{
delete eff;
eff = NULL;
}
}
void Element::doInteraction(Entity *ent, float mult, float touchWidth)
{
ElementEffectData *eff = this->eff;
Vector pos = position;
pos.y -= (height*scale.y)/2;
float hitPerc=0;
Vector p = ent->position;
if (p.x > position.x-touchWidth && p.x < position.x+touchWidth)
{
float h2 = (height*scale.y)/2.0f;
if (p.y < position.y+h2 && p.y > position.y-h2)
{
eff->touching = true;
eff->wavyWaving = true;
hitPerc = pos.y - p.y;
hitPerc /= float(height*scale.y);
hitPerc = (1.0f-hitPerc)-1.0f;
eff->hitPerc = hitPerc;
eff->touchVel = ent->vel;
eff->effectMult = mult;
}
}
}
void Element::updateEffects(float dt)
{
switch (eff->elementEffectType)
{
case EFX_ALPHA:
alpha.update(dt);
break;
case EFX_WAVY:
//debugLog("EXF_WAVY update");
/// check player position
{
// if a big wavy doesn't work, this is probably why
{
ElementEffectData *eff = this->eff;
if (eff->touching)
{
eff->touching = false;
float ramp = eff->touchVel.getLength2D()/800.0f;
if (ramp < 0) ramp = 0;
if (ramp > 1) ramp = 1;
eff->wavyMagnitude = 100 * ramp + 16;
if (eff->touchVel.x < 0)
eff->wavyMagnitude = -eff->wavyMagnitude;
eff->wavyAngleOffset = (eff->hitPerc-0.5f)*PI;
eff->wavySave = eff->wavy;
eff->wavyLerpIn = 0;
}
if (eff->wavyWaving)
{
float spd = PI*1.1f;
float magRedSpd = 48;
float lerpSpd = 5.0;
float wavySz = float(eff->wavy.size());
for (size_t i = 0; i < eff->wavy.size(); i++)
{
float weight = float(i)/wavySz;
if (eff->wavyFlip)
weight = 1.0f-weight;
if (weight < 0.125f)
weight *= 0.5f;
eff->wavy[i] = sinf(eff->wavyAngleOffset + (float(i)/wavySz)*PI)*float(eff->wavyMagnitude*eff->effectMult)*weight;
if (!eff->wavySave.empty())
{
if (eff->wavyLerpIn < 1)
eff->wavy[i] = eff->wavy[i]*eff->wavyLerpIn + (eff->wavySave[i]*(1.0f-eff->wavyLerpIn));
}
}
if (eff->wavyLerpIn < 1)
{
eff->wavyLerpIn += dt*lerpSpd;
if (eff->wavyLerpIn > 1)
eff->wavyLerpIn = 1;
}
eff->wavyAngleOffset += dt*spd;
if (eff->wavyMagnitude > 0)
{
eff->wavyMagnitude -= magRedSpd*dt;
if (eff->wavyMagnitude < 0)
eff->wavyMagnitude = 0;
}
else
{
eff->wavyMagnitude += magRedSpd*dt;
if (eff->wavyMagnitude > 0)
eff->wavyMagnitude = 0;
}
setGridFromWavy();
}
else
{
//std::cout << "not waving";
setGridFromWavy();
}
}
}
break;
}
}
void Element::update(float dt)
{
if (!core->particlesPaused)
{
updateLife(dt);
if (eff)
updateEffects(dt);
if(grid)
grid->update(dt);
}
}
Element::~Element()
{
freeEffectData();
}
void Element::destroy()
{
Quad::destroy();
}
int Element::getElementEffectIndex()
{
return eff ? eff->elementEffectIndex : -1;
}
void Element::setGridFromWavy()
{
if(grid && eff->wavy.size())
grid->setFromWavy(&eff->wavy[0], eff->wavy.size(), width);
}
void Element::setElementEffectByIndex(int eidx)
{
deleteGrid();
setBlendType(BLEND_DEFAULT);
alpha.stop();
alpha = 1;
ElementEffect e = dsq->getElementEffectByIndex(eidx);
if(e.type != EFX_NONE)
ensureEffectData();
switch(e.type)
{
case EFX_SEGS:
{
setSegs(e.segsx, e.segsy, e.segs_dgox, e.segs_dgoy, e.segs_dgmx, e.segs_dgmy, e.segs_dgtm, e.segs_dgo);
}
break;
case EFX_ALPHA:
{
setBlendType(e.blendType);
alpha = e.alpha;
}
break;
case EFX_WAVY:
{
eff->wavy.resize(e.segsy, 0.0f);
float bity = float(getHeight())/float(e.segsy);
eff->wavyFlip = e.wavy_flip;
eff->wavyMin = bity;
eff->wavyMax = bity*1.2f;
if(RenderGrid *g = createGrid(2, e.segsy))
{
g->gridType = GRID_UNDEFINED; // by default it's GRID_WAVY, but that would reset during update
setGridFromWavy();
}
}
break;
default:
freeEffectData();
break;
}
if (eff)
{
eff->elementEffectIndex = eidx;
eff->elementEffectType = e.type;
}
}
// shamelessly ripped from paint.net default palette
static const Vector s_tagColors[] =
{
/* 0 */ Vector(0.5f, 0.5f, 0.5f),
/* 1 */ Vector(1,0,0),
/* 2 */ Vector(1, 0.415686f, 0),
/* 3 */ Vector(1,0.847059f, 0),
/* 4 */ Vector(0.298039f,1,0),
/* 5 */ Vector(0,1,1),
/* 6 */ Vector(0,0.580392,1),
/* 7 */ Vector(0,0.149020f,1),
/* 8 */ Vector(0.282353f,0,1),
/* 9 */ Vector(0.698039f,0,1),
/* 10 */ Vector(1,0,1), // anything outside of the pretty range
};
static inline const Vector& getTagColor(int tag)
{
const unsigned idx = std::min<unsigned>(unsigned(tag), Countof(s_tagColors)-1);
return s_tagColors[idx];
}
void Element::render(const RenderState& rs) const
{
// FIXME: this should be part of the layer render, not here
// (not relevant until Elements are batched per-layer)
if (game->isSceneEditorActive() && this->bgLayer == game->sceneEditor.bgLayer
&& game->sceneEditor.editType == ET_ELEMENTS)
{
Vector tagColor = getTagColor(tag);
bool hl = false;
if (!game->sceneEditor.selectedElements.empty())
{
for (size_t i = 0; i < game->sceneEditor.selectedElements.size(); i++)
{
if (this == game->sceneEditor.selectedElements[i])
{
hl = true;
break;
}
}
}
else
{
hl = game->sceneEditor.editingElement == this;
}
if(hl)
tagColor += Vector(0.5f, 0.5f, 0.5f);
RenderState rs2(rs);
rs2.forceRenderBorder = true;
rs2.forceRenderCenter = true;
rs2.renderBorderColor = tagColor;
Quad::render(rs2);
}
else // render normally
Quad::render(rs);
}
void Element::fillGrid()
{
if (life == 1 && !_hidden)
{
if (elementFlag == EF_SOLID)
{
game->fillGridFromQuad(this, OT_INVISIBLE, true);
}
else if (elementFlag == EF_HURT)
{
game->fillGridFromQuad(this, OT_HURT, false);
}
else if (elementFlag == EF_SOLID2)
{
game->fillGridFromQuad(this, OT_INVISIBLE, false);
}
else if (elementFlag == EF_SOLID3)
{
game->fillGridFromQuad(this, OT_INVISIBLEIN, false);
}
}
}
void Element::setTag(int tag)
{
this->tag = tag;
}