Ejemplo n.º 1
0
bool matrix_3x3_square_to_quad(const float dx0, const float dy0,
                               const float dx1, const float dy1,
                               const float dx3, const float dy3,
                               const float dx2, const float dy2,
                               math_matrix_3x3 *mat)
{
   float ax  = dx0 - dx1 + dx2 - dx3;
   float ay  = dy0 - dy1 + dy2 - dy3;

   if (floatIsZero(ax) && floatIsZero(ay)) {
      /* affine case */
      matrix_3x3_inits(mat,
                       dx1 - dx0, dy1 - dy0,  0,
                       dx2 - dx1, dy2 - dy1,  0,
                       dx0,       dy0,        1);
   } else {
      float a, b, c, d, e, f, g, h;
      float ax1 = dx1 - dx2;
      float ax2 = dx3 - dx2;
      float ay1 = dy1 - dy2;
      float ay2 = dy3 - dy2;

      /* determinants */
      float gtop    =  ax  * ay2 - ax2 * ay;
      float htop    =  ax1 * ay  - ax  * ay1;
      float bottom  =  ax1 * ay2 - ax2 * ay1;

      if (!bottom)
         return false;

      g = gtop / bottom;
      h = htop / bottom;

      a = dx1 - dx0 + g * dx1;
      b = dx3 - dx0 + h * dx3;
      c = dx0;
      d = dy1 - dy0 + g * dy1;
      e = dy3 - dy0 + h * dy3;
      f = dy0;

      matrix_3x3_inits(mat,
                       a, d, g,
                       b, e, h,
                       c, f, 1.f);
   }

   return true;
}
Ejemplo n.º 2
0
/* Given: Points (x0, y0) and (x1, y1)
 * Return: TRUE if a solution exists, FALSE otherwise
 *         Circle centers are written to (cx0, cy0) and (cx1, cy1)
 */
