forked from Mirrors/openclonk
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.
parent
955a321885
commit
c46f406943
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue