Smoother movements on objects on moving solidmasks

The behavior is still not perfect yet since the attachment of the object
to the SolidMask may re-position the object by 1 pixel. I am not sure
this can be solved correctly since there are three coordinates involved
who can be (and, generally, are) different on a sub-pixel level. These
are the object's position itself the position of the solidmask object
and the position of the solidmask (which is constrained to pixel boundaries).
However, the attachment code only knows the object and the solidmask, not
the solidmask object, so it possibly cannot properly account for this.
Armin Burgmeier 2012-01-12 00:49:12 +01:00
parent 955a321885
commit c46f406943
4 changed files with 20 additions and 10 deletions

View File

@ -185,14 +185,14 @@ void C4SolidMask::Put(bool fCauseInstability, C4TargetRect *pClipRect, bool fRes
// restore attached object positions if moved
if (fRestoreAttachment && iAttachingObjectsCount)
{
int32_t dx = pForObject->GetX() - MaskRemovalX;
int32_t dy = pForObject->GetY() - MaskRemovalY;
if (dx|dy)
C4Real dx = pForObject->GetFixedX() - MaskRemovalX;
C4Real dy = pForObject->GetFixedY() - MaskRemovalY;
if (dx != Fix0 || dy != Fix0)
for (int i = 0; i < iAttachingObjectsCount; ++i)
{
C4Object *pObj = ppAttachingObjects[i];
if (pObj->IsMoveableBySolidMask(pForObject->GetPlane()))
if (!pObj->Shape.ContactCheck(pObj->GetX()+dx, pObj->GetY()+dy))
if (!pObj->Shape.ContactCheck(pObj->GetFixedX()+dx, pObj->GetFixedY()+dy))
if (pObj->iLastAttachMovementFrame != Game.FrameCounter)
{
pObj->iLastAttachMovementFrame = Game.FrameCounter;
@ -282,8 +282,8 @@ void C4SolidMask::Remove(bool fBackupAttachment)
// backup attachment if desired: Backup old pos and all objects that attach to or lie on the SolidMask
if (fBackupAttachment)
{
MaskRemovalX = pForObject->GetX();
MaskRemovalY = pForObject->GetY();
MaskRemovalX = pForObject->GetFixedX();
MaskRemovalY = pForObject->GetFixedY();
iAttachingObjectsCount = 0;
C4LArea SolidArea(&::Objects.Sectors, MaskPutRect.x-1, MaskPutRect.y-1, MaskPutRect.Wdt+2, MaskPutRect.Hgt+2);
C4LSector *pSct; C4Object *pObj;
@ -397,7 +397,7 @@ C4SolidMask::C4SolidMask(C4Object *pForObject) : pForObject(pForObject)
// zero fields
MaskPut=false;
MaskPutRotation=0;
MaskRemovalX=MaskRemovalY=0;
MaskRemovalX=MaskRemovalY=Fix0;
ppAttachingObjects=NULL;
iAttachingObjectsCount=iAttachingObjectsCapacity=0;
// Update linked list

View File

@ -32,7 +32,7 @@ protected:
int MaskPutRotation; // rotation in which the mask was put (and resides in the buffers)
int MatBuffPitch; // pitch (and width) of mat buffer
int32_t MaskRemovalX, MaskRemovalY; // last position mask was removed from
C4Real MaskRemovalX, MaskRemovalY; // last position mask was removed from
class C4Object **ppAttachingObjects; // objects to be moved with mask motion
int iAttachingObjectsCount, iAttachingObjectsCapacity;

View File

@ -241,7 +241,7 @@ void C4Object::DoMovement()
}
// store previous position
int32_t ix0=GetX(); int32_t iy0=GetY();
C4Real ix0=GetFixedX(); C4Real iy0=GetFixedY();
// store previous movement and ocf
C4Real oldxdir(xdir), oldydir(ydir);
@ -349,6 +349,10 @@ void C4Object::DoMovement()
}
while (Abs<C4Real>(fix_x - ctcox) > C4REAL10(5) || Abs<C4Real>(fix_y - ctcoy) > C4REAL10(5));
}
if(fix_x != new_x || fix_y != new_y)
if (pSolidMaskData)
pSolidMaskData->Remove(true);
fix_x = new_x;
fix_y = new_y;
// Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -455,7 +459,7 @@ void C4Object::DoMovement()
UpdateFace(true);
else
// pos changed?
if ((ix0-GetX())|(iy0-GetY())) UpdatePos();
if ((ix0-GetFixedX())|(iy0-GetFixedY())) UpdatePos();
}
void C4Object::Stabilize()
@ -506,6 +510,11 @@ void C4Object::ForcePosition(C4Real tx, C4Real ty)
}
void C4Object::MovePosition(int32_t dx, int32_t dy)
{
MovePosition(itofix(dx), itofix(dy));
}
void C4Object::MovePosition(C4Real dx, C4Real dy)
{
// move object position; repositions SolidMask
if (pSolidMaskData) pSolidMaskData->Remove(true);

View File

@ -294,6 +294,7 @@ public:
void CopyMotion(C4Object *from);
void ForcePosition(C4Real tx, C4Real ty);
void MovePosition(int32_t dx, int32_t dy);
void MovePosition(C4Real dx, C4Real dy);
void DoMotion(int32_t mx, int32_t my);
bool ActivateEntrance(int32_t by_plr, C4Object *by_obj);
bool Incinerate(int32_t iCausedBy, bool fBlasted=false, C4Object *pIncineratingObject=NULL);