static VGboolean
find_unit_circles(double x0, double y0, double x1, double y1,
                  double *cx0, double *cy0,
                  double *cx1, double *cy1)
{
   /* Compute differences and averages */
   double dx = x0 - x1;
   double dy = y0 - y1;
   double xm = (x0 + x1)/2;
   double ym = (y0 + y1)/2;
   double dsq, disc, s, sdx, sdy;

   /* Solve for intersecting unit circles */
   dsq = dx*dx + dy*dy;
   if (dsq == 0.0) return VG_FALSE; /* Points are coincident */
   disc = 1.0/dsq - 1.0/4.0;

   /* the precision we care about here is around float so if we're
    * around the float defined zero then make it official to avoid
    * precision problems later on */
   if (floatIsZero(disc))
      disc = 0.0;

   if (disc < 0.0) return VG_FALSE; /* Points are too far apart */
   s = sqrt(disc);
   sdx = s*dx;
   sdy = s*dy;
   *cx0 = xm + sdy;
   *cy0 = ym - sdx;
   *cx1 = xm - sdy;
   *cy1 = ym + sdx;
   return VG_TRUE;
}
Ejemplo n.º 3
0
bool matrix_3x3_invert(math_matrix_3x3 *mat)
{
   float det = matrix_3x3_determinant(mat);

   if (floatIsZero(det))
      return false;

   matrix_3x3_adjoint(mat);
   matrix_3x3_divide_scalar(mat, det);
   return true;
}
Ejemplo n.º 4
0
static INLINE boolean
is_affine(float *matrix)
{
    return floatIsZero(matrix[2]) && floatIsZero(matrix[5])
	&& floatsEqual(matrix[8], 1);
}
Ejemplo n.º 5
0
void Hero::update()
{
	if (myIsDead)
		return;

	Entity::update();

	if (mSpawnPoint.x < -100 && mSpawnPoint.y < -100)
	{
		mSpawnPoint = getPosition();
	}

	if (mRopeState == RopeState_Dissapearing) {
		mRopeDissapearCounter++;
		if (mRopeDissapearCounter >= ROPE_DISSAPPEAR_TICKS) {
			mRopeState = RopeState_Retracted;
		}
	}

	float acceleration = mOnGround ? GROUND_ACCELERATION : AIR_ACCELERATION;
	bool airRunning = false;

	if (Input::isHeld(Button_Left)) {
		mVelocity.x -= acceleration;

		if (mRopeState == RopeState_Attached && !mOnGround) {
			mFacingDirection = Direction_Left;
			airRunning = true;
			mMovementState = MovementState_AirRun;
		}
	}

	if (Input::isHeld(Button_Right)) {
		mVelocity.x += acceleration;

		if (mRopeState == RopeState_Attached && !mOnGround) {
			mFacingDirection = Direction_Right;
			airRunning = true;
			mMovementState = MovementState_AirRun;
		}
	}

	if (Input::isPressed(Button_Jump)) {
		if (!mJumpPrepressed && mOnGround)
			Sound::playSample("data/sounds/jump.wav");
		mJumpPrepressed = true;
	}

	if (mOnGround && mJumpPrepressed) {
		mVelocity.y = -JUMP_VELOCITY;
		if (mRopeState != RopeState_Attached) {
			mJumpHeld = true;
		}
		mJumpPrepressed = false;
	}

	if (Input::isReleased(Button_Jump)) {
		if (mJumpHeld && mVelocity.y < 0) {
			mVelocity.y *= 0.5f;
		}

		mJumpHeld = false;
		mJumpPrepressed = false;
	}

	if (Input::isReleased(Button_Fire)) {
		detachHook();
	}

	if (mVelocity.y >= 0) {
		mJumpHeld = false;
	}

	if (!airRunning) {
		mMovementState = MovementState_Still;
	}

	if (mOnGround) {
		if (mVelocity.x > 0) {
			mFacingDirection = Direction_Right;
		} else if (mVelocity.x < 0) {
			mFacingDirection = Direction_Left;
		}

		if (abs(mVelocity.x) > GROUND_STOP_VELOCITY)
		{
			mMovementState = MovementState_Run;
		}
	}
	else if (!airRunning)
	{
		if (mVelocity.y > 0)
			mMovementState = MovementState_Jump;
		else
			mMovementState = MovementState_Fall;
	}

	if (mMovementState == MovementState_Still)
	{
		mVelocity.x = 0;
	}

	if (Input::isPressed(Button_Fire)) {
		Sound::playSample("data/sounds/rope.wav");
		mRopeState = RopeState_Moving;
		mRopePosition = mPosition;
		mRopeVelocity = float2::ZERO;

		if (Input::isHeld(Button_Left)) {
			mRopeVelocity.x -= 1;
		}

		if (Input::isHeld(Button_Right)) {
			mRopeVelocity.x += 1;
		}

		if (Input::isHeld(Button_Up)) {
			mRopeVelocity.y -= 1;
		}

		if (Input::isHeld(Button_Down)) {
			mRopeVelocity.y += 1;
		}

		if (floatIsZero(mRopeVelocity)) {
			mRopeVelocity.x = (mFacingDirection == Direction_Left ? -1 : 1);
		}

		mRopeVelocity = adjustRopeDirection(normalize(mVelocity + normalize(mRopeVelocity) * ROPE_SPEED)) * ROPE_SPEED;

		if (mRopeVelocity.x < 0) {
			mFacingDirection = Direction_Left;
		} else if (mRopeVelocity.x > 0) {
			mFacingDirection = Direction_Right;
		}
	}

	if (mRopeState == RopeState_Moving) {
		const int substeps = 25;
		for (int i = 0; i < substeps; i++) {
			mRopePosition += mRopeVelocity / (substeps * Time::TicksPerSecond);
			int tileX = (int)(mRopePosition.x / mRoom->getTileWidth());
			int tileY = (int)(mRopePosition.y / mRoom->getTileHeight());
			if (mRoom->isHookable(tileX, tileY)) {
				//Sound::stopSample("data/sounds/rope.wav");
				Sound::playSample("data/sounds/hook.wav");
				mRopeState = RopeState_Attached;
				mJumpHeld = false;

				ParticleSystem* particleSystem = new ParticleSystem(
					mAnimationHookParticle,
					2,
					30,
					10,
					1,
					50,
					10,
					-normalize(mRopeVelocity)*10,
					1.0);

				particleSystem->setPosition(mRopePosition);

				mRoom->addEntity(particleSystem);

				break;
			}

			if (length(mRopePosition-mPosition) > mRopeMaxLenghth)
			{
				detachHook();
				Sound::playSample("data/sounds/no_hook.wav");
				break;
			}

			if (mRoom->isCollidable(tileX, tileY)) {
				detachHook();
				Sound::playSample("data/sounds/no_hook.wav");
				break;
			}

			if (mRoom->damageDone((int)(mRopePosition.x), (int)(mRopePosition.y))) {
				detachHook();
				break;
			}

			mHookedEntity = mRoom->findHookableEntity(mRopePosition);
			if (mHookedEntity != 0) {
				Sound::playSample("data/sounds/hook.wav");
				mRopeState = RopeState_Attached;
				mJumpHeld = false;
				mHookedEntityOffset = mRopePosition - mHookedEntity->getPosition();
				mHookedEntityOffset.x = floor(mHookedEntityOffset.x);
				mHookedEntityOffset.y = floor(mHookedEntityOffset.y);
			}
		}
	}

	if (mRopeState == RopeState_Attached) {
		if (mHookedEntity != 0) {
			mRopePosition = mHookedEntity->getPosition() + mHookedEntityOffset;
		}

		float2 ropeToHero = mPosition - mRopePosition;
		if (lengthCompare(ropeToHero, ROPE_REST_LENGTH) > 0) {
			float2 ropeRestPoint = mRopePosition + normalize(ropeToHero) * ROPE_REST_LENGTH;
			float2 heroToRestPoint = ropeRestPoint - mPosition;
			float2 ropeAcceleration = heroToRestPoint * ROPE_SPRING_CONSTANT;
			if (lengthCompare(ropeAcceleration, ROPE_MAX_ACCELERATION) > 0) {
				ropeAcceleration = normalize(ropeAcceleration) * ROPE_MAX_ACCELERATION;
			}
			mVelocity += ropeAcceleration;
		}

		if (Input::isHeld(Button_Up)) {
			mVelocity.y -= acceleration;
		}

		if (Input::isHeld(Button_Down)) {
			mVelocity.y += acceleration;
		}

		int ropeTileX = (int)(mRopePosition.x / mRoom->getTileWidth());
		int ropeTileY = (int)(mRopePosition.y / mRoom->getTileWidth());
		if (mHookedEntity == 0 && !mRoom->isHookable(ropeTileX, ropeTileY)) {
			detachHook();
		}
	}

	unsigned int bumps = moveWithCollision();
	
	if ((bumps & (Direction_Left | Direction_Right)) != 0) {
		mVelocity.x = 0;
	}

	if ((bumps & (Direction_Up | Direction_Down)) != 0) {
		mVelocity.y = 0;
	}

	float gravity = mJumpHeld ? JUMP_GRAVITY : GRAVITY;
	mVelocity.y += gravity;
	bool ground = ((bumps & Direction_Down) != 0);
	if (ground && !mOnGround && mRopeState != RopeState_Attached)
	{
		Sound::playSample("data/sounds/land.wav");
	}
	mOnGround = ground;

	float drag = mOnGround ? GROUND_DRAG : AIR_DRAG;
	mVelocity *= drag;

	mFrame ++;
	
	if (mBlinkingTicksLeft)
	{
		mBlinkingTicksLeft --;
	}
}
Ejemplo n.º 6
0
static VGboolean find_angles(struct arc *arc)
{
   double vec0[2], vec1[2];
   double lambda1, lambda2;
   double angle;
   struct matrix matrix;

   if (floatIsZero(arc->a) || floatIsZero(arc->b)) {
      return VG_FALSE;
   }
   /* map the points to an identity circle */
   matrix_load_identity(&matrix);
   matrix_scale(&matrix, 1.f, arc->a/arc->b);
   matrix_rotate(&matrix, -arc->theta);
   matrix_map_point(&matrix,
                    arc->x1, arc->y1,
                    &arc->x1, &arc->y1);
   matrix_map_point(&matrix,
                    arc->x2, arc->y2,
                    &arc->x2, &arc->y2);
   matrix_map_point(&matrix,
                    arc->cx, arc->cy,
                    &arc->cx, &arc->cy);

#if DEBUG_ARCS
   debug_printf("Matrix 3 [%f, %f, %f| %f, %f, %f| %f, %f, %f]\n",
                matrix.m[0], matrix.m[1], matrix.m[2],
                matrix.m[3], matrix.m[4], matrix.m[5],
                matrix.m[6], matrix.m[7], matrix.m[8]);
   debug_printf("Endpoints [%f, %f], [%f, %f]\n",
                arc->x1, arc->y1, arc->x2, arc->y2);
#endif

   vec0[0] = arc->x1 - arc->cx;
   vec0[1] = arc->y1 - arc->cy;
   vec1[0] = arc->x2 - arc->cx;
   vec1[1] = arc->y2 - arc->cy;

#if DEBUG_ARCS
   debug_printf("Vec is [%f, %f], [%f, %f], [%f, %f]\n",
                vec0[0], vec0[1], vec1[0], vec1[1], arc->cx, arc->cy);
#endif

   lambda1 = vector_orientation(vec0);

   if (isnan(lambda1))
      lambda1 = 0.f;

   if (arc->type == VG_SCWARC_TO ||
       arc->type == VG_SCCWARC_TO)
      angle = vector_angles(vec0, vec1);
   else if (arc->type == VG_LCWARC_TO ||
            arc->type == VG_LCCWARC_TO) {
      angle = 2*M_PI - vector_angles(vec0, vec1);
   } else
      abort();

   if (isnan(angle))
      angle = M_PI;


   if (arc->type == VG_SCWARC_TO ||
       arc->type == VG_LCWARC_TO)
      lambda2 = lambda1 - angle;
   else
      lambda2 = lambda1 + angle;

#if DEBUG_ARCS
   debug_printf("Angle is %f and (%f, %f)\n", angle, lambda1, lambda2);
#endif

#if 0
   arc->eta1 = atan2(sin(lambda1) / arc->b,
                     cos(lambda1) / arc->a);
   arc->eta2 = atan2(sin(lambda2) / arc->b,
                     cos(lambda2) / arc->a);

   /* make sure we have eta1 <= eta2 <= eta1 + 2 PI */
   arc->eta2 -= two_pi * floor((arc->eta2 - arc->eta1) / two_pi);

   /* the preceding correction fails if we have exactly et2 - eta1 = 2 PI
      it reduces the interval to zero length */
   if ((lambda2 - lambda1 > M_PI) && (arc->eta2 - arc->eta1 < M_PI)) {
      arc->eta2 += 2 * M_PI;
   }
#else
   arc->eta1 = lambda1;
   arc->eta2 = lambda2;
#endif

   return VG_TRUE;
}