SpaceCadetPinball/SpaceCadetPinball/TFlipper.cpp

185 lines
4.1 KiB
C++

#include "pch.h"
#include "TFlipper.h"
#include "control.h"
#include "loader.h"
#include "pb.h"
#include "render.h"
#include "TFlipperEdge.h"
#include "timer.h"
#include "TPinballTable.h"
TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
{
visualStruct visual{};
loader::query_visual(groupIndex, 0, &visual);
HardHitSoundId = visual.SoundIndex4;
SoftHitSoundId = visual.SoundIndex3;
Elasticity = visual.Elasticity;
Timer = 0;
Smoothness = visual.Smoothness;
auto collMult = *loader::query_float_attribute(groupIndex, 0, 803);
auto retractTime = *loader::query_float_attribute(groupIndex, 0, 805);
auto extendTime = *loader::query_float_attribute(groupIndex, 0, 804);
/*Full tilt hack: different flipper speed*/
if (pb::FullTiltMode)
{
retractTime = 0.08f;
extendTime = 0.04f;
}
auto vecT2 = reinterpret_cast<vector3*>(loader::query_float_attribute(groupIndex, 0, 802));
auto vecT1 = reinterpret_cast<vector3*>(loader::query_float_attribute(groupIndex, 0, 801));
auto origin = reinterpret_cast<vector3*>(loader::query_float_attribute(groupIndex, 0, 800));
auto flipperEdge = new TFlipperEdge(
this,
&ActiveFlag,
visual.CollisionGroup,
table,
origin,
vecT1,
vecT2,
extendTime,
retractTime,
collMult,
Elasticity,
Smoothness);
FlipperEdge = flipperEdge;
if (flipperEdge)
{
ExtendAnimationFrameTime = flipperEdge->ExtendTime / static_cast<float>(ListBitmap->size() - 1);
RetractAnimationFrameTime = flipperEdge->RetractTime / static_cast<float>(ListBitmap->size() - 1);
}
BmpIndex = 0;
InputTime = 0.0;
}
TFlipper::~TFlipper()
{
delete FlipperEdge;
}
int TFlipper::Message(int code, float value)
{
if (code == 1 || code == 2 || (code > 1008 && code <= 1011) || code == 1022)
{
float timerTime;
int command = code;
if (code == 1)
{
control::handler(1, this);
TimerTime = ExtendAnimationFrameTime;
loader::play_sound(HardHitSoundId);
}
else if (code == 2)
{
TimerTime = RetractAnimationFrameTime;
loader::play_sound(SoftHitSoundId);
}
else
{
// Retract for all non-input messages
command = 2;
TimerTime = RetractAnimationFrameTime;
}
if (MessageField)
{
// Message arrived before animation is finished
auto inputDt = value - FlipperEdge->InputTime;
timerTime = inputDt - floor(inputDt / TimerTime) * TimerTime;
if (timerTime < 0.0f)
timerTime = 0.0;
}
else
{
timerTime = TimerTime;
}
MessageField = command;
InputTime = value;
if (Timer)
timer::kill(Timer);
Timer = timer::set(timerTime, this, TimerExpired);
FlipperEdge->SetMotion(command, value);
}
if (code == 1020 || code == 1024)
{
if (MessageField)
{
if (Timer)
timer::kill(Timer);
BmpIndex = -1;
MessageField = 2;
TimerExpired(Timer, this);
FlipperEdge->SetMotion(code, value);
}
}
return 0;
}
void TFlipper::port_draw()
{
FlipperEdge->port_draw();
}
void TFlipper::Collision(TBall* ball, vector2* nextPosition, vector2* direction, float distance, TEdgeSegment* edge)
{
}
void TFlipper::TimerExpired(int timerId, void* caller)
{
auto flip = static_cast<TFlipper*>(caller);
int bmpCountSub1 = flip->ListBitmap->size() - 1;
auto newBmpIndex = static_cast<int>(floor((pb::time_now - flip->InputTime) / flip->TimerTime));
if (newBmpIndex > bmpCountSub1)
newBmpIndex = bmpCountSub1;
if (newBmpIndex < 0)
newBmpIndex = 0;
bool bmpIndexOutOfBounds = false;
if (flip->MessageField == 1)
{
flip->BmpIndex = newBmpIndex;
if (flip->BmpIndex >= bmpCountSub1)
{
flip->BmpIndex = bmpCountSub1;
bmpIndexOutOfBounds = true;
}
}
if (flip->MessageField == 2)
{
flip->BmpIndex = bmpCountSub1 - newBmpIndex;
if (flip->BmpIndex <= 0)
{
flip->BmpIndex = 0;
bmpIndexOutOfBounds = true;
}
}
if (bmpIndexOutOfBounds)
{
flip->MessageField = 0;
flip->Timer = 0;
}
else
{
flip->Timer = timer::set(flip->TimerTime, flip, TimerExpired);
}
auto bmp = flip->ListBitmap->at(flip->BmpIndex);
auto zMap = flip->ListZMap->at(flip->BmpIndex);
render::sprite_set(
flip->RenderSprite,
bmp,
zMap,
bmp->XPosition - flip->PinballTable->XOffset,
bmp->YPosition - flip->PinballTable->YOffset);
}